@assistant-ui/react-ag-ui 0.0.29 → 0.0.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +41 -0
  2. package/dist/index.d.ts +2 -1
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/runtime/AgUiThreadRuntimeCore.d.ts +11 -0
  5. package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
  6. package/dist/runtime/AgUiThreadRuntimeCore.js +185 -12
  7. package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
  8. package/dist/runtime/adapter/run-aggregator.d.ts +10 -1
  9. package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
  10. package/dist/runtime/adapter/run-aggregator.js +52 -6
  11. package/dist/runtime/adapter/run-aggregator.js.map +1 -1
  12. package/dist/runtime/adapter/subscriber.d.ts +5 -0
  13. package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
  14. package/dist/runtime/adapter/subscriber.js +55 -36
  15. package/dist/runtime/adapter/subscriber.js.map +1 -1
  16. package/dist/runtime/event-parser.d.ts +5 -1
  17. package/dist/runtime/event-parser.d.ts.map +1 -1
  18. package/dist/runtime/event-parser.js +48 -2
  19. package/dist/runtime/event-parser.js.map +1 -1
  20. package/dist/runtime/types.d.ts +22 -0
  21. package/dist/runtime/types.d.ts.map +1 -1
  22. package/dist/useAgUiRuntime.d.ts +6 -2
  23. package/dist/useAgUiRuntime.d.ts.map +1 -1
  24. package/dist/useAgUiRuntime.js +7 -1
  25. package/dist/useAgUiRuntime.js.map +1 -1
  26. package/package.json +4 -5
  27. package/src/index.ts +5 -0
  28. package/src/runtime/AgUiThreadRuntimeCore.ts +250 -11
  29. package/src/runtime/adapter/run-aggregator.ts +67 -9
  30. package/src/runtime/adapter/subscriber.ts +53 -43
  31. package/src/runtime/event-parser.ts +64 -3
  32. package/src/runtime/types.ts +31 -1
  33. package/src/useAgUiRuntime.ts +23 -3
