Skip to content

Refresh the vendored Agents SDK to 0.24.0 / Think 0.19.0 - #81

Merged
MiguelsPizza merged 2 commits into
mainfrom
alex/agents-0.24-refresh
Sep 23, 2026
Merged

MiguelsPizza merged 2 commits into
mainfrom
alex/agents-0.24-refresh

Conversation

@MiguelsPizza

@MiguelsPizza MiguelsPizza commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Refresh the vendored Agents SDK fork from agents 0.23.0 / Think 0.18.0 (upstream 5f7ad7e4) to agents 0.24.0 / think 0.19.0 (upstream c076e4c9), reconcile the fork's retained divergences, and close a replay-after-Stop hole in the fork's turn queue that Rook's host admission tail used to cover. The runtime package (src/) is unchanged, so Rook keeps its rook-runtime-29498e2e7123 pin and consumes only a new rook-sdk-<sha12> pre-release.

Upstream review

Every commit between the pins was reviewed against the fork: Lifecycle claims #2248, WebSockets protocol + Cap'n Web transport #2249, Queue capability #2245, State capability #2179, WebSockets owns state sync + connection flags #2257, fiber result #2244, deps #2288, browser interaction contract #2291 (types only, not exported), Think recovery #2256, Think retries across restarts #2297, Think peer #2304. A three-way merge of the six packages touched 90 files: 45 fast-forwarded (byte-identical to the base in the fork), 23 added, 1 deleted, 12 merged clean, 9 conflicted (17 hunks in think.ts).

Resolutions, all recorded in place in vendor/agents/docs/fork-diff.md with their source markers:

  • agents. Manifests keep the fork's newer dev dependencies; dynamic-agents.ts keeps the fork's signatures and takes upstream's connection-flag helpers; the state tests keep the fork's lossless cases (the _stateSentinel/resetStateCacheForHydration helpers are deleted, they would have written the capability object into _state). The fork's lossless migratePersistedState hook is re-homed from Agent.get state() onto the State capability's load path (state/index.ts, +27 lines) so the connect-time state push and broadcastState see migrated state and a rejecting override still fails construction. Its return type becomes TState. isInternalJsStubProp stays exported. No agents or ai-chat row retires.
  • think. Hunks 1–9 keep the fork's reordered streaming bodies with upstream's twelve outcome-stamp edits hand-ported; 10–12 take upstream's cutover helpers with the fork's stream retention moved into _streamCutoverOptions; 13, 16, 17 take the connection-less continuation as a queue item that carries the Stop epoch; 14–15 keep the fork's merged recovery body inside upstream's acceptance handoff. The dry run's one silent mis-merge (an error stamp after every WebSocket persist) is dropped. The fork's stopCurrentWork, resetTurnState(true), _historyGeneration, the abort check in _admitTurn and the public skipChatRequest stay (a rename back to upstream's private name is deferred to the next refresh so Rook can adopt 0.24 and delete its tail in separate steps). Markers: 34 in think.ts (29 + 5).
  • Fork-owned fixes. A persisted chat request that resolves stale after stopCurrentWork() now records its completed-request receipt, so a reconnecting client's replay is refused instead of re-running the stopped turn (red before, green after). Child cancellation dequeues a pending connection-less continuation, which as a queue item was invisible to cancelAgentToolRun until the alarm ran it (residual: an item the root already dispatched can still start one turn).
  • Tests. New workerd cases in agent-tool-reattach-recovery.test.ts pin the fork's semantics over two real sockets: Stop with a queued second request (persisted and broadcast at admission, empty done, stays in history, replay refused), per-request cancel of a queued request, and the accepted overlap ordering (uA, uB, aA, with the second turn ending on Think's continuation prompt). Two upstream tests are adapted to the fork's stream retention; one is retitled.

