@assistant-ui/react-ag-ui 0.0.64 → 0.0.66

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 (35) hide show
  1. package/dist/runtime/AgUiThreadRuntimeCore.d.ts +19 -3
  2. package/dist/runtime/AgUiThreadRuntimeCore.d.ts.map +1 -1
  3. package/dist/runtime/AgUiThreadRuntimeCore.js +193 -39
  4. package/dist/runtime/AgUiThreadRuntimeCore.js.map +1 -1
  5. package/dist/runtime/adapter/conversions.d.ts.map +1 -1
  6. package/dist/runtime/adapter/conversions.js +19 -29
  7. package/dist/runtime/adapter/conversions.js.map +1 -1
  8. package/dist/runtime/adapter/run-aggregator.d.ts +4 -16
  9. package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
  10. package/dist/runtime/adapter/run-aggregator.js +100 -23
  11. package/dist/runtime/adapter/run-aggregator.js.map +1 -1
  12. package/dist/runtime/event-parser.d.ts.map +1 -1
  13. package/dist/runtime/event-parser.js +16 -8
  14. package/dist/runtime/event-parser.js.map +1 -1
  15. package/dist/runtime/types.d.ts +30 -5
  16. package/dist/runtime/types.d.ts.map +1 -1
  17. package/dist/runtime/types.js +8 -0
  18. package/dist/runtime/types.js.map +1 -0
  19. package/dist/useAgUiRuntime.d.ts.map +1 -1
  20. package/dist/useAgUiRuntime.js +80 -33
  21. package/dist/useAgUiRuntime.js.map +1 -1
  22. package/package.json +7 -6
  23. package/src/runtime/AgUiThreadRuntimeCore.test.ts +380 -6
  24. package/src/runtime/AgUiThreadRuntimeCore.ts +314 -70
  25. package/src/runtime/adapter/conversions.content.test.ts +41 -0
  26. package/src/runtime/adapter/conversions.nested-tool-calls.test.ts +107 -0
  27. package/src/runtime/adapter/conversions.ts +37 -64
  28. package/src/runtime/adapter/run-aggregator.reasoning.test.ts +143 -0
  29. package/src/runtime/adapter/run-aggregator.ts +163 -40
  30. package/src/runtime/event-parser.ts +18 -4
  31. package/src/runtime/types.ts +43 -11
  32. package/src/useAgUiRuntime.external-store.test.tsx +51 -0
  33. package/src/useAgUiRuntime.queue.test.tsx +63 -2
  34. package/src/useAgUiRuntime.thread-switch.test.tsx +587 -3
  35. package/src/useAgUiRuntime.ts +106 -44
@@ -20,7 +20,7 @@ type CoreOptions = {
20
20
  onError?: (error: Error) => void;
21
21
  onCancel?: () => void;
22
22
  history?: ThreadHistoryAdapter;
23
- notifyUpdate: () => void;
23
+ isThreadSwitching?: () => boolean;
24
24
  };
