@convex-dev/agent 0.5.0-alpha.1 → 0.6.0-alpha.0
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 +32 -27
- package/dist/UIMessages.d.ts +46 -0
- package/dist/UIMessages.d.ts.map +1 -0
- package/dist/UIMessages.js +546 -0
- package/dist/UIMessages.js.map +1 -0
- package/dist/client/createTool.d.ts +129 -27
- package/dist/client/createTool.d.ts.map +1 -1
- package/dist/client/createTool.js +66 -12
- package/dist/client/createTool.js.map +1 -1
- 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 +1323 -192
- package/dist/client/definePlaygroundAPI.d.ts.map +1 -1
- package/dist/client/definePlaygroundAPI.js +52 -28
- package/dist/client/definePlaygroundAPI.js.map +1 -1
- package/dist/client/files.d.ts +20 -7
- package/dist/client/files.d.ts.map +1 -1
- package/dist/client/files.js +68 -11
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +1056 -965
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +242 -748
- package/dist/client/index.js.map +1 -1
- 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 +175 -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 +346 -35
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +350 -39
- package/dist/client/search.js.map +1 -1
- package/dist/client/start.d.ts +84 -0
- package/dist/client/start.d.ts.map +1 -0
- package/dist/client/start.js +171 -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 +93 -0
- package/dist/client/streamText.js.map +1 -0
- package/dist/client/streaming.d.ts +3705 -32
- package/dist/client/streaming.d.ts.map +1 -1
- package/dist/client/streaming.js +141 -59
- package/dist/client/streaming.js.map +1 -1
- 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 +265 -128
- package/dist/client/types.d.ts.map +1 -1
- 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 +24 -2178
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js +10 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +3119 -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 +4 -18
- 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 +10 -38
- package/dist/component/_generated/server.d.ts.map +1 -1
- package/dist/component/_generated/server.js +9 -5
- package/dist/component/_generated/server.js.map +1 -1
- package/dist/component/files.d.ts +16 -10
- package/dist/component/files.d.ts.map +1 -1
- package/dist/component/files.js +10 -2
- package/dist/component/files.js.map +1 -1
- package/dist/component/messages.d.ts +2553 -342
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +387 -154
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts +5697 -3584
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +18 -41
- package/dist/component/schema.js.map +1 -1
- package/dist/component/streams.d.ts +35 -335
- package/dist/component/streams.d.ts.map +1 -1
- package/dist/component/streams.js +114 -73
- package/dist/component/streams.js.map +1 -1
- package/dist/component/threads.d.ts +16 -16
- package/dist/component/users.d.ts +4 -4
- package/dist/component/vector/index.d.ts +1 -1
- package/dist/component/vector/index.d.ts.map +1 -1
- package/dist/component/vector/index.js +1 -3
- package/dist/component/vector/index.js.map +1 -1
- package/dist/deltas.d.ts +43 -0
- package/dist/deltas.d.ts.map +1 -0
- package/dist/deltas.js +447 -0
- package/dist/deltas.js.map +1 -0
- package/dist/mapping.d.ts +20 -20
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +313 -96
- package/dist/mapping.js.map +1 -1
- 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 +5 -77
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +6 -160
- package/dist/react/index.js.map +1 -1
- package/dist/react/optimisticallySendMessage.d.ts +36 -3
- package/dist/react/optimisticallySendMessage.d.ts.map +1 -1
- package/dist/react/optimisticallySendMessage.js +35 -9
- package/dist/react/optimisticallySendMessage.js.map +1 -1
- package/dist/react/types.d.ts +4 -18
- package/dist/react/types.d.ts.map +1 -1
- package/dist/react/useDeltaStreams.d.ts +10 -0
- package/dist/react/useDeltaStreams.d.ts.map +1 -0
- package/dist/react/useDeltaStreams.js +101 -0
- package/dist/react/useDeltaStreams.js.map +1 -0
- package/dist/react/useSmoothText.d.ts +13 -12
- package/dist/react/useSmoothText.d.ts.map +1 -1
- package/dist/react/useSmoothText.js +32 -15
- package/dist/react/useSmoothText.js.map +1 -1
- 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 +20 -4
- package/dist/shared.d.ts.map +1 -1
- package/dist/shared.js +45 -8
- package/dist/shared.js.map +1 -1
- package/dist/validators.d.ts +22981 -5666
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +245 -137
- package/dist/validators.js.map +1 -1
- package/package.json +98 -50
- package/src/UIMessages.combineUIMessages.test.ts +239 -0
- package/src/UIMessages.test.ts +273 -0
- package/src/UIMessages.ts +739 -0
- package/src/client/createTool.ts +293 -76
- package/src/client/defaultComponent.ts +17 -0
- package/src/client/definePlaygroundAPI.ts +67 -31
- package/src/client/files.ts +100 -20
- package/src/client/index.test.ts +40 -85
- package/src/client/index.ts +520 -1290
- package/src/client/messages.ts +237 -0
- package/src/client/mockModel.ts +245 -0
- package/src/client/saveInputMessages.test.ts +583 -0
- package/src/client/saveInputMessages.ts +101 -0
- package/src/client/search.test.ts +1207 -0
- package/src/client/search.ts +577 -70
- package/src/client/start.ts +310 -0
- package/src/client/streamText.ts +163 -0
- package/src/client/streaming.test.ts +186 -0
- package/src/client/streaming.ts +219 -97
- package/src/client/threads.ts +83 -0
- package/src/client/types.ts +368 -219
- package/src/client/utils.ts +27 -0
- package/src/component/_generated/api.ts +64 -0
- package/src/component/_generated/component.ts +4913 -0
- package/src/component/_generated/{server.d.ts → server.ts} +33 -21
- package/src/component/files.ts +11 -2
- package/src/component/messages.test.ts +195 -51
- package/src/component/messages.ts +490 -201
- package/src/component/schema.ts +20 -46
- package/src/component/setup.test.ts +7 -0
- package/src/component/streams.ts +184 -83
- package/src/component/users.test.ts +0 -1
- package/src/component/vector/index.ts +1 -3
- package/src/deltas.test.ts +626 -0
- package/src/deltas.ts +570 -0
- package/src/fromUIMessages.test.ts +497 -0
- package/src/mapping.test.ts +103 -6
- package/src/mapping.ts +422 -161
- package/src/react/SmoothText.tsx +9 -0
- package/src/react/index.ts +10 -230
- package/src/react/optimisticallySendMessage.ts +55 -12
- package/src/react/types.ts +6 -39
- package/src/react/useDeltaStreams.ts +154 -0
- package/src/react/useSmoothText.ts +56 -36
- package/src/react/useStreamingUIMessages.ts +143 -0
- package/src/react/useThreadMessages.ts +262 -0
- package/src/react/useUIMessages.test.ts +255 -0
- package/src/react/useUIMessages.ts +195 -0
- package/src/shared.ts +88 -12
- package/src/test.ts +18 -0
- package/src/toUIMessages.test.ts +1269 -0
- package/src/validators.test.ts +18 -19
- package/src/validators.ts +325 -185
- package/dist/client/_generated/_ignore.d.ts +0 -1
- package/dist/client/_generated/_ignore.d.ts.map +0 -1
- package/dist/client/_generated/_ignore.js +0 -3
- package/dist/client/_generated/_ignore.js.map +0 -1
- package/dist/client/listMessages.d.ts +0 -22
- package/dist/client/listMessages.d.ts.map +0 -1
- package/dist/client/listMessages.js +0 -25
- package/dist/client/listMessages.js.map +0 -1
- package/dist/package.json +0 -3
- package/dist/react/deltas.d.ts +0 -26
- package/dist/react/deltas.d.ts.map +0 -1
- package/dist/react/deltas.js +0 -384
- package/dist/react/deltas.js.map +0 -1
- package/dist/react/toUIMessages.d.ts +0 -15
- package/dist/react/toUIMessages.d.ts.map +0 -1
- package/dist/react/toUIMessages.js +0 -211
- package/dist/react/toUIMessages.js.map +0 -1
- package/src/client/listMessages.ts +0 -38
- package/src/component/_generated/api.d.ts +0 -2202
- package/src/component/_generated/api.js +0 -23
- package/src/component/_generated/server.js +0 -90
- package/src/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +0 -1
- package/src/react/deltas.test.ts +0 -315
- package/src/react/deltas.ts +0 -478
- package/src/react/toUIMessages.test.ts +0 -420
- package/src/react/toUIMessages.ts +0 -253
- package/src/vitest.config.ts +0 -7
- /package/src/component/_generated/{dataModel.d.ts → dataModel.ts} +0 -0
package/README.md
CHANGED
|
@@ -21,34 +21,39 @@ The Agent component is a core building block for building AI agents. It manages
|
|
|
21
21
|
threads and messages, around which you Agents can cooperate in static or dynamic
|
|
22
22
|
workflows.
|
|
23
23
|
|
|
24
|
-
- [Agents](
|
|
25
|
-
represent units of use-case-specific prompting with
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
[
|
|
24
|
+
- [Agents](https://docs.convex.dev/agents/agent-usage) provide an abstraction
|
|
25
|
+
for using LLMs to represent units of use-case-specific prompting with
|
|
26
|
+
associated models, prompts,
|
|
27
|
+
[Tool Calls](https://docs.convex.dev/agents/tools), and behavior in relation
|
|
28
|
+
to other Agents, functions, APIs, and more.
|
|
29
|
+
- [Threads](https://docs.convex.dev/agents/threads) persist
|
|
30
|
+
[messages](https://docs.convex.dev/agents/messages) and can be shared by
|
|
31
|
+
multiple users and agents (including
|
|
32
|
+
[human agents](https://docs.convex.dev/agents/human-agents)).
|
|
31
33
|
- Streaming text and objects using deltas over websockets so all clients stay in
|
|
32
34
|
sync efficiently, without http streaming. Enables streaming from async
|
|
33
35
|
functions.
|
|
34
|
-
- [Conversation context](
|
|
35
|
-
LLM call, including built-in hybrid vector/text
|
|
36
|
-
thread and opt-in search for messages from other
|
|
37
|
-
specified user).
|
|
38
|
-
- [RAG](
|
|
39
|
-
other sources, either up front in the prompt or as tool
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
- [
|
|
36
|
+
- [Conversation context](https://docs.convex.dev/agents/context) is
|
|
37
|
+
automatically included in each LLM call, including built-in hybrid vector/text
|
|
38
|
+
search for messages in the thread and opt-in search for messages from other
|
|
39
|
+
threads (for the same specified user).
|
|
40
|
+
- [RAG](https://docs.convex.dev/agents/rag) techniques are supported for prompt
|
|
41
|
+
augmentation from other sources, either up front in the prompt or as tool
|
|
42
|
+
calls. Integrates with the
|
|
43
|
+
[RAG Component](https://www.convex.dev/components/rag), or DIY.
|
|
44
|
+
- [Workflows](https://docs.convex.dev/agents/workflows) allow building
|
|
45
|
+
multi-step operations that can span agents, users, durably and reliably.
|
|
46
|
+
- [Files](https://docs.convex.dev/agents/files) are supported in thread history
|
|
47
|
+
with automatic saving to [file storage](https://docs.convex.dev/file-storage)
|
|
48
|
+
and ref-counting.
|
|
49
|
+
- [Debugging](https://docs.convex.dev/agents/debugging) is enabled by callbacks,
|
|
50
|
+
the [agent playground](https://docs.convex.dev/agents/playground) where you
|
|
51
|
+
can inspect all metadata and iterate on prompts and context settings, and
|
|
52
|
+
inspection in the dashboard.
|
|
53
|
+
- [Usage tracking](https://docs.convex.dev/agents/usage-tracking) is easy to set
|
|
54
|
+
up, enabling usage attribution per-provider, per-model, per-user, per-agent,
|
|
55
|
+
for billing & more.
|
|
56
|
+
- [Rate limiting](https://docs.convex.dev/agents/rate-limiting), powered by the
|
|
52
57
|
[Rate Limiter Component](https://www.convex.dev/components/rate-limiter),
|
|
53
58
|
helps control the rate at which users can interact with agents and keep you
|
|
54
59
|
from exceeding your LLM provider's limits.
|
|
@@ -58,13 +63,13 @@ workflows.
|
|
|
58
63
|
[](https://youtu.be/tUKMPUlOCHY)
|
|
59
64
|
**Read the [docs](https://docs.convex.dev/agents) for more details.**
|
|
60
65
|
|
|
61
|
-
Play with the
|
|
66
|
+
Play with the example:
|
|
62
67
|
|
|
63
68
|
```sh
|
|
64
69
|
git clone https://github.com/get-convex/agent.git
|
|
65
70
|
cd agent
|
|
66
71
|
npm run setup
|
|
67
|
-
npm run
|
|
72
|
+
npm run dev
|
|
68
73
|
```
|
|
69
74
|
|
|
70
75
|
Found a bug? Feature request?
|
|
@@ -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;AA+dD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CA2CpE"}
|
|
@@ -0,0 +1,546 @@
|
|
|
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
|
+
// Collect all parts from all messages
|
|
267
|
+
const allParts = [];
|
|
268
|
+
for (const message of group) {
|
|
269
|
+
const coreMessage = message.message && toModelMessage(message.message);
|
|
270
|
+
if (!coreMessage)
|
|
271
|
+
continue;
|
|
272
|
+
const content = coreMessage.content;
|
|
273
|
+
const nonStringContent = content && typeof content !== "string" ? content : [];
|
|
274
|
+
const text = extractTextFromMessageDoc(message);
|
|
275
|
+
const partCommon = {
|
|
276
|
+
state: message.streaming ? "streaming" : "done",
|
|
277
|
+
...(message.providerMetadata
|
|
278
|
+
? { providerMetadata: message.providerMetadata }
|
|
279
|
+
: {}),
|
|
280
|
+
};
|
|
281
|
+
// Add reasoning parts
|
|
282
|
+
if (message.reasoning &&
|
|
283
|
+
!nonStringContent.some((c) => c.type === "reasoning")) {
|
|
284
|
+
allParts.push({
|
|
285
|
+
type: "reasoning",
|
|
286
|
+
text: message.reasoning,
|
|
287
|
+
...partCommon,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
// Add text parts if no structured content
|
|
291
|
+
if (text && !nonStringContent.length) {
|
|
292
|
+
allParts.push({
|
|
293
|
+
type: "text",
|
|
294
|
+
text: text,
|
|
295
|
+
...partCommon,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
// Add all structured content parts
|
|
299
|
+
for (const contentPart of nonStringContent) {
|
|
300
|
+
switch (contentPart.type) {
|
|
301
|
+
case "text":
|
|
302
|
+
allParts.push({
|
|
303
|
+
...partCommon,
|
|
304
|
+
...contentPart,
|
|
305
|
+
});
|
|
306
|
+
break;
|
|
307
|
+
case "reasoning":
|
|
308
|
+
allParts.push({
|
|
309
|
+
...partCommon,
|
|
310
|
+
...contentPart,
|
|
311
|
+
});
|
|
312
|
+
break;
|
|
313
|
+
case "file":
|
|
314
|
+
case "image":
|
|
315
|
+
allParts.push(toUIFilePart(contentPart));
|
|
316
|
+
break;
|
|
317
|
+
case "tool-call": {
|
|
318
|
+
allParts.push({
|
|
319
|
+
type: "step-start",
|
|
320
|
+
});
|
|
321
|
+
const toolPart = {
|
|
322
|
+
type: `tool-${contentPart.toolName}`,
|
|
323
|
+
toolCallId: contentPart.toolCallId,
|
|
324
|
+
input: contentPart.input,
|
|
325
|
+
providerExecuted: contentPart.providerExecuted,
|
|
326
|
+
...(message.streaming
|
|
327
|
+
? { state: "input-streaming" }
|
|
328
|
+
: {
|
|
329
|
+
state: "input-available",
|
|
330
|
+
callProviderMetadata: message.providerMetadata,
|
|
331
|
+
}),
|
|
332
|
+
};
|
|
333
|
+
allParts.push(toolPart);
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
case "tool-result": {
|
|
337
|
+
const typedPart = contentPart;
|
|
338
|
+
// Check if this is an execution-denied result
|
|
339
|
+
if (typedPart.output?.type === "execution-denied") {
|
|
340
|
+
const call = allParts.find((part) => part.type === `tool-${contentPart.toolName}` &&
|
|
341
|
+
"toolCallId" in part &&
|
|
342
|
+
part.toolCallId === contentPart.toolCallId);
|
|
343
|
+
if (call) {
|
|
344
|
+
call.state = "output-denied";
|
|
345
|
+
if (!("approval" in call) || !call.approval) {
|
|
346
|
+
call.approval = {
|
|
347
|
+
id: "",
|
|
348
|
+
approved: false,
|
|
349
|
+
reason: typedPart.output.reason,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
const approval = call.approval;
|
|
354
|
+
approval.approved = false;
|
|
355
|
+
approval.reason = typedPart.output.reason;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
}
|
|
360
|
+
const output = typeof typedPart.output?.type === "string"
|
|
361
|
+
? typedPart.output.value
|
|
362
|
+
: typedPart.output;
|
|
363
|
+
// Check for error at both the content part level (isError) and message level
|
|
364
|
+
// isError may exist on stored tool results but isn't in ToolResultPart type
|
|
365
|
+
const hasError = contentPart.isError || message.error;
|
|
366
|
+
const errorText = message.error || (hasError ? String(output) : undefined);
|
|
367
|
+
const call = allParts.find((part) => part.type === `tool-${contentPart.toolName}` &&
|
|
368
|
+
"toolCallId" in part &&
|
|
369
|
+
part.toolCallId === contentPart.toolCallId);
|
|
370
|
+
if (call) {
|
|
371
|
+
if (hasError) {
|
|
372
|
+
call.state = "output-error";
|
|
373
|
+
call.errorText = errorText ?? "Unknown error";
|
|
374
|
+
call.output = output;
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
call.state = "output-available";
|
|
378
|
+
call.output = output;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
// Tool call is on a previous page - create standalone tool part
|
|
383
|
+
if (hasError) {
|
|
384
|
+
allParts.push({
|
|
385
|
+
type: `tool-${contentPart.toolName}`,
|
|
386
|
+
toolCallId: contentPart.toolCallId,
|
|
387
|
+
state: "output-error",
|
|
388
|
+
input: undefined,
|
|
389
|
+
errorText: errorText ?? "Unknown error",
|
|
390
|
+
callProviderMetadata: message.providerMetadata,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
allParts.push({
|
|
395
|
+
type: `tool-${contentPart.toolName}`,
|
|
396
|
+
toolCallId: contentPart.toolCallId,
|
|
397
|
+
state: "output-available",
|
|
398
|
+
input: undefined,
|
|
399
|
+
output,
|
|
400
|
+
callProviderMetadata: message.providerMetadata,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
case "tool-approval-request": {
|
|
407
|
+
// Find the matching tool call
|
|
408
|
+
const typedPart = contentPart;
|
|
409
|
+
const toolCallPart = allParts.find((part) => "toolCallId" in part && part.toolCallId === typedPart.toolCallId);
|
|
410
|
+
if (toolCallPart) {
|
|
411
|
+
toolCallPart.state = "approval-requested";
|
|
412
|
+
toolCallPart.approval = {
|
|
413
|
+
id: typedPart.approvalId,
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
console.warn("Tool approval request without preceding tool call", contentPart);
|
|
418
|
+
}
|
|
419
|
+
break;
|
|
420
|
+
}
|
|
421
|
+
case "tool-approval-response": {
|
|
422
|
+
// Find the tool call that has this approval by matching approval.id
|
|
423
|
+
const typedPart = contentPart;
|
|
424
|
+
const toolCallPart = allParts.find((part) => "approval" in part &&
|
|
425
|
+
part.approval
|
|
426
|
+
?.id === typedPart.approvalId);
|
|
427
|
+
if (toolCallPart) {
|
|
428
|
+
if (typedPart.approved) {
|
|
429
|
+
toolCallPart.state = "approval-responded";
|
|
430
|
+
toolCallPart.approval = {
|
|
431
|
+
id: typedPart.approvalId,
|
|
432
|
+
approved: true,
|
|
433
|
+
reason: typedPart.reason,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
toolCallPart.state = "output-denied";
|
|
438
|
+
toolCallPart.approval = {
|
|
439
|
+
id: typedPart.approvalId,
|
|
440
|
+
approved: false,
|
|
441
|
+
reason: typedPart.reason,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
else {
|
|
446
|
+
console.warn("Tool approval response without matching approval request", contentPart);
|
|
447
|
+
}
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
default: {
|
|
451
|
+
const maybeSource = contentPart;
|
|
452
|
+
if (maybeSource.type === "source") {
|
|
453
|
+
allParts.push(toSourcePart(maybeSource));
|
|
454
|
+
}
|
|
455
|
+
else {
|
|
456
|
+
console.warn("Unknown content part type for assistant", contentPart);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
// Add source parts
|
|
462
|
+
for (const source of message.sources ?? []) {
|
|
463
|
+
allParts.push(toSourcePart(source));
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
return {
|
|
467
|
+
...common,
|
|
468
|
+
role: "assistant",
|
|
469
|
+
text: joinText(allParts),
|
|
470
|
+
status,
|
|
471
|
+
parts: allParts,
|
|
472
|
+
metadata: group.find((m) => m.metadata)?.metadata,
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
function toSourcePart(part) {
|
|
476
|
+
if (part.sourceType === "url") {
|
|
477
|
+
return {
|
|
478
|
+
type: "source-url",
|
|
479
|
+
url: part.url,
|
|
480
|
+
sourceId: part.id,
|
|
481
|
+
providerMetadata: part.providerMetadata,
|
|
482
|
+
title: part.title,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
return {
|
|
486
|
+
type: "source-document",
|
|
487
|
+
mediaType: part.mediaType,
|
|
488
|
+
sourceId: part.id,
|
|
489
|
+
title: part.title,
|
|
490
|
+
filename: part.filename,
|
|
491
|
+
providerMetadata: part.providerMetadata,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
export function combineUIMessages(messages) {
|
|
495
|
+
const combined = messages.reduce((acc, message) => {
|
|
496
|
+
if (!acc.length) {
|
|
497
|
+
return [message];
|
|
498
|
+
}
|
|
499
|
+
const previous = acc.at(-1);
|
|
500
|
+
if (message.order !== previous.order ||
|
|
501
|
+
previous.role !== message.role ||
|
|
502
|
+
message.role !== "assistant") {
|
|
503
|
+
acc.push(message);
|
|
504
|
+
return acc;
|
|
505
|
+
}
|
|
506
|
+
// We will replace it with a combined message
|
|
507
|
+
acc.pop();
|
|
508
|
+
const newParts = [...previous.parts];
|
|
509
|
+
for (const part of message.parts) {
|
|
510
|
+
const toolCallId = getToolCallId(part);
|
|
511
|
+
if (!toolCallId) {
|
|
512
|
+
newParts.push(part);
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
const previousPartIndex = newParts.findIndex((p) => getToolCallId(p) === toolCallId);
|
|
516
|
+
if (previousPartIndex === -1) {
|
|
517
|
+
// Tool call not found in previous parts, add it as new
|
|
518
|
+
newParts.push(part);
|
|
519
|
+
continue;
|
|
520
|
+
}
|
|
521
|
+
const previousPart = newParts.splice(previousPartIndex, 1)[0];
|
|
522
|
+
newParts.push(mergeParts(previousPart, part));
|
|
523
|
+
}
|
|
524
|
+
acc.push({
|
|
525
|
+
...previous,
|
|
526
|
+
...pick(message, ["status", "metadata", "agentName"]),
|
|
527
|
+
parts: newParts,
|
|
528
|
+
text: joinText(newParts),
|
|
529
|
+
});
|
|
530
|
+
return acc;
|
|
531
|
+
}, []);
|
|
532
|
+
return combined;
|
|
533
|
+
}
|
|
534
|
+
function getToolCallId(part) {
|
|
535
|
+
return part.toolCallId;
|
|
536
|
+
}
|
|
537
|
+
function mergeParts(previousPart, part) {
|
|
538
|
+
const merged = { ...previousPart };
|
|
539
|
+
for (const [key, value] of Object.entries(part)) {
|
|
540
|
+
if (value !== undefined) {
|
|
541
|
+
merged[key] = value;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return merged;
|
|
545
|
+
}
|
|
546
|
+
//# sourceMappingURL=UIMessages.js.map
|