fabro/lib/apps/fabro-server/src
Bryan Helmkamp 1978257aa5
Interrupt a live agent stage's model turn over Petri
Petri 639ce3e added `ControlService::interrupt_firing` and the `LiveTurns`
capability a host installs beside the pause hooks. Fabro now drives it:
`RunControls::interrupt(stage, text)` resolves its stage the way a steer
does (a label, a node name, or the run's one live agent stage) and stops
that stage's current model turn, keeping the session; the text, when
given, is the stage's next input. `engine::run` installs the live-turn set
as a runtime capability, so without it no interrupt could ever land.

The worker maps `run.interrupt` and `run.interrupt_then_steer`, both of
which now carry an optional `stage`, to that call. The control bus is
one-way, so a refusal is recorded the way a refused steer is: a
`run.notice` on the run's stream whose code says why (`no_live_turn` when
Petri refuses a stage with no turn in flight, `no_such_stage`,
`interrupt_refused`).

The server's `POST /runs/{id}/interrupt` and `POST /runs/{id}/steer` with
`interrupt=true` forward the control and answer 202, replacing the 501
`interrupt_unsupported` stub. The interrupt endpoint takes an optional
body (`stage`, `text`), refuses a finished run with 409
`run_not_interruptible`, and forwards an interrupt of a blocked run, since
an agent stage may be running a turn beside the question and the worker
judges each stage itself. `fabro events --pretty` prints the delivered
interrupt and the stage's `attractor.turn.interrupted` report.

Verified on the twin: `fabro steer --interrupt` during a long tool call
ends the turn, the text is the agent's next request, and the stream
carries the `$interrupt` record and the interrupted-turn report; an
interrupt of a gate stage is refused with `no_live_turn` and the gate's
question is untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-18 22:38:17 -04:00
..
auth Keep auth code store naming consistent 2026-08-24 17:26:17 -04:00
demo Remove the [server.slatedb] settings and the SlateDB prefix probe 2026-09-18 16:00:24 -04:00
prompts Render the run title prompt with Jinja instead of string replacement 2026-07-27 17:23:16 -04:00
server Interrupt a live agent stage's model turn over Petri 2026-09-18 22:38:17 -04:00
worker_control refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
automation_materializer.rs Delete the legacy run event log, its reducer and its types 2026-09-18 14:09:17 -04:00
canonical_host.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
canonical_origin.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
csp.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
diagnostics.rs Read the Daytona scopes fabro needs from the provider's health 2026-09-11 12:36:29 -06:00
error.rs Add the Petri run store endpoints to the API 2026-09-17 20:12:20 -04:00
git_checkout.rs Consolidate server Git subprocess ownership 2026-09-11 17:36:40 -06:00
github_webhooks.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
install.rs Remove the [server.slatedb] settings and the SlateDB prefix probe 2026-09-18 16:00:24 -04:00
interp.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
jwt_auth.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
lib.rs Run the server's lifecycle over platform records instead of run_events 2026-09-18 12:32:06 -04:00
manifest_validation.rs Delete fabro-validate and fabro-acp; validate on Petri's check 2026-09-18 11:32:04 -04:00
petri_check.rs Delete fabro-validate and fabro-acp; validate on Petri's check 2026-09-18 11:32:04 -04:00
petri_runs.rs Run the server's lifecycle over platform records instead of run_events 2026-09-18 12:32:06 -04:00
principal_middleware.rs Serve the Petri run store to workers 2026-09-17 20:12:20 -04:00
request_id.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
run_compiler.rs Delete fabro-validate and fabro-acp; validate on Petri's check 2026-09-18 11:32:04 -04:00
run_files.rs Remove the engine flag: every run is a Petri run 2026-09-18 09:58:21 -04:00
run_files_security.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
run_intent.rs Return 404 when a worker's originating run is missing 2026-09-12 10:58:05 -06:00
run_manifest.rs Delete fabro-validate and fabro-acp; validate on Petri's check 2026-09-18 11:32:04 -04:00
run_selector.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
run_title_generation.rs Import lithos-llm types directly instead of through fabro-types 2026-09-10 10:03:08 -06:00
run_tool_create.rs Carry usage as lithos-llm's Usage and rename billing to usage 2026-09-14 12:31:34 -06:00
security_headers.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00
serve.rs Remove the [server.slatedb] settings and the SlateDB prefix probe 2026-09-18 16:00:24 -04:00
server.rs Interrupt a live agent stage's model turn over Petri 2026-09-18 22:38:17 -04:00
server_secrets.rs Expose lithos request and response shapes through the API, server, CLI, and web 2026-09-09 17:26:57 -06:00
spawn_env.rs Forward the Docker daemon selection and Daytona credentials to Petri workers 2026-09-18 09:10:29 -04:00
startup.rs Remove expired startup secret migrations 2026-09-05 14:05:48 -04:00
static_files.rs feat(web): tell open tabs when a new build ships 2026-07-25 14:45:26 -04:00
test_support.rs Remove the [server.slatedb] settings and the SlateDB prefix probe 2026-09-18 16:00:24 -04:00
web_auth.rs Serve CLI auth sessions from SQLite 2026-07-26 00:00:15 -04:00
worker_runtime.rs Forward the Docker daemon selection and Daytona credentials to Petri workers 2026-09-18 09:10:29 -04:00
worker_token.rs refactor: organize crates into three layers 2026-07-23 17:59:34 -04:00