25
25
  export declare class AgUiThreadRuntimeCore {
26
26
  private agent;
@@ -30,7 +30,9 @@ export declare class AgUiThreadRuntimeCore {
30
30
  private autoCancelPendingToolCalls;
31
31
  private onError;
32
32
  private onCancel;
33
- private readonly notifyUpdate;
33
+ private readonly listeners;
34
+ private snapshot;
35
+ private readonly isThreadSwitching;
34
36
  private readonly reportedErrors;
35
37
  private runtime;
36
38
  private readonly session;
@@ -45,13 +47,23 @@ export declare class AgUiThreadRuntimeCore {
45
47
  private readonly persistedHistoryIds;
46
48
  private readonly historyWrites;
47
49
  private _isLoading;
50
+ private _historyImportPromise;
51
+ private historyMutationGeneration;
48
52
  private _loadPromise;
49
53
  private _loadRequested;
50
54
  private pendingResume;
51
55
  private pendingA2uiResumeOwner;
52
56
  private pendingA2uiAction;
53
57
  constructor(options: CoreOptions);
54
- updateOptions(options: Omit<CoreOptions, "notifyUpdate">): void;
58
+ subscribe: (listener: () => void) => (() => void);
59
+ getSnapshot: () => {
60
+ isLoading: boolean;
61
+ isRunning: boolean;
62
+ messageRepository: ExportedMessageRepository;
63
+ state: ReadonlyJSONValue | undefined;
64
+ };
65
+ private publishUpdate;
66
+ updateOptions(options: CoreOptions): void;
55
67
  attachRuntime(runtime: AssistantRuntime): void;
56
68
  detachRuntime(): void;
57
69
  getMessages(): readonly ThreadMessage[];
@@ -60,6 +72,8 @@ export declare class AgUiThreadRuntimeCore {
60
72
  isRunning(): boolean;
61
73
  get isLoading(): boolean;
62
74
  __internal_load(): Promise<void>;
75
+ private waitForHistoryImport;
76
+ private deferUntilHistoryImported;
63
77
  append(message: AppendMessage): Promise<void>;
64
78
  appendVoiceTranscript(message: ThreadMessage): void;
65
79
  private maybeAutoCancelPendingToolCalls;
@@ -142,6 +156,8 @@ export declare class AgUiThreadRuntimeCore {
142
156
  private updateAssistantMessage;
143
157
  private preserveToolResults;
144
158
  private preserveToolInteractions;
159
+ private mergeSnapshotAssistantContent;
160
+ private reconcileSnapshotNestedContent;
145
161
  private mergeAssistantMetadata;
146
162
  private handleEvent;
147
163
  private updateActiveAssistantState;
@@ -1 +1 @@
1
- {"version":3,"file":"AgUiThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EAEzB,4BAA4B,EAE5B,oBAAoB,EACpB,aAAa,EAEb,wBAAwB,EACzB,MAAM,oBAAoB,CAAC;AAQ5B,OAAO,KAAK,EACV,aAAa,EAId,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,EAAE,MAAM,EAAE,oBAAiB;AAEvC,OAAO,KAAK,EAEV,aAAa,EACb,eAAe,EACf,oBAAoB,EACrB,mBAAgB;AACjB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAwChE,KAAK,SAAS,GAAG,WAAW,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC;AACzD,KAAK,YAAY,GAAG,CAClB,OAAO,EAAE,mBAAmB,KACzB,cAAc,CAAC,kBAAkB,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;AACvD,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAYF,KAAK,WAAW,GAAG;IACjB,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IACtB,gBAAgB,CAAC,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACpD,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAmCF,qBAAa,qBAAqB;IAChC,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,0BAA0B,CAAsB;IACxD,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,QAAQ,CAA2B;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAyB;IAExD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAerB;IACH,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,eAAe,CAAgC;IAGvD,OAAO,CAAC,cAAc,CAA8B;IACpD,OAAO,CAAC,aAAa,CAAgC;IACrD,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,aAAa,CAAwB;IAC7C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAAoC;IAC5E,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IACxD,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAqB;IACzD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAoC;IAClE,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,aAAa,CACd;IACP,OAAO,CAAC,sBAAsB,CAAgC;IAC9D,OAAO,CAAC,iBAAiB,CAAsC;gBAEnD,OAAO,EAAE,WAAW;IAYhC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC;IAqBxD,aAAa,CAAC,OAAO,EAAE,gBAAgB;IAIvC,aAAa;IAOb,WAAW,IAAI,SAAS,aAAa,EAAE;IAIvC,oBAAoB,IAAI,yBAAyB;IAIjD,QAAQ,IAAI,iBAAiB,GAAG,SAAS;IAIzC,SAAS,IAAI,OAAO;IAIpB,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAkD1B,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBnD,qBAAqB,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAQnD,OAAO,CAAC,+BAA+B;IAQvC,OAAO,CAAC,WAAW;IAeb,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3C,MAAM,CACV,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,MAAM,GAAE;QAAE,SAAS,CAAC,EAAE,SAAS,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAMV,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAW7B,OAAO,CAAC,cAAc;IAiBtB,OAAO,CAAC,kBAAkB;IAapB,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,iBAAiB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB1E,OAAO,CAAC,yBAAyB;IAOjC,OAAO,CAAC,2BAA2B;IAgBnC,oBAAoB,IAAI;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,SAAS,aAAa,EAAE,CAAC;KACtC,GAAG,IAAI;IAYR,mBAAmB,IAAI;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,EAAE,MAAM,EAAE,CAAC;KACvB,GAAG,IAAI;IAYF,wBAAwB,CAC5B,SAAS,EAAE,SAAS,eAAe,EAAE,GACpC,OAAO,CAAC,IAAI,CAAC;IAiChB;;;;;OAKG;YACW,mBAAmB;IAWjC;;;;;;OAMG;IACH,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAYjC,OAAO,CAAC,0BAA0B;IAwB5B,qBAAqB,CACzB,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,IAAI,CAAC;IAsEV,SAAS,CACb,OAAO,EAAE,mBAAmB,EAC5B,SAAS,CAAC,EAAE,SAAS,eAAe,EAAE,GACrC,OAAO,CAAC,IAAI,CAAC;IA4ChB,OAAO,CAAC,sBAAsB;IAkB9B,OAAO,CAAC,yBAAyB;IAiCjC,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,sBAAsB;IAmC9B,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAiBhE,OAAO,CAAC,yBAAyB;IAiBjC,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAqC5C,qBAAqB,CAAC,OAAO,EAAE;QACnC,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,wBAAwB,CAAC;KACvC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDjB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IA6BrD,OAAO,CAAC,2BAA2B;IAanC,OAAO,CAAC,6BAA6B;IAiCrC,OAAO,CAAC,cAAc;IAMtB,qBAAqB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI;IAwE/D,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,GAAG,IAAI;IAKjD,QAAQ,CACN,IAAI,EACA,iBAAiB,GACjB,CAAC,CAAC,IAAI,EAAE,iBAAiB,GAAG,SAAS,KAAK,iBAAiB,CAAC,GAC/D,IAAI;IAMP,UAAU,IAAI,IAAI;IAKlB,gBAAgB,IAAI,IAAI;YAyBV,QAAQ;YA6QR,mBAAmB;IA2DjC,OAAO,CAAC,aAAa;IAqCrB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,mBAAmB;IAkE3B,OAAO,CAAC,sBAAsB;IAiD9B,OAAO,CAAC,mBAAmB;IAiC3B,OAAO,CAAC,wBAAwB;IAwBhC,OAAO,CAAC,sBAAsB;IA6B9B,OAAO,CAAC,WAAW;IAmFnB,OAAO,CAAC,0BAA0B;IAyBlC,OAAO,CAAC,uBAAuB;IA0E/B,OAAO,CAAC,6BAA6B;IA6DrC,OAAO,CAAC,sBAAsB;IA0E9B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,2BAA2B;IAQnC,OAAO,CAAC,uBAAuB;IAsD/B,OAAO,CAAC,iBAAiB;IAqBzB,OAAO,CAAC,iBAAiB;CA8B1B"}
1
+ {"version":3,"file":"AgUiThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../../src/runtime/AgUiThreadRuntimeCore.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { readMcpAppResourceUri } from "./mcp-tool-result.js";
3
+ import { AG_UI_METADATA_NAMESPACE } from "./types.js";
3
4
  import { buildToolApprovalResume, projectAgUiToolApprovals, withSettledToolApprovals, withToolApprovalDecision } from "./adapter/tool-approval.js";
4
- import { AG_UI_METADATA_NAMESPACE, RunAggregator, isPlainObject, tryParseJSON } from "./adapter/run-aggregator.js";
5
+ import { RunAggregator, isPlainObject, tryParseJSON } from "./adapter/run-aggregator.js";
5
6
  import { fromAgUiMessages, toAgUiMessages, toAgUiTools } from "./adapter/conversions.js";
6
7
  import { createAgUiSubscriber } from "./adapter/subscriber.js";
7
8
  import { fromThreadMessageLike, generateId, isMcpAppUri } from "@assistant-ui/core";
@@ -12,6 +13,7 @@ const optimisticPrefix = "__optimistic__";
12
13
  const generateOptimisticId = () => `${optimisticPrefix}${generateId()}`;
13
14
  const isOptimisticId = (id) => id.startsWith(optimisticPrefix);
14
15
  const isResolvedToolCall = (part) => part.type === "tool-call" && "result" in part && part.result !== void 0;
16
+ const isActivityPart = (part) => part.type === "data" && part.name.startsWith("agui-activity/");
15
17
  const FALLBACK_USER_STATUS = {
16
18
  type: "complete",
17
19
  reason: "unknown"
@@ -40,7 +42,9 @@ var AgUiThreadRuntimeCore = class {
40
42
  autoCancelPendingToolCalls;
41
43
  onError;
42
44
  onCancel;
43
- notifyUpdate;
45
+ listeners = /* @__PURE__ */ new Set();
46
+ snapshot;
47
+ isThreadSwitching;
44
48
  reportedErrors = /* @__PURE__ */ new WeakSet();
45
49
  runtime;
46
50
  session = createMessageRepositorySession({ decorateExport: (exported, repository) => {
@@ -68,6 +72,8 @@ var AgUiThreadRuntimeCore = class {
68
72
  persistedHistoryIds = /* @__PURE__ */ new Set();
69
73
  historyWrites = /* @__PURE__ */ new Map();
70
74
  _isLoading = false;
75
+ _historyImportPromise;
76
+ historyMutationGeneration = 0;
71
77
  _loadPromise;
72
78
  _loadRequested = false;
73
79
  pendingResume = null;
@@ -82,7 +88,21 @@ var AgUiThreadRuntimeCore = class {
82
88
  this.onError = options.onError;
83
89
  this.onCancel = options.onCancel;
84
90
  this.history = options.history;
85
- this.notifyUpdate = options.notifyUpdate;
91
+ this.isThreadSwitching = options.isThreadSwitching;
92
+ }
93
+ subscribe = (listener) => {
94
+ this.listeners.add(listener);
95
+ return () => this.listeners.delete(listener);
96
+ };
97
+ getSnapshot = () => this.snapshot ??= {
98
+ isLoading: this._isLoading,
99
+ isRunning: this.isRunningFlag,
100
+ messageRepository: this.session.export(),
101
+ state: this.stateSnapshot
102
+ };
103
+ publishUpdate() {
104
+ this.snapshot = void 0;
105
+ for (const listener of this.listeners) listener();
86
106
  }
87
107
  updateOptions(options) {
88
108
  this.agent = options.agent;
@@ -124,18 +144,25 @@ var AgUiThreadRuntimeCore = class {
124
144
  this._loadRequested = true;
125
145
  if (this._loadPromise) return this._loadPromise;
126
146
  if (!this.history) return Promise.resolve();
127
- const promise = this.history.load();
128
- this._isLoading = true;
129
- this._loadPromise = promise.then(async (repo) => {
147
+ const promise = this.history.load().then((repo) => {
130
148
  if (!repo) return;
131
149
  this.session.applyExternalMessageRepository(repo);
132
150
  this.assistantHistoryParents.clear();
133
151
  this.snapshotHistoryIds.clear();
134
152
  this.persistedHistoryIds.clear();
135
153
  for (const { message } of repo.messages) this.persistedHistoryIds.add(message.id);
136
- this.notifyUpdate();
154
+ this.publishUpdate();
137
155
  if (repo.state !== void 0) this.loadExternalState(repo.state);
138
- if (repo.unstable_resume) {
156
+ return repo;
157
+ });
158
+ this._isLoading = true;
159
+ this._historyImportPromise = promise.then(() => {
160
+ this._historyImportPromise = void 0;
161
+ }, () => {
162
+ this._historyImportPromise = void 0;
163
+ });
164
+ this._loadPromise = promise.then(async (repo) => {
165
+ if (repo?.unstable_resume) {
139
166
  const parentId = repo.headId ?? this.session.headId;
140
167
  const resumeStream = this.history?.resume?.bind(this.history);
141
168
  await this.startRun(parentId, this.lastRunConfig, void 0, resumeStream);
@@ -145,12 +172,43 @@ var AgUiThreadRuntimeCore = class {
145
172
  this.reportError(error);
146
173
  }).finally(() => {
147
174
  this._isLoading = false;
148
- this.notifyUpdate();
175
+ this.publishUpdate();
149
176
  });
150
- this.notifyUpdate();
177
+ this.publishUpdate();
151
178
  return this._loadPromise;
152
179
  }
180
+ waitForHistoryImport() {
181
+ const historyImport = this._historyImportPromise;
182
+ if (!historyImport) return void 0;
183
+ const generation = this.historyMutationGeneration;
184
+ return historyImport.then(() => generation === this.historyMutationGeneration && !this.isThreadSwitching?.());
185
+ }
186
+ deferUntilHistoryImported(callback) {
187
+ const historyImport = this._historyImportPromise;
188
+ if (!historyImport) return false;
189
+ const generation = this.historyMutationGeneration;
190
+ historyImport.then(() => {
191
+ if (generation !== this.historyMutationGeneration || this.isThreadSwitching?.()) return;
192
+ try {
193
+ callback();
194
+ } catch (error) {
195
+ this.reportError(error);
196
+ }
197
+ });
198
+ return true;
199
+ }
153
200
  async append(message) {
201
+ const historyImport = this._historyImportPromise;
202
+ if (historyImport) {
203
+ const wasAtTail = message.parentId === this.session.headId;
204
+ const generation = this.historyMutationGeneration;
205
+ await historyImport;
206
+ if (generation !== this.historyMutationGeneration || this.isThreadSwitching?.()) return;
207
+ if (wasAtTail) message = {
208
+ ...message,
209
+ parentId: this.session.headId
210
+ };
211
+ }
154
212
  const startRun = message.startRun ?? message.role === "user";
155
213
  let ownsThread = true;
156
214
  if (startRun) {
@@ -166,7 +224,7 @@ var AgUiThreadRuntimeCore = class {
166
224
  const parentId = this.session.headId;
167
225
  this.session.addOrUpdateMessage(parentId, message);
168
226
  this.session.switchToBranch(message.id);
169
- this.notifyUpdate();
227
+ this.publishUpdate();
170
228
  this.recordHistoryEntry(parentId, message);
171
229
  }
172
230
  maybeAutoCancelPendingToolCalls() {
@@ -181,7 +239,7 @@ var AgUiThreadRuntimeCore = class {
181
239
  const parentId = message.parentId === null ? null : message.parentId && this.session.hasMessage(message.parentId) ? message.parentId : this.session.headId;
182
240
  this.session.addOrUpdateMessage(parentId, threadMessage);
183
241
  this.session.switchToBranch(threadMessage.id);
184
- this.notifyUpdate();
242
+ this.publishUpdate();
185
243
  this.recordHistoryEntry(parentId, threadMessage);
186
244
  return threadMessage.id;
187
245
  }
@@ -189,11 +247,14 @@ var AgUiThreadRuntimeCore = class {
189
247
  await this.append(message);
190
248
  }
191
249
  async reload(parentId, config = {}) {
250
+ const historyImport = this.waitForHistoryImport();
251
+ if (historyImport && !await historyImport) return;
192
252
  this.assertNoPendingInterrupts();
193
253
  this.maybeAutoCancelPendingToolCalls();
194
254
  await this.startRun(parentId, config.runConfig);
195
255
  }
196
256
  async cancel() {
257
+ this.historyMutationGeneration++;
197
258
  this.abortActiveRun();
198
259
  }
199
260
  abortActiveRun() {
@@ -216,10 +277,14 @@ var AgUiThreadRuntimeCore = class {
216
277
  return false;
217
278
  }
218
279
  async resume(config) {
280
+ const historyImport = this.waitForHistoryImport();
281
+ if (historyImport && !await historyImport) return;
219
282
  this.assertNoPendingInterrupts();
220
283
  await this.startRun(config.parentId, config.runConfig ?? this.lastRunConfig, void 0, config.stream);
221
284
  }
222
285
  async resumeInFlightRun(messages) {
286
+ const historyImport = this.waitForHistoryImport();
287
+ if (historyImport && !await historyImport) return;
223
288
  const resumeStream = this.history?.resume?.bind(this.history);
224
289
  if (!resumeStream) {
225
290
  const error = /* @__PURE__ */ new Error("[agui] unstable_resume requires a ThreadHistoryAdapter with a resume() method; skipping resume after thread switch");
@@ -266,6 +331,8 @@ var AgUiThreadRuntimeCore = class {
266
331
  };
267
332
  }
268
333
  async submitInterruptResponses(responses) {
334
+ const historyImport = this.waitForHistoryImport();
335
+ if (historyImport && !await historyImport) return;
269
336
  const pending = this.getPendingInterrupts();
270
337
  if (!pending) throw new Error("[agui] submitInterruptResponses: no pending interrupts on this thread");
271
338
  const responsesById = this.collectInterruptResponses("submitInterruptResponses", pending.interrupts, responses);
@@ -313,6 +380,8 @@ var AgUiThreadRuntimeCore = class {
313
380
  if (this.isRunningFlag) throw new Error(`[agui] ${method}: a run is already in progress`);
314
381
  }
315
382
  async respondToToolApproval(options) {
383
+ const historyImport = this.waitForHistoryImport();
384
+ if (historyImport && !await historyImport) return;
316
385
  const pending = this.getPendingInterrupts();
317
386
  if (!pending) throw new Error("[agui] respondToToolApproval: no pending interrupts on this thread");
318
387
  const gatedMessage = this.session.tryGetMessage(pending.messageId)?.message;
@@ -328,7 +397,7 @@ var AgUiThreadRuntimeCore = class {
328
397
  content
329
398
  };
330
399
  })) throw new Error(`[agui] respondToToolApproval: approval "${options.approvalId}" is already decided`);
331
- this.notifyUpdate();
400
+ this.publishUpdate();
332
401
  const assistant = this.session.tryGetMessage(pending.messageId)?.message;
333
402
  if (!assistant) return;
334
403
  const resume = buildToolApprovalResume(assistant.content, pending.interrupts);
@@ -336,6 +405,8 @@ var AgUiThreadRuntimeCore = class {
336
405
  await this.resumeWithResponses(pending.messageId, resume);
337
406
  }
338
407
  async steerAway(message, responses) {
408
+ const historyImport = this.waitForHistoryImport();
409
+ if (historyImport && !await historyImport) return;
339
410
  const pending = this.getPendingInterrupts();
340
411
  if (!pending) {
341
412
  const pendingTools = this.getPendingToolCalls();
@@ -429,7 +500,7 @@ var AgUiThreadRuntimeCore = class {
429
500
  custom: newCustom
430
501
  }
431
502
  };
432
- })) this.notifyUpdate();
503
+ })) this.publishUpdate();
433
504
  }
434
505
  findMessageIdForToolCall(toolCallId) {
435
506
  let fallbackMessageId;
@@ -461,9 +532,10 @@ var AgUiThreadRuntimeCore = class {
461
532
  ...assistant,
462
533
  content
463
534
  };
464
- })) this.notifyUpdate();
535
+ })) this.publishUpdate();
465
536
  }
466
537
  addToolResult(options) {
538
+ if (this.deferUntilHistoryImported(() => this.addToolResult(options))) return;
467
539
  const sessionMessageId = this.session.tryGetMessage(options.messageId) ? options.messageId : this.findMessageIdForToolCall(options.toolCallId);
468
540
  if (sessionMessageId === void 0) return;
469
541
  if (!this.session.updateMessage(sessionMessageId, (message) => {
@@ -487,10 +559,12 @@ var AgUiThreadRuntimeCore = class {
487
559
  content
488
560
  };
489
561
  })) return;
490
- this.notifyUpdate();
562
+ this.publishUpdate();
491
563
  this.maybeResumeAfterToolResults(sessionMessageId);
492
564
  }
493
565
  async recordToolInteraction(options) {
566
+ const historyImport = this.waitForHistoryImport();
567
+ if (historyImport && !await historyImport) return;
494
568
  const sessionMessageId = this.session.tryGetMessage(options.messageId) ? options.messageId : this.findMessageIdForToolCall(options.toolCallId);
495
569
  if (sessionMessageId === void 0) throw new Error(`[agui] recordToolInteraction: message "${options.messageId}" was not found`);
496
570
  const item = this.session.tryGetMessage(sessionMessageId);
@@ -513,7 +587,7 @@ var AgUiThreadRuntimeCore = class {
513
587
  } : assistant;
514
588
  });
515
589
  if (!recorded || !updated) throw new Error(`[agui] recordToolInteraction: tool call "${options.toolCallId}" was not found on message "${options.messageId}"`);
516
- this.notifyUpdate();
590
+ this.publishUpdate();
517
591
  const message = this.session.tryGetMessage(sessionMessageId)?.message;
518
592
  const history = this.history;
519
593
  if (!message || !history?.update || !this.isPersistableStatus(message.status)) return;
@@ -523,6 +597,7 @@ var AgUiThreadRuntimeCore = class {
523
597
  }));
524
598
  }
525
599
  sendA2uiAction(action) {
600
+ if (this.deferUntilHistoryImported(() => this.sendA2uiAction(action))) return;
526
601
  this.assertNoPendingInterrupts();
527
602
  this.maybeAutoCancelPendingToolCalls();
528
603
  const parentId = this.session.headId;
@@ -571,7 +646,7 @@ var AgUiThreadRuntimeCore = class {
571
646
  reason: "unknown"
572
647
  }
573
648
  } : current)) return false;
574
- this.notifyUpdate();
649
+ this.publishUpdate();
575
650
  this.persistAssistantHistory(messageId);
576
651
  return true;
577
652
  }
@@ -633,21 +708,22 @@ var AgUiThreadRuntimeCore = class {
633
708
  for (const { message } of this.getMessageRepository().messages) this.snapshotHistoryIds.add(message.id);
634
709
  const resumeTarget = this.pendingResume?.messageId;
635
710
  if (resumeTarget !== void 0 && !this.session.getMessages().some((message) => message.id === resumeTarget)) this.pendingResume = null;
636
- this.notifyUpdate();
711
+ this.publishUpdate();
637
712
  }
638
713
  loadExternalState(state) {
639
714
  this.stateSnapshot = state;
640
- this.notifyUpdate();
715
+ this.publishUpdate();
641
716
  }
642
717
  setState(next) {
643
718
  this.stateSnapshot = typeof next === "function" ? next(this.stateSnapshot) : next;
644
- this.notifyUpdate();
719
+ this.publishUpdate();
645
720
  }
646
721
  resetState() {
647
722
  this.stateSnapshot = void 0;
648
- this.notifyUpdate();
723
+ this.publishUpdate();
649
724
  }
650
725
  resetThreadState() {
726
+ this.historyMutationGeneration++;
651
727
  const controller = this.abortController;
652
728
  const activeRunAgent = this.activeRunAgent;
653
729
  this.stateSnapshot = void 0;
@@ -665,9 +741,10 @@ var AgUiThreadRuntimeCore = class {
665
741
  } finally {
666
742
  controller.abort();
667
743
  }
668
- } else this.notifyUpdate();
744
+ } else this.publishUpdate();
669
745
  }
670
746
  async startRun(parentId, runConfig, resume, resumeStream) {
747
+ if (this.isThreadSwitching?.()) return;
671
748
  if (!this.supersedeActiveRun()) return;
672
749
  const normalizedRunConfig = runConfig ?? {};
673
750
  this.lastRunConfig = normalizedRunConfig;
@@ -924,7 +1001,7 @@ var AgUiThreadRuntimeCore = class {
924
1001
  }
925
1002
  setRunning(running) {
926
1003
  this.isRunningFlag = running;
927
- this.notifyUpdate();
1004
+ this.publishUpdate();
928
1005
  }
929
1006
  finishRun(controller) {
930
1007
  if (this.abortController !== controller) return;
@@ -950,7 +1027,7 @@ var AgUiThreadRuntimeCore = class {
950
1027
  };
951
1028
  this.session.addOrUpdateMessage(parentId ?? this.session.headId, assistant);
952
1029
  this.session.switchToBranch(id);
953
- this.notifyUpdate();
1030
+ this.publishUpdate();
954
1031
  return id;
955
1032
  }
956
1033
  reassignAssistantId(oldId, newId) {
@@ -998,7 +1075,7 @@ var AgUiThreadRuntimeCore = class {
998
1075
  }, settle);
999
1076
  }
1000
1077
  }
