1.0.0-rc.3

AgJSON 1.0.0-rc.3: a client abort under ADK 2.3.0 closes as a cancelled turn

The third release candidate for 1.0.0. All six packages move to 1.0.0-rc.3 together, and they ship spec revision 1.0.0-rc.3 (AGJSON_VERSION), a revision of rc.2 before 1.0.0.

Installing the release candidate

The release candidate is published under the rc tag. latest stays on 0.12.7:

npm i @silverprotocol/core@rc

Install each framework package you use the same way, so every @silverprotocol/* package in your lockfile is on 1.0.0-rc.3. While a release candidate is the most recent publish, a package’s page on npmjs.com shows no README; each package still carries its README.

1.0.0-rc.3 doesn’t include 0.12.7’s change: its @silverprotocol/core still calls the global structuredClone.

Upgrading from rc.2

  • Google ADK: with @google/adk 2.3.0, a run the host aborts now closes as a cancelled turn. From 2.3.0, when a host passes abortSignal to runAsync and aborts, ADK ends the run with one last event: error code INVOCATION_ABORTED, message “Invocation was aborted by client.”. That event also answers, with an error, every tool call the run left unanswered, a pending approval request included. The rc.2 package read that event as an in-band error: it emitted an error event and closed the turn turn.error at flush(), and when an approval was pending it first closed a paused turn naming an approval ADK had already answered, then an empty error turn. rc.3 closes the turn from that event with one turn.abort whose reason is "cancelled", after a failed tool.done for each call it answers, and emits no error or turn.error. A UI that renders an aborted turn shows the user’s stop as a stop, the unanswered calls as failed tool rows, and no stale approval card. A host on @google/adk 2.2.1, or one that passes no abortSignal, sees no change.

Google ADK

  • A client abort closes turn.abort with reason "cancelled" (see Upgrading; §8.0 item 35). The package recognizes ADK’s abort event by its error code alone, as ADK does; an event with any other error code beside an error message still closes turn.error, as before. Which close a host gets depends on whether it keeps reading after it aborts:

    • It keeps reading until runAsync returns: the abort event is the run’s last event, and the turn closes on it as turn.abort "cancelled". This is the close to aim for: keep reading runAsync after you abort.
    • It stops reading at the abort: the host never receives the abort event, and flush() closes the turn as it closes any stream that ends early. That’s paused, naming the approval, when one was pending and ADK had already signalled the pause; turn.abort with reason "stream-truncated" otherwise; and no turn at all if the abort came before ADK yielded anything.

    runLive is unchanged: it yields no abort event, and a Live barge-in still closes turn.abort "interrupted" (§8.0 item 17). Under the spec’s host obligation 4, a host sends no host-completion event after an abort.

  • An answered approval request is no longer pending. An ask stays pending only while its adk_request_* call has no response in the run. Once a response answers it within the run, as ADK’s abort event does, the turn no longer closes paused on that ask (§8.0 item 26). No recorded stream answers such a call within its run, so no recorded pause changes.

  • What else the cancelled close carries. The turn’s usage, when any model call reported it, rides the message.end before the turn.abort. The abort event’s code and message ride the event-level provider-raw block verbatim. An in-band error earlier in the same run still emits its non-terminal error event, and the abort still closes the turn as "cancelled", with no turn.error.

  • ADK 2.3.0 changes one credential URL. The auth URL in ADK’s own OAuth2 credential request no longer ends with an empty redirect_uri=. The package carries that URL as ADK builds it, in the call’s tool.args, the hitl.ask and the paused close, so those values change when you move to 2.3.0, whichever package version you run.

@silverprotocol/richtext

  • A fenced code block indented one to three spaces, or continuing a list item, now parses as a code block. CommonMark allows up to three spaces before a fence, and a fence can continue a list item at the item’s content column. The parser matched only an unindented fence, so an indented one parsed as paragraphs. Up to the fence’s own indent is now stripped from each line of its body. List items still hold inline content only, so a fence that continues an item closes the list and follows it as a top-level code-fence block, and a later item opens a new list that keeps its number. The AST types don’t change.

Spec: AgJSON 1.0.0-rc.3

rc.3 revises rc.2. The revision note in SPEC §15 lists the change:

  • §8.0 item 35: an event whose errorCode is "INVOCATION_ABORTED" is no longer an in-band invocation error. A normalizer targeting ADK closes the run’s turn from that event with one turn.abort whose reason is "cancelled", after the event’s own tool responses have closed their calls as item 25 directs, and emits no error or turn.error for it.
  • §8.0 item 26: an ask is pending while its adk_request_* call has no response in the run, so a sealed ask closes nothing paused.
  • §10 item 70 tests both over captured @google/adk 2.3.0 streams.

reason stays an open string (§12). No closed set, schema or fold rule changes. rc.2 envelopes remain accepted (same major, §12).

Verified versions

Each framework package is verified end to end, tool calls included, against a live run at:

  • @anthropic-ai/claude-agent-sdk 0.3.296;
  • @openai/agents 0.20.0;
  • @google/adk 2.3.0, with @google/genai 2.30.0;
  • ai 7.0.137.

Wire version

1.0.0-rc.3. Replaying every recorded stream through the 1.0.0-rc.2 and 1.0.0-rc.3 packages, all 107 runs give byte-identical events and fold to the same result: the Claude Agent SDK (32), OpenAI Agents SDK (16) and Vercel AI SDK (9) streams, and the Google ADK streams (25, each with and without the host-completion event). No recorded stream carries ADK’s abort event. Of the 672 runs of the engine-built fixtures, only the 40 aborted runs among the new client-abort fixtures give different output, closing as described above; their 8 unaborted control runs don’t.

The 1.0.0-rc.3 packages are built from typescript-sdk commit 35368cf5, the commit npm’s provenance for all six 1.0.0-rc.3 packages attests.