What a consumer must know

  • One-way storage on the first 0.24 wake. cf_agents_queues rows lift into the Lifecycle job queue and the table is dropped (upstream removes the lift in the next minor, so deployments must pass through 0.24; rows with malformed payloads are dropped); Agent's cf_schema_version row moves to the cf_agents:schema_version KV key; Think drops cf_think_workflow_notifications; cf_think_submissions gains nullable result_status and output_json. A 0.23 build reopening a 0.24 database recreates its tables harmlessly but drops due queue jobs and queued continuation, media-eviction and workflow-notification items.
  • Agent.queue() is alarm-driven. It returns before its callback runs; dequeue*/getQueue* are async; queued callbacks do not see the enqueuer's connection. The extension example's e2e now polls for its result. Think's submission drain, workflow notifications, connection-less continuations and media eviction run as queue items, one at a time, looked up by callback name. The job driver's 30-second slow-dispatch warning (already in 0.23) now also covers them.
  • Stop. The Stop semantics are the fork's stopCurrentWork (fork-diff row "Cancellation and recovery"); upstream has only the per-request cancel. Two limitations are pinned by tests rather than fixed: a request admitted while another turn runs is persisted before that turn's answer, and a cancel that arrives before the message is persisted is dropped.
  • Cap'n Web. The SDK's transport: "capnweb" is documented as unsupported on do-runtime (docs/browser-compatibility.md); the experimental ?__agents_rpc=capnweb endpoint and callablesFromDecorated are gone. agents/client and agents/react now import capnweb statically (about 58 KB minified).
  • Watch item, not fixed here. 0.24's Queue stable ids are not scoped per owner for facet items stored on the root, so one facet's connectionless-continuation or media-eviction item can overwrite the root's or another facet's pending item.

Testing

Gate Result
pnpm sdk:check (sherif, exports, oxfmt, oxlint, tsgo) pass
pnpm sdk:test (retries disabled) 1,960 tests: react 83, chat 309, agents 433, ai-chat 85, think 763, voice 21, shell 194; browser lanes think 64, shell 8
pnpm typecheck / pnpm test:unit pass / 1,020
conformance (workerd, node, node-transformed, browser, browser-transformed) 81 / 81 / 81 / 94 / 81
pnpm test:examples (extension + vibe-platform, Chrome) both ALL PASS
pnpm check:package / pnpm sdk:pack pass / six tarballs

Rook adoption: WebMCP-org/rook#179 pins rook-sdk-9364bfadb749 (cut from this branch head) and deletes Rook's admission tail on top.

🤖 Generated with Claude Code

MiguelsPizza and others added 2 commits September 23, 2026 09:45
Three-way merge of upstream 5f7ad7e4..c076e4c9 onto the six-package fork:
90 files, 9 conflicted (17 hunks in think.ts). Every retained divergence is
reconciled in place in docs/fork-diff.md and carries its source marker.

agents: Queue, State and WebSockets are Lifecycle capabilities; capabilities
declare claims. The fork's lossless migratePersistedState hook moves onto the
State capability's load path so the connect-time state push sees migrated
state. Lifecycle status() replaces starting(); the experimental capnweb
endpoint and callablesFromDecorated are gone. The Cap'n Web transport is
documented as unsupported on do-runtime.

think: the submission drain, workflow notifications, connection-less
continuations and media eviction run as alarm-driven queue items; the
connection-less continuation carries the Stop epoch; the fork's stream
retention lives in _streamCutoverOptions; upstream's acceptance handoff wraps
the fork's merged recovery body; the dry run's silent mis-merge (an error stamp
after every WebSocket persist) is dropped.

Two fork-owned fixes: a persisted chat request that resolves stale after
stopCurrentWork() now records its completed-request receipt, so a replay is
refused instead of re-running the stopped turn; and child cancellation dequeues
a pending connection-less continuation. New workerd cases pin the fork's Stop,
cancel and overlap semantics (uA, uB, aA with the continuation prompt).

First wake on 0.24 is one-way: cf_agents_queues lifts into the job queue and
is dropped, the Agent schema version moves to a KV key, and Think drops
cf_think_workflow_notifications.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Agent.queue() now returns before its callback runs, so the extension example's
e2e polls for the sdk-queue result instead of reading it immediately, and the
vibe-platform export pins the tested agents 0.24.0. Docs wording follows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@MiguelsPizza
MiguelsPizza merged commit e9bd5fd into main Sep 23, 2026
1 check passed
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