0.5.3

Tables in the rich-text AST — plus OpenAI Agents 0.17 support

Two consumer-driven changes in one cohort, both filed from the first downstream host to hit them. The wire vocabulary is untouched — AGJSON_VERSION stays 1.0.0-draft.2.

@silverprotocol/richtext learns tables

Agents fall back to markdown pipe tables whenever a result is tabular, and until now the rich-text AST deliberately parsed them as literal text — the honest fail-safe, but a chat bubble full of | # | Task | is not what anyone wanted (typescript-sdk#23, from a docs capture pass on a downstream chat kit). The block vocabulary gains a table node covering the GFM pipe-table subset: a header row, a delimiter row that supplies per-column alignment, and body rows of inline content.

parseRichText("| # | Task |\n|:-:|------|\n| 1 | **Ship** it |");
// [{ type: "table", align: ["center", undefined], header: { cells: […] }, rows: [{ cells: […] }] }]

The header fixes the column count and every row has exactly that many cells — short rows are padded with empty cells, long rows drop the excess, which is GFM’s rule and what every renderer the model was trained against already does. Outer pipes are optional, \| is the cell-pipe escape (it works inside code spans), and cells carry inline content only, through the same parser and the same safety policy: raw HTML stays literal text, unsafe link targets get no href. The streaming contract holds: the delimiter row has to complete before the table forms, so a renderer sees a paragraph flip once into a table and never flap back; body rows then grow in place.

This is an additive union member. A host that switches exhaustively on block.type should add a table arm in the same change that bumps the package — TypeScript will not force the issue when the switch returns ReactNode, and a missing arm renders a table as nothing.

OpenAI Agents 0.17 supported

@openai/agents 0.17.0 landed outside the declared peer range (typescript-sdk#24). All seven agents-core wire files the facet consumes are byte-identical to 0.16.0, and the provider package’s only change is websocket replay-safety bookkeeping — a wire no-op. The range widens to >=0.2.0 <0.18.

The live capture that accompanies the widening earned its keep: the census caught a wrapper-level field the type inventory cannot see. Since agents-core 0.15.0, RunToolCallOutputItem.executionStatus is "executed" when the runner actually invoked a function tool and absent when the result was synthesized instead — an input-guardrail rejection, a cancellation, a refused approval. The facet now carries it verbatim on tool.done providerMetadata, beside the existing caller carry, so a consumer can tell a tool’s own result from a runner substitute.

The compatibility tables on each npm page carry the dated evidence.