1001
- this.notifyUpdate();
1078
+ this.publishUpdate();
1002
1079
  return !collidesWithExisting;
1003
1080
  }
1004
1081
  updateAssistantMessage(messageId, update) {
@@ -1021,7 +1098,7 @@ var AgUiThreadRuntimeCore = class {
1021
1098
  const stableId = generateId();
1022
1099
  this.reassignAssistantId(messageId, stableId);
1023
1100
  resolvedMessageId = stableId;
1024
- } else this.notifyUpdate();
1101
+ } else this.publishUpdate();
1025
1102
  if (this.isPersistableStatus(latestStatus)) this.persistAssistantHistory(resolvedMessageId);
1026
1103
  this.maybeResumeAfterToolResults(resolvedMessageId);
1027
1104
  return resolvedMessageId;
@@ -1058,6 +1135,77 @@ var AgUiThreadRuntimeCore = class {
1058
1135
  });
1059
1136
  return changed ? content : next;
1060
1137
  }
1138
+ mergeSnapshotAssistantContent(previous, next, snapshotHasReasoning, snapshotHasActivity) {
1139
+ const shouldKeep = (part) => part.type === "reasoning" ? this.showThinking && !snapshotHasReasoning : isActivityPart(part) && !snapshotHasActivity;
1140
+ const kept = previous.filter(shouldKeep);
1141
+ const merged = this.reconcileSnapshotNestedContent(previous, this.preserveToolInteractions(previous, next));
1142
+ if (kept.length === 0) return merged;
1143
+ const mergedByType = /* @__PURE__ */ new Map();
1144
+ const mergedTools = /* @__PURE__ */ new Map();
1145
+ for (const [index, part] of merged.entries()) if (part.type === "tool-call") mergedTools.set(part.toolCallId, index);
1146
+ else {
1147
+ const indexes = mergedByType.get(part.type) ?? [];
1148
+ indexes.push(index);
1149
+ mergedByType.set(part.type, indexes);
1150
+ }
1151
+ const previousOrdinals = /* @__PURE__ */ new Map();
1152
+ const insertions = Array.from({ length: merged.length + 1 }, () => []);
1153
+ let predecessorIndex = -1;
1154
+ for (const part of previous) {
1155
+ if (shouldKeep(part)) {
1156
+ insertions[predecessorIndex + 1].push(part);
1157
+ continue;
1158
+ }
1159
+ let matchedIndex;
1160
+ if (part.type === "tool-call") matchedIndex = mergedTools.get(part.toolCallId);
1161
+ else {
1162
+ const ordinal = previousOrdinals.get(part.type) ?? 0;
1163
+ matchedIndex = mergedByType.get(part.type)?.[ordinal];
1164
+ previousOrdinals.set(part.type, ordinal + 1);
1165
+ }
1166
+ if (matchedIndex !== void 0) predecessorIndex = matchedIndex;
1167
+ }
1168
+ const result = [];
1169
+ for (const [index, part] of merged.entries()) result.push(...insertions[index], part);
1170
+ result.push(...insertions[merged.length]);
1171
+ return result;
1172
+ }
1173
+ reconcileSnapshotNestedContent(previous, next) {
1174
+ const nestedIds = /* @__PURE__ */ new Set();
1175
+ for (const part of previous) {
1176
+ if (part.type !== "tool-call" || !part.messages) continue;
1177
+ for (const nested of part.messages) {
1178
+ if (nested.role !== "assistant") continue;
1179
+ for (const call of iterateToolCallParts(nested.content)) nestedIds.add(call.toolCallId);
1180
+ }
1181
+ }
1182
+ const flattened = /* @__PURE__ */ new Map();
1183
+ for (const part of next) if (part.type === "tool-call" && nestedIds.has(part.toolCallId)) flattened.set(part.toolCallId, part);
1184
+ const carried = flattened.size === 0 ? previous : mapToolCallPartsDeep(previous, (part) => {
1185
+ const snapshot = flattened.get(part.toolCallId);
1186
+ if (!snapshot) return part;
1187
+ return {
1188
+ ...part,
1189
+ ...snapshot.result !== void 0 ? { result: snapshot.result } : {},
1190
+ ...snapshot.isError !== void 0 ? { isError: snapshot.isError } : {},
1191
+ ...snapshot.artifact !== void 0 ? { artifact: snapshot.artifact } : {}
1192
+ };
1193
+ }).content;
1194
+ const previousCalls = /* @__PURE__ */ new Map();
1195
+ for (const part of carried) {
1196
+ if (part.type !== "tool-call") continue;
1197
+ previousCalls.set(part.toolCallId, part);
1198
+ }
1199
+ return next.flatMap((part) => {
1200
+ if (part.type === "tool-call" && flattened.has(part.toolCallId)) return [];
1201
+ if (part.type !== "tool-call") return [part];
1202
+ const prior = previousCalls.get(part.toolCallId);
1203
+ return prior?.messages === void 0 ? [part] : [{
1204
+ ...part,
1205
+ messages: prior.messages
1206
+ }];
1207
+ });
1208
+ }
1061
1209
  mergeAssistantMetadata(current, incoming) {
1062
1210
  const annotations = incoming.unstable_annotations ? [...current.unstable_annotations, ...incoming.unstable_annotations] : current.unstable_annotations;
1063
1211
  const data = incoming.unstable_data ? [...current.unstable_data, ...incoming.unstable_data] : current.unstable_data;
@@ -1138,7 +1286,7 @@ var AgUiThreadRuntimeCore = class {
1138
1286
  }
1139
1287
  };
