0.12.5

The fold no longer throws on an inherited JSON Patch name or a deeply nested event

A patch release. All six packages move to 0.12.5 together. @silverprotocol/core, @silverprotocol/claude-agent-sdk and @silverprotocol/openai-agents change. The spec revision stays 1.0.0-draft.8. It fixes two ways a single event could make the reference ingest or fold throw, instead of refusing that event and going on.

@silverprotocol/core

  • A JSON Patch operation that names an inherited member now fails. The patch applier behind state.delta and memory.write now resolves each path token against an object’s own members only, as RFC 6901 defines. Before 0.12.5, a replace, remove, move, copy or test whose path named an inherited name, such as toString or hasOwnProperty, resolved through the object’s prototype. The operation was applied, or it copied a function into the state, and result() then threw. Such an operation now fails, as does one whose path passes through a member the object doesn’t own. The fold leaves the state or record unchanged and asks for a snapshot resync, as it does for any patch it can’t apply. This is a defect fix: the applier now follows RFC 6902, which the spec names for these patches (§5, §14), and no field’s meaning changes.
  • An event nested past a fixed depth no longer throws. Validating or folding an event nested a few thousand levels deep threw a RangeError out of ingestAgEvent(), Reducer.push() or result(). ingestAgEvent() and Reducer.push() now measure the nesting first, without recursion. An event holding a value nested more than 1,016 levels below its root isn’t folded: ingestAgEvent() reports it in place as an ext.agjson.ignored event, which keeps its seq slot, and Reducer.push() counts its slot and folds nothing from it. That’s how the spec’s trust-boundary rule (§5.0) treats any event whose body fails validation. A JSON Patch whose result would nest past the same bound fails like any patch that can’t be applied, so successive patches can’t build a value past it. The bound is the 1,000 levels at which the reference normalizers cap a carried value, plus 16 for the envelope around it, so no event they emit reaches it. In 0.12.5 that cap also covers the JSON strings the Claude and OpenAI packages parse (below). This is a defect fix: an event the fold can’t take is now reported, as §5.0 requires, and ingestAgEvent() keeps its documented promise never to throw. No field’s meaning changes.
  • No consumer-side parse throws on a deep value. JsonValue now validates in one pass, without recursion, so a value nested deeper than the call stack allows now parses where it used to throw. Its output and its reported issues are otherwise unchanged. ingestAgEvent() and the stored-record readers also treat a parse that throws as a failed parse: ingest returns the ext.agjson.ignored event in the event’s slot, and a reader reports the record as unreadable. Neither throws.
  • The stored-record readers read back what the fold builds. readStoredAgMessage(), readStoredAgMessages() and readStoredAgMemoryRecords() now accept a record up to 1,032 levels deep, the depth a fold can build from events within the bound. 0.12.4 reported a record deeper than 1,000 levels as unreadable and left it out.
  • No public type changes.

Claude Agent SDK

  • A streamed tool input is capped at 1,000 levels. The package parses a streamed tool call’s input from the model’s JSON text, and that value skipped the 1,000-level cap every other carried value has. A node past the cap is now replaced by the string "[MaxDepth]", as in any other capped value, so the event stays within the bound. The model’s text still rides the tool.args.delta events whole, and an input within the cap is carried as before.

OpenAI Agents SDK

  • The JSON strings the package parses are capped at 1,000 levels. That’s a function call’s arguments, a hosted tool call’s arguments, and a tool’s string output read for structuredContent. A node past the cap is now replaced by "[MaxDepth]", and when arguments are cut, the full string rides ext.openai.unparsed. The tool’s output string still rides the tool.done content whole. A value within the cap is unchanged.

The other three packages change only their version.

Who should upgrade

A host that ingests or folds events from a source it doesn’t control: a network peer, a stored transcript, another process. Upgrade @silverprotocol/core to 0.12.5, including where another package pins it (check your lockfile).

Wire version

1.0.0-draft.8, unchanged. Replaying every recorded stream, and the ADK pause fixtures, through the 0.12.4 and 0.12.5 packages, all 148 runs give byte-identical events: the Claude Agent SDK (31), OpenAI Agents SDK (16) and Vercel AI SDK (9) streams, and the Google ADK streams (24) and pause fixtures (22), each with and without the host-completion event. No recorded stream patches an inherited name or nests past the bound.

The v0.12.5 release is tagged at typescript-sdk commit 10d3cdc2, the commit npm’s provenance for all six 0.12.5 packages attests.