Skip to content

feat(agent): cancellation, timeouts, typed errors, and lifecycle helpers#13

Merged
ThomasK33 merged 1 commit into
mainfrom
feat/agent-cancellation-timeouts-lifecycle
Jun 24, 2026
Merged

feat(agent): cancellation, timeouts, typed errors, and lifecycle helpers#13
ThomasK33 merged 1 commit into
mainfrom
feat/agent-cancellation-timeouts-lifecycle

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Why

An external team integrated @coder/ai-sdk-agent into a durable deep-research
fan-out (Vercel Workflow) and reported that the friction was concentrated in
cancellation, timeouts, quota visibility, error typing, and lifecycle. This PR
hardens those paths, then adds a quality + correctness pass on top.

What changed

Cancellation & timeouts

  • abortSignal now interrupts the server-side run, not just the local
    WebSocket — a wedged turn stops generating and releases its workspace instead
    of running on, orphaned. Tearing down a stream() (cancel) interrupts too.
  • New requestTimeoutMs: a per-segment time budget. On expiry the run is
    interrupted and the call rejects with a retryable CoderChatError
    (kind: "timeout") instead of hanging. Documented as per-segment, with
    abortSignal: AbortSignal.timeout(ms) for total wall-clock.

Typed, retryable errors

  • A stream that ends before the turn settles rejects with CoderChatError
    (kind: "stream_closed", retryable) rather than reporting a truncated result
    as a clean stop.
  • Transport failures and server error events are classified into typed,
    retryable errors (no more bare DOMException/non-retryable transport errors
    bypassing the documented retry contract).

API & lifecycle

  • CoderAgent.listModels() to discover valid model hints.
  • await using support via Symbol.asyncDispose (interrupt + archive on scope
    exit), so cleanup rides scope exit instead of a forgotten finally.
  • A warning when responseFormat/JSON-schema output is requested — chatd does
    not constrain output server-side; use @coder/ai-sdk-provider +
    generateObject instead.

Docs

  • Agent-vs-provider decision guide (agent/provider/root READMEs), error handling,
    workspaces & quota, a durable-workflow recipe, and timeout/cleanup semantics.

Process

Built from the integration feedback, then refined with a /simplify pass and a
max-effort /code-review pass. The review caught a real regression the simplify
pass had introduced (a caller's own AbortSignal.timeout being misclassified as
the agent's timeout) plus several edge cases in the new error/interrupt paths —
all fixed here, each with a regression test.

Testing

  • 49 unit tests in @coder/ai-sdk-agent (8 new, covering abort→interrupt,
    timeout, stream-close, transport error, caller-timeout classification, cancel,
    and the responseFormat warning); 178 across the repo. All green.
  • pnpm check (format + lint + typecheck) and pnpm build pass.

Known follow-ups (out of scope)

  • A caller-aborted createChat leaves a chat whose id we never received, so it
    can't be interrupted — needs client-generated ids or a reconcile sweep.
  • The requires_action safety-counter (pre-existing) can finish a turn as
    tool-calls with no tool calls if action_required never arrives.

🤖 Generated with Claude Code

Hardens CoderAgent based on external integration feedback (durable deep-research
fan-out on Vercel Workflow), then a quality + correctness pass.

- abortSignal now interrupts the *server* run (not just the local socket); a
  stream cancel() interrupts too, so wedged turns stop holding their workspace.
- requestTimeoutMs: per-segment time budget that interrupts and rejects with a
  retryable CoderChatError (kind: "timeout") instead of hanging.
- A stream that ends before the turn settles now rejects with a retryable
  CoderChatError (kind: "stream_closed") rather than reporting a truncated
  result as a clean stop; transport errors and server error events are
  classified into typed, retryable errors too.
- CoderAgent.listModels() to discover model hints.
- await using support via Symbol.asyncDispose (interrupt + archive on scope exit).
- Warn when responseFormat/JSON-schema output is requested (unsupported
  server-side; use @coder/ai-sdk-provider + generateObject instead).
- Docs: Agent-vs-provider decision guide, error handling, workspaces/quota,
  durable-workflow recipe, and timeout semantics.

Change-Id: I19e900ea5a4e8d7c8ff34813ae5f47399dc5d28d
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33 ThomasK33 added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit 08fa1dd Jun 24, 2026
6 checks passed
This was referenced Jun 24, 2026
@ThomasK33 ThomasK33 deleted the feat/agent-cancellation-timeouts-lifecycle branch June 24, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant