@convex-dev/agent 0.6.0 → 0.6.1
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/UIMessages.d.ts +46 -0
- package/dist/UIMessages.d.ts.map +1 -0
- package/dist/UIMessages.js +634 -0
- package/dist/UIMessages.js.map +1 -0
- package/dist/client/createTool.d.ts +167 -0
- package/dist/client/createTool.d.ts.map +1 -0
- package/dist/client/createTool.js +116 -0
- package/dist/client/createTool.js.map +1 -0
- package/dist/client/defaultComponent.d.ts +11 -0
- package/dist/client/defaultComponent.d.ts.map +1 -0
- package/dist/client/defaultComponent.js +7 -0
- package/dist/client/defaultComponent.js.map +1 -0
- package/dist/client/definePlaygroundAPI.d.ts +1725 -0
- package/dist/client/definePlaygroundAPI.d.ts.map +1 -0
- package/dist/client/definePlaygroundAPI.js +271 -0
- package/dist/client/definePlaygroundAPI.js.map +1 -0
- package/dist/client/files.d.ts +69 -0
- package/dist/client/files.d.ts.map +1 -0
- package/dist/client/files.js +181 -0
- package/dist/client/files.js.map +1 -0
- package/dist/client/index.d.ts +2091 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +929 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/messages.d.ts +461 -0
- package/dist/client/messages.d.ts.map +1 -0
- package/dist/client/messages.js +106 -0
- package/dist/client/messages.js.map +1 -0
- package/dist/client/mockModel.d.ts +42 -0
- package/dist/client/mockModel.d.ts.map +1 -0
- package/dist/client/mockModel.js +182 -0
- package/dist/client/mockModel.js.map +1 -0
- package/dist/client/saveInputMessages.d.ts +20 -0
- package/dist/client/saveInputMessages.d.ts.map +1 -0
- package/dist/client/saveInputMessages.js +58 -0
- package/dist/client/saveInputMessages.js.map +1 -0
- package/dist/client/search.d.ts +493 -0
- package/dist/client/search.d.ts.map +1 -0
- package/dist/client/search.js +435 -0
- package/dist/client/search.js.map +1 -0
- package/dist/client/start.d.ts +84 -0
- package/dist/client/start.d.ts.map +1 -0
- package/dist/client/start.js +185 -0
- package/dist/client/start.js.map +1 -0
- package/dist/client/streamText.d.ts +46 -0
- package/dist/client/streamText.d.ts.map +1 -0
- package/dist/client/streamText.js +127 -0
- package/dist/client/streamText.js.map +1 -0
- package/dist/client/streaming.d.ts +3778 -0
- package/dist/client/streaming.d.ts.map +1 -0
- package/dist/client/streaming.js +330 -0
- package/dist/client/streaming.js.map +1 -0
- package/dist/client/threads.d.ts +46 -0
- package/dist/client/threads.d.ts.map +1 -0
- package/dist/client/threads.js +49 -0
- package/dist/client/threads.js.map +1 -0
- package/dist/client/types.d.ts +461 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/utils.d.ts +4 -0
- package/dist/client/utils.d.ts.map +1 -0
- package/dist/client/utils.js +21 -0
- package/dist/client/utils.js.map +1 -0
- package/dist/component/_generated/api.d.ts +48 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +3120 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/apiKeys.d.ts +11 -0
- package/dist/component/apiKeys.d.ts.map +1 -0
- package/dist/component/apiKeys.js +69 -0
- package/dist/component/apiKeys.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +3 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/files.d.ts +97 -0
- package/dist/component/files.d.ts.map +1 -0
- package/dist/component/files.js +190 -0
- package/dist/component/files.js.map +1 -0
- package/dist/component/messages.d.ts +3851 -0
- package/dist/component/messages.d.ts.map +1 -0
- package/dist/component/messages.js +757 -0
- package/dist/component/messages.js.map +1 -0
- package/dist/component/schema.d.ts +8029 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +147 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/streams.d.ts +128 -0
- package/dist/component/streams.d.ts.map +1 -0
- package/dist/component/streams.js +413 -0
- package/dist/component/streams.js.map +1 -0
- package/dist/component/threads.d.ts +115 -0
- package/dist/component/threads.d.ts.map +1 -0
- package/dist/component/threads.js +208 -0
- package/dist/component/threads.js.map +1 -0
- package/dist/component/users.d.ts +52 -0
- package/dist/component/users.d.ts.map +1 -0
- package/dist/component/users.js +229 -0
- package/dist/component/users.js.map +1 -0
- package/dist/component/vector/index.d.ts +61 -0
- package/dist/component/vector/index.d.ts.map +1 -0
- package/dist/component/vector/index.js +146 -0
- package/dist/component/vector/index.js.map +1 -0
- package/dist/component/vector/tables.d.ts +58 -0
- package/dist/component/vector/tables.d.ts.map +1 -0
- package/dist/component/vector/tables.js +56 -0
- package/dist/component/vector/tables.js.map +1 -0
- package/dist/deltas.d.ts +43 -0
- package/dist/deltas.d.ts.map +1 -0
- package/dist/deltas.js +446 -0
- package/dist/deltas.js.map +1 -0
- package/dist/mapping.d.ts +76 -0
- package/dist/mapping.d.ts.map +1 -0
- package/dist/mapping.js +720 -0
- package/dist/mapping.js.map +1 -0
- package/dist/react/SmoothText.d.ts +5 -0
- package/dist/react/SmoothText.d.ts.map +1 -0
- package/dist/react/SmoothText.js +6 -0
- package/dist/react/SmoothText.js.map +1 -0
- package/dist/react/index.d.ts +25 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +70 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/optimisticallySendMessage.d.ts +42 -0
- package/dist/react/optimisticallySendMessage.d.ts.map +1 -0
- package/dist/react/optimisticallySendMessage.js +74 -0
- package/dist/react/optimisticallySendMessage.js.map +1 -0
- package/dist/react/types.d.ts +12 -0
- package/dist/react/types.d.ts.map +1 -0
- package/dist/react/types.js +2 -0
- package/dist/react/types.js.map +1 -0
- package/dist/react/useDeltaStreams.d.ts +10 -0
- package/dist/react/useDeltaStreams.d.ts.map +1 -0
- package/dist/react/useDeltaStreams.js +106 -0
- package/dist/react/useDeltaStreams.js.map +1 -0
- package/dist/react/useSmoothText.d.ts +27 -0
- package/dist/react/useSmoothText.d.ts.map +1 -0
- package/dist/react/useSmoothText.js +68 -0
- package/dist/react/useSmoothText.js.map +1 -0
- package/dist/react/useStreamingUIMessages.d.ts +22 -0
- package/dist/react/useStreamingUIMessages.d.ts.map +1 -0
- package/dist/react/useStreamingUIMessages.js +92 -0
- package/dist/react/useStreamingUIMessages.js.map +1 -0
- package/dist/react/useThreadMessages.d.ts +104 -0
- package/dist/react/useThreadMessages.d.ts.map +1 -0
- package/dist/react/useThreadMessages.js +148 -0
- package/dist/react/useThreadMessages.js.map +1 -0
- package/dist/react/useUIMessages.d.ts +96 -0
- package/dist/react/useUIMessages.d.ts.map +1 -0
- package/dist/react/useUIMessages.js +108 -0
- package/dist/react/useUIMessages.js.map +1 -0
- package/dist/shared.d.ts +26 -0
- package/dist/shared.d.ts.map +1 -0
- package/dist/shared.js +67 -0
- package/dist/shared.js.map +1 -0
- package/dist/validators.d.ts +24516 -0
- package/dist/validators.d.ts.map +1 -0
- package/dist/validators.js +475 -0
- package/dist/validators.js.map +1 -0
- package/package.json +39 -39
- package/src/UIMessages.ts +0 -9
- package/src/client/approval.test.ts +144 -0
- package/src/client/index.ts +17 -9
- package/src/client/search.ts +0 -29
- package/src/client/start.ts +2 -2
- package/src/client/streamText.ts +9 -0
- package/src/client/streaming.ts +30 -23
- package/src/component/_generated/dataModel.ts +1 -1
- package/src/component/_generated/server.ts +0 -5
- package/src/mapping.ts +38 -22
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type UIMessage as AIUIMessage, type UIDataTypes, type UITools } from "ai";
|
|
2
|
+
import type { MessageDoc, MessageStatus, ProviderOptions } from "./validators.js";
|
|
3
|
+
export type UIStatus = "streaming" | MessageStatus;
|
|
4
|
+
export type UIMessage<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools> = AIUIMessage<METADATA, DATA_PARTS, TOOLS> & {
|
|
5
|
+
key: string;
|
|
6
|
+
order: number;
|
|
7
|
+
stepOrder: number;
|
|
8
|
+
status: UIStatus;
|
|
9
|
+
agentName?: string;
|
|
10
|
+
userId?: string;
|
|
11
|
+
text: string;
|
|
12
|
+
_creationTime: number;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Converts a list of UIMessages to MessageDocs, along with extra metadata that
|
|
16
|
+
* may be available to associate with the MessageDocs.
|
|
17
|
+
* @param messages - The UIMessages to convert to MessageDocs.
|
|
18
|
+
* @param meta - The metadata to add to the MessageDocs.
|
|
19
|
+
* @returns
|
|
20
|
+
*/
|
|
21
|
+
export declare function fromUIMessages<METADATA = unknown>(messages: UIMessage<METADATA>[], meta: {
|
|
22
|
+
threadId: string;
|
|
23
|
+
userId?: string;
|
|
24
|
+
model?: string;
|
|
25
|
+
provider?: string;
|
|
26
|
+
providerOptions?: ProviderOptions;
|
|
27
|
+
metadata?: METADATA;
|
|
28
|
+
}): Promise<(MessageDoc & {
|
|
29
|
+
streaming: boolean;
|
|
30
|
+
metadata?: METADATA;
|
|
31
|
+
})[]>;
|
|
32
|
+
type ExtraFields<METADATA = unknown> = {
|
|
33
|
+
streaming?: boolean;
|
|
34
|
+
metadata?: METADATA;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Converts a list of MessageDocs to UIMessages.
|
|
38
|
+
* This is somewhat lossy, as many fields are not supported by UIMessages, e.g.
|
|
39
|
+
* the model, provider, userId, etc.
|
|
40
|
+
* The UIMessage type is the augmented type that includes more fields such as
|
|
41
|
+
* key, order, stepOrder, status, agentName, text, etc.
|
|
42
|
+
*/
|
|
43
|
+
export declare function toUIMessages<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools>(messages: (MessageDoc & ExtraFields<METADATA>)[]): UIMessage<METADATA, DATA_PARTS, TOOLS>[];
|
|
44
|
+
export declare function combineUIMessages(messages: UIMessage[]): UIMessage[];
|
|
45
|
+
export {};
|
|
46
|
+
//# sourceMappingURL=UIMessages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UIMessages.d.ts","sourceRoot":"","sources":["../src/UIMessages.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,IAAI,WAAW,EAU7B,KAAK,WAAW,EAChB,KAAK,OAAO,EACb,MAAM,IAAI,CAAC;AAUZ,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,eAAe,EAGhB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,aAAa,CAAC;AAEnD,MAAM,MAAM,SAAS,CACnB,QAAQ,GAAG,OAAO,EAClB,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,KAAK,SAAS,OAAO,GAAG,OAAO,IAC7B,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,GAAG;IAC7C,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,QAAQ,GAAG,OAAO,EACrD,QAAQ,EAAE,SAAS,CAAC,QAAQ,CAAC,EAAE,EAC/B,IAAI,EAAE;IACJ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,GACA,OAAO,CAAC,CAAC,UAAU,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,EAAE,CAAC,CAiEvE;AA8BD,KAAK,WAAW,CAAC,QAAQ,GAAG,OAAO,IAAI;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,GAAG,OAAO,EAClB,UAAU,SAAS,WAAW,GAAG,WAAW,EAC5C,KAAK,SAAS,OAAO,GAAG,OAAO,EAE/B,QAAQ,EAAE,CAAC,UAAU,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAE,GAC/C,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,CAAC,EAAE,CAiB1C;AA6lBD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA2CpE"}
|
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
import { convertToModelMessages, } from "ai";
|
|
2
|
+
import { toModelMessage, fromModelMessage, toUIFilePart } from "./mapping.js";
|
|
3
|
+
import { extractReasoning, extractText, isTool, joinText, sorted, } from "./shared.js";
|
|
4
|
+
import { omit, pick } from "convex-helpers";
|
|
5
|
+
/**
|
|
6
|
+
* Converts a list of UIMessages to MessageDocs, along with extra metadata that
|
|
7
|
+
* may be available to associate with the MessageDocs.
|
|
8
|
+
* @param messages - The UIMessages to convert to MessageDocs.
|
|
9
|
+
* @param meta - The metadata to add to the MessageDocs.
|
|
10
|
+
* @returns
|
|
11
|
+
*/
|
|
12
|
+
export async function fromUIMessages(messages, meta) {
|
|
13
|
+
const nested = await Promise.all(messages.map(async (uiMessage) => {
|
|
14
|
+
const stepOrder = uiMessage.stepOrder;
|
|
15
|
+
const commonFields = {
|
|
16
|
+
...pick(meta, [
|
|
17
|
+
"threadId",
|
|
18
|
+
"userId",
|
|
19
|
+
"model",
|
|
20
|
+
"provider",
|
|
21
|
+
"providerOptions",
|
|
22
|
+
"metadata",
|
|
23
|
+
]),
|
|
24
|
+
...omit(uiMessage, ["parts", "role", "key", "text", "userId"]),
|
|
25
|
+
userId: uiMessage.userId ?? meta.userId,
|
|
26
|
+
status: uiMessage.status === "streaming" ? "pending" : "success",
|
|
27
|
+
streaming: uiMessage.status === "streaming",
|
|
28
|
+
// to override
|
|
29
|
+
_id: uiMessage.id,
|
|
30
|
+
tool: false,
|
|
31
|
+
};
|
|
32
|
+
const modelMessages = await convertToModelMessages([uiMessage]);
|
|
33
|
+
return modelMessages
|
|
34
|
+
.map((modelMessage, i) => {
|
|
35
|
+
if (modelMessage.content.length === 0) {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
const message = fromModelMessage(modelMessage);
|
|
39
|
+
const tool = isTool(message);
|
|
40
|
+
const doc = {
|
|
41
|
+
...commonFields,
|
|
42
|
+
_id: uiMessage.id + `-${i}`,
|
|
43
|
+
stepOrder: stepOrder + i,
|
|
44
|
+
message,
|
|
45
|
+
tool,
|
|
46
|
+
text: extractText(message),
|
|
47
|
+
reasoning: extractReasoning(message),
|
|
48
|
+
finishReason: tool ? "tool-calls" : "stop",
|
|
49
|
+
sources: fromSourceParts(uiMessage.parts),
|
|
50
|
+
};
|
|
51
|
+
if (Array.isArray(modelMessage.content)) {
|
|
52
|
+
// Find a content part with providerOptions (type assertion needed for SDK compatibility)
|
|
53
|
+
const partWithProviderOptions = modelMessage.content.find((c) => "providerOptions" in c && c.providerOptions !== undefined);
|
|
54
|
+
if (partWithProviderOptions?.providerOptions) {
|
|
55
|
+
// convertToModelMessages changes providerMetadata to providerOptions
|
|
56
|
+
const providerOptions = partWithProviderOptions.providerOptions;
|
|
57
|
+
if (providerOptions) {
|
|
58
|
+
doc.providerMetadata = providerOptions;
|
|
59
|
+
doc.providerOptions ??= providerOptions;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return doc;
|
|
64
|
+
})
|
|
65
|
+
.filter((d) => d !== undefined);
|
|
66
|
+
}));
|
|
67
|
+
return nested.flat();
|
|
68
|
+
}
|
|
69
|
+
function fromSourceParts(parts) {
|
|
70
|
+
return parts
|
|
71
|
+
.map((part) => {
|
|
72
|
+
if (part.type === "source-url") {
|
|
73
|
+
return {
|
|
74
|
+
type: "source",
|
|
75
|
+
sourceType: "url",
|
|
76
|
+
url: part.url,
|
|
77
|
+
id: part.sourceId,
|
|
78
|
+
providerMetadata: part.providerMetadata,
|
|
79
|
+
title: part.title,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (part.type === "source-document") {
|
|
83
|
+
return {
|
|
84
|
+
type: "source",
|
|
85
|
+
sourceType: "document",
|
|
86
|
+
mediaType: part.mediaType,
|
|
87
|
+
id: part.sourceId,
|
|
88
|
+
providerMetadata: part.providerMetadata,
|
|
89
|
+
title: part.title,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
})
|
|
94
|
+
.filter((p) => p !== undefined);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Converts a list of MessageDocs to UIMessages.
|
|
98
|
+
* This is somewhat lossy, as many fields are not supported by UIMessages, e.g.
|
|
99
|
+
* the model, provider, userId, etc.
|
|
100
|
+
* The UIMessage type is the augmented type that includes more fields such as
|
|
101
|
+
* key, order, stepOrder, status, agentName, text, etc.
|
|
102
|
+
*/
|
|
103
|
+
export function toUIMessages(messages) {
|
|
104
|
+
// Group assistant and tool messages together
|
|
105
|
+
const assistantGroups = groupAssistantMessages(sorted(messages));
|
|
106
|
+
const uiMessages = [];
|
|
107
|
+
for (const group of assistantGroups) {
|
|
108
|
+
if (group.role === "system") {
|
|
109
|
+
uiMessages.push(createSystemUIMessage(group.message));
|
|
110
|
+
}
|
|
111
|
+
else if (group.role === "user") {
|
|
112
|
+
uiMessages.push(createUserUIMessage(group.message));
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
// Assistant/tool group
|
|
116
|
+
uiMessages.push(createAssistantUIMessage(group.messages));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return uiMessages;
|
|
120
|
+
}
|
|
121
|
+
function groupAssistantMessages(messages) {
|
|
122
|
+
const groups = [];
|
|
123
|
+
let currentAssistantGroup = [];
|
|
124
|
+
let currentOrder;
|
|
125
|
+
for (const message of messages) {
|
|
126
|
+
const coreMessage = message.message && toModelMessage(message.message);
|
|
127
|
+
if (!coreMessage)
|
|
128
|
+
continue;
|
|
129
|
+
if (coreMessage.role === "user" || coreMessage.role === "system") {
|
|
130
|
+
// Finish any current assistant group
|
|
131
|
+
if (currentAssistantGroup.length > 0) {
|
|
132
|
+
groups.push({
|
|
133
|
+
role: "assistant",
|
|
134
|
+
messages: currentAssistantGroup,
|
|
135
|
+
});
|
|
136
|
+
currentAssistantGroup = [];
|
|
137
|
+
currentOrder = undefined;
|
|
138
|
+
}
|
|
139
|
+
// Add singleton group
|
|
140
|
+
groups.push({
|
|
141
|
+
role: coreMessage.role,
|
|
142
|
+
message,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Assistant or tool message
|
|
147
|
+
// Start new group if order changes or this is the first assistant/tool message
|
|
148
|
+
if (currentOrder !== undefined && message.order !== currentOrder) {
|
|
149
|
+
if (currentAssistantGroup.length > 0) {
|
|
150
|
+
groups.push({
|
|
151
|
+
role: "assistant",
|
|
152
|
+
messages: currentAssistantGroup,
|
|
153
|
+
});
|
|
154
|
+
currentAssistantGroup = [];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
currentOrder = message.order;
|
|
158
|
+
currentAssistantGroup.push(message);
|
|
159
|
+
// End group if this is an assistant message without tool calls
|
|
160
|
+
if (coreMessage.role === "assistant" && !message.tool) {
|
|
161
|
+
groups.push({
|
|
162
|
+
role: "assistant",
|
|
163
|
+
messages: currentAssistantGroup,
|
|
164
|
+
});
|
|
165
|
+
currentAssistantGroup = [];
|
|
166
|
+
currentOrder = undefined;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
// Add any remaining assistant group
|
|
171
|
+
if (currentAssistantGroup.length > 0) {
|
|
172
|
+
groups.push({
|
|
173
|
+
role: "assistant",
|
|
174
|
+
messages: currentAssistantGroup,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
return groups;
|
|
178
|
+
}
|
|
179
|
+
function createSystemUIMessage(message) {
|
|
180
|
+
const text = extractTextFromMessageDoc(message);
|
|
181
|
+
const partCommon = {
|
|
182
|
+
state: message.streaming ? "streaming" : "done",
|
|
183
|
+
...(message.providerMetadata
|
|
184
|
+
? { providerMetadata: message.providerMetadata }
|
|
185
|
+
: {}),
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
id: message._id,
|
|
189
|
+
_creationTime: message._creationTime,
|
|
190
|
+
order: message.order,
|
|
191
|
+
stepOrder: message.stepOrder,
|
|
192
|
+
status: message.streaming ? "streaming" : message.status,
|
|
193
|
+
key: `${message.threadId}-${message.order}-${message.stepOrder}`,
|
|
194
|
+
text,
|
|
195
|
+
role: "system",
|
|
196
|
+
agentName: message.agentName,
|
|
197
|
+
userId: message.userId,
|
|
198
|
+
parts: [{ type: "text", text, ...partCommon }],
|
|
199
|
+
metadata: message.metadata,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function extractTextFromMessageDoc(message) {
|
|
203
|
+
return ((message.message && extractText(message.message)) || message.text || "");
|
|
204
|
+
}
|
|
205
|
+
function createUserUIMessage(message) {
|
|
206
|
+
const text = extractTextFromMessageDoc(message);
|
|
207
|
+
const coreMessage = toModelMessage(message.message);
|
|
208
|
+
const content = coreMessage.content;
|
|
209
|
+
const nonStringContent = content && typeof content !== "string" ? content : [];
|
|
210
|
+
const partCommon = {
|
|
211
|
+
state: message.streaming ? "streaming" : "done",
|
|
212
|
+
...(message.providerMetadata
|
|
213
|
+
? { providerMetadata: message.providerMetadata }
|
|
214
|
+
: {}),
|
|
215
|
+
};
|
|
216
|
+
const parts = [];
|
|
217
|
+
if (text && !nonStringContent.length) {
|
|
218
|
+
parts.push({ type: "text", text });
|
|
219
|
+
}
|
|
220
|
+
for (const contentPart of nonStringContent) {
|
|
221
|
+
switch (contentPart.type) {
|
|
222
|
+
case "text":
|
|
223
|
+
parts.push({ type: "text", text: contentPart.text, ...partCommon });
|
|
224
|
+
break;
|
|
225
|
+
case "file":
|
|
226
|
+
case "image":
|
|
227
|
+
parts.push(toUIFilePart(contentPart));
|
|
228
|
+
break;
|
|
229
|
+
default:
|
|
230
|
+
console.warn("Unknown content part type for user", contentPart);
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return {
|
|
235
|
+
id: message._id,
|
|
236
|
+
_creationTime: message._creationTime,
|
|
237
|
+
order: message.order,
|
|
238
|
+
stepOrder: message.stepOrder,
|
|
239
|
+
status: message.streaming ? "streaming" : message.status,
|
|
240
|
+
key: `${message.threadId}-${message.order}-${message.stepOrder}`,
|
|
241
|
+
text,
|
|
242
|
+
role: "user",
|
|
243
|
+
userId: message.userId,
|
|
244
|
+
parts,
|
|
245
|
+
metadata: message.metadata,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function createAssistantUIMessage(groupUnordered) {
|
|
249
|
+
const group = sorted(groupUnordered);
|
|
250
|
+
const firstMessage = group[0];
|
|
251
|
+
// Use first message for special fields
|
|
252
|
+
const common = {
|
|
253
|
+
id: firstMessage._id,
|
|
254
|
+
_creationTime: firstMessage._creationTime,
|
|
255
|
+
order: firstMessage.order,
|
|
256
|
+
stepOrder: firstMessage.stepOrder,
|
|
257
|
+
key: `${firstMessage.threadId}-${firstMessage.order}-${firstMessage.stepOrder}`,
|
|
258
|
+
agentName: firstMessage.agentName,
|
|
259
|
+
userId: firstMessage.userId,
|
|
260
|
+
};
|
|
261
|
+
// Get status from last message
|
|
262
|
+
const lastMessage = group[group.length - 1];
|
|
263
|
+
const status = lastMessage.streaming
|
|
264
|
+
? "streaming"
|
|
265
|
+
: lastMessage.status;
|
|
266
|
+
const approvalParts = [];
|
|
267
|
+
const executionDeniedResults = [];
|
|
268
|
+
for (const message of group) {
|
|
269
|
+
const rawContent = message.message?.content;
|
|
270
|
+
if (Array.isArray(rawContent)) {
|
|
271
|
+
for (const part of rawContent) {
|
|
272
|
+
if (part.type === "tool-approval-request" ||
|
|
273
|
+
part.type === "tool-approval-response") {
|
|
274
|
+
approvalParts.push(part);
|
|
275
|
+
}
|
|
276
|
+
// Check for execution-denied in tool-result outputs
|
|
277
|
+
if (part.type === "tool-result" &&
|
|
278
|
+
typeof part.output === "object" &&
|
|
279
|
+
part.output !== null &&
|
|
280
|
+
part.output.type === "execution-denied") {
|
|
281
|
+
executionDeniedResults.push({
|
|
282
|
+
toolCallId: part.toolCallId,
|
|
283
|
+
reason: part.output.reason,
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Collect all parts from all messages
|
|
290
|
+
const allParts = [];
|
|
291
|
+
for (const message of group) {
|
|
292
|
+
const coreMessage = message.message && toModelMessage(message.message);
|
|
293
|
+
if (!coreMessage)
|
|
294
|
+
continue;
|
|
295
|
+
const content = coreMessage.content;
|
|
296
|
+
const nonStringContent = content && typeof content !== "string" ? content : [];
|
|
297
|
+
const text = extractTextFromMessageDoc(message);
|
|
298
|
+
const partCommon = {
|
|
299
|
+
state: message.streaming ? "streaming" : "done",
|
|
300
|
+
...(message.providerMetadata
|
|
301
|
+
? { providerMetadata: message.providerMetadata }
|
|
302
|
+
: {}),
|
|
303
|
+
};
|
|
304
|
+
// Add reasoning parts
|
|
305
|
+
if (message.reasoning &&
|
|
306
|
+
!nonStringContent.some((c) => c.type === "reasoning")) {
|
|
307
|
+
allParts.push({
|
|
308
|
+
type: "reasoning",
|
|
309
|
+
text: message.reasoning,
|
|
310
|
+
...partCommon,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
// Add text parts if no structured content
|
|
314
|
+
if (text && !nonStringContent.length) {
|
|
315
|
+
allParts.push({
|
|
316
|
+
type: "text",
|
|
317
|
+
text: text,
|
|
318
|
+
...partCommon,
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
// Add all structured content parts
|
|
322
|
+
for (const contentPart of nonStringContent) {
|
|
323
|
+
switch (contentPart.type) {
|
|
324
|
+
case "text":
|
|
325
|
+
allParts.push({
|
|
326
|
+
...partCommon,
|
|
327
|
+
...contentPart,
|
|
328
|
+
});
|
|
329
|
+
break;
|
|
330
|
+
case "reasoning":
|
|
331
|
+
allParts.push({
|
|
332
|
+
...partCommon,
|
|
333
|
+
...contentPart,
|
|
334
|
+
});
|
|
335
|
+
break;
|
|
336
|
+
case "file":
|
|
337
|
+
case "image":
|
|
338
|
+
allParts.push(toUIFilePart(contentPart));
|
|
339
|
+
break;
|
|
340
|
+
case "tool-call": {
|
|
341
|
+
allParts.push({
|
|
342
|
+
type: "step-start",
|
|
343
|
+
});
|
|
344
|
+
const toolPart = {
|
|
345
|
+
type: `tool-${contentPart.toolName}`,
|
|
346
|
+
toolCallId: contentPart.toolCallId,
|
|
347
|
+
input: contentPart.input,
|
|
348
|
+
providerExecuted: contentPart.providerExecuted,
|
|
349
|
+
...(message.streaming
|
|
350
|
+
? { state: "input-streaming" }
|
|
351
|
+
: {
|
|
352
|
+
state: "input-available",
|
|
353
|
+
callProviderMetadata: message.providerMetadata,
|
|
354
|
+
}),
|
|
355
|
+
};
|
|
356
|
+
allParts.push(toolPart);
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
case "tool-result": {
|
|
360
|
+
// Note: execution-denied outputs are handled separately via pre-extraction
|
|
361
|
+
// from raw content (converted to text format for providers in start.ts).
|
|
362
|
+
// See executionDeniedResults processing at the end of this function.
|
|
363
|
+
const typedPart = contentPart;
|
|
364
|
+
// Check if this is an execution-denied result
|
|
365
|
+
if (typedPart.output?.type === "execution-denied") {
|
|
366
|
+
const call = allParts.find((part) => part.type === `tool-${contentPart.toolName}` &&
|
|
367
|
+
"toolCallId" in part &&
|
|
368
|
+
part.toolCallId === contentPart.toolCallId);
|
|
369
|
+
if (call) {
|
|
370
|
+
call.state = "output-denied";
|
|
371
|
+
if (!("approval" in call) || !call.approval) {
|
|
372
|
+
call.approval = {
|
|
373
|
+
id: "",
|
|
374
|
+
approved: false,
|
|
375
|
+
reason: typedPart.output.reason,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
const approval = call.approval;
|
|
380
|
+
approval.approved = false;
|
|
381
|
+
approval.reason = typedPart.output.reason;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
const output = typeof typedPart.output?.type === "string"
|
|
387
|
+
? typedPart.output.value
|
|
388
|
+
: typedPart.output;
|
|
389
|
+
// Check for error at both the content part level (isError) and message level
|
|
390
|
+
// isError may exist on stored tool results but isn't in ToolResultPart type
|
|
391
|
+
const hasError = contentPart.isError || message.error;
|
|
392
|
+
const errorText = message.error || (hasError ? String(output) : undefined);
|
|
393
|
+
const call = allParts.find((part) => part.type === `tool-${contentPart.toolName}` &&
|
|
394
|
+
"toolCallId" in part &&
|
|
395
|
+
part.toolCallId === contentPart.toolCallId);
|
|
396
|
+
if (call) {
|
|
397
|
+
if (hasError) {
|
|
398
|
+
call.state = "output-error";
|
|
399
|
+
call.errorText = errorText ?? "Unknown error";
|
|
400
|
+
call.output = output;
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
call.state = "output-available";
|
|
404
|
+
call.output = output;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
// Tool call is on a previous page - create standalone tool part
|
|
409
|
+
if (hasError) {
|
|
410
|
+
allParts.push({
|
|
411
|
+
type: `tool-${contentPart.toolName}`,
|
|
412
|
+
toolCallId: contentPart.toolCallId,
|
|
413
|
+
state: "output-error",
|
|
414
|
+
input: undefined,
|
|
415
|
+
errorText: errorText ?? "Unknown error",
|
|
416
|
+
callProviderMetadata: message.providerMetadata,
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
allParts.push({
|
|
421
|
+
type: `tool-${contentPart.toolName}`,
|
|
422
|
+
toolCallId: contentPart.toolCallId,
|
|
423
|
+
state: "output-available",
|
|
424
|
+
input: undefined,
|
|
425
|
+
output,
|
|
426
|
+
callProviderMetadata: message.providerMetadata,
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
case "tool-approval-request": {
|
|
433
|
+
// Find the matching tool call
|
|
434
|
+
const typedPart = contentPart;
|
|
435
|
+
const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === typedPart.toolCallId);
|
|
436
|
+
if (toolCallPart) {
|
|
437
|
+
toolCallPart.state = "approval-requested";
|
|
438
|
+
toolCallPart.approval = {
|
|
439
|
+
id: typedPart.approvalId,
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
else {
|
|
443
|
+
console.warn("Tool approval request without preceding tool call", contentPart);
|
|
444
|
+
}
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
case "tool-approval-response": {
|
|
448
|
+
// Find the tool call that has this approval by matching approval.id
|
|
449
|
+
const typedPart = contentPart;
|
|
450
|
+
const toolCallPart = allParts.find((part) => "approval" in part &&
|
|
451
|
+
part.approval
|
|
452
|
+
?.id === typedPart.approvalId);
|
|
453
|
+
if (toolCallPart) {
|
|
454
|
+
if (typedPart.approved) {
|
|
455
|
+
toolCallPart.state = "approval-responded";
|
|
456
|
+
toolCallPart.approval = {
|
|
457
|
+
id: typedPart.approvalId,
|
|
458
|
+
approved: true,
|
|
459
|
+
reason: typedPart.reason,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
toolCallPart.state = "output-denied";
|
|
464
|
+
toolCallPart.approval = {
|
|
465
|
+
id: typedPart.approvalId,
|
|
466
|
+
approved: false,
|
|
467
|
+
reason: typedPart.reason,
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
else {
|
|
472
|
+
console.warn("Tool approval response without matching approval request", contentPart);
|
|
473
|
+
}
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
default: {
|
|
477
|
+
const maybeSource = contentPart;
|
|
478
|
+
if (maybeSource.type === "source") {
|
|
479
|
+
allParts.push(toSourcePart(maybeSource));
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
console.warn("Unknown content part type for assistant", contentPart);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
// Add source parts
|
|
488
|
+
for (const source of message.sources ?? []) {
|
|
489
|
+
allParts.push(toSourcePart(source));
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Final output states that should not be overwritten by approval processing
|
|
493
|
+
const finalStates = new Set([
|
|
494
|
+
"output-available",
|
|
495
|
+
"output-error",
|
|
496
|
+
"output-denied",
|
|
497
|
+
]);
|
|
498
|
+
// Process approval parts to update tool call states
|
|
499
|
+
for (const approvalPart of approvalParts) {
|
|
500
|
+
if (approvalPart.type === "tool-approval-request") {
|
|
501
|
+
const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === approvalPart.toolCallId);
|
|
502
|
+
if (toolCallPart) {
|
|
503
|
+
// Always set approval info (needed for response matching), but only
|
|
504
|
+
// update state if not in a final state
|
|
505
|
+
toolCallPart.approval = {
|
|
506
|
+
id: approvalPart.approvalId,
|
|
507
|
+
};
|
|
508
|
+
if (!finalStates.has(toolCallPart.state)) {
|
|
509
|
+
toolCallPart.state = "approval-requested";
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
else if (approvalPart.type === "tool-approval-response") {
|
|
514
|
+
const toolCallPart = allParts.find((part) => "approval" in part &&
|
|
515
|
+
part.approval?.id ===
|
|
516
|
+
approvalPart.approvalId);
|
|
517
|
+
if (toolCallPart) {
|
|
518
|
+
// Always update approval info, but only update state if not in a final state
|
|
519
|
+
toolCallPart.approval = {
|
|
520
|
+
id: approvalPart.approvalId,
|
|
521
|
+
approved: approvalPart.approved,
|
|
522
|
+
reason: approvalPart.reason,
|
|
523
|
+
};
|
|
524
|
+
if (!finalStates.has(toolCallPart.state)) {
|
|
525
|
+
if (approvalPart.approved) {
|
|
526
|
+
toolCallPart.state = "approval-responded";
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
toolCallPart.state = "output-denied";
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
// Process execution-denied results to update tool call states
|
|
536
|
+
for (const denied of executionDeniedResults) {
|
|
537
|
+
const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === denied.toolCallId);
|
|
538
|
+
if (toolCallPart) {
|
|
539
|
+
toolCallPart.state = "output-denied";
|
|
540
|
+
if (!("approval" in toolCallPart) || !toolCallPart.approval) {
|
|
541
|
+
toolCallPart.approval = {
|
|
542
|
+
id: "",
|
|
543
|
+
approved: false,
|
|
544
|
+
reason: denied.reason,
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
else {
|
|
548
|
+
const approval = toolCallPart.approval;
|
|
549
|
+
approval.approved = false;
|
|
550
|
+
approval.reason = denied.reason;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
return {
|
|
555
|
+
...common,
|
|
556
|
+
role: "assistant",
|
|
557
|
+
text: joinText(allParts),
|
|
558
|
+
status,
|
|
559
|
+
parts: allParts,
|
|
560
|
+
metadata: group.find((m) => m.metadata)?.metadata,
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
function toSourcePart(part) {
|
|
564
|
+
if (part.sourceType === "url") {
|
|
565
|
+
return {
|
|
566
|
+
type: "source-url",
|
|
567
|
+
url: part.url,
|
|
568
|
+
sourceId: part.id,
|
|
569
|
+
providerMetadata: part.providerMetadata,
|
|
570
|
+
title: part.title,
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
return {
|
|
574
|
+
type: "source-document",
|
|
575
|
+
mediaType: part.mediaType,
|
|
576
|
+
sourceId: part.id,
|
|
577
|
+
title: part.title,
|
|
578
|
+
filename: part.filename,
|
|
579
|
+
providerMetadata: part.providerMetadata,
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
export function combineUIMessages(messages) {
|
|
583
|
+
const combined = messages.reduce((acc, message) => {
|
|
584
|
+
if (!acc.length) {
|
|
585
|
+
return [message];
|
|
586
|
+
}
|
|
587
|
+
const previous = acc.at(-1);
|
|
588
|
+
if (message.order !== previous.order ||
|
|
589
|
+
previous.role !== message.role ||
|
|
590
|
+
message.role !== "assistant") {
|
|
591
|
+
acc.push(message);
|
|
592
|
+
return acc;
|
|
593
|
+
}
|
|
594
|
+
// We will replace it with a combined message
|
|
595
|
+
acc.pop();
|
|
596
|
+
const newParts = [...previous.parts];
|
|
597
|
+
for (const part of message.parts) {
|
|
598
|
+
const toolCallId = getToolCallId(part);
|
|
599
|
+
if (!toolCallId) {
|
|
600
|
+
newParts.push(part);
|
|
601
|
+
continue;
|
|
602
|
+
}
|
|
603
|
+
const previousPartIndex = newParts.findIndex((p) => getToolCallId(p) === toolCallId);
|
|
604
|
+
if (previousPartIndex === -1) {
|
|
605
|
+
// Tool call not found in previous parts, add it as new
|
|
606
|
+
newParts.push(part);
|
|
607
|
+
continue;
|
|
608
|
+
}
|
|
609
|
+
const previousPart = newParts.splice(previousPartIndex, 1)[0];
|
|
610
|
+
newParts.push(mergeParts(previousPart, part));
|
|
611
|
+
}
|
|
612
|
+
acc.push({
|
|
613
|
+
...previous,
|
|
614
|
+
...pick(message, ["status", "metadata", "agentName"]),
|
|
615
|
+
parts: newParts,
|
|
616
|
+
text: joinText(newParts),
|
|
617
|
+
});
|
|
618
|
+
return acc;
|
|
619
|
+
}, []);
|
|
620
|
+
return combined;
|
|
621
|
+
}
|
|
622
|
+
function getToolCallId(part) {
|
|
623
|
+
return part.toolCallId;
|
|
624
|
+
}
|
|
625
|
+
function mergeParts(previousPart, part) {
|
|
626
|
+
const merged = { ...previousPart };
|
|
627
|
+
for (const [key, value] of Object.entries(part)) {
|
|
628
|
+
if (value !== undefined) {
|
|
629
|
+
merged[key] = value;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
return merged;
|
|
633
|
+
}
|
|
634
|
+
//# sourceMappingURL=UIMessages.js.map
|