mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-27 01:21:25 +00:00
## Summary
This makes the advertised mid-run steering path real: users can send
append or interrupt steering messages through the API, CLI, and web UI,
and the worker delivers them to live API-mode agent sessions or buffers
them for the next session. The change adds the control protocol, session
interrupt machinery, workflow hub, server route/OpenAPI/client updates,
and UI feedback needed for the whole path.
### Plan Summary
- Add `SteerKind`/`run.steer` wire protocol and `POST /runs/{id}/steer`
- Deliver steers through subprocess JSONL or the in-process
`SteeringHub`
- Support append and interrupt behavior in agent sessions, with bounded
buffering and events
- Expose steering in the CLI/web UI and surface SSE toasts
## Flow
```mermaid
flowchart TB
UI["CLI / Web UI"] --> API["POST /runs/{id}/steer"]
API -->|"subprocess transport"| Control["Worker control JSONL"]
API -->|"in-process transport"| Hub["SteeringHub"]
Control --> Hub
Hub -->|"active API sessions"| Session["SessionControlHandle"]
Hub -->|"no active session"| Pending["Pending buffer"]
Pending -->|"first future API session"| Session
Session --> Agent["Session round loop"]
Agent --> Events["RunEvent stream"]
Events --> UI
```
## What changed and why
- Agent sessions now expose a lightweight `SessionControlHandle`, drain
steering at the top of each round, and use a replaceable round
cancellation token for interrupts. LLM waits are cancelled promptly,
while tool execution observes cancellation cooperatively so every
committed `tool_use` still gets a matching `tool_result`.
- `SteeringHub` owns active API session registration, broadcast
delivery, pending buffering, FIFO queue caps, and steering
lifecycle/drop events. A completion coordinator closes the
final-response race without introducing a workflow dependency into the
agent crate.
- The server route replaces the 501 stub, validates run state and
best-effort CLI-only steerability, and forwards through either
subprocess control JSONL or the in-process hub. OpenAPI and generated
clients now include the request type.
- The CLI and web UI can send append or interrupt steers. Run detail and
board views open the new composer, and shared SSE subscriptions now
support per-subscriber event callbacks so invalidation and steering
toasts can coexist on one EventSource.
## Review notes
- Steering actors stay on top-level `RunEvent.actor`; event props only
carry steering kind/drop metadata.
- Buffered steers replay as append messages to the first API session
that registers after an empty-active period. Per-stage targeting remains
out of scope.
- CLI-mode agent stages are still not steerable; the server returns a
best-effort 409 when all active agent stages are CLI-mode, while the
worker hub remains the authoritative safety net.
- No persistence or schema migration is required; active and pending
steering state is in memory.
- New tests focus on protocol round-trips, hub buffering/bounds, session
steering-loop behavior, SSE fanout, and basic server rejection paths.
⚒️ Generated with [Fabro](https://fabro.sh)
---------
Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Bryan Helmkamp <bryan@brynary.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| archive.rs | ||
| artifact_cp.rs | ||
| artifact_list.rs | ||
| attach.rs | ||
| auth.rs | ||
| config.rs | ||
| create.rs | ||
| diff.rs | ||
| discord.rs | ||
| docs.rs | ||
| doctor.rs | ||
| dump.rs | ||
| exec.rs | ||
| fabro.rs | ||
| fork.rs | ||
| graph.rs | ||
| inspect.rs | ||
| install.rs | ||
| json_global.rs | ||
| logs.rs | ||
| mod.rs | ||
| model.rs | ||
| model_list.rs | ||
| model_test.rs | ||
| parse.rs | ||
| pr.rs | ||
| pr_close.rs | ||
| pr_create.rs | ||
| pr_merge.rs | ||
| pr_view.rs | ||
| preflight.rs | ||
| provider.rs | ||
| provider_login.rs | ||
| ps.rs | ||
| render_graph.rs | ||
| repo.rs | ||
| repo_deinit.rs | ||
| repo_init.rs | ||
| resume.rs | ||
| rewind.rs | ||
| rm.rs | ||
| run.rs | ||
| runner.rs | ||
| sandbox_cp.rs | ||
| sandbox_preview.rs | ||
| sandbox_ssh.rs | ||
| secret.rs | ||
| secret_list.rs | ||
| secret_rm.rs | ||
| secret_set.rs | ||
| send_analytics.rs | ||
| send_panic.rs | ||
| server_start.rs | ||
| server_status.rs | ||
| server_stop.rs | ||
| start.rs | ||
| support.rs | ||
| system.rs | ||
| system_df.rs | ||
| system_events.rs | ||
| system_info.rs | ||
| system_prune.rs | ||
| test_panic.rs | ||
| top_level.rs | ||
| unarchive.rs | ||
| uninstall.rs | ||
| upgrade.rs | ||
| validate.rs | ||
| version.rs | ||
| wait.rs | ||
| worker_auth.rs | ||
| workflow.rs | ||
| workflow_create.rs | ||
| workflow_list.rs | ||