@@ -1 +1 @@
1
- {"version":3,"file":"useAgUiRuntime.js","sourceRoot":"","sources":["../src/useAgUiRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAgUiRuntime.js","sourceRoot":"","sources":["../src/useAgUiRuntime.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC1E,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EAAE,UAAU,EAAE,4BAAyB;AAM9C,OAAO,EAAE,qBAAqB,EAAE,2CAAwC;AASxE,MAAM,UAAU,cAAc,CAC5B,OAA8B;IAE9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3E,MAAM,CAAC,QAAQ,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC3C,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,MAAM,CAA+B,IAAI,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,kBAAkB,EAAE,CAAC;IAE7C,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,EAAE,OAAO,IAAI,eAAe,EAAE,OAAO,CAAC;IAC7E,MAAM,iBAAiB,GAAG,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC;IAEvD,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,OAAO,CAAC,OAAO,GAAG,IAAI,qBAAqB,CAAC;YAC1C,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,MAAM;YACN,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,IAAI;YAC1C,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;YACpD,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;YACvD,GAAG,CAAC,cAAc,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;YAClD,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IAC7B,IAAI,CAAC,aAAa,CAAC;QACjB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,MAAM;QACN,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,IAAI;QAC1C,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;QACpD,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvD,GAAG,CAAC,cAAc,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;KACnD,CAAC,CAAC;IAEH,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAE9C,EAAE,CAAC,CAAC;IAEN,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CACxD,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,KAAK,WAAW,CAC/B,CAAC;IAEF,MAAM,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACnC,IAAI,OAAO;YACT,OAAO,OAAO,CAAC;QACjB,CAAC;KACF,CAAC,CAAC,CAAC;IAEJ,MAAM,kBAAkB,GAAG,MAAM,CAAC;QAChC,KAAK,EAAE,GAAG,EAAE,GAAE,CAAC;QACf,KAAK,EAAE,GAAkB,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE;QAC7C,MAAM,EAAE,CAAC,WAAmB,EAAE,QAAiB,EAAE,EAAE,GAAE,CAAC;KACvD,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE;QAC9B,IAAI,CAAC,iBAAiB;YAAE,OAAO,SAAS,CAAC;QAEzC,MAAM,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,GAAG,iBAAiB,CAAC;QAEpE,OAAO;YACL,QAAQ,EAAE,iBAAiB,CAAC,QAAQ;YACpC,mBAAmB,EAAE,mBAAmB;gBACtC,CAAC,CAAC,KAAK,IAAI,EAAE;oBACT,kBAAkB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;oBACnC,MAAM,mBAAmB,EAAE,CAAC;oBAC5B,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;gBACjC,CAAC;gBACH,CAAC,CAAC,SAAS;YACb,gBAAgB,EAAE,gBAAgB;gBAChC,CAAC,CAAC,KAAK,EAAE,QAAgB,EAAE,EAAE;oBACzB,kBAAkB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;oBACnC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,QAAQ,CAAC,CAAC;oBAChD,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBAC5C,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;wBACjB,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACvC,CAAC;gBACH,CAAC;gBACH,CAAC,CAAC,SAAS;SACd,CAAC;IACJ,CAAC,EAAE,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC,CAAC;IAE9B,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,MAAM,eAAe,GAAG,OAAO,CAC7B,GAAG,EAAE,CAAC,CAAC;QACL,WAAW,EAAE,QAAQ,EAAE,WAAW,IAAI,eAAe,EAAE,WAAW;QAClE,MAAM,EAAE,QAAQ,EAAE,MAAM;QACxB,SAAS,EAAE,QAAQ,EAAE,SAAS;QAC9B,QAAQ,EAAE,QAAQ,EAAE,QAAQ;QAC5B,UAAU;KACX,CAAC,EACF,CAAC,QAAQ,EAAE,eAAe,EAAE,UAAU,CAAC,CACxC,CAAC;IAEF,MAAM,eAAe,GAAG,kBAAkB,CAAC;QACzC,KAAK,EAAE;YACL,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE;YAC5B,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,iBAAiB;SACjD;QACD,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,KAAK;QACjE,QAAQ,EAAE,CAAC,OAAO,EAAE,EAAE;YACpB,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB,EAAE,CAAC;gBACvC,MAAM,SAAS,GAAG,IAAI,CAAC,wBAAwB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;gBACpE,IAAI,SAAS,EAAE,CAAC;oBACd,IAAI,CAAC,aAAa,CAAC;wBACjB,SAAS;wBACT,UAAU,EAAE,OAAO,CAAC,UAAU;wBAC9B,QAAQ,EAAE,OAAO,CAAC,QAAQ;wBAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;wBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;wBACxB,GAAG,CAAC,OAAO,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC;qBACxD,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QACD,eAAe;KAChB,CAAC,CAAC;IACH,kBAAkB,CAAC,OAAO,GAAG,eAAe,CAAC;IAE7C,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE;QACH,KAAK,QAAQ,CAAC,CAAC,6BAA6B;QAE5C,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE;YAC5B,KAAK,EAAE,IAAI,CAAC,QAAQ,EAAE;YACtB,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,iBAAiB;YAChD,KAAK,EAAE,CAAC,OAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YACvD,MAAM,EAAE,CAAC,OAAsB,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACtD,QAAQ,EAAE,CAAC,QAAuB,EAAE,MAA2B,EAAE,EAAE,CACjE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC;YAC/B,QAAQ,EAAE,KAAK,IAAI,EAAE;gBACnB,IAAI,CAAC,MAAM,EAAE,CAAC;gBACd,MAAM,kBAAkB,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC3C,CAAC;YACD,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YACzD,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;YACzC,gBAAgB,EAAE,CAAC,OAAO,EAAE,EAAE,CAC5B,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAC/B,OAAO,CAAC,UAAU,EAClB,OAAO,CAAC,OAAO,CAChB;YACH,WAAW,EAAE,CAAC,QAAkC,EAAE,EAAE,CAClD,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC;YACtC,QAAQ,EAAE,CAAC,QAAkC,EAAE,EAAE,CAC/C,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC;YACtC,mBAAmB,EAAE,CAAC,KAAwB,EAAE,EAAE,CAChD,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC;YAC/B,QAAQ,EAAE,eAAe;SACoB,CAAC;IAClD,CAAC;IACD,wGAAwG;IACxG,wGAAwG;IACxG,CAAC,eAAe,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,CAAC,CACrD,CAAC;IAEF,MAAM,WAAW,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAEnD,MAAM,OAAO,GAAG,OAAO,CAAuB,GAAG,EAAE;QACjD,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,CAAyB,CAAC;QACnE,OAAO,CAAC,6BAA6B,GAAG,GAAG,EAAE,CAC3C,IAAI,CAAC,oBAAoB,EAAE,EAAE,UAAU,IAAI,EAAE,CAAC;QAChD,OAAO,CAAC,iCAAiC,GAAG,CAAC,SAAS,EAAE,EAAE,CACxD,IAAI,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC;QAC3C,OAAO,OAAO,CAAC;IACjB,CAAC,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAExB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,OAAO,CAAC;AACjB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-ag-ui",
3
- "version": "0.0.29",
3
+ "version": "0.0.30",
4
4
  "description": "AG-UI protocol adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "ag-ui",
@@ -30,8 +30,8 @@
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
32
  "@ag-ui/client": "^0.0.53",
33
- "@assistant-ui/core": "^0.2.0",
34
- "assistant-stream": "^0.3.13"
33
+ "@assistant-ui/core": "^0.2.1",
34
+ "assistant-stream": "^0.3.14"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@types/react": "*",
@@ -50,8 +50,7 @@
50
50
  "@assistant-ui/x-buildutils": "0.0.7"
51
51
  },
52
52
  "publishConfig": {
53
- "access": "public",
54
- "provenance": true
53
+ "access": "public"
55
54
  },
56
55
  "homepage": "https://www.assistant-ui.com/",
57
56
  "repository": {
package/src/index.ts CHANGED
@@ -1,5 +1,10 @@
1
1
  export { useAgUiRuntime } from "./useAgUiRuntime";
2
+ export type { AgUiAssistantRuntime } from "./useAgUiRuntime";
2
3
  export type {
4
+ AgUiInterrupt,
5
+ AgUiInterruptReason,
6
+ AgUiResumeEntry,
7
+ AgUiRunFinishedOutcome,
3
8
  UseAgUiRuntimeOptions,
4
9
  UseAgUiRuntimeAdapters,
5
10
  UseAgUiThreadListAdapter,
@@ -1,6 +1,11 @@
1
1
  "use client";
2
2
 
3
- import { generateId, fromThreadMessageLike } from "@assistant-ui/core/internal";
3
+ import {
4
+ generateId,
5
+ generateOptimisticId,
6
+ isOptimisticId,
7
+ fromThreadMessageLike,
8
+ } from "@assistant-ui/core/internal";
4
9
  import type {
5
10
  AddToolResultOptions,
6
11
  AppendMessage,
@@ -13,9 +18,13 @@ import type {
13
18
  } from "@assistant-ui/core";
14
19
  import type { HttpAgent } from "@ag-ui/client";
15
20
  import type { Logger } from "./logger";
16
- import type { AgUiEvent } from "./types";
21
+ import type { AgUiEvent, AgUiInterrupt, AgUiResumeEntry } from "./types";
17
22
  import type { ReadonlyJSONValue } from "assistant-stream/utils";
18
- import { RunAggregator } from "./adapter/run-aggregator";
23
+ import {
24
+ AG_UI_METADATA_NAMESPACE,
25
+ type AgUiCustomMetadata,
26
+ RunAggregator,
27
+ } from "./adapter/run-aggregator";
19
28
  import {
20
29
  fromAgUiMessages,
21
30
  toAgUiMessages,
@@ -23,6 +32,8 @@ import {
23
32
  } from "./adapter/conversions";
24
33
  import { createAgUiSubscriber } from "./adapter/subscriber";
25
34
 
35
+ const symbolResumeShim = Symbol("agui-resume-shim");
36
+
26
37
  type RunConfig = NonNullable<AppendMessage["runConfig"]>;
27
38
  type ResumeRunConfig = {
28
39
  parentId: string | null;
@@ -72,6 +83,7 @@ export class AgUiThreadRuntimeCore {
72
83
  this.onCancel = options.onCancel;
73
84
  this.history = options.history;
74
85
  this.notifyUpdate = options.notifyUpdate;
86
+ this.installResumeShim();
75
87
  }
76
88
 
77
89
  updateOptions(options: Omit<CoreOptions, "notifyUpdate">) {
@@ -81,6 +93,7 @@ export class AgUiThreadRuntimeCore {
81
93
  this.onError = options.onError;
82
94
  this.onCancel = options.onCancel;
83
95
  this.history = options.history;
96
+ this.installResumeShim();
84
97
  }
85
98
 
86
99
  attachRuntime(runtime: AssistantRuntime) {
@@ -143,6 +156,7 @@ export class AgUiThreadRuntimeCore {
143
156
 
144
157
  async append(message: AppendMessage): Promise<void> {
145
158
  const startRun = message.startRun ?? message.role === "user";
159
+ if (startRun) this.assertNoPendingInterrupts();
146
160
  if (message.sourceId) {
147
161
  this.messages = this.messages.filter(
148
162
  (entry) => entry.id !== message.sourceId,
@@ -167,6 +181,7 @@ export class AgUiThreadRuntimeCore {
167
181
  parentId: string | null,
168
182
  config: { runConfig?: RunConfig } = {},
169
183
  ): Promise<void> {
184
+ this.assertNoPendingInterrupts();
170
185
  this.resetHead(parentId);
171
186
  this.notifyUpdate();
172
187
  await this.startRun(parentId, config.runConfig);
@@ -178,6 +193,7 @@ export class AgUiThreadRuntimeCore {
178
193
  }
179
194
 
180
195
  async resume(config: ResumeRunConfig): Promise<void> {
196
+ this.assertNoPendingInterrupts();
181
197
  if (config.stream) {
182
198
  this.logger.debug?.(
183
199
  "[agui] resume stream is not supported, falling back to regular run",
@@ -189,6 +205,143 @@ export class AgUiThreadRuntimeCore {
189
205
  );
190
206
  }
191
207
 
208
+ private assertNoPendingInterrupts(): void {
209
+ if (!this.getPendingInterrupts()) return;
210
+ throw new Error(
211
+ "[agui] cannot start a new run while interrupts are pending; resolve them with submitInterruptResponses()",
212
+ );
213
+ }
214
+
215
+ getPendingInterrupts(): {
216
+ messageId: string;
217
+ interrupts: readonly AgUiInterrupt[];
218
+ } | null {
219
+ const assistant = this.messages.findLast((m) => m.role === "assistant") as
220
+ | ThreadAssistantMessage
221
+ | undefined;
222
+ if (
223
+ !assistant ||
224
+ assistant.status?.type !== "requires-action" ||
225
+ assistant.status.reason !== "interrupt"
226
+ ) {
227
+ return null;
228
+ }
229
+ const stored = (
230
+ assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as
231
+ | AgUiCustomMetadata
232
+ | undefined
233
+ )?.interrupts;
234
+ if (!stored?.length) return null;
235
+ return { messageId: assistant.id, interrupts: stored };
236
+ }
237
+
238
+ async submitInterruptResponses(
239
+ responses: readonly AgUiResumeEntry[],
240
+ ): Promise<void> {
241
+ const pending = this.getPendingInterrupts();
242
+ if (!pending) {
243
+ throw new Error(
244
+ "[agui] submitInterruptResponses: no pending interrupts on this thread",
245
+ );
246
+ }
247
+
248
+ const responsesById = new Map<string, AgUiResumeEntry>();
249
+ for (const entry of responses) {
250
+ if (!entry || typeof entry.interruptId !== "string") {
251
+ throw new Error(
252
+ "[agui] submitInterruptResponses: every entry must have an interruptId",
253
+ );
254
+ }
255
+ if (entry.status !== "resolved" && entry.status !== "cancelled") {
256
+ throw new Error(
257
+ `[agui] submitInterruptResponses: invalid status "${entry.status}" for interrupt ${entry.interruptId}`,
258
+ );
259
+ }
260
+ if (responsesById.has(entry.interruptId)) {
261
+ throw new Error(
262
+ `[agui] submitInterruptResponses: duplicate response for interrupt ${entry.interruptId}`,
263
+ );
264
+ }
265
+ responsesById.set(entry.interruptId, entry);
266
+ }
267
+
268
+ const openIds = pending.interrupts.map((i) => i.id);
269
+ const missing = openIds.filter((id) => !responsesById.has(id));
270
+ if (missing.length > 0) {
271
+ throw new Error(
272
+ `[agui] submitInterruptResponses: missing responses for open interrupts: ${missing.join(", ")}`,
273
+ );
274
+ }
275
+ const known = new Set(openIds);
276
+ const unknownIds = [...responsesById.keys()].filter((id) => !known.has(id));
277
+ if (unknownIds.length > 0) {
278
+ throw new Error(
279
+ `[agui] submitInterruptResponses: unknown interrupt ids: ${unknownIds.join(", ")}`,
280
+ );
281
+ }
282
+
283
+ const now = Date.now();
284
+ for (const interrupt of pending.interrupts) {
285
+ if (!interrupt.expiresAt) continue;
286
+ const expiry = new Date(interrupt.expiresAt).getTime();
287
+ if (Number.isNaN(expiry)) {
288
+ throw new Error(
289
+ `[agui] submitInterruptResponses: interrupt ${interrupt.id} has malformed expiresAt "${interrupt.expiresAt}"`,
290
+ );
291
+ }
292
+ if (expiry <= now) {
293
+ throw new Error(
294
+ `[agui] submitInterruptResponses: interrupt ${interrupt.id} expired at ${interrupt.expiresAt}`,
295
+ );
296
+ }
297
+ }
298
+
299
+ const resume: AgUiResumeEntry[] = openIds.map(
300
+ (id) => responsesById.get(id)!,
301
+ );
302
+
303
+ if (this.isRunningFlag) {
304
+ throw new Error(
305
+ "[agui] submitInterruptResponses: a run is already in progress",
306
+ );
307
+ }
308
+
309
+ this.clearPendingInterrupts(pending.messageId);
310
+ await this.startRun(pending.messageId, this.lastRunConfig, resume);
311
+ }
312
+
313
+ private clearPendingInterrupts(messageId: string): void {
314
+ let touched = false;
315
+ this.messages = this.messages.map((message) => {
316
+ if (message.id !== messageId || message.role !== "assistant")
317
+ return message;
318
+ const assistant = message as ThreadAssistantMessage;
319
+ if (
320
+ assistant.status?.type !== "requires-action" ||
321
+ assistant.status.reason !== "interrupt"
322
+ ) {
323
+ return assistant;
324
+ }
325
+ touched = true;
326
+ const aguiMeta = assistant.metadata.custom[AG_UI_METADATA_NAMESPACE] as
327
+ | AgUiCustomMetadata
328
+ | undefined;
329
+ const { interrupts: _drop, ...restAgui } = aguiMeta ?? {};
330
+ const newCustom = { ...assistant.metadata.custom };
331
+ if (Object.keys(restAgui).length > 0) {
332
+ newCustom[AG_UI_METADATA_NAMESPACE] = restAgui;
333
+ } else {
334
+ delete newCustom[AG_UI_METADATA_NAMESPACE];
335
+ }
336
+ return {
337
+ ...assistant,
338
+ status: { type: "complete" as const, reason: "unknown" as const },
339
+ metadata: { ...assistant.metadata, custom: newCustom },
340
+ };
341
+ });
342
+ if (touched) this.notifyUpdate();
343
+ }
344
+
192
345
  findMessageIdForToolCall(toolCallId: string): string | undefined {
193
346
  let fallbackMessageId: string | undefined;
194
347
  for (let index = this.messages.length - 1; index >= 0; index--) {
@@ -288,6 +441,7 @@ export class AgUiThreadRuntimeCore {
288
441
  private async startRun(
289
442
  parentId: string | null,
290
443
  runConfig?: RunConfig,
444
+ resume?: AgUiResumeEntry[],
291
445
  ): Promise<void> {
292
446
  const normalizedRunConfig = runConfig ?? {};
293
447
  this.lastRunConfig = normalizedRunConfig;
@@ -300,6 +454,7 @@ export class AgUiThreadRuntimeCore {
300
454
  runId,
301
455
  normalizedRunConfig,
302
456
  historicalMessages,
457
+ resume,
303
458
  );
304
459
  const assistantParentId = parentId ?? this.messages.at(-1)?.id ?? null;
305
460
  let assistantMessageId: string | undefined;
@@ -314,7 +469,18 @@ export class AgUiThreadRuntimeCore {
314
469
  const aggregator = new RunAggregator({
315
470
  showThinking: this.showThinking,
316
471
  logger: this.logger,
317
- emit: (update) => this.updateAssistantMessage(ensureAssistant(), update),
472
+ emit: (update) => {
473
+ const resolved = this.updateAssistantMessage(ensureAssistant(), update);
474
+ if (resolved !== assistantMessageId) {
475
+ assistantMessageId = resolved;
476
+ }
477
+ },
478
+ onServerMessageId: (serverId) => {
479
+ const placeholder = ensureAssistant();
480
+ if (placeholder === serverId) return;
481
+ this.reassignAssistantId(placeholder, serverId);
482
+ assistantMessageId = serverId;
483
+ },
318
484
  });
319
485
  const dispatch = (event: AgUiEvent) => this.handleEvent(aggregator, event);
320
486
 
@@ -335,6 +501,7 @@ export class AgUiThreadRuntimeCore {
335
501
  const subscriber = createAgUiSubscriber({
336
502
  dispatch,
337
503
  runId,
504
+ logger: this.logger,
338
505
  onRunFailed: (error) => {
339
506
  this.pendingError = error;
340
507
  this.onError?.(error);
@@ -348,6 +515,7 @@ export class AgUiThreadRuntimeCore {
348
515
  try {
349
516
  (this.agent as any).messages = input.messages;
350
517
  (this.agent as any).threadId = input.threadId;
518
+ (this.agent as any).state = input.state ?? null;
351
519
  } catch {
352
520
  // ignore
353
521
  }
@@ -376,6 +544,7 @@ export class AgUiThreadRuntimeCore {
376
544
  runId: string,
377
545
  runConfig: RunConfig | undefined,
378
546
  historyMessages: readonly ThreadMessage[] | undefined,
547
+ resume?: AgUiResumeEntry[],
379
548
  ) {
380
549
  const threadId = this.agent.threadId || "main";
381
550
  const messages = toAgUiMessages(historyMessages ?? this.messages);
@@ -394,6 +563,28 @@ export class AgUiThreadRuntimeCore {
394
563
  ...(context?.config ?? {}),
395
564
  ...(runConfig?.custom ? { runConfig: runConfig.custom } : {}),
396
565
  },
566
+ ...(resume !== undefined ? { resume } : {}),
567
+ };
568
+ }
569
+
570
+ private installResumeShim(): void {
571
+ const agent = this.agent as any;
572
+ if (agent[symbolResumeShim]) return;
573
+ agent[symbolResumeShim] = true;
574
+ const onInstance = Object.hasOwn(agent, "prepareRunAgentInput");
575
+ const original = onInstance
576
+ ? agent.prepareRunAgentInput
577
+ : Object.getPrototypeOf(agent)?.prepareRunAgentInput;
578
+ if (typeof original !== "function") return;
579
+ agent.prepareRunAgentInput = function (
580
+ this: unknown,
581
+ params: { resume?: unknown } | undefined,
582
+ ) {
583
+ const input = original.call(this, params);
584
+ if (params?.resume !== undefined && input && typeof input === "object") {
585
+ return { ...(input as object), resume: params.resume };
586
+ }
587
+ return input;
397
588
  };
398
589
  }
399
590
 
@@ -410,7 +601,7 @@ export class AgUiThreadRuntimeCore {
410
601
  }
411
602
 
412
603
  private insertAssistantPlaceholder(): string {
413
- const id = generateId();
604
+ const id = generateOptimisticId();
414
605
  const assistant: ThreadAssistantMessage = {
415
606
  id,
416
607
  role: "assistant",
@@ -430,10 +621,43 @@ export class AgUiThreadRuntimeCore {
430
621
  return id;
431
622
  }
432
623
 
624
+ private reassignAssistantId(oldId: string, newId: string): void {
625
+ if (oldId === newId) return;
626
+
627
+ const collidesWithExisting = this.messages.some((m) => m.id === newId);
628
+
629
+ if (collidesWithExisting) {
630
+ this.logger.debug?.(
631
+ "[agui] reassignAssistantId: server id already present in messages, dropping placeholder",
632
+ { oldId, newId },
633
+ );
634
+ this.messages = this.messages.filter((m) => m.id !== oldId);
635
+ } else {
636
+ this.messages = this.messages.map((m) =>
637
+ m.id === oldId ? { ...m, id: newId } : m,
638
+ );
639
+ }
640
+
641
+ const pendingParent = this.assistantHistoryParents.get(oldId);
642
+ if (pendingParent !== undefined) {
643
+ this.assistantHistoryParents.delete(oldId);
644
+ if (!this.assistantHistoryParents.has(newId)) {
645
+ this.assistantHistoryParents.set(newId, pendingParent);
646
+ }
647
+ }
648
+
649
+ if (this.recordedHistoryIds.has(oldId)) {
650
+ this.recordedHistoryIds.delete(oldId);
651
+ this.recordedHistoryIds.add(newId);
652
+ }
653
+
654
+ this.notifyUpdate();
655
+ }
656
+
433
657
  private updateAssistantMessage(
434
658
  messageId: string,
435
659
  update: ChatModelRunResult,
436
- ) {
660
+ ): string {
437
661
  let touched = false;
438
662
  let latestStatus: MessageStatus | undefined;
439
663
  this.messages = this.messages.map((message) => {
@@ -453,12 +677,22 @@ export class AgUiThreadRuntimeCore {
453
677
  metadata,
454
678
  };
455
679
  });
456
- if (touched) {
680
+ if (!touched) return messageId;
681
+
682
+ let resolvedMessageId = messageId;
683
+ const isSettled =
684
+ latestStatus !== undefined && latestStatus.type !== "running";
685
+ if (isSettled && isOptimisticId(messageId)) {
686
+ const stableId = generateId();
687
+ this.reassignAssistantId(messageId, stableId);
688
+ resolvedMessageId = stableId;
689
+ } else {
457
690
  this.notifyUpdate();
458
- if (this.isTerminalStatus(latestStatus)) {
459
- this.persistAssistantHistory(messageId);
460
- }
461
691
  }
692
+ if (this.isPersistableStatus(latestStatus)) {
693
+ this.persistAssistantHistory(resolvedMessageId);
694
+ }
695
+ return resolvedMessageId;
462
696
  }
463
697
 
464
698
  private mergeAssistantMetadata(
@@ -558,6 +792,11 @@ export class AgUiThreadRuntimeCore {
558
792
  return status?.type === "complete" || status?.type === "incomplete";
559
793
  }
560
794
 
795
+ private isPersistableStatus(status?: MessageStatus): boolean {
796
+ if (this.isTerminalStatus(status)) return true;
797
+ return status?.type === "requires-action" && status.reason === "interrupt";
798
+ }
799
+
561
800
  private recordHistoryEntry(parentId: string | null, message: ThreadMessage) {
562
801
  this.appendHistoryItem(parentId, message);
563
802
  }
@@ -576,7 +815,7 @@ export class AgUiThreadRuntimeCore {
576
815
  if (parentId === undefined) return;
577
816
  const message = this.messages.find((m) => m.id === messageId);
578
817
  if (!message || message.role !== "assistant") return;
579
- if (!this.isTerminalStatus(message.status)) return;
818
+ if (!this.isPersistableStatus(message.status)) return;
580
819
  this.assistantHistoryParents.delete(messageId);
581
820
  this.appendHistoryItem(parentId, message);
582
821
  }
@@ -5,9 +5,15 @@ import type {
5
5
  ThreadAssistantMessagePart,
6
6
  ToolCallMessagePart,
7
7
  } from "@assistant-ui/core";
8
- import type { AgUiEvent } from "../types";
8
+ import type { AgUiEvent, AgUiInterrupt } from "../types";
9
9
  import type { Logger } from "../logger";
10
10
 
11
+ export const AG_UI_METADATA_NAMESPACE = "agui";
12
+
13
+ export type AgUiCustomMetadata = {
14
+ interrupts?: AgUiInterrupt[];
15
+ };
16
+
11
17
  type Emit = (update: ChatModelRunResult) => void;
12
18
 
13
19
  type ToolCallState = {
@@ -18,12 +24,14 @@ type ToolCallState = {
18
24
  result: unknown;
19
25
  isError: boolean | undefined;
20
26
  parentMessageId?: string;
27
+ toolMessageId?: string;
21
28
  };
22
29
 
23
30
  export type RunAggregatorOptions = {
24
31
  showThinking: boolean;
25
32
  logger: Logger;
26
33
  emit: Emit;
34
+ onServerMessageId?: (messageId: string) => void;
27
35
  };
28
36
 
29
37
  /**
@@ -36,8 +44,10 @@ export class RunAggregator {
36
44
  private readonly emitUpdate: Emit;
37
45
  private readonly showThinking: boolean;
38
46
  private readonly logger: Logger;
47
+ private readonly onServerMessageId: ((messageId: string) => void) | undefined;
39
48
 
40
49
  private status: ChatModelRunResult["status"] | undefined;
50
+ private interrupts: AgUiInterrupt[] | undefined;
41
51
  private readonly textParts = new Map<
42
52
  string,
43
53
  { buffer: string; touched: boolean }
@@ -53,11 +63,13 @@ export class RunAggregator {
53
63
  )[] = [];
54
64
  private hasReasoningPart = false;
55
65
  private textPartCounter = 0;
66
+ private serverMessageIdReported = false;
56
67
 
57
68
  constructor(options: RunAggregatorOptions) {
58
69
  this.emitUpdate = options.emit;
59
70
  this.showThinking = options.showThinking;
60
71
  this.logger = options.logger;
72
+ this.onServerMessageId = options.onServerMessageId;
61
73
  }
62
74
 
63
75
  handle(event: AgUiEvent): void {
@@ -71,18 +83,29 @@ export class RunAggregator {
71
83
  this.hasReasoningPart = false;
72
84
  this.textPartCounter = 0;
73
85
  this.activeTextMessageId = undefined;
86
+ this.interrupts = undefined;
87
+ this.serverMessageIdReported = false;
74
88
  this.status = { type: "running" };
75
89
  this.emit();
76
90
  break;
77
91
  }
78
92
  case "RUN_FINISHED": {
93
+ if (event.outcome?.type === "interrupt") {
94
+ this.interrupts = event.outcome.interrupts;
95
+ this.status = { type: "requires-action", reason: "interrupt" };
96
+ this.emit();
97
+ break;
98
+ }
99
+
100
+ this.interrupts = undefined;
79
101
  const hasUnresolvedToolCalls = Array.from(this.toolCalls.values()).some(
80
102
  (tc) => tc.result === undefined,
81
103
  );
82
104
 
83
- this.status = hasUnresolvedToolCalls
84
- ? { type: "requires-action", reason: "tool-calls" }
85
- : { type: "complete", reason: "unknown" };
105
+ this.status =
106
+ event.outcome?.type === "success" || !hasUnresolvedToolCalls
107
+ ? { type: "complete", reason: "unknown" }
108
+ : { type: "requires-action", reason: "tool-calls" };
86
109
  this.emit();
87
110
  break;
88
111
  }
@@ -102,6 +125,7 @@ export class RunAggregator {
102
125
  }
103
126
 
104
127
  case "TEXT_MESSAGE_START": {
128
+ this.reportServerMessageId(event.messageId);
105
129
  const id = this.startTextMessage(event.messageId);
106
130
  if (id) {
107
131
  this.markTextPartTouched(id);
@@ -111,15 +135,16 @@ export class RunAggregator {
111
135
  }
112
136
  case "TEXT_MESSAGE_CONTENT":
113
137
  case "TEXT_MESSAGE_CHUNK": {
138
+ const incomingId = "messageId" in event ? event.messageId : undefined;
139
+ this.reportServerMessageId(incomingId);
114
140
  if (!event.delta) break;
115
- const id = this.resolveTextMessageId(
116
- "messageId" in event ? event.messageId : undefined,
117
- );
141
+ const id = this.resolveTextMessageId(incomingId);
118
142
  this.appendText(id, event.delta);
119
143
  this.emit();
120
144
  break;
121
145
  }
122
146
  case "TEXT_MESSAGE_END": {
147
+ this.reportServerMessageId(event.messageId);
123
148
  if (event.messageId && this.activeTextMessageId === event.messageId) {
124
149
  this.activeTextMessageId = undefined;
125
150
  }
@@ -145,6 +170,7 @@ export class RunAggregator {
145
170
  break;
146
171
 
147
172
  case "TOOL_CALL_START": {
173
+ this.reportServerMessageId(event.parentMessageId);
148
174
  this.startToolCall(
149
175
  event.toolCallId,
150
176
  event.toolCallName,
@@ -155,6 +181,9 @@ export class RunAggregator {
155
181
  }
156
182
  case "TOOL_CALL_ARGS":
157
183
  case "TOOL_CALL_CHUNK": {
184
+ if (event.type === "TOOL_CALL_CHUNK") {
185
+ this.reportServerMessageId(event.parentMessageId);
186
+ }
158
187
  if (!event.delta) break;
159
188
  this.appendToolArgs(event.toolCallId, event.delta);
160
189
  this.emit();
@@ -169,6 +198,7 @@ export class RunAggregator {
169
198
  event.toolCallId,
170
199
  event.content ?? "",
171
200
  event.role === "tool" ? false : undefined,
201
+ event.messageId,
172
202
  );
173
203
  this.emit();
174
204
  break;
@@ -180,6 +210,12 @@ export class RunAggregator {
180
210
  }
181
211
  }
182
212
 
213
+ private reportServerMessageId(messageId: string | undefined): void {
214
+ if (this.serverMessageIdReported || !messageId) return;
215
+ this.serverMessageIdReported = true;
216
+ this.onServerMessageId?.(messageId);
217
+ }
218
+
183
219
  private clearTextParts(): void {
184
220
  this.textParts.clear();
185
221
  }
@@ -281,7 +317,12 @@ export class RunAggregator {
281
317
  }
282
318
  }
283
319
 
284
- private finishToolCall(id: string, content: string, isError?: boolean) {
320
+ private finishToolCall(
321
+ id: string,
322
+ content: string,
323
+ isError?: boolean,
324
+ toolMessageId?: string,
325
+ ) {
285
326
  if (!id) return;
286
327
  let entry = this.toolCalls.get(id);
287
328
  if (!entry) {
@@ -304,6 +345,9 @@ export class RunAggregator {
304
345
  }
305
346
  entry.result = this.tryParseJSON(content);
306
347
  entry.isError = isError;
348
+ if (toolMessageId) {
349
+ entry.toolMessageId = toolMessageId;
350
+ }
307
351
  }
308
352
 
309
353
  private tryParseJSON(value: string): unknown {
@@ -351,13 +395,27 @@ export class RunAggregator {
351
395
  ...(entry.result !== undefined ? { result: entry.result } : {}),
352
396
  ...(entry.isError !== undefined ? { isError: entry.isError } : {}),
353
397
  ...(entry.parentMessageId ? { parentId: entry.parentMessageId } : {}),
354
- } as ToolCallMessagePart;
398
+ ...(entry.toolMessageId
399
+ ? { unstable_toolMessageId: entry.toolMessageId }
400
+ : {}),
401
+ } as ToolCallMessagePart & { unstable_toolMessageId?: string };
355
402
  snapshot.push(toolPart);
356
403
  }
357
404
 
358
405
  const result: ChatModelRunResult = {
359
406
  content: snapshot,
360
407
  ...(this.status ? { status: this.status } : undefined),
408
+ ...(this.interrupts
409
+ ? {
410
+ metadata: {
411
+ custom: {
412
+ [AG_UI_METADATA_NAMESPACE]: {
413
+ interrupts: this.interrupts,
414
+ } satisfies AgUiCustomMetadata,
415
+ },
416
+ },
417
+ }
418
+ : undefined),
361
419
  };
362
420
  this.emitUpdate(result);
363
421
  }