1140
1288
  });
1141
- this.notifyUpdate();
1289
+ this.publishUpdate();
1142
1290
  }
1143
1291
  applyCrossRunToolResult(messageId, event) {
1144
1292
  if (!this.session.updateMessage(messageId, (message) => {
@@ -1176,7 +1324,7 @@ var AgUiThreadRuntimeCore = class {
1176
1324
  content
1177
1325
  };
1178
1326
  })) return;
1179
- this.notifyUpdate();
1327
+ this.publishUpdate();
1180
1328
  this.maybeCompleteAfterToolResults(messageId);
1181
1329
  }
1182
1330
  applyCrossRunActivitySnapshot(messageId, toolCallId, event) {
@@ -1215,28 +1363,34 @@ var AgUiThreadRuntimeCore = class {
1215
1363
  content
1216
1364
  };
1217
1365
  })) return;
1218
- this.notifyUpdate();
1366
+ this.publishUpdate();
1219
1367
  this.maybeCompleteAfterToolResults(messageId);
1220
1368
  }
1221
1369
  importMessagesSnapshot(rawMessages, activeAssistantId) {
1222
1370
  try {
1223
- const activeMessage = activeAssistantId ? this.session.tryGetMessage(activeAssistantId)?.message : void 0;
1371
+ const activeAssistantItem = activeAssistantId ? this.session.tryGetMessage(activeAssistantId) : void 0;
1372
+ const activeMessage = activeAssistantItem?.message;
1373
+ const activeAssistantParentId = activeAssistantItem?.parentId;
1224
1374
  const activeAssistant = activeMessage?.role === "assistant" ? activeMessage : void 0;
1225
1375
  const normalized = fromAgUiMessages(rawMessages, { showThinking: this.showThinking });
1226
1376
  const converted = [];
1227
1377
  for (const message of normalized) try {
1228
- const convertedMessage = fromThreadMessageLike(message, generateId(), FALLBACK_USER_STATUS);
1229
- const existing = this.session.tryGetMessage(convertedMessage.id)?.message;
1230
- if (convertedMessage.role === "assistant" && existing?.role === "assistant") converted.push({
1231
- ...convertedMessage,
1232
- content: this.preserveToolInteractions(existing.content, convertedMessage.content)
1233
- });
1234
- else converted.push(convertedMessage);
1378
+ converted.push(fromThreadMessageLike(message, generateId(), FALLBACK_USER_STATUS));
1235
1379
  } catch (error) {
1236
1380
  this.logger.error?.("[agui] failed to import message from snapshot", error);
1237
1381
  }
1382
+ const snapshotHasReasoning = converted.some((message) => message.role === "assistant" && message.content.some((part) => part.type === "reasoning"));
1383
+ const snapshotHasActivity = converted.some((message) => message.role === "assistant" && message.content.some(isActivityPart));
1384
+ for (let index = 0; index < converted.length; index++) {
1385
+ const convertedMessage = converted[index];
1386
+ const existing = this.session.tryGetMessage(convertedMessage.id)?.message;
1387
+ if (convertedMessage.role === "assistant" && existing?.role === "assistant") converted[index] = {
1388
+ ...convertedMessage,
1389
+ content: this.mergeSnapshotAssistantContent(existing.content, convertedMessage.content, snapshotHasReasoning, snapshotHasActivity)
1390
+ };
1391
+ }
1238
1392
  const snapshotContainsActiveAssistant = converted.some((message) => message.id === activeAssistant?.id);
1239
- const preservesActiveAssistant = activeAssistant !== void 0 && !snapshotContainsActiveAssistant && (activeAssistant.metadata.isOptimistic !== true || converted.at(-1)?.role !== "assistant");
1393
+ const preservesActiveAssistant = activeAssistant !== void 0 && !snapshotContainsActiveAssistant && (activeAssistant.metadata.isOptimistic !== true || converted.at(-1)?.role !== "assistant" || activeAssistantParentId !== void 0 && converted.at(-1)?.id === activeAssistantParentId);
1240
1394
  if (preservesActiveAssistant) converted.push(activeAssistant);
1241
1395
  this.applyExternalMessages(converted);
1242
1396
  if (activeAssistant !== void 0) {