guanghu/docs/adr/0148-cancellable-ai-agent-streams.md
Guanghu Domestic Migration 9b41d51231
Some checks are pending
Auto-update PR branches / Update open PR branches (push) Waiting to run
CI / Frontend Static Quality Checks (push) Waiting to run
CI / Frontend Tests & Coverage (push) Waiting to run
CI / Rust Tests & Quality Checks (push) Waiting to run
CI / Linux build verification (push) Waiting to run
Deploy docs / Build VitePress site (push) Waiting to run
Deploy docs / Deploy to GitHub Pages (push) Blocked by required conditions
Release (Alpha) / Compute alpha version (push) Waiting to run
Release (Alpha) / Build release artifacts (push) Blocked by required conditions
Release (Alpha) / GitHub Release (alpha) (push) Blocked by required conditions
Release (Alpha) / Update docs and release pages (push) Blocked by required conditions
chore: import sanitized domestic snapshot for REPO-004
Source snapshot: 514ab1975951d94342ea38e64101d5a0f1c51c77
2026-07-17 15:55:28 +08:00

2.0 KiB

type, id, title, status, date, supersedes
type id title status date supersedes
ADR 0148 Cancellable AI agent streams active 2026-06-28

Context

ADR-0133 gave every AI stream a request-scoped event name so concurrent or rapidly reused renderer sessions do not share Tauri event channels. Users can still start long-running CLI-agent work that spawns local subprocesses, and closing or ignoring the frontend stream only suppresses stale renderer callbacks. Without a backend cancellation path, the selected CLI can keep running after the user has decided to stop the response.

The stop control needs to work across the shared JSON-line runtime and line-oriented adapters such as Antigravity, Kiro, and Hermes without giving the renderer access to arbitrary process ids.

Decision

Tolaria treats the request-scoped AI-agent event name as the cancellation handle for app-managed CLI-agent streams.

The desktop backend wraps stream_ai_agent execution in an AI-agent stream scope. When an adapter spawns a child process, it registers that child under the current scoped stream id through a shared process registry. The renderer can then call abort_ai_agent_stream(event_name) with the same scoped id used for event delivery. The command validates the ai-agent-stream-* prefix and safe character set before killing the registered child, and returns false when no active child is present.

Direct AI-model streams are not registered in this process registry because they do not spawn local CLI children.

Consequences

  • The stop button can abort an in-flight app-managed CLI process instead of only ignoring late stream events.
  • New CLI-agent adapters that spawn subprocesses must register their child after taking stdout/stderr handles and wait through the registered wrapper.
  • The renderer never receives or supplies OS process ids; cancellation remains scoped to validated AI-agent stream names.
  • A stop can race with process startup or natural completion, so both frontend and backend stop paths are idempotent.