SuperPi.Conversation.Machine (super_pi v0.1.0)

Copy Markdown View Source

Runtime Conversation Turn Coordinator (:gen_statem with [:handle_event_function, :state_enter]) synchronized with durable Fsmx tasks (SuperPi.Durable.TaskEngine) and the 12-hook SuperPi.Extension pipeline (REQ-FSM-01..REQ-FSM-06, 09 - Data Flows and Extension Injection Points.md).

States

  • :recovering — Runs TaskEngine.reconcile_on_open!/1 on startup and transitions to :idle.
  • :idle — Accepts submit/3 (:queue, :steer, :write) and manual compact/2.
  • :preparing_request — Runs before_agent_start, derives context (Context.derive/1), runs before_request and before_provider_request.
  • :streaming_llm — Streams or invokes the configured llm_responder and normalizes events; handles mid-stream :steer preemption.
  • :executing_tools — Runs tool calls one at a time: before_tool in the machine, then wrap_tool -> SandboxRunner -> after_tool in a task, so the machine still answers cancel, steer and get_state while a tool runs. Then after_tools. A :steer lets the running tool finish and skips the rest of the batch.
  • :sleeping_backoff — Pauses turn execution when provider rate-limits/retries occur (TaskEngine.sleep_until/3).
  • :awaiting_children — A tool result carried the control directive %{"await" => ...} (delegate_subagent). The durable task is waiting on its child tasks and the machine parks, like :sleeping_backoff, still answering cancel, get_state and compact. A child that settles wakes the task and tells the machine ({:task_woken, task_id}, from TaskEngine, on any node). A poll (config :super_pi, :await_poll_ms, default 5 s) covers a lost message. On wake the machine stores one user message per child with its summary and goes on at :preparing_request. Not a tool result: the tool call already has one (the acknowledgement), and a second result for one call id is refused by the providers.
  • :compacting — Runs before_compact or default compaction and records pi.compaction with head_entry_id.
  • :settling_run — Runs after_run verification gate; either loops back to :preparing_request ({:continue, prompt}) or completes the durable pi.generation task and returns to :idle.

Summary

Functions

Cancels the running turn: stops the LLM request or the running tool (with its OS processes), records a "cancelled" result for every tool call without a result, marks the durable task cancelled, replies {:error, :cancelled} to the waiting submit caller and returns to :idle.

Runs manual compaction. During a turn the request waits until the conversation is idle, so a compaction never lands between a tool call and its result. opts[:timeout] (default 30 s) bounds the wait. Returns {:ok, :noop}, {:ok, :cancelled} or {:ok, result}.

Returns the current {:state, data} snapshot of the :gen_statem.

Tells the machine that a pending pi.generation task was stored for it (a scheduled run, see SuperPi.Schedule). An idle machine starts the task at once. A busy one starts it when its turn ends. A machine that is still recovering finds the task itself.

submit/3 for entry points (gateway, RPC): a machine that exits or a call that times out is {:error, reason}, not an exit of the caller.

Updates the active extension pipeline for the conversation machine.

Submits user input with mode :queue (default), :steer (preempts active tool batch/stream), or :write (passive append).

Functions

cancel(pid_or_via)

Cancels the running turn: stops the LLM request or the running tool (with its OS processes), records a "cancelled" result for every tool call without a result, marks the durable task cancelled, replies {:error, :cancelled} to the waiting submit caller and returns to :idle.

The subtree goes with it: the task's live children (subagents, also while the turn is parked in :awaiting_children) are aborted bottom-up by TaskEngine.cancel_task/2, which calls abort_task!/1 on each, and the machines of those children are cancelled.

child_spec(opts)

compact(pid_or_via, opts \\ [])

Runs manual compaction. During a turn the request waits until the conversation is idle, so a compaction never lands between a tool call and its result. opts[:timeout] (default 30 s) bounds the wait. Returns {:ok, :noop}, {:ok, :cancelled} or {:ok, result}.

get_state(pid_or_via)

Returns the current {:state, data} snapshot of the :gen_statem.

resume_pending(pid_or_via)

Tells the machine that a pending pi.generation task was stored for it (a scheduled run, see SuperPi.Schedule). An idle machine starts the task at once. A busy one starts it when its turn ends. A machine that is still recovering finds the task itself.

safe_submit(pid_or_via, text, opts \\ [])

submit/3 for entry points (gateway, RPC): a machine that exits or a call that times out is {:error, reason}, not an exit of the caller.

set_extensions(pid_or_via, extensions)

Updates the active extension pipeline for the conversation machine.

start_link(opts)

submit(pid_or_via, text, opts \\ [])

Submits user input with mode :queue (default), :steer (preempts active tool batch/stream), or :write (passive append).

via_tuple(conversation_id)