@assistant-ui/react-a2a 0.2.21 → 0.2.23

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.
@@ -1,5 +1,6 @@
1
1
  "use client";
2
- import { a2aMessageToContent, isTerminalTaskState, taskStateToMessageStatus } from "./conversions.js";
2
+ import { a2aMessageToContent, contentPartsToA2AParts, isTerminalTaskState, taskStateToMessageStatus } from "./conversions.js";
3
+ import { MessageRepository } from "@assistant-ui/core/internal";
3
4
  import { fromThreadMessageLike, generateId } from "@assistant-ui/core";
4
5
  //#region src/A2AThreadRuntimeCore.ts
5
6
  const FALLBACK_USER_STATUS = {
@@ -16,7 +17,8 @@ var A2AThreadRuntimeCore = class {
16
17
  history;
17
18
  notifyUpdate;
18
19
  runtime;
19
- messages = [];
20
+ repository = new MessageRepository();
21
+ exportedRepository;
20
22
  isRunningFlag = false;
21
23
  abortController = null;
22
24
  pendingError = null;
@@ -60,7 +62,52 @@ var A2AThreadRuntimeCore = class {
60
62
  return this.runtime;
61
63
  }
62
64
  getMessages() {
63
- return this.messages;
65
+ return this.repository.getMessages();
66
+ }
67
+ getMessageRepository() {
68
+ this.exportedRepository ??= this.repository.export();
69
+ return this.exportedRepository;
70
+ }
71
+ tryGetMessage(messageId) {
72
+ try {
73
+ return this.repository.getMessage(messageId);
74
+ } catch {
75
+ return;
76
+ }
77
+ }
78
+ tryGetMessages(messageId) {
79
+ try {
80
+ return this.repository.getMessages(messageId);
81
+ } catch {
82
+ return;
83
+ }
84
+ }
85
+ hasMessage(messageId) {
86
+ return this.tryGetMessage(messageId) !== void 0;
87
+ }
88
+ addOrUpdateMessage(parentId, message) {
89
+ this.repository.addOrUpdateMessage(parentId, message);
90
+ this.exportedRepository = void 0;
91
+ }
92
+ switchToBranch(messageId) {
93
+ this.repository.switchToBranch(messageId);
94
+ this.exportedRepository = void 0;
95
+ }
96
+ resetRepositoryHead(messageId) {
97
+ this.repository.resetHead(messageId);
98
+ this.exportedRepository = void 0;
99
+ }
100
+ clearRepository() {
101
+ this.repository.clear();
102
+ this.exportedRepository = void 0;
103
+ }
104
+ updateMessage(messageId, updater) {
105
+ const item = this.tryGetMessage(messageId);
106
+ if (!item) return false;
107
+ const message = updater(item.message);
108
+ if (message === item.message) return false;
109
+ this.addOrUpdateMessage(item.parentId, message);
110
+ return true;
64
111
  }
65
112
  getTask() {
66
113
  return this.currentTask;
@@ -84,10 +131,7 @@ var A2AThreadRuntimeCore = class {
84
131
  const agentCardPromise = this.client.getAgentCard().catch(() => void 0);
85
132
  this._loadPromise = Promise.all([historyPromise, agentCardPromise]).then(([repo, agentCard]) => {
86
133
  if (agentCard) this.agentCardValue = agentCard;
87
- if (repo) {
88
- const messages = repo.messages.map((item) => item.message);
89
- this.applyExternalMessages(messages);
90
- }
134
+ if (repo) this.applyExternalMessageRepository(repo);
91
135
  }).catch((error) => {
92
136
  this.onError?.(error instanceof Error ? error : new Error(String(error)));
93
137
  }).finally(() => {
@@ -99,12 +143,12 @@ var A2AThreadRuntimeCore = class {
99
143
  }
100
144
  async append(message) {
101
145
  const startRun = message.startRun ?? message.role === "user";
102
- if (message.sourceId) this.messages = this.messages.filter((entry) => entry.id !== message.sourceId);
103
- this.resetHead(message.parentId);
104
146
  const threadMessage = fromThreadMessageLike(message, generateId(), FALLBACK_USER_STATUS);
105
- this.messages = [...this.messages, threadMessage];
147
+ const parentId = message.parentId === null ? null : message.parentId && this.hasMessage(message.parentId) ? message.parentId : this.repository.headId;
148
+ this.addOrUpdateMessage(parentId, threadMessage);
149
+ this.switchToBranch(threadMessage.id);
106
150
  this.notifyUpdate();
107
- this.recordHistoryEntry(message.parentId ?? null, threadMessage);
151
+ this.recordHistoryEntry(parentId, threadMessage);
108
152
  if (!startRun) return;
109
153
  await this.startRun(threadMessage);
110
154
  }
@@ -112,10 +156,9 @@ var A2AThreadRuntimeCore = class {
112
156
  await this.append(message);
113
157
  }
114
158
  async reload(parentId, _config = {}) {
115
- this.resetHead(parentId);
116
- this.notifyUpdate();
117
- for (let i = this.messages.length - 1; i >= 0; i--) if (this.messages[i].role === "user") {
118
- await this.startRun(this.messages[i]);
159
+ const messages = parentId === null ? [] : this.tryGetMessages(parentId) ?? this.getMessages();
160
+ for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") {
161
+ await this.startRun(messages[i]);
119
162
  return;
120
163
  }
121
164
  }
@@ -127,15 +170,101 @@ var A2AThreadRuntimeCore = class {
127
170
  this.currentTask = updated;
128
171
  } catch {}
129
172
  }
130
- applyExternalMessages(messages) {
173
+ appendLinearChain(messages) {
174
+ let parentId = null;
175
+ let lastId = null;
176
+ const seen = /* @__PURE__ */ new Set();
177
+ for (const message of messages) {
178
+ if (seen.has(message.id)) continue;
179
+ seen.add(message.id);
180
+ this.addOrUpdateMessage(parentId, message);
181
+ parentId = message.id;
182
+ lastId = message.id;
183
+ }
184
+ return lastId;
185
+ }
186
+ finalizeExternalApply() {
131
187
  this.assistantHistoryParents.clear();
132
- this.messages = [...messages];
133
188
  this.recordedHistoryIds.clear();
134
- for (const message of this.messages) this.recordedHistoryIds.add(message.id);
189
+ for (const { message } of this.getMessageRepository().messages) this.recordedHistoryIds.add(message.id);
135
190
  this.currentTask = void 0;
136
191
  this.currentArtifacts = [];
137
192
  this.notifyUpdate();
138
193
  }
194
+ applyExternalMessages(messages) {
195
+ if (messages.length === 0) this.clearRepository();
196
+ else {
197
+ let expectedParentId = null;
198
+ let lastAppliedId = null;
199
+ let hardReplace = false;
200
+ const seen = /* @__PURE__ */ new Set();
201
+ for (const message of messages) {
202
+ if (seen.has(message.id)) continue;
203
+ seen.add(message.id);
204
+ const existing = this.tryGetMessage(message.id);
205
+ if (existing && existing.parentId !== expectedParentId) {
206
+ hardReplace = true;
207
+ break;
208
+ }
209
+ this.addOrUpdateMessage(expectedParentId, message);
210
+ expectedParentId = message.id;
211
+ lastAppliedId = message.id;
212
+ }
213
+ if (hardReplace) {
214
+ this.clearRepository();
215
+ lastAppliedId = this.appendLinearChain(messages);
216
+ }
217
+ this.resetRepositoryHead(lastAppliedId);
218
+ }
219
+ this.finalizeExternalApply();
220
+ }
221
+ applyExternalMessageRepository(loaded) {
222
+ const headId = loaded.headId ?? loaded.messages.at(-1)?.message.id ?? null;
223
+ const ids = /* @__PURE__ */ new Set();
224
+ let degenerate = false;
225
+ for (const { message } of loaded.messages) {
226
+ if (ids.has(message.id)) {
227
+ degenerate = true;
228
+ break;
229
+ }
230
+ ids.add(message.id);
231
+ }
232
+ if (headId !== null && !ids.has(headId)) degenerate = true;
233
+ if (!degenerate) {
234
+ this.clearRepository();
235
+ let pending = [...loaded.messages];
236
+ const importedIds = /* @__PURE__ */ new Set();
237
+ while (pending.length > 0) {
238
+ const unresolved = [];
239
+ let progressed = false;
240
+ for (const item of pending) {
241
+ if (item.parentId !== null && !importedIds.has(item.parentId)) {
242
+ unresolved.push(item);
243
+ continue;
244
+ }
245
+ this.addOrUpdateMessage(item.parentId, item.message);
246
+ importedIds.add(item.message.id);
247
+ progressed = true;
248
+ }
249
+ if (!progressed) {
250
+ degenerate = true;
251
+ break;
252
+ }
253
+ pending = unresolved;
254
+ }
255
+ }
256
+ if (degenerate) {
257
+ this.clearRepository();
258
+ let previousId = null;
259
+ for (const { message } of loaded.messages) {
260
+ const existing = this.tryGetMessage(message.id);
261
+ this.addOrUpdateMessage(existing ? existing.parentId : previousId, message);
262
+ previousId = message.id;
263
+ }
264
+ this.resetRepositoryHead(previousId);
265
+ } else this.resetRepositoryHead(headId);
266
+ this.finalizeExternalApply();
267
+ }
139
268
  async startRun(userThreadMessage) {
140
269
  if (this.abortController) {
141
270
  this.abortController.abort();
@@ -145,7 +274,7 @@ var A2AThreadRuntimeCore = class {
145
274
  if (this.currentTask && isTerminalTaskState(this.currentTask.status.state)) this.currentTask = void 0;
146
275
  this.currentArtifacts = [];
147
276
  const assistantParentId = userThreadMessage.id;
148
- const assistantId = this.insertAssistantPlaceholder();
277
+ const assistantId = this.insertAssistantPlaceholder(assistantParentId);
149
278
  this.markPendingAssistantHistory(assistantId, assistantParentId);
150
279
  const abortController = new AbortController();
151
280
  this.abortController = abortController;
@@ -291,11 +420,8 @@ var A2AThreadRuntimeCore = class {
291
420
  threadMessageToA2AMessage(message) {
292
421
  const parts = [];
293
422
  if (message.role === "user") {
294
- for (const part of message.content) if (part.type === "text") parts.push({ text: part.text });
295
- else if (part.type === "image") parts.push({
296
- url: part.image,
297
- mediaType: "image/*"
298
- });
423
+ parts.push(...contentPartsToA2AParts(message.content));
424
+ for (const attachment of message.attachments ?? []) parts.push(...contentPartsToA2AParts(attachment.content ?? [], attachment.contentType));
299
425
  }
300
426
  const a2aMsg = {
301
427
  messageId: message.id,
@@ -306,7 +432,7 @@ var A2AThreadRuntimeCore = class {
306
432
  if (this.currentTask?.id && !isTerminalTaskState(this.currentTask.status.state)) a2aMsg.taskId = this.currentTask.id;
307
433
  return a2aMsg;
308
434
  }
309
- insertAssistantPlaceholder() {
435
+ insertAssistantPlaceholder(parentId) {
310
436
  const id = generateId();
311
437
  const assistant = {
312
438
  id,
@@ -322,13 +448,14 @@ var A2AThreadRuntimeCore = class {
322
448
  custom: {}
323
449
  }
324
450
  };
325
- this.messages = [...this.messages, assistant];
451
+ this.addOrUpdateMessage(parentId, assistant);
452
+ this.switchToBranch(id);
326
453
  this.notifyUpdate();
327
454
  return id;
328
455
  }
329
456
  updateAssistantContent(messageId, content) {
330
- this.messages = this.messages.map((message) => {
331
- if (message.id !== messageId || message.role !== "assistant") return message;
457
+ this.updateMessage(messageId, (message) => {
458
+ if (message.role !== "assistant") return message;
332
459
  return {
333
460
  ...message,
334
461
  content
@@ -336,22 +463,21 @@ var A2AThreadRuntimeCore = class {
336
463
  });
337
464
  }
338
465
  updateAssistantStatus(messageId, status) {
339
- let touched = false;
340
- this.messages = this.messages.map((message) => {
341
- if (message.id !== messageId || message.role !== "assistant") return message;
342
- touched = true;
466
+ if (this.updateMessage(messageId, (message) => {
467
+ if (message.role !== "assistant") return message;
343
468
  return {
344
469
  ...message,
345
470
  status
346
471
  };
347
- });
348
- if (touched) {
472
+ })) {
349
473
  this.notifyUpdate();
350
474
  if (status.type === "complete" || status.type === "incomplete") this.persistAssistantHistory(messageId);
351
475
  }
352
476
  }
353
477
  getAssistantStatus(messageId) {
354
- return this.messages.find((m) => m.id === messageId && m.role === "assistant")?.status;
478
+ const msg = this.tryGetMessage(messageId)?.message;
479
+ if (msg?.role !== "assistant") return void 0;
480
+ return msg.status;
355
481
  }
356
482
  setRunning(running) {
357
483
  this.isRunningFlag = running;
@@ -361,15 +487,6 @@ var A2AThreadRuntimeCore = class {
361
487
  if (this.abortController === controller) this.abortController = null;
362
488
  this.setRunning(false);
363
489
  }
364
- resetHead(parentId) {
365
- if (!parentId) {
366
- if (this.messages.length) this.messages = [];
367
- return;
368
- }
369
- const idx = this.messages.findIndex((message) => message.id === parentId);
370
- if (idx === -1) return;
371
- this.messages = this.messages.slice(0, idx + 1);
372
- }
373
490
  recordHistoryEntry(parentId, message) {
374
491
  this.appendHistoryItem(parentId, message);
375
492
  }
@@ -381,7 +498,7 @@ var A2AThreadRuntimeCore = class {
381
498
  if (!this.history) return;
382
499
  const parentId = this.assistantHistoryParents.get(messageId);
383
500
  if (parentId === void 0) return;
384
- const message = this.messages.find((m) => m.id === messageId);
501
+ const message = this.tryGetMessage(messageId)?.message;
385
502
  if (!message || message.role !== "assistant") return;
386
503
  if (message.status?.type !== "complete" && message.status?.type !== "incomplete") return;
387
504
  this.assistantHistoryParents.delete(messageId);
@@ -1 +1 @@
1
- {"version":3,"file":"A2AThreadRuntimeCore.js","names":[],"sources":["../src/A2AThreadRuntimeCore.ts"],"sourcesContent":["\"use client\";\n\nimport { generateId, fromThreadMessageLike } from \"@assistant-ui/core\";\nimport type {\n AppendMessage,\n AssistantRuntime,\n MessageStatus,\n ThreadAssistantMessage,\n ThreadHistoryAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport type { A2AClient } from \"./A2AClient\";\nimport type {\n A2AArtifact,\n A2AAgentCard,\n A2AMessage,\n A2APart,\n A2ASendMessageConfiguration,\n A2AStreamEvent,\n A2ATask,\n A2ATaskArtifactUpdateEvent,\n A2ATaskStatusUpdateEvent,\n} from \"./types\";\nimport {\n a2aMessageToContent,\n isTerminalTaskState,\n taskStateToMessageStatus,\n} from \"./conversions\";\n\nexport type A2AThreadRuntimeCoreOptions = {\n client: A2AClient;\n contextId?: string | undefined;\n configuration?: A2ASendMessageConfiguration | undefined;\n onError?: ((error: Error) => void) | undefined;\n onCancel?: (() => void) | undefined;\n onArtifactComplete?: ((artifact: A2AArtifact) => void) | undefined;\n history?: ThreadHistoryAdapter | undefined;\n notifyUpdate: () => void;\n};\n\nconst FALLBACK_USER_STATUS = {\n type: \"complete\",\n reason: \"unknown\",\n} as const;\n\nexport class A2AThreadRuntimeCore {\n private client: A2AClient;\n private contextId: string | undefined;\n private configuration: A2ASendMessageConfiguration | undefined;\n private onError: ((error: Error) => void) | undefined;\n private onCancel: (() => void) | undefined;\n private onArtifactComplete: ((artifact: A2AArtifact) => void) | undefined;\n private history: ThreadHistoryAdapter | undefined;\n private readonly notifyUpdate: () => void;\n\n private runtime: AssistantRuntime | undefined;\n private messages: ThreadMessage[] = [];\n private isRunningFlag = false;\n private abortController: AbortController | null = null;\n private pendingError: Error | null = null;\n\n // A2A-specific state\n private currentTask: A2ATask | undefined;\n private currentArtifacts: A2AArtifact[] = [];\n private agentCardValue: A2AAgentCard | undefined;\n\n // History tracking\n private readonly assistantHistoryParents = new Map<string, string | null>();\n private readonly recordedHistoryIds = new Set<string>();\n private _isLoading = false;\n private _loadPromise: Promise<void> | undefined;\n\n constructor(options: A2AThreadRuntimeCoreOptions) {\n this.client = options.client;\n this.contextId = options.contextId;\n this.configuration = options.configuration;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.onArtifactComplete = options.onArtifactComplete;\n this.history = options.history;\n this.notifyUpdate = options.notifyUpdate;\n }\n\n updateOptions(options: Omit<A2AThreadRuntimeCoreOptions, \"notifyUpdate\">) {\n this.client = options.client;\n this.contextId = options.contextId;\n this.configuration = options.configuration;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.onArtifactComplete = options.onArtifactComplete;\n this.history = options.history;\n }\n\n attachRuntime(runtime: AssistantRuntime) {\n this.runtime = runtime;\n }\n\n detachRuntime() {\n this.runtime = undefined;\n // Abort in-flight requests on unmount\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n }\n\n getRuntime(): AssistantRuntime | undefined {\n return this.runtime;\n }\n\n getMessages(): readonly ThreadMessage[] {\n return this.messages;\n }\n\n getTask(): A2ATask | undefined {\n return this.currentTask;\n }\n\n getArtifacts(): readonly A2AArtifact[] {\n return this.currentArtifacts;\n }\n\n getAgentCard(): A2AAgentCard | undefined {\n return this.agentCardValue;\n }\n\n isRunning(): boolean {\n return this.isRunningFlag;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n __internal_load(): Promise<void> {\n if (this._loadPromise) return this._loadPromise;\n\n this._isLoading = true;\n\n const historyPromise = this.history?.load() ?? Promise.resolve(null);\n const agentCardPromise = this.client.getAgentCard().catch(() => undefined);\n\n this._loadPromise = Promise.all([historyPromise, agentCardPromise])\n .then(([repo, agentCard]) => {\n if (agentCard) {\n this.agentCardValue = agentCard;\n }\n if (repo) {\n const messages = repo.messages.map((item) => item.message);\n this.applyExternalMessages(messages);\n }\n })\n .catch((error) => {\n this.onError?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n })\n .finally(() => {\n this._isLoading = false;\n this.notifyUpdate();\n });\n\n this.notifyUpdate();\n return this._loadPromise;\n }\n\n async append(message: AppendMessage): Promise<void> {\n const startRun = message.startRun ?? message.role === \"user\";\n if (message.sourceId) {\n this.messages = this.messages.filter(\n (entry) => entry.id !== message.sourceId,\n );\n }\n this.resetHead(message.parentId);\n\n const threadMessage = fromThreadMessageLike(\n message as any,\n generateId(),\n FALLBACK_USER_STATUS,\n );\n this.messages = [...this.messages, threadMessage];\n this.notifyUpdate();\n this.recordHistoryEntry(message.parentId ?? null, threadMessage);\n\n if (!startRun) return;\n await this.startRun(threadMessage);\n }\n\n async edit(message: AppendMessage): Promise<void> {\n await this.append(message);\n }\n\n async reload(\n parentId: string | null,\n _config: { runConfig?: Record<string, unknown> } = {},\n ): Promise<void> {\n this.resetHead(parentId);\n this.notifyUpdate();\n\n // Find the last user message to re-run\n for (let i = this.messages.length - 1; i >= 0; i--) {\n if (this.messages[i]!.role === \"user\") {\n await this.startRun(this.messages[i]!);\n return;\n }\n }\n }\n\n async cancel(): Promise<void> {\n if (!this.abortController) return;\n\n // Abort locally first so the stream stops immediately\n this.abortController.abort();\n\n // Then try to cancel the task on the server\n if (this.currentTask?.id) {\n try {\n const updated = await this.client.cancelTask(this.currentTask.id);\n this.currentTask = updated;\n } catch {\n // Server cancel failed; local abort already handled\n }\n }\n }\n\n applyExternalMessages(messages: readonly ThreadMessage[]): void {\n this.assistantHistoryParents.clear();\n this.messages = [...messages];\n this.recordedHistoryIds.clear();\n for (const message of this.messages) {\n this.recordedHistoryIds.add(message.id);\n }\n // Reset task-specific state to prevent leaking into new thread\n this.currentTask = undefined;\n this.currentArtifacts = [];\n this.notifyUpdate();\n }\n\n // --- Run logic ---\n\n private async startRun(userThreadMessage: ThreadMessage): Promise<void> {\n // Cancel any in-progress run before starting a new one\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n\n const a2aMessage = this.threadMessageToA2AMessage(userThreadMessage);\n\n // Clear task if previous task reached terminal state\n if (\n this.currentTask &&\n isTerminalTaskState(this.currentTask.status.state)\n ) {\n this.currentTask = undefined;\n }\n\n this.currentArtifacts = [];\n\n const assistantParentId = userThreadMessage.id;\n const assistantId = this.insertAssistantPlaceholder();\n this.markPendingAssistantHistory(assistantId, assistantParentId);\n\n const abortController = new AbortController();\n this.abortController = abortController;\n\n abortController.signal.addEventListener(\n \"abort\",\n () => {\n this.updateAssistantStatus(assistantId, {\n type: \"incomplete\",\n reason: \"cancelled\",\n });\n this.finishRun(abortController);\n this.onCancel?.();\n },\n { once: true },\n );\n\n this.setRunning(true);\n\n // Check if agent supports streaming; fall back to sync sendMessage if not\n const supportsStreaming =\n this.agentCardValue?.capabilities?.streaming !== false;\n\n try {\n if (supportsStreaming) {\n await this.runStreaming(a2aMessage, assistantId, abortController);\n } else {\n await this.runSync(a2aMessage, assistantId, abortController);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.updateAssistantStatus(assistantId, {\n type: \"incomplete\",\n reason: \"error\",\n });\n this.onError?.(err);\n this.pendingError = this.pendingError ?? err;\n }\n } finally {\n this.finishRun(abortController);\n }\n\n if (this.pendingError) {\n const err = this.pendingError;\n this.pendingError = null;\n throw err;\n }\n }\n\n private async runStreaming(\n a2aMessage: A2AMessage,\n assistantId: string,\n abortController: AbortController,\n ): Promise<void> {\n const stream = this.client.streamMessage(\n a2aMessage,\n this.configuration,\n undefined, // metadata\n abortController.signal,\n );\n\n for await (const event of stream) {\n if (abortController.signal.aborted) break;\n this.handleStreamEvent(assistantId, event);\n }\n\n if (!abortController.signal.aborted) {\n const lastStatus = this.getAssistantStatus(assistantId);\n if (lastStatus?.type === \"running\") {\n this.updateAssistantStatus(assistantId, {\n type: \"complete\",\n reason: \"stop\",\n });\n }\n }\n }\n\n private async runSync(\n a2aMessage: A2AMessage,\n assistantId: string,\n abortController: AbortController,\n ): Promise<void> {\n const result = await this.client.sendMessage(\n a2aMessage,\n this.configuration,\n undefined, // metadata\n abortController.signal,\n );\n\n if (abortController.signal.aborted) return;\n\n // Result is either A2ATask or A2AMessage\n if (\"id\" in result && \"status\" in result) {\n // It's a Task\n this.handleTaskSnapshot(assistantId, result as A2ATask);\n } else if (\"messageId\" in result && \"parts\" in result) {\n // It's a Message\n this.handleMessage(assistantId, result as A2AMessage);\n this.updateAssistantStatus(assistantId, {\n type: \"complete\",\n reason: \"stop\",\n });\n }\n }\n\n private handleStreamEvent(assistantId: string, event: A2AStreamEvent) {\n switch (event.type) {\n case \"statusUpdate\":\n this.handleStatusUpdate(assistantId, event.event);\n break;\n case \"artifactUpdate\":\n this.handleArtifactUpdate(event.event);\n break;\n case \"message\":\n this.handleMessage(assistantId, event.message);\n break;\n case \"task\":\n this.handleTaskSnapshot(assistantId, event.task);\n break;\n }\n }\n\n private handleStatusUpdate(\n assistantId: string,\n event: A2ATaskStatusUpdateEvent,\n ) {\n if (!this.currentTask) {\n this.currentTask = {\n id: event.taskId,\n contextId: event.contextId,\n status: event.status,\n };\n } else {\n this.currentTask = { ...this.currentTask, status: event.status };\n }\n\n if (event.contextId) {\n this.contextId = event.contextId;\n }\n\n if (event.status.message) {\n const content = a2aMessageToContent(event.status.message);\n this.updateAssistantContent(assistantId, content);\n }\n\n const status = taskStateToMessageStatus(event.status.state);\n this.updateAssistantStatus(assistantId, status);\n\n this.notifyUpdate();\n }\n\n private handleArtifactUpdate(event: A2ATaskArtifactUpdateEvent) {\n const { artifact, append, lastChunk } = event;\n const existingIdx = this.currentArtifacts.findIndex(\n (a) => a.artifactId === artifact.artifactId,\n );\n\n let updated: A2AArtifact;\n if (existingIdx >= 0 && append) {\n const existing = this.currentArtifacts[existingIdx]!;\n updated = {\n ...existing,\n parts: [...existing.parts, ...artifact.parts],\n };\n this.currentArtifacts = [\n ...this.currentArtifacts.slice(0, existingIdx),\n updated,\n ...this.currentArtifacts.slice(existingIdx + 1),\n ];\n } else if (existingIdx >= 0) {\n updated = artifact;\n this.currentArtifacts = [\n ...this.currentArtifacts.slice(0, existingIdx),\n updated,\n ...this.currentArtifacts.slice(existingIdx + 1),\n ];\n } else {\n updated = artifact;\n this.currentArtifacts = [...this.currentArtifacts, updated];\n }\n\n if (lastChunk) {\n this.onArtifactComplete?.(updated);\n }\n\n this.notifyUpdate();\n }\n\n private handleMessage(assistantId: string, message: A2AMessage) {\n if (message.role !== \"agent\") return;\n\n const content = a2aMessageToContent(message);\n this.updateAssistantContent(assistantId, content);\n this.notifyUpdate();\n }\n\n private handleTaskSnapshot(assistantId: string, task: A2ATask) {\n this.currentTask = task;\n\n if (task.contextId) {\n this.contextId = task.contextId;\n }\n if (task.artifacts) {\n this.currentArtifacts = task.artifacts;\n }\n\n if (task.status.message) {\n const content = a2aMessageToContent(task.status.message);\n this.updateAssistantContent(assistantId, content);\n }\n\n const status = taskStateToMessageStatus(task.status.state);\n this.updateAssistantStatus(assistantId, status);\n\n this.notifyUpdate();\n }\n\n // --- Message helpers ---\n\n private threadMessageToA2AMessage(message: ThreadMessage): A2AMessage {\n const parts: A2APart[] = [];\n\n if (message.role === \"user\") {\n for (const part of message.content) {\n if (part.type === \"text\") {\n parts.push({ text: part.text });\n } else if (part.type === \"image\") {\n parts.push({ url: part.image, mediaType: \"image/*\" });\n }\n }\n }\n\n const a2aMsg: A2AMessage = {\n messageId: message.id,\n role: \"user\",\n parts,\n };\n\n if (this.contextId) {\n a2aMsg.contextId = this.contextId;\n }\n // Only attach taskId if current task is NOT in terminal state\n if (\n this.currentTask?.id &&\n !isTerminalTaskState(this.currentTask.status.state)\n ) {\n a2aMsg.taskId = this.currentTask.id;\n }\n\n return a2aMsg;\n }\n\n private insertAssistantPlaceholder(): string {\n const id = generateId();\n const assistant: ThreadAssistantMessage = {\n id,\n role: \"assistant\",\n createdAt: new Date(),\n status: { type: \"running\" },\n content: [],\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n steps: [],\n custom: {},\n },\n };\n this.messages = [...this.messages, assistant];\n this.notifyUpdate();\n return id;\n }\n\n private updateAssistantContent(\n messageId: string,\n content: ThreadAssistantMessage[\"content\"],\n ) {\n this.messages = this.messages.map((message) => {\n if (message.id !== messageId || message.role !== \"assistant\")\n return message;\n return { ...message, content };\n });\n }\n\n private updateAssistantStatus(messageId: string, status: MessageStatus) {\n let touched = false;\n this.messages = this.messages.map((message) => {\n if (message.id !== messageId || message.role !== \"assistant\")\n return message;\n touched = true;\n return { ...message, status };\n });\n if (touched) {\n this.notifyUpdate();\n if (status.type === \"complete\" || status.type === \"incomplete\") {\n this.persistAssistantHistory(messageId);\n }\n }\n }\n\n private getAssistantStatus(messageId: string): MessageStatus | undefined {\n const msg = this.messages.find(\n (m) => m.id === messageId && m.role === \"assistant\",\n );\n return msg?.status;\n }\n\n // --- Lifecycle helpers ---\n\n private setRunning(running: boolean) {\n this.isRunningFlag = running;\n this.notifyUpdate();\n }\n\n private finishRun(controller: AbortController | null) {\n if (this.abortController === controller) {\n this.abortController = null;\n }\n this.setRunning(false);\n }\n\n private resetHead(parentId: string | null | undefined) {\n if (!parentId) {\n if (this.messages.length) {\n this.messages = [];\n }\n return;\n }\n const idx = this.messages.findIndex((message) => message.id === parentId);\n if (idx === -1) return;\n this.messages = this.messages.slice(0, idx + 1);\n }\n\n // --- History persistence ---\n\n private recordHistoryEntry(parentId: string | null, message: ThreadMessage) {\n this.appendHistoryItem(parentId, message);\n }\n\n private markPendingAssistantHistory(\n messageId: string,\n parentId: string | null,\n ) {\n if (!this.history) return;\n this.assistantHistoryParents.set(messageId, parentId);\n }\n\n private persistAssistantHistory(messageId: string) {\n if (!this.history) return;\n const parentId = this.assistantHistoryParents.get(messageId);\n if (parentId === undefined) return;\n const message = this.messages.find((m) => m.id === messageId);\n if (!message || message.role !== \"assistant\") return;\n if (\n message.status?.type !== \"complete\" &&\n message.status?.type !== \"incomplete\"\n )\n return;\n this.assistantHistoryParents.delete(messageId);\n this.appendHistoryItem(parentId, message);\n }\n\n private appendHistoryItem(parentId: string | null, message: ThreadMessage) {\n if (!this.history || this.recordedHistoryIds.has(message.id)) return;\n this.recordedHistoryIds.add(message.id);\n void this.history.append({ parentId, message }).catch(() => {\n this.recordedHistoryIds.delete(message.id);\n });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"A2AThreadRuntimeCore.js","names":[],"sources":["../src/A2AThreadRuntimeCore.ts"],"sourcesContent":["\"use client\";\n\nimport { generateId, fromThreadMessageLike } from \"@assistant-ui/core\";\nimport type {\n AppendMessage,\n AssistantRuntime,\n ExportedMessageRepository,\n MessageStatus,\n ThreadAssistantMessage,\n ThreadHistoryAdapter,\n ThreadMessage,\n} from \"@assistant-ui/core\";\nimport { MessageRepository } from \"@assistant-ui/core/internal\";\nimport type { A2AClient } from \"./A2AClient\";\nimport type {\n A2AArtifact,\n A2AAgentCard,\n A2AMessage,\n A2APart,\n A2ASendMessageConfiguration,\n A2AStreamEvent,\n A2ATask,\n A2ATaskArtifactUpdateEvent,\n A2ATaskStatusUpdateEvent,\n} from \"./types\";\nimport {\n a2aMessageToContent,\n contentPartsToA2AParts,\n isTerminalTaskState,\n taskStateToMessageStatus,\n} from \"./conversions\";\n\nexport type A2AThreadRuntimeCoreOptions = {\n client: A2AClient;\n contextId?: string | undefined;\n configuration?: A2ASendMessageConfiguration | undefined;\n onError?: ((error: Error) => void) | undefined;\n onCancel?: (() => void) | undefined;\n onArtifactComplete?: ((artifact: A2AArtifact) => void) | undefined;\n history?: ThreadHistoryAdapter | undefined;\n notifyUpdate: () => void;\n};\n\nconst FALLBACK_USER_STATUS = {\n type: \"complete\",\n reason: \"unknown\",\n} as const;\n\nexport class A2AThreadRuntimeCore {\n private client: A2AClient;\n private contextId: string | undefined;\n private configuration: A2ASendMessageConfiguration | undefined;\n private onError: ((error: Error) => void) | undefined;\n private onCancel: (() => void) | undefined;\n private onArtifactComplete: ((artifact: A2AArtifact) => void) | undefined;\n private history: ThreadHistoryAdapter | undefined;\n private readonly notifyUpdate: () => void;\n\n private runtime: AssistantRuntime | undefined;\n private readonly repository = new MessageRepository();\n private exportedRepository: ExportedMessageRepository | undefined;\n private isRunningFlag = false;\n private abortController: AbortController | null = null;\n private pendingError: Error | null = null;\n\n // A2A-specific state\n private currentTask: A2ATask | undefined;\n private currentArtifacts: A2AArtifact[] = [];\n private agentCardValue: A2AAgentCard | undefined;\n\n // History tracking\n private readonly assistantHistoryParents = new Map<string, string | null>();\n private readonly recordedHistoryIds = new Set<string>();\n private _isLoading = false;\n private _loadPromise: Promise<void> | undefined;\n\n constructor(options: A2AThreadRuntimeCoreOptions) {\n this.client = options.client;\n this.contextId = options.contextId;\n this.configuration = options.configuration;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.onArtifactComplete = options.onArtifactComplete;\n this.history = options.history;\n this.notifyUpdate = options.notifyUpdate;\n }\n\n updateOptions(options: Omit<A2AThreadRuntimeCoreOptions, \"notifyUpdate\">) {\n this.client = options.client;\n this.contextId = options.contextId;\n this.configuration = options.configuration;\n this.onError = options.onError;\n this.onCancel = options.onCancel;\n this.onArtifactComplete = options.onArtifactComplete;\n this.history = options.history;\n }\n\n attachRuntime(runtime: AssistantRuntime) {\n this.runtime = runtime;\n }\n\n detachRuntime() {\n this.runtime = undefined;\n // Abort in-flight requests on unmount\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n }\n\n getRuntime(): AssistantRuntime | undefined {\n return this.runtime;\n }\n\n getMessages(): readonly ThreadMessage[] {\n return this.repository.getMessages();\n }\n\n getMessageRepository(): ExportedMessageRepository {\n this.exportedRepository ??= this.repository.export();\n return this.exportedRepository;\n }\n\n private tryGetMessage(messageId: string) {\n try {\n return this.repository.getMessage(messageId);\n } catch {\n return undefined;\n }\n }\n\n private tryGetMessages(\n messageId: string,\n ): readonly ThreadMessage[] | undefined {\n try {\n return this.repository.getMessages(messageId);\n } catch {\n return undefined;\n }\n }\n\n private hasMessage(messageId: string): boolean {\n return this.tryGetMessage(messageId) !== undefined;\n }\n\n private addOrUpdateMessage(\n parentId: string | null,\n message: ThreadMessage,\n ): void {\n this.repository.addOrUpdateMessage(parentId, message);\n this.exportedRepository = undefined;\n }\n\n private switchToBranch(messageId: string): void {\n this.repository.switchToBranch(messageId);\n this.exportedRepository = undefined;\n }\n\n private resetRepositoryHead(messageId: string | null): void {\n this.repository.resetHead(messageId);\n this.exportedRepository = undefined;\n }\n\n private clearRepository(): void {\n this.repository.clear();\n this.exportedRepository = undefined;\n }\n\n private updateMessage(\n messageId: string,\n updater: (message: ThreadMessage) => ThreadMessage,\n ): boolean {\n const item = this.tryGetMessage(messageId);\n if (!item) return false;\n const message = updater(item.message);\n if (message === item.message) return false;\n this.addOrUpdateMessage(item.parentId, message);\n return true;\n }\n\n getTask(): A2ATask | undefined {\n return this.currentTask;\n }\n\n getArtifacts(): readonly A2AArtifact[] {\n return this.currentArtifacts;\n }\n\n getAgentCard(): A2AAgentCard | undefined {\n return this.agentCardValue;\n }\n\n isRunning(): boolean {\n return this.isRunningFlag;\n }\n\n get isLoading(): boolean {\n return this._isLoading;\n }\n\n __internal_load(): Promise<void> {\n if (this._loadPromise) return this._loadPromise;\n\n this._isLoading = true;\n\n const historyPromise = this.history?.load() ?? Promise.resolve(null);\n const agentCardPromise = this.client.getAgentCard().catch(() => undefined);\n\n this._loadPromise = Promise.all([historyPromise, agentCardPromise])\n .then(([repo, agentCard]) => {\n if (agentCard) {\n this.agentCardValue = agentCard;\n }\n if (repo) {\n this.applyExternalMessageRepository(repo);\n }\n })\n .catch((error) => {\n this.onError?.(\n error instanceof Error ? error : new Error(String(error)),\n );\n })\n .finally(() => {\n this._isLoading = false;\n this.notifyUpdate();\n });\n\n this.notifyUpdate();\n return this._loadPromise;\n }\n\n async append(message: AppendMessage): Promise<void> {\n const startRun = message.startRun ?? message.role === \"user\";\n\n const threadMessage = fromThreadMessageLike(\n message as any,\n generateId(),\n FALLBACK_USER_STATUS,\n );\n const parentId =\n message.parentId === null\n ? null\n : message.parentId && this.hasMessage(message.parentId)\n ? message.parentId\n : this.repository.headId;\n this.addOrUpdateMessage(parentId, threadMessage);\n this.switchToBranch(threadMessage.id);\n this.notifyUpdate();\n this.recordHistoryEntry(parentId, threadMessage);\n\n if (!startRun) return;\n await this.startRun(threadMessage);\n }\n\n async edit(message: AppendMessage): Promise<void> {\n await this.append(message);\n }\n\n async reload(\n parentId: string | null,\n _config: { runConfig?: Record<string, unknown> } = {},\n ): Promise<void> {\n const messages =\n parentId === null\n ? []\n : (this.tryGetMessages(parentId) ?? this.getMessages());\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i]!.role === \"user\") {\n await this.startRun(messages[i]!);\n return;\n }\n }\n }\n\n async cancel(): Promise<void> {\n if (!this.abortController) return;\n\n // Abort locally first so the stream stops immediately\n this.abortController.abort();\n\n // Then try to cancel the task on the server\n if (this.currentTask?.id) {\n try {\n const updated = await this.client.cancelTask(this.currentTask.id);\n this.currentTask = updated;\n } catch {\n // Server cancel failed; local abort already handled\n }\n }\n }\n\n private appendLinearChain(messages: readonly ThreadMessage[]): string | null {\n let parentId: string | null = null;\n let lastId: string | null = null;\n const seen = new Set<string>();\n\n for (const message of messages) {\n if (seen.has(message.id)) continue;\n seen.add(message.id);\n this.addOrUpdateMessage(parentId, message);\n parentId = message.id;\n lastId = message.id;\n }\n\n return lastId;\n }\n\n private finalizeExternalApply(): void {\n this.assistantHistoryParents.clear();\n this.recordedHistoryIds.clear();\n for (const { message } of this.getMessageRepository().messages) {\n this.recordedHistoryIds.add(message.id);\n }\n this.currentTask = undefined;\n this.currentArtifacts = [];\n this.notifyUpdate();\n }\n\n applyExternalMessages(messages: readonly ThreadMessage[]): void {\n if (messages.length === 0) {\n this.clearRepository();\n } else {\n let expectedParentId: string | null = null;\n let lastAppliedId: string | null = null;\n let hardReplace = false;\n const seen = new Set<string>();\n\n for (const message of messages) {\n if (seen.has(message.id)) continue;\n seen.add(message.id);\n const existing = this.tryGetMessage(message.id);\n if (existing && existing.parentId !== expectedParentId) {\n hardReplace = true;\n break;\n }\n this.addOrUpdateMessage(expectedParentId, message);\n expectedParentId = message.id;\n lastAppliedId = message.id;\n }\n\n if (hardReplace) {\n this.clearRepository();\n lastAppliedId = this.appendLinearChain(messages);\n }\n\n this.resetRepositoryHead(lastAppliedId);\n }\n\n this.finalizeExternalApply();\n }\n\n private applyExternalMessageRepository(\n loaded: ExportedMessageRepository,\n ): void {\n const headId = loaded.headId ?? loaded.messages.at(-1)?.message.id ?? null;\n const ids = new Set<string>();\n let degenerate = false;\n for (const { message } of loaded.messages) {\n if (ids.has(message.id)) {\n degenerate = true;\n break;\n }\n ids.add(message.id);\n }\n if (headId !== null && !ids.has(headId)) degenerate = true;\n\n if (!degenerate) {\n this.clearRepository();\n let pending = [...loaded.messages];\n const importedIds = new Set<string>();\n\n while (pending.length > 0) {\n const unresolved: typeof pending = [];\n let progressed = false;\n for (const item of pending) {\n if (item.parentId !== null && !importedIds.has(item.parentId)) {\n unresolved.push(item);\n continue;\n }\n this.addOrUpdateMessage(item.parentId, item.message);\n importedIds.add(item.message.id);\n progressed = true;\n }\n if (!progressed) {\n degenerate = true;\n break;\n }\n pending = unresolved;\n }\n }\n\n if (degenerate) {\n this.clearRepository();\n let previousId: string | null = null;\n for (const { message } of loaded.messages) {\n const existing = this.tryGetMessage(message.id);\n this.addOrUpdateMessage(\n existing ? existing.parentId : previousId,\n message,\n );\n previousId = message.id;\n }\n this.resetRepositoryHead(previousId);\n } else {\n this.resetRepositoryHead(headId);\n }\n\n this.finalizeExternalApply();\n }\n\n // --- Run logic ---\n\n private async startRun(userThreadMessage: ThreadMessage): Promise<void> {\n // Cancel any in-progress run before starting a new one\n if (this.abortController) {\n this.abortController.abort();\n this.abortController = null;\n }\n\n const a2aMessage = this.threadMessageToA2AMessage(userThreadMessage);\n\n // Clear task if previous task reached terminal state\n if (\n this.currentTask &&\n isTerminalTaskState(this.currentTask.status.state)\n ) {\n this.currentTask = undefined;\n }\n\n this.currentArtifacts = [];\n\n const assistantParentId = userThreadMessage.id;\n const assistantId = this.insertAssistantPlaceholder(assistantParentId);\n this.markPendingAssistantHistory(assistantId, assistantParentId);\n\n const abortController = new AbortController();\n this.abortController = abortController;\n\n abortController.signal.addEventListener(\n \"abort\",\n () => {\n this.updateAssistantStatus(assistantId, {\n type: \"incomplete\",\n reason: \"cancelled\",\n });\n this.finishRun(abortController);\n this.onCancel?.();\n },\n { once: true },\n );\n\n this.setRunning(true);\n\n // Check if agent supports streaming; fall back to sync sendMessage if not\n const supportsStreaming =\n this.agentCardValue?.capabilities?.streaming !== false;\n\n try {\n if (supportsStreaming) {\n await this.runStreaming(a2aMessage, assistantId, abortController);\n } else {\n await this.runSync(a2aMessage, assistantId, abortController);\n }\n } catch (error) {\n if (!abortController.signal.aborted) {\n const err = error instanceof Error ? error : new Error(String(error));\n this.updateAssistantStatus(assistantId, {\n type: \"incomplete\",\n reason: \"error\",\n });\n this.onError?.(err);\n this.pendingError = this.pendingError ?? err;\n }\n } finally {\n this.finishRun(abortController);\n }\n\n if (this.pendingError) {\n const err = this.pendingError;\n this.pendingError = null;\n throw err;\n }\n }\n\n private async runStreaming(\n a2aMessage: A2AMessage,\n assistantId: string,\n abortController: AbortController,\n ): Promise<void> {\n const stream = this.client.streamMessage(\n a2aMessage,\n this.configuration,\n undefined, // metadata\n abortController.signal,\n );\n\n for await (const event of stream) {\n if (abortController.signal.aborted) break;\n this.handleStreamEvent(assistantId, event);\n }\n\n if (!abortController.signal.aborted) {\n const lastStatus = this.getAssistantStatus(assistantId);\n if (lastStatus?.type === \"running\") {\n this.updateAssistantStatus(assistantId, {\n type: \"complete\",\n reason: \"stop\",\n });\n }\n }\n }\n\n private async runSync(\n a2aMessage: A2AMessage,\n assistantId: string,\n abortController: AbortController,\n ): Promise<void> {\n const result = await this.client.sendMessage(\n a2aMessage,\n this.configuration,\n undefined, // metadata\n abortController.signal,\n );\n\n if (abortController.signal.aborted) return;\n\n // Result is either A2ATask or A2AMessage\n if (\"id\" in result && \"status\" in result) {\n // It's a Task\n this.handleTaskSnapshot(assistantId, result as A2ATask);\n } else if (\"messageId\" in result && \"parts\" in result) {\n // It's a Message\n this.handleMessage(assistantId, result as A2AMessage);\n this.updateAssistantStatus(assistantId, {\n type: \"complete\",\n reason: \"stop\",\n });\n }\n }\n\n private handleStreamEvent(assistantId: string, event: A2AStreamEvent) {\n switch (event.type) {\n case \"statusUpdate\":\n this.handleStatusUpdate(assistantId, event.event);\n break;\n case \"artifactUpdate\":\n this.handleArtifactUpdate(event.event);\n break;\n case \"message\":\n this.handleMessage(assistantId, event.message);\n break;\n case \"task\":\n this.handleTaskSnapshot(assistantId, event.task);\n break;\n }\n }\n\n private handleStatusUpdate(\n assistantId: string,\n event: A2ATaskStatusUpdateEvent,\n ) {\n if (!this.currentTask) {\n this.currentTask = {\n id: event.taskId,\n contextId: event.contextId,\n status: event.status,\n };\n } else {\n this.currentTask = { ...this.currentTask, status: event.status };\n }\n\n if (event.contextId) {\n this.contextId = event.contextId;\n }\n\n if (event.status.message) {\n const content = a2aMessageToContent(event.status.message);\n this.updateAssistantContent(assistantId, content);\n }\n\n const status = taskStateToMessageStatus(event.status.state);\n this.updateAssistantStatus(assistantId, status);\n\n this.notifyUpdate();\n }\n\n private handleArtifactUpdate(event: A2ATaskArtifactUpdateEvent) {\n const { artifact, append, lastChunk } = event;\n const existingIdx = this.currentArtifacts.findIndex(\n (a) => a.artifactId === artifact.artifactId,\n );\n\n let updated: A2AArtifact;\n if (existingIdx >= 0 && append) {\n const existing = this.currentArtifacts[existingIdx]!;\n updated = {\n ...existing,\n parts: [...existing.parts, ...artifact.parts],\n };\n this.currentArtifacts = [\n ...this.currentArtifacts.slice(0, existingIdx),\n updated,\n ...this.currentArtifacts.slice(existingIdx + 1),\n ];\n } else if (existingIdx >= 0) {\n updated = artifact;\n this.currentArtifacts = [\n ...this.currentArtifacts.slice(0, existingIdx),\n updated,\n ...this.currentArtifacts.slice(existingIdx + 1),\n ];\n } else {\n updated = artifact;\n this.currentArtifacts = [...this.currentArtifacts, updated];\n }\n\n if (lastChunk) {\n this.onArtifactComplete?.(updated);\n }\n\n this.notifyUpdate();\n }\n\n private handleMessage(assistantId: string, message: A2AMessage) {\n if (message.role !== \"agent\") return;\n\n const content = a2aMessageToContent(message);\n this.updateAssistantContent(assistantId, content);\n this.notifyUpdate();\n }\n\n private handleTaskSnapshot(assistantId: string, task: A2ATask) {\n this.currentTask = task;\n\n if (task.contextId) {\n this.contextId = task.contextId;\n }\n if (task.artifacts) {\n this.currentArtifacts = task.artifacts;\n }\n\n if (task.status.message) {\n const content = a2aMessageToContent(task.status.message);\n this.updateAssistantContent(assistantId, content);\n }\n\n const status = taskStateToMessageStatus(task.status.state);\n this.updateAssistantStatus(assistantId, status);\n\n this.notifyUpdate();\n }\n\n // --- Message helpers ---\n\n private threadMessageToA2AMessage(message: ThreadMessage): A2AMessage {\n const parts: A2APart[] = [];\n\n if (message.role === \"user\") {\n parts.push(...contentPartsToA2AParts(message.content));\n for (const attachment of message.attachments ?? []) {\n parts.push(\n ...contentPartsToA2AParts(\n attachment.content ?? [],\n attachment.contentType,\n ),\n );\n }\n }\n\n const a2aMsg: A2AMessage = {\n messageId: message.id,\n role: \"user\",\n parts,\n };\n\n if (this.contextId) {\n a2aMsg.contextId = this.contextId;\n }\n // Only attach taskId if current task is NOT in terminal state\n if (\n this.currentTask?.id &&\n !isTerminalTaskState(this.currentTask.status.state)\n ) {\n a2aMsg.taskId = this.currentTask.id;\n }\n\n return a2aMsg;\n }\n\n private insertAssistantPlaceholder(parentId: string): string {\n const id = generateId();\n const assistant: ThreadAssistantMessage = {\n id,\n role: \"assistant\",\n createdAt: new Date(),\n status: { type: \"running\" },\n content: [],\n metadata: {\n unstable_state: null,\n unstable_annotations: [],\n unstable_data: [],\n steps: [],\n custom: {},\n },\n };\n this.addOrUpdateMessage(parentId, assistant);\n this.switchToBranch(id);\n this.notifyUpdate();\n return id;\n }\n\n private updateAssistantContent(\n messageId: string,\n content: ThreadAssistantMessage[\"content\"],\n ) {\n this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n return { ...message, content };\n });\n }\n\n private updateAssistantStatus(messageId: string, status: MessageStatus) {\n const touched = this.updateMessage(messageId, (message) => {\n if (message.role !== \"assistant\") return message;\n return { ...message, status };\n });\n if (touched) {\n this.notifyUpdate();\n if (status.type === \"complete\" || status.type === \"incomplete\") {\n this.persistAssistantHistory(messageId);\n }\n }\n }\n\n private getAssistantStatus(messageId: string): MessageStatus | undefined {\n const msg = this.tryGetMessage(messageId)?.message;\n if (msg?.role !== \"assistant\") return undefined;\n return msg.status;\n }\n\n // --- Lifecycle helpers ---\n\n private setRunning(running: boolean) {\n this.isRunningFlag = running;\n this.notifyUpdate();\n }\n\n private finishRun(controller: AbortController | null) {\n if (this.abortController === controller) {\n this.abortController = null;\n }\n this.setRunning(false);\n }\n\n // --- History persistence ---\n\n private recordHistoryEntry(parentId: string | null, message: ThreadMessage) {\n this.appendHistoryItem(parentId, message);\n }\n\n private markPendingAssistantHistory(\n messageId: string,\n parentId: string | null,\n ) {\n if (!this.history) return;\n this.assistantHistoryParents.set(messageId, parentId);\n }\n\n private persistAssistantHistory(messageId: string) {\n if (!this.history) return;\n const parentId = this.assistantHistoryParents.get(messageId);\n if (parentId === undefined) return;\n const message = this.tryGetMessage(messageId)?.message;\n if (!message || message.role !== \"assistant\") return;\n if (\n message.status?.type !== \"complete\" &&\n message.status?.type !== \"incomplete\"\n )\n return;\n this.assistantHistoryParents.delete(messageId);\n this.appendHistoryItem(parentId, message);\n }\n\n private appendHistoryItem(parentId: string | null, message: ThreadMessage) {\n if (!this.history || this.recordedHistoryIds.has(message.id)) return;\n this.recordedHistoryIds.add(message.id);\n void this.history.append({ parentId, message }).catch(() => {\n this.recordedHistoryIds.delete(message.id);\n });\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { A2AExtras } from "./types.js";
2
-
3
2
  //#region src/a2aExtras.d.ts
4
3
  declare const a2aExtras: import("@assistant-ui/core/internal").RuntimeExtras<A2AExtras>;
5
4
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"a2aExtras.d.ts","names":[],"sources":["../src/a2aExtras.ts"],"mappings":";;;cAGa,SAAA,wCAAS,aAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"a2aExtras.d.ts","names":[],"sources":["../src/a2aExtras.ts"],"mappings":";;cAGa,iDAAS,cAAA"}
@@ -1,6 +1,5 @@
1
1
  import { A2AMessage, A2APart, A2ATaskState } from "./types.js";
2
2
  import { MessageStatus, ThreadAssistantMessage } from "@assistant-ui/core";
3
-
4
3
  //#region src/conversions.d.ts
5
4
  declare function a2aPartToContent(part: A2APart): ThreadAssistantMessage["content"][number];
6
5
  declare function a2aPartsToContent(parts: A2APart[]): ThreadAssistantMessage["content"];
@@ -9,9 +8,12 @@ declare function isInterruptedTaskState(state: A2ATaskState): boolean;
9
8
  declare function taskStateToMessageStatus(state: A2ATaskState): MessageStatus;
10
9
  declare function contentPartsToA2AParts(content: ReadonlyArray<{
11
10
  type: string;
12
- text?: string;
13
- image?: string;
14
- }>): A2APart[];
11
+ text?: string | undefined;
12
+ image?: string | undefined;
13
+ data?: string | undefined;
14
+ mimeType?: string | undefined;
15
+ filename?: string | undefined;
16
+ }>, fallbackMimeType?: string): A2APart[];
15
17
  declare function a2aMessageToContent(message: A2AMessage): ThreadAssistantMessage["content"];
16
18
  //#endregion
17
19
  export { a2aMessageToContent, a2aPartToContent, a2aPartsToContent, contentPartsToA2AParts, isInterruptedTaskState, isTerminalTaskState, taskStateToMessageStatus };
@@ -1 +1 @@
1
- {"version":3,"file":"conversions.d.ts","names":[],"sources":["../src/conversions.ts"],"mappings":";;;;iBASgB,gBAAA,CACd,IAAA,EAAM,OAAA,GACL,sBAAsB;AAAA,iBA+BT,iBAAA,CACd,KAAA,EAAO,OAAA,KACN,sBAAsB;AAAA,iBAgBT,mBAAA,CAAoB,KAAmB,EAAZ,YAAY;AAAA,iBAIvC,sBAAA,CAAuB,KAAmB,EAAZ,YAAY;AAAA,iBAI1C,wBAAA,CAAyB,KAAA,EAAO,YAAA,GAAe,aAAa;AAAA,iBAoB5D,sBAAA,CACd,OAAA,EAAS,aAAA;EACP,IAAA;EACA,IAAA;EACA,KAAA;AAAA,KAED,OAAO;AAAA,iBAgBM,mBAAA,CACd,OAAA,EAAS,UAAA,GACR,sBAAsB"}
1
+ {"version":3,"file":"conversions.d.ts","names":[],"sources":["../src/conversions.ts"],"mappings":";;;iBAUgB,iBACd,MAAM,UACL;iBA+Ba,kBACd,OAAO,YACN;iBAgBa,oBAAoB,OAAO;iBAI3B,uBAAuB,OAAO;iBAI9B,yBAAyB,OAAO,eAAe;iBAoB/C,uBACd,SAAS;EACP;EACA;EACA;EACA;EACA;EACA;IAEF,4BACC;iBAqDa,oBACd,SAAS,aACR"}
@@ -1,4 +1,5 @@
1
1
  "use client";
2
+ import { httpUrlPattern, parseDataUrl } from "@assistant-ui/core/internal";
2
3
  //#region src/conversions.ts
3
4
  function isImageMediaType(mediaType) {
4
5
  return !!mediaType && mediaType.startsWith("image/");
@@ -78,16 +79,44 @@ function taskStateToMessageStatus(state) {
78
79
  default: return { type: "running" };
79
80
  }
80
81
  }
81
- function contentPartsToA2AParts(content) {
82
+ function contentPartsToA2AParts(content, fallbackMimeType) {
82
83
  return content.map((part) => {
83
84
  switch (part.type) {
84
85
  case "text": return { text: part.text ?? "" };
85
- case "image":
86
+ case "image": {
86
87
  if (!part.image) return null;
88
+ const parsed = parseDataUrl(part.image);
89
+ if (parsed) return {
90
+ raw: parsed.data,
91
+ mediaType: parsed.mimeType,
92
+ ...part.filename && { filename: part.filename }
93
+ };
87
94
  return {
88
95
  url: part.image,
89
- mediaType: "image/*"
96
+ ...fallbackMimeType && { mediaType: fallbackMimeType },
97
+ ...part.filename && { filename: part.filename }
98
+ };
99
+ }
100
+ case "file": {
101
+ if (!part.data) return null;
102
+ const declaredMimeType = part.mimeType || fallbackMimeType;
103
+ if (httpUrlPattern.test(part.data)) return {
104
+ url: part.data,
105
+ ...declaredMimeType && { mediaType: declaredMimeType },
106
+ ...part.filename && { filename: part.filename }
107
+ };
108
+ const parsed = parseDataUrl(part.data);
109
+ if (parsed) return {
110
+ raw: parsed.data,
111
+ mediaType: parsed.mimeType,
112
+ ...part.filename && { filename: part.filename }
113
+ };
114
+ return {
115
+ raw: part.data,
116
+ ...declaredMimeType && { mediaType: declaredMimeType },
117
+ ...part.filename && { filename: part.filename }
90
118
  };
119
+ }
91
120
  default: return null;
92
121
  }
93
122
  }).filter((p) => p !== null);
@@ -1 +1 @@
1
- {"version":3,"file":"conversions.js","names":[],"sources":["../src/conversions.ts"],"sourcesContent":["\"use client\";\n\nimport type { MessageStatus, ThreadAssistantMessage } from \"@assistant-ui/core\";\nimport type { A2AMessage, A2APart, A2ATaskState } from \"./types\";\n\nfunction isImageMediaType(mediaType?: string): boolean {\n return !!mediaType && mediaType.startsWith(\"image/\");\n}\n\nexport function a2aPartToContent(\n part: A2APart,\n): ThreadAssistantMessage[\"content\"][number] {\n if (part.text !== undefined) {\n return { type: \"text\", text: part.text };\n }\n if (part.url !== undefined) {\n if (isImageMediaType(part.mediaType)) {\n return { type: \"image\", image: part.url };\n }\n return {\n type: \"text\",\n text: part.filename ? `[${part.filename}](${part.url})` : part.url,\n };\n }\n if (part.raw !== undefined) {\n if (isImageMediaType(part.mediaType)) {\n return {\n type: \"image\",\n image: `data:${part.mediaType};base64,${part.raw}`,\n };\n }\n return {\n type: \"text\",\n text: `[File: ${part.filename ?? \"download\"}]`,\n };\n }\n if (part.data !== undefined) {\n return { type: \"text\", text: JSON.stringify(part.data, null, 2) };\n }\n return { type: \"text\", text: \"\" };\n}\n\nexport function a2aPartsToContent(\n parts: A2APart[],\n): ThreadAssistantMessage[\"content\"] {\n return parts.map(a2aPartToContent);\n}\n\nconst TERMINAL_STATES = new Set<A2ATaskState>([\n \"completed\",\n \"failed\",\n \"canceled\",\n \"rejected\",\n]);\n\nconst INTERRUPTED_STATES = new Set<A2ATaskState>([\n \"input_required\",\n \"auth_required\",\n]);\n\nexport function isTerminalTaskState(state: A2ATaskState): boolean {\n return TERMINAL_STATES.has(state);\n}\n\nexport function isInterruptedTaskState(state: A2ATaskState): boolean {\n return INTERRUPTED_STATES.has(state);\n}\n\nexport function taskStateToMessageStatus(state: A2ATaskState): MessageStatus {\n switch (state) {\n case \"submitted\":\n case \"working\":\n return { type: \"running\" };\n case \"completed\":\n return { type: \"complete\", reason: \"stop\" };\n case \"failed\":\n case \"rejected\":\n return { type: \"incomplete\", reason: \"error\" };\n case \"canceled\":\n return { type: \"incomplete\", reason: \"cancelled\" };\n case \"input_required\":\n case \"auth_required\":\n return { type: \"requires-action\", reason: \"interrupt\" };\n default:\n return { type: \"running\" };\n }\n}\n\nexport function contentPartsToA2AParts(\n content: ReadonlyArray<{\n type: string;\n text?: string;\n image?: string;\n }>,\n): A2APart[] {\n return content\n .map((part): A2APart | null => {\n switch (part.type) {\n case \"text\":\n return { text: part.text ?? \"\" };\n case \"image\":\n if (!part.image) return null;\n return { url: part.image, mediaType: \"image/*\" };\n default:\n return null;\n }\n })\n .filter((p): p is A2APart => p !== null);\n}\n\nexport function a2aMessageToContent(\n message: A2AMessage,\n): ThreadAssistantMessage[\"content\"] {\n return a2aPartsToContent(message.parts);\n}\n"],"mappings":";;AAKA,SAAS,iBAAiB,WAA6B;CACrD,OAAO,CAAC,CAAC,aAAa,UAAU,WAAW,QAAQ;AACrD;AAEA,SAAgB,iBACd,MAC2C;CAC3C,IAAI,KAAK,SAAS,KAAA,GAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK;CAAK;CAEzC,IAAI,KAAK,QAAQ,KAAA,GAAW;EAC1B,IAAI,iBAAiB,KAAK,SAAS,GACjC,OAAO;GAAE,MAAM;GAAS,OAAO,KAAK;EAAI;EAE1C,OAAO;GACL,MAAM;GACN,MAAM,KAAK,WAAW,IAAI,KAAK,SAAS,IAAI,KAAK,IAAI,KAAK,KAAK;EACjE;CACF;CACA,IAAI,KAAK,QAAQ,KAAA,GAAW;EAC1B,IAAI,iBAAiB,KAAK,SAAS,GACjC,OAAO;GACL,MAAM;GACN,OAAO,QAAQ,KAAK,UAAU,UAAU,KAAK;EAC/C;EAEF,OAAO;GACL,MAAM;GACN,MAAM,UAAU,KAAK,YAAY,WAAW;EAC9C;CACF;CACA,IAAI,KAAK,SAAS,KAAA,GAChB,OAAO;EAAE,MAAM;EAAQ,MAAM,KAAK,UAAU,KAAK,MAAM,MAAM,CAAC;CAAE;CAElE,OAAO;EAAE,MAAM;EAAQ,MAAM;CAAG;AAClC;AAEA,SAAgB,kBACd,OACmC;CACnC,OAAO,MAAM,IAAI,gBAAgB;AACnC;AAEA,MAAM,kCAAkB,IAAI,IAAkB;CAC5C;CACA;CACA;CACA;AACF,CAAC;AAED,MAAM,qCAAqB,IAAI,IAAkB,CAC/C,kBACA,eACF,CAAC;AAED,SAAgB,oBAAoB,OAA8B;CAChE,OAAO,gBAAgB,IAAI,KAAK;AAClC;AAEA,SAAgB,uBAAuB,OAA8B;CACnE,OAAO,mBAAmB,IAAI,KAAK;AACrC;AAEA,SAAgB,yBAAyB,OAAoC;CAC3E,QAAQ,OAAR;EACE,KAAK;EACL,KAAK,WACH,OAAO,EAAE,MAAM,UAAU;EAC3B,KAAK,aACH,OAAO;GAAE,MAAM;GAAY,QAAQ;EAAO;EAC5C,KAAK;EACL,KAAK,YACH,OAAO;GAAE,MAAM;GAAc,QAAQ;EAAQ;EAC/C,KAAK,YACH,OAAO;GAAE,MAAM;GAAc,QAAQ;EAAY;EACnD,KAAK;EACL,KAAK,iBACH,OAAO;GAAE,MAAM;GAAmB,QAAQ;EAAY;EACxD,SACE,OAAO,EAAE,MAAM,UAAU;CAC7B;AACF;AAEA,SAAgB,uBACd,SAKW;CACX,OAAO,QACJ,KAAK,SAAyB;EAC7B,QAAQ,KAAK,MAAb;GACE,KAAK,QACH,OAAO,EAAE,MAAM,KAAK,QAAQ,GAAG;GACjC,KAAK;IACH,IAAI,CAAC,KAAK,OAAO,OAAO;IACxB,OAAO;KAAE,KAAK,KAAK;KAAO,WAAW;IAAU;GACjD,SACE,OAAO;EACX;CACF,CAAC,CAAC,CACD,QAAQ,MAAoB,MAAM,IAAI;AAC3C;AAEA,SAAgB,oBACd,SACmC;CACnC,OAAO,kBAAkB,QAAQ,KAAK;AACxC"}
1
+ {"version":3,"file":"conversions.js","names":[],"sources":["../src/conversions.ts"],"sourcesContent":["\"use client\";\n\nimport type { MessageStatus, ThreadAssistantMessage } from \"@assistant-ui/core\";\nimport { httpUrlPattern, parseDataUrl } from \"@assistant-ui/core/internal\";\nimport type { A2AMessage, A2APart, A2ATaskState } from \"./types\";\n\nfunction isImageMediaType(mediaType?: string): boolean {\n return !!mediaType && mediaType.startsWith(\"image/\");\n}\n\nexport function a2aPartToContent(\n part: A2APart,\n): ThreadAssistantMessage[\"content\"][number] {\n if (part.text !== undefined) {\n return { type: \"text\", text: part.text };\n }\n if (part.url !== undefined) {\n if (isImageMediaType(part.mediaType)) {\n return { type: \"image\", image: part.url };\n }\n return {\n type: \"text\",\n text: part.filename ? `[${part.filename}](${part.url})` : part.url,\n };\n }\n if (part.raw !== undefined) {\n if (isImageMediaType(part.mediaType)) {\n return {\n type: \"image\",\n image: `data:${part.mediaType};base64,${part.raw}`,\n };\n }\n return {\n type: \"text\",\n text: `[File: ${part.filename ?? \"download\"}]`,\n };\n }\n if (part.data !== undefined) {\n return { type: \"text\", text: JSON.stringify(part.data, null, 2) };\n }\n return { type: \"text\", text: \"\" };\n}\n\nexport function a2aPartsToContent(\n parts: A2APart[],\n): ThreadAssistantMessage[\"content\"] {\n return parts.map(a2aPartToContent);\n}\n\nconst TERMINAL_STATES = new Set<A2ATaskState>([\n \"completed\",\n \"failed\",\n \"canceled\",\n \"rejected\",\n]);\n\nconst INTERRUPTED_STATES = new Set<A2ATaskState>([\n \"input_required\",\n \"auth_required\",\n]);\n\nexport function isTerminalTaskState(state: A2ATaskState): boolean {\n return TERMINAL_STATES.has(state);\n}\n\nexport function isInterruptedTaskState(state: A2ATaskState): boolean {\n return INTERRUPTED_STATES.has(state);\n}\n\nexport function taskStateToMessageStatus(state: A2ATaskState): MessageStatus {\n switch (state) {\n case \"submitted\":\n case \"working\":\n return { type: \"running\" };\n case \"completed\":\n return { type: \"complete\", reason: \"stop\" };\n case \"failed\":\n case \"rejected\":\n return { type: \"incomplete\", reason: \"error\" };\n case \"canceled\":\n return { type: \"incomplete\", reason: \"cancelled\" };\n case \"input_required\":\n case \"auth_required\":\n return { type: \"requires-action\", reason: \"interrupt\" };\n default:\n return { type: \"running\" };\n }\n}\n\nexport function contentPartsToA2AParts(\n content: ReadonlyArray<{\n type: string;\n text?: string | undefined;\n image?: string | undefined;\n data?: string | undefined;\n mimeType?: string | undefined;\n filename?: string | undefined;\n }>,\n fallbackMimeType?: string,\n): A2APart[] {\n return content\n .map((part): A2APart | null => {\n switch (part.type) {\n case \"text\":\n return { text: part.text ?? \"\" };\n case \"image\": {\n if (!part.image) return null;\n const parsed = parseDataUrl(part.image);\n if (parsed) {\n return {\n raw: parsed.data,\n mediaType: parsed.mimeType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n return {\n url: part.image,\n ...(fallbackMimeType && { mediaType: fallbackMimeType }),\n ...(part.filename && { filename: part.filename }),\n };\n }\n case \"file\": {\n if (!part.data) return null;\n const declaredMimeType = part.mimeType || fallbackMimeType;\n if (httpUrlPattern.test(part.data)) {\n return {\n url: part.data,\n ...(declaredMimeType && { mediaType: declaredMimeType }),\n ...(part.filename && { filename: part.filename }),\n };\n }\n const parsed = parseDataUrl(part.data);\n if (parsed) {\n return {\n raw: parsed.data,\n mediaType: parsed.mimeType,\n ...(part.filename && { filename: part.filename }),\n };\n }\n return {\n raw: part.data,\n ...(declaredMimeType && { mediaType: declaredMimeType }),\n ...(part.filename && { filename: part.filename }),\n };\n }\n default:\n return null;\n }\n })\n .filter((p): p is A2APart => p !== null);\n}\n\nexport function a2aMessageToContent(\n message: A2AMessage,\n): ThreadAssistantMessage[\"content\"] {\n return a2aPartsToContent(message.parts);\n}\n"],"mappings":"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"}
package/dist/hooks.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import { A2AAgentCard, A2AArtifact, A2ATask } from "./types.js";
2
-
3
2
  //#region src/hooks.d.ts
4
3
  /** The current A2A task, if a run is in progress. */
5
4
  declare const useA2ATask: () => A2ATask | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;;cAKa,UAAA,QAA+C,OAArC;;cAGV,eAAA,iBAAyD,WAA1C;;cAGf,eAAA,QAAyD,YAA1C"}
1
+ {"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":";;;cAKa,kBAAA;;cAGA,gCAAA;;cAGA,uBAAA"}