Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
## Unreleased

### Features

- **ag-ui:** expose complete interrupt sessions, optional atomic persistence and authoritative recovery, and provider lifetime cleanup.

### Fixes

- **langgraph:** retain null-payload resume commands and combined message/state input for intentional retry without reusing an aborted signal.
- **ag-ui:** retain exact resume decisions, roll failed state back to committed boundaries, and reject stale callbacks and concurrent recovery actions.

### Breaking changes

- **ag-ui:** native batches take precedence over compatibility events in `auto` mode. Select `legacy-command` or `mastra-command` explicitly for backends requiring command transport.
- **ag-ui:** resume requires a pending batch and each native ID exactly once; scalar responses apply only to single-entry batches. New messages, regeneration, and client-tool continuation cannot abandon an unresolved interrupt.
- **ag-ui:** uncertain resumes require authoritative reconciliation before retry. Durable client claims require an application-provided atomic store; backend duplicate-effect protection requires server idempotency.

## 0.1.0 (2026-09-08)

### 🚀 Features
Expand Down
297 changes: 289 additions & 8 deletions apps/website/content/docs/ag-ui/api/api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,18 @@
"description": "Extra HTTP headers sent with every request (e.g. auth tokens).",
"optional": true
},
{
"name": "interruptTransport",
"type": "InterruptTransport",
"description": "Explicit compatibility wire profile; auto prefers protocol-native outcomes.",
"optional": true
},
{
"name": "persistence",
"type": "AgUiInterruptPersistence",
"description": "Optional application-owned durable thread storage and reconciliation.",
"optional": true
},
{
"name": "telemetry",
"type": "false | AgentRuntimeTelemetrySink",
Expand Down Expand Up @@ -440,7 +452,19 @@
{
"name": "interrupt",
"type": "Signal<AgentInterrupt | undefined>",
"description": "",
"description": "Optional display projection of the pending interrupt. A runtime may expose\na separate full batch and lifecycle surface. A cleared display projection\ndoes not by itself prove that resumed backend work completed.",
"optional": true
},
{
"name": "interruptSession",
"type": "Signal<InterruptSessionSnapshot>",
"description": "Full interrupt batch and its request ownership phase.",
"optional": false
},
{
"name": "isInputBlocked",
"type": "Signal<boolean>",
"description": "Optional gate for ordinary composer input while the runtime requires resolution or recovery. Resume actions remain adapter-controlled.",
"optional": true
},
{
Expand All @@ -455,6 +479,12 @@
"description": "",
"optional": false
},
{
"name": "ready",
"type": "Promise<void>",
"description": "Resolves after persisted thread state is hydrated; actions wait for it.",
"optional": false
},
{
"name": "regenerate",
"type": "(assistantMessageIndex: number) => Promise<void>",
Expand All @@ -464,7 +494,7 @@
{
"name": "retry",
"type": "() => Promise<void>",
"description": "Re-run the last submitted input after a failure. No-op if a run is already\n in flight or there is nothing to retry. Clears `error` and sets loading.",
"description": "Re-run the captured submission after a failure, including a resume command\nwith no message payload. Does not append another user message or reuse an\naborted request signal. Does not restart an in-flight request; no-op when\nnothing is saved.\nAdapters may reject unsafe resume retries until the backend outcome has\nbeen reconciled; a transport failure alone does not prove non-execution.",
"optional": false
},
{
Expand Down Expand Up @@ -492,16 +522,43 @@
"optional": false
},
{
"name": "submit",
"type": "(input: AgentSubmitInput, opts: AgentSubmitOptions) => Promise<void>",
"name": "toolCalls",
"type": "Signal<ToolCall[]>",
"description": "",
"optional": false
}
],
"methods": [
{
"name": "dispose",
"signature": "dispose(): void",
"description": "Unsubscribe and stop local work. Does not cancel backend checkpoints.",
"params": []
},
{
"name": "toolCalls",
"type": "Signal<ToolCall[]>",
"name": "reconcileInterrupt",
"signature": "reconcileInterrupt(): Promise<void>",
"description": "Recover an uncertain attempt using the configured authoritative reconciler.",
"params": []
},
{
"name": "submit",
"signature": "submit(input: AgentSubmitInput, opts: AgUiSubmitOptions): Promise<void>",
"description": "",
"optional": false
"params": [
{
"name": "input",
"type": "AgentSubmitInput",
"description": "",
"optional": false
},
{
"name": "opts",
"type": "AgUiSubmitOptions",
"description": "",
"optional": true
}
]
}
],
"examples": []
Expand Down Expand Up @@ -538,6 +595,102 @@
],
"examples": []
},
{
"name": "AgUiInterruptPersistence",
"kind": "interface",
"description": "",
"properties": [
{
"name": "namespace",
"type": "string",
"description": "",
"optional": false
},
{
"name": "reconcile",
"type": "(record: AgUiThreadRecord) => Promise<object | object>",
"description": "",
"optional": true
},
{
"name": "store",
"type": "object",
"description": "",
"optional": false
}
],
"examples": []
},
{
"name": "AgUiSubmitOptions",
"kind": "interface",
"description": "Adapter-specific submit guards in addition to cancellation.",
"properties": [
{
"name": "interruptGeneration",
"type": "number",
"description": "Generation captured when rendering the interrupt decision; rejects stale controls.",
"optional": true
},
{
"name": "signal",
"type": "AbortSignal",
"description": "",
"optional": true
}
],
"examples": []
},
{
"name": "AgUiThreadRecord",
"kind": "interface",
"description": "",
"properties": [
{
"name": "committed",
"type": "ThreadSnapshot",
"description": "",
"optional": false
},
{
"name": "namespace",
"type": "string",
"description": "",
"optional": false
},
{
"name": "resumeInput",
"type": "ThreadSnapshot",
"description": "",
"optional": true
},
{
"name": "revision",
"type": "number",
"description": "",
"optional": false
},
{
"name": "session",
"type": "InterruptSessionSnapshot",
"description": "",
"optional": false
},
{
"name": "threadId",
"type": "string",
"description": "",
"optional": false
},
{
"name": "version",
"type": "1",
"description": "",
"optional": false
}
],
"examples": []
},
{
"name": "CustomStreamEvent",
"kind": "interface",
Expand All @@ -558,6 +711,108 @@
],
"examples": []
},
{
"name": "InterruptSessionSnapshot",
"kind": "interface",
"description": "",
"properties": [
{
"name": "attempt",
"type": "ResumeAttempt",
"description": "",
"optional": true
},
{
"name": "generation",
"type": "number",
"description": "",
"optional": false
},
{
"name": "interrupts",
"type": "object[]",
"description": "",
"optional": false
},
{
"name": "legacy",
"type": "AgentInterrupt",
"description": "",
"optional": true
},
{
"name": "phase",
"type": "InterruptSessionPhase",
"description": "",
"optional": false
},
{
"name": "runId",
"type": "string",
"description": "",
"optional": true
}
],
"examples": []
},
{
"name": "ResumeAttempt",
"kind": "interface",
"description": "",
"properties": [
{
"name": "generation",
"type": "number",
"description": "",
"optional": false
},
{
"name": "id",
"type": "string",
"description": "",
"optional": false
},
{
"name": "input",
"type": "AgentSubmitInput",
"description": "",
"optional": false
},
{
"name": "parameters",
"type": "object",
"description": "",
"optional": false
},
{
"name": "runId",
"type": "string",
"description": "",
"optional": false
}
],
"examples": []
},
{
"name": "ThreadSnapshot",
"kind": "interface",
"description": "Serializable protocol state at a confirmed run boundary.",
"properties": [
{
"name": "messages",
"type": "object | object | object | object | object | object | object[]",
"description": "",
"optional": false
},
{
"name": "state",
"type": "Record<string, unknown>",
"description": "",
"optional": false
}
],
"examples": []
},
{
"name": "ToAgentOptions",
"kind": "interface",
Expand All @@ -569,6 +824,18 @@
"description": "A2UI client capabilities (catalog negotiation) to advertise to the agent.\nWhen set, they are seeded once into the AG-UI shared state under the\n`a2ui_client_capabilities` key, so every RunAgentInput.state carries them.\nUse `@threadplane/chat`'s `a2uiClientCapabilities()` for the renderer's\nstandard value.",
"optional": true
},
{
"name": "interruptTransport",
"type": "InterruptTransport",
"description": "Native outcomes take precedence in auto mode; select a legacy profile explicitly when required.",
"optional": true
},
{
"name": "persistence",
"type": "AgUiInterruptPersistence",
"description": "Application-owned durable storage. Requires a stable source threadId and scoped namespace.",
"optional": true
},
{
"name": "telemetry",
"type": "false | AgentRuntimeTelemetrySink",
Expand All @@ -585,6 +852,20 @@
"signature": "readonly { events: readonly BaseEvent[]; when: \"initial\" | { toolMessageFor: string } }[]",
"examples": []
},
{
"name": "InterruptSessionPhase",
"kind": "type",
"description": "",
"signature": "\"none\" | \"collecting\" | \"pending\" | \"claimed\" | \"resuming\" | \"acknowledged\" | \"uncertain\" | \"recovery-required\"",
"examples": []
},
{
"name": "InterruptTransport",
"kind": "type",
"description": "",
"signature": "\"auto\" | \"protocol\" | \"legacy-command\" | \"mastra-command\"",
"examples": []
},
{
"name": "bridgeCitationsState",
"kind": "function",
Expand Down Expand Up @@ -678,7 +959,7 @@
{
"name": "toAgent",
"kind": "function",
"description": "Wraps an AG-UI AbstractAgent into the runtime-neutral Agent contract.\n\nThe adapter subscribes to source.subscribe({ onEvent }) and reduces every\nevent into the produced Agent's signals. submit() optimistically appends the\nuser message to both our signals and the source agent's internal message\nlist, then calls source.runAgent(). stop() calls source.abortRun().\n\nSubscription cleanup: the returned Agent does NOT manage its own lifetime.\nCallers using DI should rely on the provider's destroy hook; direct callers\nof toAgent() should treat the returned object's lifecycle as tied to the\nagent instance they constructed. The subscriber registered via\nsource.subscribe() will fire for the lifetime of source.",
"description": "Wraps an AG-UI AbstractAgent into the runtime-neutral Agent contract.\n\nThe adapter subscribes to source.subscribe({ onEvent }) and reduces every\nevent into the produced Agent's signals. submit() optimistically appends the\nuser message to both our signals and the source agent's internal message\nlist, then calls source.runAgent(). stop() calls source.abortRun().\n\nSubscription cleanup: providers dispose the adapter with their injector.\nDirect callers must call dispose() when they no longer need the adapter.",
"signature": "toAgent(source: AbstractAgent<>, options: ToAgentOptions): AgUiAgent<>",
"params": [
{
Expand Down
Loading
Loading