@assistant-ui/react-ag-ui 0.1.0 → 0.1.2
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/README.md +2 -0
- package/dist/agUiExtras.js +1 -2
- package/dist/hooks.js +1 -2
- package/dist/runtime/AgUiThreadController.d.ts +11 -0
- package/dist/runtime/AgUiThreadController.d.ts.map +1 -1
- package/dist/runtime/AgUiThreadController.js +565 -89
- package/dist/runtime/AgUiThreadController.js.map +1 -1
- package/dist/runtime/adapter/conversions.d.ts +9 -1
- package/dist/runtime/adapter/conversions.d.ts.map +1 -1
- package/dist/runtime/adapter/conversions.js +194 -12
- package/dist/runtime/adapter/conversions.js.map +1 -1
- package/dist/runtime/adapter/replay-content.d.ts +9 -0
- package/dist/runtime/adapter/replay-content.d.ts.map +1 -0
- package/dist/runtime/adapter/replay-content.js +185 -0
- package/dist/runtime/adapter/replay-content.js.map +1 -0
- package/dist/runtime/adapter/run-aggregator.d.ts +1 -0
- package/dist/runtime/adapter/run-aggregator.d.ts.map +1 -1
- package/dist/runtime/adapter/run-aggregator.js +35 -14
- package/dist/runtime/adapter/run-aggregator.js.map +1 -1
- package/dist/runtime/adapter/subscriber.d.ts +0 -1
- package/dist/runtime/adapter/subscriber.d.ts.map +1 -1
- package/dist/runtime/adapter/subscriber.js +2 -10
- package/dist/runtime/adapter/subscriber.js.map +1 -1
- package/dist/runtime/adapter/tool-approval.d.ts +2 -0
- package/dist/runtime/adapter/tool-approval.d.ts.map +1 -1
- package/dist/runtime/adapter/tool-approval.js +23 -6
- package/dist/runtime/adapter/tool-approval.js.map +1 -1
- package/dist/runtime/agUiThreadState.d.ts +1 -1
- package/dist/runtime/agUiThreadState.d.ts.map +1 -1
- package/dist/runtime/agUiThreadState.js +3 -4
- package/dist/runtime/agUiThreadState.js.map +1 -1
- package/dist/runtime/event-parser.d.ts.map +1 -1
- package/dist/runtime/event-parser.js +2 -2
- package/dist/runtime/event-parser.js.map +1 -1
- package/dist/runtime/interrupt-internals.js +1 -2
- package/dist/runtime/logger.js +1 -2
- package/dist/runtime/mcp-tool-result.js +1 -2
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/runtime/types.js +3 -3
- package/dist/runtime/types.js.map +1 -1
- package/dist/useAgUiRuntime.js +1 -2
- package/package.json +6 -6
- package/src/runtime/AgUiThreadController.deferred-results.test.ts +548 -0
- package/src/runtime/AgUiThreadController.disconnect.test.ts +914 -0
- package/src/runtime/AgUiThreadController.interrupt-history.test.ts +392 -0
- package/src/runtime/AgUiThreadController.replay.test.ts +3939 -0
- package/src/runtime/AgUiThreadController.snapshot-head-move.test.ts +167 -0
- package/src/runtime/AgUiThreadController.subagent-snapshot.test.ts +854 -0
- package/src/runtime/AgUiThreadController.test.ts +119 -0
- package/src/runtime/AgUiThreadController.ts +1184 -136
- package/src/runtime/adapter/conversions.content.test.ts +242 -1
- package/src/runtime/adapter/conversions.subagent-messages.test.ts +550 -0
- package/src/runtime/adapter/conversions.ts +349 -28
- package/src/runtime/adapter/replay-content.test.ts +235 -0
- package/src/runtime/adapter/replay-content.ts +306 -0
- package/src/runtime/adapter/run-aggregator.metadata.test.ts +151 -0
- package/src/runtime/adapter/run-aggregator.ts +52 -9
- package/src/runtime/adapter/subscriber.test.ts +1 -1
- package/src/runtime/adapter/subscriber.ts +1 -6
- package/src/runtime/adapter/tool-approval.ts +41 -3
- package/src/runtime/agUiThreadState.test.ts +21 -2
- package/src/runtime/agUiThreadState.ts +12 -3
- package/src/runtime/event-parser.ts +3 -0
- package/src/runtime/types.ts +5 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ContentPart, RunAgentParameters } from "@ag-ui/client";
|
|
2
|
-
import type { ThreadMessageLike as CoreThreadMessageLike } from "@assistant-ui/core";
|
|
2
|
+
import type { ThreadMessageLike as CoreThreadMessageLike, PartProviderMetadata } from "@assistant-ui/core";
|
|
3
3
|
import { type Tool } from "assistant-stream";
|
|
4
4
|
type AttachmentLike = {
|
|
5
5
|
name?: string | undefined;
|
|
@@ -57,6 +57,7 @@ export type AgUiMessage = {
|
|
|
57
57
|
error?: string;
|
|
58
58
|
metadata?: Record<string, unknown>;
|
|
59
59
|
};
|
|
60
|
+
export declare function withAgUiPartMessageMetadata(providerMetadata: PartProviderMetadata | undefined, messageMetadata: Record<string, unknown> | undefined): PartProviderMetadata;
|
|
60
61
|
export type FromAgUiMessagesOptions = {
|
|
61
62
|
/**
|
|
62
63
|
* Whether to convert `reasoning` messages into visible reasoning parts.
|
|
@@ -65,6 +66,13 @@ export type FromAgUiMessagesOptions = {
|
|
|
65
66
|
showThinking?: boolean;
|
|
66
67
|
};
|
|
67
68
|
export declare function fromAgUiMessages(messages: readonly unknown[], options?: FromAgUiMessagesOptions): CoreThreadMessageLike[];
|
|
69
|
+
/**
|
|
70
|
+
* Converts AG-UI messages, nesting each subagent run's messages under the tool
|
|
71
|
+
* call `SUBAGENT_STARTED.parentToolCallId` announced for it. A message's
|
|
72
|
+
* `subagentRunId` names its run; a run with no announced spawning call in
|
|
73
|
+
* `messages` stays in the parent thread.
|
|
74
|
+
*/
|
|
75
|
+
export declare function fromAgUiSnapshotMessages(messages: readonly unknown[], options?: FromAgUiMessagesOptions, subagentParentToolCallIds?: ReadonlyMap<string, string | undefined>): CoreThreadMessageLike[];
|
|
68
76
|
export declare function toAgUiMessages(messages: readonly ThreadMessageLike[]): AgUiMessage[];
|
|
69
77
|
type AgUiTool = NonNullable<RunAgentParameters["tools"]>[number];
|
|
70
78
|
export declare function toAgUiTools(tools: Record<string, Tool> | undefined): AgUiTool[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversions.d.ts","sourceRoot":"","sources":["../../../src/runtime/adapter/conversions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,WAAW,EAEX,kBAAkB,EACnB,MAAM,eAAe,CAAC;AAEvB,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"conversions.d.ts","sourceRoot":"","sources":["../../../src/runtime/adapter/conversions.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import { parseMcpToolCallResult, readMcpAppResourceUri, toolContentText } from "../mcp-tool-result.js";
|
|
3
3
|
import { AG_UI_METADATA_NAMESPACE } from "../types.js";
|
|
4
4
|
import { projectAgUiToolApprovals } from "./tool-approval.js";
|
|
5
|
-
import { generateId } from "@assistant-ui/core";
|
|
5
|
+
import { fromThreadMessageLike, generateId } from "@assistant-ui/core";
|
|
6
6
|
import { getAutoStatus, parseDataUrl, resolveFilePartSource, resolveImageMediaType, walkToolCallTree } from "@assistant-ui/core/internal";
|
|
7
7
|
import { applyA2uiOperations, surfaceToPresentToolCall } from "@assistant-ui/generative-ui/a2ui";
|
|
8
8
|
import { toToolsJSONSchema } from "assistant-stream";
|
|
9
|
-
|
|
9
|
+
// src/runtime/adapter/conversions.ts
|
|
10
10
|
const isObject = (value) => typeof value === "object" && value !== null;
|
|
11
11
|
const getString = (record, key) => {
|
|
12
12
|
const value = record[key];
|
|
@@ -63,11 +63,15 @@ function withAgUiPartMessageMetadata(providerMetadata, messageMetadata) {
|
|
|
63
63
|
if (!messageMetadata) return providerMetadata ?? {};
|
|
64
64
|
const existing = providerMetadata ?? {};
|
|
65
65
|
const namespaced = isObject(existing["agui"]) ? existing[AG_UI_METADATA_NAMESPACE] : {};
|
|
66
|
+
const previousMessageMetadata = isObject(namespaced.messageMetadata) ? namespaced.messageMetadata : {};
|
|
66
67
|
return {
|
|
67
68
|
...existing,
|
|
68
69
|
[AG_UI_METADATA_NAMESPACE]: {
|
|
69
70
|
...namespaced,
|
|
70
|
-
messageMetadata
|
|
71
|
+
messageMetadata: {
|
|
72
|
+
...previousMessageMetadata,
|
|
73
|
+
...messageMetadata
|
|
74
|
+
}
|
|
71
75
|
}
|
|
72
76
|
};
|
|
73
77
|
}
|
|
@@ -141,6 +145,11 @@ function mediaTypeForMime(mimeType) {
|
|
|
141
145
|
return "document";
|
|
142
146
|
}
|
|
143
147
|
function buildPartSource(value, declaredMimeType, sourceType) {
|
|
148
|
+
if (sourceType === "id") return {
|
|
149
|
+
type: "file",
|
|
150
|
+
value,
|
|
151
|
+
...declaredMimeType !== void 0 && { mimeType: declaredMimeType }
|
|
152
|
+
};
|
|
144
153
|
const source = resolveFilePartSource({
|
|
145
154
|
data: value,
|
|
146
155
|
mimeType: declaredMimeType ?? "application/octet-stream",
|
|
@@ -245,6 +254,11 @@ function partSourceToString(value) {
|
|
|
245
254
|
isUrl: true,
|
|
246
255
|
...mimeType !== void 0 && { mimeType }
|
|
247
256
|
};
|
|
257
|
+
if (type === "file") return {
|
|
258
|
+
value: sourceValue,
|
|
259
|
+
isId: true,
|
|
260
|
+
...mimeType !== void 0 && { mimeType }
|
|
261
|
+
};
|
|
248
262
|
if (type === "data") {
|
|
249
263
|
const resolvedMimeType = mimeType ?? "application/octet-stream";
|
|
250
264
|
return {
|
|
@@ -298,11 +312,12 @@ function toUserContentLayout(content) {
|
|
|
298
312
|
}
|
|
299
313
|
const part = normalizeInputPart(rawPart);
|
|
300
314
|
if (!part || !mediaInputTypes.has(getString(part, "type") ?? "")) continue;
|
|
301
|
-
if (
|
|
302
|
-
|
|
315
|
+
if (!partSourceToString(part.source)) continue;
|
|
316
|
+
if (isObject(part.source) && part.source.type === "file") fileSourceParts.push({
|
|
317
|
+
index: mediaIndex,
|
|
303
318
|
part
|
|
304
319
|
});
|
|
305
|
-
|
|
320
|
+
mediaIndex++;
|
|
306
321
|
}
|
|
307
322
|
return {
|
|
308
323
|
fileSourceParts,
|
|
@@ -322,7 +337,7 @@ function toSnapshotAttachments(content) {
|
|
|
322
337
|
if (!source) continue;
|
|
323
338
|
const { filename, providerMetadata } = readPartMetadata(part.metadata);
|
|
324
339
|
const id = attachments.length.toString();
|
|
325
|
-
if (type === "image") {
|
|
340
|
+
if (type === "image" && !source.isId) {
|
|
326
341
|
attachments.push({
|
|
327
342
|
id,
|
|
328
343
|
type: "image",
|
|
@@ -350,6 +365,7 @@ function toSnapshotAttachments(content) {
|
|
|
350
365
|
data: source.value,
|
|
351
366
|
mimeType,
|
|
352
367
|
...source.isUrl && { sourceType: "url" },
|
|
368
|
+
...source.isId && { sourceType: "id" },
|
|
353
369
|
...filename !== void 0 && { filename },
|
|
354
370
|
...providerMetadata && { providerMetadata }
|
|
355
371
|
}]
|
|
@@ -398,10 +414,16 @@ function buildUserContent(message) {
|
|
|
398
414
|
const restoresText = textSlots.length > 0 && textSlots.map(({ part }) => part.text).join("\n") === mergedText;
|
|
399
415
|
const fileSourceSlots = readContentSlots(namespaced.fileSourceParts).flatMap(({ index, entry: { part } }) => isObject(part) && mediaInputTypes.has(getString(part, "type") ?? "") && isObject(part.source) && part.source.type === "file" && typeof part.source.value === "string" ? [{
|
|
400
416
|
index,
|
|
401
|
-
part
|
|
417
|
+
part,
|
|
418
|
+
value: part.source.value
|
|
402
419
|
}] : []);
|
|
403
420
|
const ordered = restoresText ? converted.filter((part) => part.type !== "text") : converted;
|
|
404
|
-
for (const { index, part } of fileSourceSlots.sort((a, b) => a.index - b.index)) {
|
|
421
|
+
for (const { index, part, value } of fileSourceSlots.sort((a, b) => a.index - b.index)) {
|
|
422
|
+
const attached = ordered.findIndex((contentPart) => contentPart.type !== "text" && contentPart.source.type === "file" && contentPart.source.value === value && !fileSourceSlots.some((slot) => slot.part === contentPart));
|
|
423
|
+
if (attached !== -1) {
|
|
424
|
+
ordered[attached] = part;
|
|
425
|
+
continue;
|
|
426
|
+
}
|
|
405
427
|
const mediaPositions = ordered.flatMap((contentPart, position) => contentPart.type !== "text" ? [position] : []);
|
|
406
428
|
ordered.splice(mediaPositions[index] ?? ordered.length, 0, part);
|
|
407
429
|
}
|
|
@@ -643,7 +665,160 @@ function foldTurnRecords(previous, message) {
|
|
|
643
665
|
...Object.keys(metadata).length > 0 ? { metadata } : {}
|
|
644
666
|
};
|
|
645
667
|
}
|
|
668
|
+
const readSubagentRunId = (record) => {
|
|
669
|
+
const runId = getString(record, "subagentRunId");
|
|
670
|
+
return runId?.trim() ? runId : void 0;
|
|
671
|
+
};
|
|
672
|
+
const readToolCallIds = (record) => extractAssistantToolCalls(record).flatMap((part) => part.toolCallId ? [part.toolCallId] : []);
|
|
646
673
|
function fromAgUiMessages(messages, options) {
|
|
674
|
+
return fromAgUiSnapshotMessages(messages, options);
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* Converts AG-UI messages, nesting each subagent run's messages under the tool
|
|
678
|
+
* call `SUBAGENT_STARTED.parentToolCallId` announced for it. A message's
|
|
679
|
+
* `subagentRunId` names its run; a run with no announced spawning call in
|
|
680
|
+
* `messages` stays in the parent thread.
|
|
681
|
+
*/
|
|
682
|
+
function fromAgUiSnapshotMessages(messages, options, subagentParentToolCallIds) {
|
|
683
|
+
const records = messages.filter(isObject);
|
|
684
|
+
const callOwners = /* @__PURE__ */ new Map();
|
|
685
|
+
for (const record of records) {
|
|
686
|
+
if (getString(record, "role") !== "assistant") continue;
|
|
687
|
+
for (const toolCallId of readToolCallIds(record)) callOwners.set(toolCallId, readSubagentRunId(record));
|
|
688
|
+
}
|
|
689
|
+
const spawningCalls = /* @__PURE__ */ new Map();
|
|
690
|
+
for (const record of records) {
|
|
691
|
+
const runId = readSubagentRunId(record);
|
|
692
|
+
if (runId === void 0 || spawningCalls.has(runId)) continue;
|
|
693
|
+
const toolCallId = subagentParentToolCallIds?.get(runId);
|
|
694
|
+
if (toolCallId !== void 0 && callOwners.has(toolCallId)) spawningCalls.set(runId, toolCallId);
|
|
695
|
+
}
|
|
696
|
+
if (spawningCalls.size === 0) return convertAgUiMessages(messages, options);
|
|
697
|
+
const reachesRoot = (runId) => {
|
|
698
|
+
let current = runId;
|
|
699
|
+
for (let depth = 0; current !== void 0; depth++) {
|
|
700
|
+
const toolCallId = spawningCalls.get(current);
|
|
701
|
+
if (toolCallId === void 0 || depth > 16) return false;
|
|
702
|
+
current = callOwners.get(toolCallId);
|
|
703
|
+
}
|
|
704
|
+
return true;
|
|
705
|
+
};
|
|
706
|
+
const nestedRuns = new Set([...spawningCalls.keys()].filter(reachesRoot));
|
|
707
|
+
const groups = /* @__PURE__ */ new Map();
|
|
708
|
+
for (const record of records) {
|
|
709
|
+
const ownRunId = readSubagentRunId(record);
|
|
710
|
+
const answered = getString(record, "role") === "tool" ? getToolCallId(record) : void 0;
|
|
711
|
+
const runId = answered !== void 0 && callOwners.has(answered) ? callOwners.get(answered) : ownRunId;
|
|
712
|
+
const role = getString(record, "role");
|
|
713
|
+
const group = role !== "user" && role !== "system" && role !== "developer" && runId !== void 0 && nestedRuns.has(runId) ? runId : void 0;
|
|
714
|
+
const members = groups.get(group) ?? [];
|
|
715
|
+
members.push(record);
|
|
716
|
+
groups.set(group, members);
|
|
717
|
+
}
|
|
718
|
+
const runsBySpawningCall = /* @__PURE__ */ new Map();
|
|
719
|
+
for (const runId of nestedRuns) {
|
|
720
|
+
const toolCallId = spawningCalls.get(runId);
|
|
721
|
+
runsBySpawningCall.set(toolCallId, [...runsBySpawningCall.get(toolCallId) ?? [], runId]);
|
|
722
|
+
}
|
|
723
|
+
const convertGroup = (group) => convertAgUiMessages(groups.get(group) ?? [], options).map((message) => {
|
|
724
|
+
if (message.role !== "assistant" || !Array.isArray(message.content)) return message;
|
|
725
|
+
const nested = [];
|
|
726
|
+
const content = message.content.map((part) => {
|
|
727
|
+
if (part.type !== "tool-call") return part;
|
|
728
|
+
const runIds = runsBySpawningCall.get(part.toolCallId);
|
|
729
|
+
if (!runIds) return part;
|
|
730
|
+
const subagents = runIds.map(toSubagentMessage);
|
|
731
|
+
nested.push(...subagents);
|
|
732
|
+
return {
|
|
733
|
+
...part,
|
|
734
|
+
messages: [...part.messages ?? [], ...subagents]
|
|
735
|
+
};
|
|
736
|
+
});
|
|
737
|
+
return liftSubagentState({
|
|
738
|
+
...message,
|
|
739
|
+
content
|
|
740
|
+
}, nested);
|
|
741
|
+
});
|
|
742
|
+
const toSubagentMessage = (runId) => {
|
|
743
|
+
const messages = convertGroup(runId).filter((message) => message.role === "assistant");
|
|
744
|
+
const folded = messages.map((message) => typeof message.content === "string" ? {
|
|
745
|
+
...message,
|
|
746
|
+
content: message.content ? [{
|
|
747
|
+
type: "text",
|
|
748
|
+
text: message.content
|
|
749
|
+
}] : []
|
|
750
|
+
} : message).reduce((merged, message) => merged ? foldTurnRecords(merged, message) : message, void 0);
|
|
751
|
+
const content = Array.isArray(folded?.content) ? folded.content : [];
|
|
752
|
+
const pendingToolCallIds = new Set(messages.filter((message) => message.status?.type === "requires-action" && message.status.reason === "tool-calls").flatMap((message) => admittedUnresolvedToolCallIds(message, true)));
|
|
753
|
+
const metadata = pendingToolCallIds.size ? withPendingToolCallIds(folded?.metadata, pendingToolCallIds) : folded?.metadata;
|
|
754
|
+
return fromThreadMessageLike({
|
|
755
|
+
id: runId,
|
|
756
|
+
role: "assistant",
|
|
757
|
+
content,
|
|
758
|
+
...metadata ? { metadata } : {}
|
|
759
|
+
}, runId, subagentStatus(folded?.metadata, messages));
|
|
760
|
+
};
|
|
761
|
+
return convertGroup(void 0);
|
|
762
|
+
}
|
|
763
|
+
const hasUnresolvedToolCall = (content) => content.some((part) => isObject(part) && part.type === "tool-call" && part.result === void 0);
|
|
764
|
+
function admittedUnresolvedToolCallIds(message, includeNested) {
|
|
765
|
+
if (message.role !== "assistant" || !Array.isArray(message.content)) return [];
|
|
766
|
+
const listed = readPersistedPendingToolCallIds(message.metadata);
|
|
767
|
+
if (listed) return listed;
|
|
768
|
+
return message.content.flatMap((part) => {
|
|
769
|
+
if (part.type !== "tool-call") return [];
|
|
770
|
+
return (includeNested ? [part, ...Array.from(walkToolCallTree(part.messages ?? []), ({ part }) => part)] : [part]).flatMap((call) => call.result === void 0 && call.toolCallId ? [call.toolCallId] : []);
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
function withPendingToolCallIds(metadata, ids) {
|
|
774
|
+
return {
|
|
775
|
+
...isObject(metadata) ? metadata : {},
|
|
776
|
+
custom: {
|
|
777
|
+
...readCustomMetadata(metadata),
|
|
778
|
+
[AG_UI_METADATA_NAMESPACE]: {
|
|
779
|
+
...readNamespacedMetadata(metadata),
|
|
780
|
+
pendingToolCallIds: [...ids]
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
}
|
|
785
|
+
function subagentStatus(metadata, messages) {
|
|
786
|
+
const hasInterrupt = readPersistedInterrupts(metadata) !== void 0;
|
|
787
|
+
const hasPendingToolCall = messages.some((message) => message.status?.type === "requires-action" && message.status.reason === "tool-calls");
|
|
788
|
+
return hasInterrupt || hasPendingToolCall ? getAutoStatus(false, false, hasInterrupt, hasPendingToolCall, void 0) : {
|
|
789
|
+
type: "complete",
|
|
790
|
+
reason: "unknown"
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* A nested run's open interrupts and unanswered calls surface on the message
|
|
795
|
+
* that spawned it, as the live run does.
|
|
796
|
+
*/
|
|
797
|
+
function liftSubagentState(message, nested) {
|
|
798
|
+
const waiting = nested.filter((subagent) => subagent.status?.type === "requires-action");
|
|
799
|
+
if (waiting.length === 0) return message;
|
|
800
|
+
const interrupts = [...readPersistedInterrupts(message.metadata) ?? [], ...waiting.flatMap((subagent) => readPersistedInterrupts(subagent.metadata) ?? [])];
|
|
801
|
+
const custom = readCustomMetadata(message.metadata);
|
|
802
|
+
const metadata = {
|
|
803
|
+
...isObject(message.metadata) ? message.metadata : {},
|
|
804
|
+
custom: {
|
|
805
|
+
...custom,
|
|
806
|
+
[AG_UI_METADATA_NAMESPACE]: {
|
|
807
|
+
...readNamespacedMetadata(message.metadata),
|
|
808
|
+
...interrupts.length > 0 ? { interrupts } : {}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
};
|
|
812
|
+
const hasInterrupt = interrupts.length > 0;
|
|
813
|
+
const hasPendingToolCall = waiting.some((subagent) => subagent.status?.type === "requires-action" && subagent.status.reason === "tool-calls") || Array.isArray(message.content) && hasUnresolvedToolCall(message.content);
|
|
814
|
+
const pendingToolCallIds = /* @__PURE__ */ new Set([...admittedUnresolvedToolCallIds(message, false), ...waiting.flatMap((subagent) => subagent.status?.type === "requires-action" && subagent.status.reason === "tool-calls" ? admittedUnresolvedToolCallIds(subagent, true) : [])]);
|
|
815
|
+
return {
|
|
816
|
+
...message,
|
|
817
|
+
metadata: pendingToolCallIds.size ? withPendingToolCallIds(metadata, pendingToolCallIds) : metadata,
|
|
818
|
+
status: getAutoStatus(false, false, hasInterrupt, hasPendingToolCall, void 0)
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
function convertAgUiMessages(messages, options) {
|
|
647
822
|
const showThinking = options?.showThinking ?? true;
|
|
648
823
|
const converted = [];
|
|
649
824
|
const a2uiBuckets = /* @__PURE__ */ new Map();
|
|
@@ -937,7 +1112,15 @@ function isToolContentParts(value) {
|
|
|
937
1112
|
}
|
|
938
1113
|
function emitToolResult(toolCallId, part, converted) {
|
|
939
1114
|
if (part.result === void 0) return;
|
|
940
|
-
|
|
1115
|
+
let resultContent;
|
|
1116
|
+
if (part.modelContent?.some((content) => content.type === "file")) resultContent = part.modelContent.flatMap((content) => {
|
|
1117
|
+
const contentPart = toContentPart(content, content.type === "file" ? content.mediaType : void 0);
|
|
1118
|
+
return contentPart ? [contentPart] : [];
|
|
1119
|
+
});
|
|
1120
|
+
else if (part.modelContent !== void 0) resultContent = extractText(part.modelContent);
|
|
1121
|
+
else if (isToolContentParts(part.result)) resultContent = part.result;
|
|
1122
|
+
else if (typeof part.result === "string") resultContent = part.result;
|
|
1123
|
+
else resultContent = JSON.stringify(part.result);
|
|
941
1124
|
const messageMetadata = readAgUiPartMessageMetadata(part.providerMetadata);
|
|
942
1125
|
converted.push({
|
|
943
1126
|
id: part.unstable_toolMessageId ?? `${toolCallId}:tool`,
|
|
@@ -1037,7 +1220,6 @@ function toAgUiTools(tools) {
|
|
|
1037
1220
|
parameters: tool.parameters
|
|
1038
1221
|
}));
|
|
1039
1222
|
}
|
|
1040
|
-
|
|
1041
|
-
export { fromAgUiMessages, toAgUiMessages, toAgUiTools };
|
|
1223
|
+
export { fromAgUiMessages, fromAgUiSnapshotMessages, toAgUiMessages, toAgUiTools, withAgUiPartMessageMetadata };
|
|
1042
1224
|
|
|
1043
1225
|
//# sourceMappingURL=conversions.js.map
|