@assistant-ui/react-a2a 0.2.36 → 0.2.37
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.
- package/dist/A2AClient.d.ts +42 -44
- package/dist/A2AClient.d.ts.map +1 -1
- package/dist/A2AClient.js +43 -7
- package/dist/A2AClient.js.map +1 -1
- package/dist/A2AThreadRuntimeCore.d.ts +98 -86
- package/dist/A2AThreadRuntimeCore.d.ts.map +1 -1
- package/dist/A2AThreadRuntimeCore.js +204 -17
- package/dist/A2AThreadRuntimeCore.js.map +1 -1
- package/dist/a2aExtras.d.ts +1 -3
- package/dist/a2aExtras.d.ts.map +1 -1
- package/dist/conversions.d.ts +18 -17
- package/dist/conversions.d.ts.map +1 -1
- package/dist/conversions.js +24 -2
- package/dist/conversions.js.map +1 -1
- package/dist/hooks.d.ts +3 -6
- package/dist/hooks.d.ts.map +1 -1
- package/dist/index.d.ts +9 -6
- package/dist/index.d.ts.map +1 -0
- package/dist/types.d.ts +207 -209
- package/dist/types.d.ts.map +1 -1
- package/dist/useA2ARuntime.d.ts +2 -4
- package/dist/useA2ARuntime.d.ts.map +1 -1
- package/dist/useA2ARuntime.js +8 -0
- package/dist/useA2ARuntime.js.map +1 -1
- package/package.json +6 -5
- package/src/A2AClient.test.ts +41 -0
- package/src/A2AClient.ts +50 -6
- package/src/A2AThreadRuntimeCore.test.ts +887 -9
- package/src/A2AThreadRuntimeCore.ts +347 -18
- package/src/conversions.test.ts +116 -0
- package/src/conversions.ts +48 -1
- package/src/useA2ARuntime.test.tsx +245 -0
- package/src/useA2ARuntime.ts +14 -0
- package/src/useA2ARuntime.voice.test.tsx +370 -0
|
@@ -1,91 +1,103 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { A2AClient } from "./A2AClient.js";
|
|
3
|
-
import {
|
|
4
|
-
//#region src/A2AThreadRuntimeCore.d.ts
|
|
1
|
+
import type { AppendMessage, AssistantRuntime, ExportedMessageRepository, ThreadHistoryAdapter, ThreadMessage, Unstable_RecordToolInteractionOptions } from "@assistant-ui/core";
|
|
2
|
+
import type { A2AClient } from "./A2AClient.js";
|
|
3
|
+
import type { A2AArtifact, A2AAgentCard, A2ASendMessageConfiguration, A2ATask } from "./types.js";
|
|
5
4
|
export type A2AThreadRuntimeCoreOptions = {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
client: A2AClient;
|
|
6
|
+
contextId?: string | undefined;
|
|
7
|
+
configuration?: A2ASendMessageConfiguration | undefined;
|
|
8
|
+
onError?: ((error: Error) => void) | undefined;
|
|
9
|
+
onCancel?: (() => void) | undefined;
|
|
10
|
+
onArtifactComplete?: ((artifact: A2AArtifact) => void) | undefined;
|
|
11
|
+
history?: ThreadHistoryAdapter | undefined;
|
|
12
|
+
notifyUpdate: () => void;
|
|
14
13
|
};
|
|
15
14
|
export declare class A2AThreadRuntimeCore {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
15
|
+
private client;
|
|
16
|
+
private contextId;
|
|
17
|
+
private configuration;
|
|
18
|
+
private onError;
|
|
19
|
+
private onCancel;
|
|
20
|
+
private onArtifactComplete;
|
|
21
|
+
private history;
|
|
22
|
+
private readonly notifyUpdate;
|
|
23
|
+
private runtime;
|
|
24
|
+
private readonly session;
|
|
25
|
+
private isRunningFlag;
|
|
26
|
+
private abortController;
|
|
27
|
+
private runGeneration;
|
|
28
|
+
private pendingError;
|
|
29
|
+
private currentTask;
|
|
30
|
+
private currentArtifacts;
|
|
31
|
+
private a2uiState;
|
|
32
|
+
private readonly a2uiMessageIds;
|
|
33
|
+
private agentCardValue;
|
|
34
|
+
private readonly assistantHistoryParents;
|
|
35
|
+
private readonly recordedHistoryIds;
|
|
36
|
+
private readonly historyWrites;
|
|
37
|
+
private _isLoading;
|
|
38
|
+
private _loadPromise;
|
|
39
|
+
private _historyLoadGeneration;
|
|
40
|
+
private _loadRequested;
|
|
41
|
+
private _agentCardPromise;
|
|
42
|
+
private _agentCardRetryAfter;
|
|
43
|
+
private _agentCardRetryDelay;
|
|
44
|
+
private _agentCardDiscoveryFailed;
|
|
45
|
+
private lastOptionsContextId;
|
|
46
|
+
constructor(options: A2AThreadRuntimeCoreOptions);
|
|
47
|
+
updateOptions(options: Omit<A2AThreadRuntimeCoreOptions, "notifyUpdate">): void;
|
|
48
|
+
/** Thread-boundary reset: applyExternalMessages alone also serves branch
|
|
49
|
+
* switches, deletes, and cancel resyncs, which must keep the live context. */
|
|
50
|
+
resetContext(): void;
|
|
51
|
+
attachRuntime(runtime: AssistantRuntime): void;
|
|
52
|
+
detachRuntime(): void;
|
|
53
|
+
getRuntime(): AssistantRuntime | undefined;
|
|
54
|
+
getMessages(): readonly ThreadMessage[];
|
|
55
|
+
getMessageRepository(): ExportedMessageRepository;
|
|
56
|
+
recordToolInteraction({ messageId, toolCallId, interaction, }: Unstable_RecordToolInteractionOptions): Promise<void>;
|
|
57
|
+
getTask(): A2ATask | undefined;
|
|
58
|
+
getArtifacts(): readonly A2AArtifact[];
|
|
59
|
+
getAgentCard(): A2AAgentCard | undefined;
|
|
60
|
+
isRunning(): boolean;
|
|
61
|
+
get isLoading(): boolean;
|
|
62
|
+
private loadAgentCard;
|
|
63
|
+
private waitForAgentCard;
|
|
64
|
+
__internal_load(): Promise<void>;
|
|
65
|
+
append(message: AppendMessage): Promise<void>;
|
|
66
|
+
appendVoiceTranscript(message: ThreadMessage): void;
|
|
67
|
+
edit(message: AppendMessage): Promise<void>;
|
|
68
|
+
reload(parentId: string | null, _config?: {
|
|
69
|
+
runConfig?: Record<string, unknown>;
|
|
70
|
+
}): Promise<void>;
|
|
71
|
+
cancel(): Promise<void>;
|
|
72
|
+
private appendLinearChain;
|
|
73
|
+
private finalizeExternalApply;
|
|
74
|
+
applyExternalMessages(messages: readonly ThreadMessage[]): void;
|
|
75
|
+
private startRun;
|
|
76
|
+
private runStreaming;
|
|
77
|
+
private runSync;
|
|
78
|
+
private handleStreamEvent;
|
|
79
|
+
private handleStatusUpdate;
|
|
80
|
+
private handleArtifactUpdate;
|
|
81
|
+
private handleMessage;
|
|
82
|
+
private handleTaskSnapshot;
|
|
83
|
+
private insertAssistantPlaceholder;
|
|
84
|
+
private updateAssistantContent;
|
|
85
|
+
private applyA2uiMessage;
|
|
86
|
+
private applyA2uiParts;
|
|
87
|
+
private a2uiSurfaceParts;
|
|
88
|
+
private withA2uiSurfaces;
|
|
89
|
+
private withPreservedToolInteractions;
|
|
90
|
+
private rebuildAssistantA2uiSurfaces;
|
|
91
|
+
private updateAssistantArtifacts;
|
|
92
|
+
private updateAssistantStatus;
|
|
93
|
+
private getAssistantStatus;
|
|
94
|
+
private isPersistableAssistantStatus;
|
|
95
|
+
private setRunning;
|
|
96
|
+
private finishRun;
|
|
97
|
+
private recordHistoryEntry;
|
|
98
|
+
private markPendingAssistantHistory;
|
|
99
|
+
private persistAssistantHistory;
|
|
100
|
+
private appendHistoryItem;
|
|
101
|
+
private chainHistoryWrite;
|
|
89
102
|
}
|
|
90
|
-
//#endregion
|
|
91
103
|
//# sourceMappingURL=A2AThreadRuntimeCore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"A2AThreadRuntimeCore.d.ts","
|
|
1
|
+
{"version":3,"file":"A2AThreadRuntimeCore.d.ts","sourceRoot":"","sources":["../src/A2AThreadRuntimeCore.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { a2aMessageToContent, isTerminalTaskState, taskStateToMessageStatus, threadMessageToA2AMessage } from "./conversions.js";
|
|
3
|
-
import { createMessageRepositorySession, invokeUserCallback } from "@assistant-ui/core/internal";
|
|
2
|
+
import { a2aMessageToContent, a2uiPartsToOperations, isTerminalTaskState, taskStateToMessageStatus, threadMessageToA2AMessage } from "./conversions.js";
|
|
3
|
+
import { appendToolInteraction, createMessageRepositorySession, invokeUserCallback } from "@assistant-ui/core/internal";
|
|
4
4
|
import { fromThreadMessageLike, generateId } from "@assistant-ui/core";
|
|
5
|
+
import { applyA2uiOperations, convertSurfaceToUISpec, surfaceToOperations } from "@assistant-ui/react-generative-ui/a2ui";
|
|
5
6
|
//#region src/A2AThreadRuntimeCore.ts
|
|
6
7
|
const INITIAL_AGENT_CARD_RETRY_DELAY_MS = 5e3;
|
|
7
8
|
const MAX_AGENT_CARD_RETRY_DELAY_MS = 3e5;
|
|
9
|
+
const isRecord$1 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10
|
+
const storedArtifact = (artifact) => ({
|
|
11
|
+
...artifact,
|
|
12
|
+
parts: artifact.parts.map(({ raw: _raw, ...part }) => part)
|
|
13
|
+
});
|
|
8
14
|
const FALLBACK_USER_STATUS = {
|
|
9
15
|
type: "complete",
|
|
10
16
|
reason: "unknown"
|
|
@@ -35,9 +41,12 @@ var A2AThreadRuntimeCore = class {
|
|
|
35
41
|
pendingError = null;
|
|
36
42
|
currentTask;
|
|
37
43
|
currentArtifacts = [];
|
|
44
|
+
a2uiState = /* @__PURE__ */ new Map();
|
|
45
|
+
a2uiMessageIds = /* @__PURE__ */ new Set();
|
|
38
46
|
agentCardValue;
|
|
39
47
|
assistantHistoryParents = /* @__PURE__ */ new Map();
|
|
40
48
|
recordedHistoryIds = /* @__PURE__ */ new Set();
|
|
49
|
+
historyWrites = /* @__PURE__ */ new Map();
|
|
41
50
|
_isLoading = false;
|
|
42
51
|
_loadPromise;
|
|
43
52
|
_historyLoadGeneration = 0;
|
|
@@ -103,6 +112,26 @@ var A2AThreadRuntimeCore = class {
|
|
|
103
112
|
getMessageRepository() {
|
|
104
113
|
return this.session.export();
|
|
105
114
|
}
|
|
115
|
+
async recordToolInteraction({ messageId, toolCallId, interaction }) {
|
|
116
|
+
const message = this.session.tryGetMessage(messageId)?.message;
|
|
117
|
+
if (!message) throw new Error("Tried to record a tool interaction on a non-existing message");
|
|
118
|
+
if (message.role !== "assistant") throw new Error("Tried to record a tool interaction on a non-assistant message");
|
|
119
|
+
const target = message.content.find((part) => part.type === "tool-call" && part.toolCallId === toolCallId);
|
|
120
|
+
if (!target || target.type !== "tool-call") throw new Error("Tried to record a tool interaction on a non-existing tool call");
|
|
121
|
+
if (this.session.updateMessage(messageId, (current) => {
|
|
122
|
+
if (current.role !== "assistant") return current;
|
|
123
|
+
return {
|
|
124
|
+
...current,
|
|
125
|
+
content: current.content.map((part) => part.type === "tool-call" && part.toolCallId === toolCallId ? {
|
|
126
|
+
...part,
|
|
127
|
+
unstable_interactions: appendToolInteraction(part.unstable_interactions, interaction)
|
|
128
|
+
} : part)
|
|
129
|
+
};
|
|
130
|
+
})) {
|
|
131
|
+
this.notifyUpdate();
|
|
132
|
+
this.persistAssistantHistory(messageId);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
106
135
|
getTask() {
|
|
107
136
|
return this.currentTask;
|
|
108
137
|
}
|
|
@@ -159,7 +188,7 @@ var A2AThreadRuntimeCore = class {
|
|
|
159
188
|
this._isLoading = true;
|
|
160
189
|
const generation = this._historyLoadGeneration;
|
|
161
190
|
const historyPromise = this.history.load();
|
|
162
|
-
this._loadPromise =
|
|
191
|
+
this._loadPromise = historyPromise.then((repo) => {
|
|
163
192
|
if (generation !== this._historyLoadGeneration) return;
|
|
164
193
|
if (repo) {
|
|
165
194
|
this.session.applyExternalMessageRepository(repo);
|
|
@@ -187,6 +216,13 @@ var A2AThreadRuntimeCore = class {
|
|
|
187
216
|
if (!startRun) return;
|
|
188
217
|
await this.startRun(threadMessage);
|
|
189
218
|
}
|
|
219
|
+
appendVoiceTranscript(message) {
|
|
220
|
+
const parentId = this.session.headId;
|
|
221
|
+
this.session.addOrUpdateMessage(parentId, message);
|
|
222
|
+
this.session.switchToBranch(message.id);
|
|
223
|
+
this.notifyUpdate();
|
|
224
|
+
this.recordHistoryEntry(parentId, message);
|
|
225
|
+
}
|
|
190
226
|
async edit(message) {
|
|
191
227
|
await this.append(message);
|
|
192
228
|
}
|
|
@@ -226,6 +262,8 @@ var A2AThreadRuntimeCore = class {
|
|
|
226
262
|
for (const { message } of this.getMessageRepository().messages) this.recordedHistoryIds.add(message.id);
|
|
227
263
|
this.currentTask = void 0;
|
|
228
264
|
this.currentArtifacts = [];
|
|
265
|
+
this.a2uiState = /* @__PURE__ */ new Map();
|
|
266
|
+
this.a2uiMessageIds.clear();
|
|
229
267
|
this.notifyUpdate();
|
|
230
268
|
}
|
|
231
269
|
applyExternalMessages(messages) {
|
|
@@ -267,6 +305,8 @@ var A2AThreadRuntimeCore = class {
|
|
|
267
305
|
});
|
|
268
306
|
if (this.currentTask && isTerminalTaskState(this.currentTask.status.state)) this.currentTask = void 0;
|
|
269
307
|
this.currentArtifacts = [];
|
|
308
|
+
this.a2uiState = /* @__PURE__ */ new Map();
|
|
309
|
+
this.a2uiMessageIds.clear();
|
|
270
310
|
const assistantParentId = userThreadMessage.id;
|
|
271
311
|
const assistantId = this.insertAssistantPlaceholder(assistantParentId);
|
|
272
312
|
this.markPendingAssistantHistory(assistantId, assistantParentId);
|
|
@@ -343,7 +383,7 @@ var A2AThreadRuntimeCore = class {
|
|
|
343
383
|
this.handleStatusUpdate(assistantId, event.event);
|
|
344
384
|
break;
|
|
345
385
|
case "artifactUpdate":
|
|
346
|
-
this.handleArtifactUpdate(event.event);
|
|
386
|
+
this.handleArtifactUpdate(assistantId, event.event);
|
|
347
387
|
break;
|
|
348
388
|
case "message":
|
|
349
389
|
this.handleMessage(assistantId, event.message);
|
|
@@ -363,6 +403,7 @@ var A2AThreadRuntimeCore = class {
|
|
|
363
403
|
};
|
|
364
404
|
if (event.contextId) this.contextId = event.contextId;
|
|
365
405
|
if (event.status.message) {
|
|
406
|
+
this.applyA2uiMessage(event.status.message);
|
|
366
407
|
const content = a2aMessageToContent(event.status.message);
|
|
367
408
|
this.updateAssistantContent(assistantId, content);
|
|
368
409
|
}
|
|
@@ -370,7 +411,7 @@ var A2AThreadRuntimeCore = class {
|
|
|
370
411
|
this.updateAssistantStatus(assistantId, status);
|
|
371
412
|
this.notifyUpdate();
|
|
372
413
|
}
|
|
373
|
-
handleArtifactUpdate(event) {
|
|
414
|
+
handleArtifactUpdate(assistantId, event) {
|
|
374
415
|
const { append, lastChunk } = event;
|
|
375
416
|
const artifact = normalizeArtifact(event.artifact);
|
|
376
417
|
const existingIdx = this.currentArtifacts.findIndex((a) => a.artifactId === artifact.artifactId);
|
|
@@ -397,11 +438,15 @@ var A2AThreadRuntimeCore = class {
|
|
|
397
438
|
updated = artifact;
|
|
398
439
|
this.currentArtifacts = [...this.currentArtifacts, updated];
|
|
399
440
|
}
|
|
441
|
+
this.applyA2uiParts(artifact.parts);
|
|
442
|
+
this.updateAssistantArtifacts(assistantId);
|
|
443
|
+
this.rebuildAssistantA2uiSurfaces(assistantId);
|
|
400
444
|
if (lastChunk) invokeRuntimeCallback("onArtifactComplete", this.onArtifactComplete, updated);
|
|
401
445
|
this.notifyUpdate();
|
|
402
446
|
}
|
|
403
447
|
handleMessage(assistantId, message) {
|
|
404
448
|
if (message.role !== "agent") return;
|
|
449
|
+
this.applyA2uiMessage(message);
|
|
405
450
|
const content = a2aMessageToContent(message);
|
|
406
451
|
this.updateAssistantContent(assistantId, content);
|
|
407
452
|
this.notifyUpdate();
|
|
@@ -415,11 +460,21 @@ var A2AThreadRuntimeCore = class {
|
|
|
415
460
|
...history === void 0 ? {} : { history }
|
|
416
461
|
};
|
|
417
462
|
if (task.contextId) this.contextId = task.contextId;
|
|
418
|
-
|
|
463
|
+
const isCompleteSnapshot = history !== void 0 && artifacts !== void 0;
|
|
464
|
+
const artifactsToApply = isCompleteSnapshot ? artifacts : artifacts?.filter((artifact) => !this.currentArtifacts.some(({ artifactId }) => artifactId === artifact.artifactId));
|
|
465
|
+
if (isCompleteSnapshot) {
|
|
466
|
+
this.currentArtifacts = artifacts;
|
|
467
|
+
this.a2uiState = /* @__PURE__ */ new Map();
|
|
468
|
+
this.a2uiMessageIds.clear();
|
|
469
|
+
} else if (artifactsToApply) this.currentArtifacts = [...this.currentArtifacts, ...artifactsToApply];
|
|
470
|
+
for (const message of history ?? []) if (message.role === "agent") this.applyA2uiMessage(message, true);
|
|
471
|
+
for (const artifact of artifactsToApply ?? []) this.applyA2uiParts(artifact.parts);
|
|
472
|
+
if (task.status.message) this.applyA2uiMessage(task.status.message, true);
|
|
473
|
+
if (isCompleteSnapshot || artifactsToApply?.length) this.updateAssistantArtifacts(assistantId);
|
|
419
474
|
if (task.status.message) {
|
|
420
475
|
const content = a2aMessageToContent(task.status.message);
|
|
421
476
|
this.updateAssistantContent(assistantId, content);
|
|
422
|
-
}
|
|
477
|
+
} else this.rebuildAssistantA2uiSurfaces(assistantId);
|
|
423
478
|
const status = taskStateToMessageStatus(task.status.state);
|
|
424
479
|
this.updateAssistantStatus(assistantId, status);
|
|
425
480
|
this.notifyUpdate();
|
|
@@ -450,10 +505,86 @@ var A2AThreadRuntimeCore = class {
|
|
|
450
505
|
if (message.role !== "assistant") return message;
|
|
451
506
|
return {
|
|
452
507
|
...message,
|
|
453
|
-
content
|
|
508
|
+
content: this.withA2uiSurfaces(content, message.content)
|
|
454
509
|
};
|
|
455
510
|
});
|
|
456
511
|
}
|
|
512
|
+
applyA2uiMessage(message, replay = false) {
|
|
513
|
+
if (message.messageId) {
|
|
514
|
+
if (replay && this.a2uiMessageIds.has(message.messageId)) return;
|
|
515
|
+
this.a2uiMessageIds.add(message.messageId);
|
|
516
|
+
}
|
|
517
|
+
this.applyA2uiParts(message.parts);
|
|
518
|
+
}
|
|
519
|
+
applyA2uiParts(parts) {
|
|
520
|
+
const operations = a2uiPartsToOperations(parts);
|
|
521
|
+
if (operations.length === 0) return;
|
|
522
|
+
this.a2uiState = applyA2uiOperations(this.a2uiState, operations).state;
|
|
523
|
+
}
|
|
524
|
+
a2uiSurfaceParts() {
|
|
525
|
+
const parts = [];
|
|
526
|
+
for (const [surfaceId, surface] of this.a2uiState) {
|
|
527
|
+
const { spec } = convertSurfaceToUISpec(surface);
|
|
528
|
+
if (!spec) continue;
|
|
529
|
+
parts.push({
|
|
530
|
+
type: "tool-call",
|
|
531
|
+
toolCallId: `a2ui:${surfaceId}`,
|
|
532
|
+
toolName: "present",
|
|
533
|
+
args: spec,
|
|
534
|
+
argsText: JSON.stringify(spec),
|
|
535
|
+
result: {},
|
|
536
|
+
artifact: { a2ui: surfaceToOperations(surface) }
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
return parts;
|
|
540
|
+
}
|
|
541
|
+
withA2uiSurfaces(content, previousContent = content) {
|
|
542
|
+
const preserved = content.filter((part) => !(part.type === "tool-call" && part.toolCallId.startsWith("a2ui:")));
|
|
543
|
+
const interactionSource = [...previousContent, ...content];
|
|
544
|
+
return this.withPreservedToolInteractions(interactionSource, [...preserved, ...this.a2uiSurfaceParts()]);
|
|
545
|
+
}
|
|
546
|
+
withPreservedToolInteractions(previousContent, content) {
|
|
547
|
+
const interactions = /* @__PURE__ */ new Map();
|
|
548
|
+
for (const part of previousContent) if (part.type === "tool-call" && part.unstable_interactions !== void 0) interactions.set(part.toolCallId, part.unstable_interactions);
|
|
549
|
+
if (interactions.size === 0) return content;
|
|
550
|
+
return content.map((part) => {
|
|
551
|
+
if (part.type !== "tool-call" || part.unstable_interactions !== void 0) return part;
|
|
552
|
+
const unstable_interactions = interactions.get(part.toolCallId);
|
|
553
|
+
return unstable_interactions === void 0 ? part : {
|
|
554
|
+
...part,
|
|
555
|
+
unstable_interactions
|
|
556
|
+
};
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
rebuildAssistantA2uiSurfaces(messageId) {
|
|
560
|
+
if (this.session.updateMessage(messageId, (message) => {
|
|
561
|
+
if (message.role !== "assistant") return message;
|
|
562
|
+
return {
|
|
563
|
+
...message,
|
|
564
|
+
content: this.withA2uiSurfaces(message.content)
|
|
565
|
+
};
|
|
566
|
+
})) this.notifyUpdate();
|
|
567
|
+
}
|
|
568
|
+
updateAssistantArtifacts(messageId) {
|
|
569
|
+
if (this.session.updateMessage(messageId, (message) => {
|
|
570
|
+
if (message.role !== "assistant") return message;
|
|
571
|
+
const custom = message.metadata.custom;
|
|
572
|
+
const a2a = isRecord$1(custom.a2a) ? custom.a2a : {};
|
|
573
|
+
return {
|
|
574
|
+
...message,
|
|
575
|
+
metadata: {
|
|
576
|
+
...message.metadata,
|
|
577
|
+
custom: {
|
|
578
|
+
...custom,
|
|
579
|
+
a2a: {
|
|
580
|
+
...a2a,
|
|
581
|
+
artifacts: this.currentArtifacts.map(storedArtifact)
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
})) this.notifyUpdate();
|
|
587
|
+
}
|
|
457
588
|
updateAssistantStatus(messageId, status) {
|
|
458
589
|
if (this.session.updateMessage(messageId, (message) => {
|
|
459
590
|
if (message.role !== "assistant") return message;
|
|
@@ -463,7 +594,7 @@ var A2AThreadRuntimeCore = class {
|
|
|
463
594
|
};
|
|
464
595
|
})) {
|
|
465
596
|
this.notifyUpdate();
|
|
466
|
-
if (
|
|
597
|
+
if (this.isPersistableAssistantStatus(status)) this.persistAssistantHistory(messageId);
|
|
467
598
|
}
|
|
468
599
|
}
|
|
469
600
|
getAssistantStatus(messageId) {
|
|
@@ -471,6 +602,9 @@ var A2AThreadRuntimeCore = class {
|
|
|
471
602
|
if (msg?.role !== "assistant") return void 0;
|
|
472
603
|
return msg.status;
|
|
473
604
|
}
|
|
605
|
+
isPersistableAssistantStatus(status) {
|
|
606
|
+
return status.type === "complete" || status.type === "incomplete" || status.type === "requires-action" && status.reason === "interrupt";
|
|
607
|
+
}
|
|
474
608
|
setRunning(running) {
|
|
475
609
|
this.isRunningFlag = running;
|
|
476
610
|
this.notifyUpdate();
|
|
@@ -481,7 +615,9 @@ var A2AThreadRuntimeCore = class {
|
|
|
481
615
|
this.setRunning(false);
|
|
482
616
|
}
|
|
483
617
|
recordHistoryEntry(parentId, message) {
|
|
484
|
-
this.appendHistoryItem(parentId, message)
|
|
618
|
+
this.appendHistoryItem(parentId, message)?.catch((error) => {
|
|
619
|
+
console.error("[react-a2a] failed to append history entry", error);
|
|
620
|
+
});
|
|
485
621
|
}
|
|
486
622
|
markPendingAssistantHistory(messageId, parentId) {
|
|
487
623
|
if (!this.history) return;
|
|
@@ -489,23 +625,74 @@ var A2AThreadRuntimeCore = class {
|
|
|
489
625
|
}
|
|
490
626
|
persistAssistantHistory(messageId) {
|
|
491
627
|
if (!this.history) return;
|
|
628
|
+
const messageData = this.session.tryGetMessage(messageId);
|
|
492
629
|
const parentId = this.assistantHistoryParents.get(messageId);
|
|
493
|
-
if (parentId === void 0) return;
|
|
494
|
-
const
|
|
630
|
+
if (parentId === void 0 && !this.recordedHistoryIds.has(messageId)) return;
|
|
631
|
+
const resolvedParentId = parentId === void 0 ? messageData?.parentId : parentId;
|
|
632
|
+
if (resolvedParentId === void 0) return;
|
|
633
|
+
const message = messageData?.message;
|
|
495
634
|
if (!message || message.role !== "assistant") return;
|
|
496
|
-
if (
|
|
497
|
-
|
|
498
|
-
this.
|
|
635
|
+
if (!this.isPersistableAssistantStatus(message.status)) return;
|
|
636
|
+
const isPausing = message.status.type === "requires-action";
|
|
637
|
+
if (isPausing && !this.history.update) return;
|
|
638
|
+
if (this.recordedHistoryIds.has(messageId)) {
|
|
639
|
+
if (this.history.update) {
|
|
640
|
+
const update = this.history.update.bind(this.history);
|
|
641
|
+
const write = this.chainHistoryWrite(messageId, () => update({
|
|
642
|
+
parentId: resolvedParentId,
|
|
643
|
+
message
|
|
644
|
+
}));
|
|
645
|
+
if (!isPausing) this.assistantHistoryParents.delete(messageId);
|
|
646
|
+
write.then(() => {
|
|
647
|
+
this.recordedHistoryIds.add(messageId);
|
|
648
|
+
}, (error) => {
|
|
649
|
+
const pending = this.historyWrites.get(messageId);
|
|
650
|
+
if (pending === void 0 || pending === write) this.assistantHistoryParents.set(messageId, resolvedParentId);
|
|
651
|
+
console.error("[react-a2a] failed to update history entry", error);
|
|
652
|
+
});
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
if (!isPausing) this.assistantHistoryParents.delete(messageId);
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const write = this.appendHistoryItem(resolvedParentId, message);
|
|
659
|
+
if (!write) return;
|
|
660
|
+
if (!isPausing) this.assistantHistoryParents.delete(messageId);
|
|
661
|
+
write.catch((error) => {
|
|
662
|
+
const pending = this.historyWrites.get(messageId);
|
|
663
|
+
if (pending === void 0 || pending === write) this.assistantHistoryParents.set(messageId, resolvedParentId);
|
|
664
|
+
console.error("[react-a2a] failed to append history entry", error);
|
|
665
|
+
});
|
|
499
666
|
}
|
|
500
667
|
appendHistoryItem(parentId, message) {
|
|
501
668
|
if (!this.history || this.recordedHistoryIds.has(message.id)) return;
|
|
502
669
|
this.recordedHistoryIds.add(message.id);
|
|
503
|
-
this.history.append(
|
|
670
|
+
const append = this.history.append.bind(this.history);
|
|
671
|
+
const write = this.chainHistoryWrite(message.id, () => append({
|
|
504
672
|
parentId,
|
|
505
673
|
message
|
|
506
|
-
})
|
|
674
|
+
}));
|
|
675
|
+
write.catch(() => {
|
|
507
676
|
this.recordedHistoryIds.delete(message.id);
|
|
508
677
|
});
|
|
678
|
+
return write;
|
|
679
|
+
}
|
|
680
|
+
chainHistoryWrite(id, write) {
|
|
681
|
+
const pending = this.historyWrites.get(id);
|
|
682
|
+
let next;
|
|
683
|
+
if (pending) next = pending.then(write, write);
|
|
684
|
+
else try {
|
|
685
|
+
next = Promise.resolve(write());
|
|
686
|
+
} catch (error) {
|
|
687
|
+
next = Promise.reject(error);
|
|
688
|
+
}
|
|
689
|
+
this.historyWrites.set(id, next);
|
|
690
|
+
next.then(() => {
|
|
691
|
+
if (this.historyWrites.get(id) === next) this.historyWrites.delete(id);
|
|
692
|
+
}, () => {
|
|
693
|
+
if (this.historyWrites.get(id) === next) this.historyWrites.delete(id);
|
|
694
|
+
});
|
|
695
|
+
return next;
|
|
509
696
|
}
|
|
510
697
|
};
|
|
511
698
|
//#endregion
|