@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
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
/**
|
|
3
|
-
* Generated `api` utility.
|
|
4
|
-
*
|
|
5
|
-
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
-
*
|
|
7
|
-
* To regenerate, run `npx convex dev`.
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import { anyApi, componentsGeneric } from "convex/server";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* A utility for referencing Convex functions in your app's API.
|
|
15
|
-
*
|
|
16
|
-
* Usage:
|
|
17
|
-
* ```js
|
|
18
|
-
* const myFunctionReference = api.myModule.myFunction;
|
|
19
|
-
* ```
|
|
20
|
-
*/
|
|
21
|
-
export const api = anyApi;
|
|
22
|
-
export const internal = anyApi;
|
|
23
|
-
export const components = componentsGeneric();
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
/* eslint-disable */
|
|
2
|
-
/**
|
|
3
|
-
* Generated utilities for implementing server-side Convex query and mutation functions.
|
|
4
|
-
*
|
|
5
|
-
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
-
*
|
|
7
|
-
* To regenerate, run `npx convex dev`.
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import {
|
|
12
|
-
actionGeneric,
|
|
13
|
-
httpActionGeneric,
|
|
14
|
-
queryGeneric,
|
|
15
|
-
mutationGeneric,
|
|
16
|
-
internalActionGeneric,
|
|
17
|
-
internalMutationGeneric,
|
|
18
|
-
internalQueryGeneric,
|
|
19
|
-
componentsGeneric,
|
|
20
|
-
} from "convex/server";
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Define a query in this Convex app's public API.
|
|
24
|
-
*
|
|
25
|
-
* This function will be allowed to read your Convex database and will be accessible from the client.
|
|
26
|
-
*
|
|
27
|
-
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
|
28
|
-
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
|
29
|
-
*/
|
|
30
|
-
export const query = queryGeneric;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Define a query that is only accessible from other Convex functions (but not from the client).
|
|
34
|
-
*
|
|
35
|
-
* This function will be allowed to read from your Convex database. It will not be accessible from the client.
|
|
36
|
-
*
|
|
37
|
-
* @param func - The query function. It receives a {@link QueryCtx} as its first argument.
|
|
38
|
-
* @returns The wrapped query. Include this as an `export` to name it and make it accessible.
|
|
39
|
-
*/
|
|
40
|
-
export const internalQuery = internalQueryGeneric;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Define a mutation in this Convex app's public API.
|
|
44
|
-
*
|
|
45
|
-
* This function will be allowed to modify your Convex database and will be accessible from the client.
|
|
46
|
-
*
|
|
47
|
-
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
|
48
|
-
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
|
49
|
-
*/
|
|
50
|
-
export const mutation = mutationGeneric;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Define a mutation that is only accessible from other Convex functions (but not from the client).
|
|
54
|
-
*
|
|
55
|
-
* This function will be allowed to modify your Convex database. It will not be accessible from the client.
|
|
56
|
-
*
|
|
57
|
-
* @param func - The mutation function. It receives a {@link MutationCtx} as its first argument.
|
|
58
|
-
* @returns The wrapped mutation. Include this as an `export` to name it and make it accessible.
|
|
59
|
-
*/
|
|
60
|
-
export const internalMutation = internalMutationGeneric;
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Define an action in this Convex app's public API.
|
|
64
|
-
*
|
|
65
|
-
* An action is a function which can execute any JavaScript code, including non-deterministic
|
|
66
|
-
* code and code with side-effects, like calling third-party services.
|
|
67
|
-
* They can be run in Convex's JavaScript environment or in Node.js using the "use node" directive.
|
|
68
|
-
* They can interact with the database indirectly by calling queries and mutations using the {@link ActionCtx}.
|
|
69
|
-
*
|
|
70
|
-
* @param func - The action. It receives an {@link ActionCtx} as its first argument.
|
|
71
|
-
* @returns The wrapped action. Include this as an `export` to name it and make it accessible.
|
|
72
|
-
*/
|
|
73
|
-
export const action = actionGeneric;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Define an action that is only accessible from other Convex functions (but not from the client).
|
|
77
|
-
*
|
|
78
|
-
* @param func - The function. It receives an {@link ActionCtx} as its first argument.
|
|
79
|
-
* @returns The wrapped function. Include this as an `export` to name it and make it accessible.
|
|
80
|
-
*/
|
|
81
|
-
export const internalAction = internalActionGeneric;
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Define a Convex HTTP action.
|
|
85
|
-
*
|
|
86
|
-
* @param func - The function. It receives an {@link ActionCtx} as its first argument, and a `Request` object
|
|
87
|
-
* as its second.
|
|
88
|
-
* @returns The wrapped endpoint function. Route a URL path to this function in `convex/http.js`.
|
|
89
|
-
*/
|
|
90
|
-
export const httpAction = httpActionGeneric;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"3.2.4","results":[[":client/index.test.ts",{"duration":75.65995979309082,"failed":false}],[":component/messages.test.ts",{"duration":43.858792304992676,"failed":false}],[":react/toUIMessages.test.ts",{"duration":4.371167182922363,"failed":false}]]}
|
package/src/react/deltas.test.ts
DELETED
|
@@ -1,315 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { mergeDeltas, applyDeltasToStreamMessage } from "./deltas.js";
|
|
3
|
-
import type {
|
|
4
|
-
StreamMessage,
|
|
5
|
-
StreamDelta,
|
|
6
|
-
TextStreamPart,
|
|
7
|
-
} from "../validators.js";
|
|
8
|
-
import { omit } from "convex-helpers";
|
|
9
|
-
|
|
10
|
-
function makeStreamMessage(
|
|
11
|
-
streamId: string,
|
|
12
|
-
order: number,
|
|
13
|
-
stepOrder: number,
|
|
14
|
-
): StreamMessage {
|
|
15
|
-
return {
|
|
16
|
-
streamId,
|
|
17
|
-
order,
|
|
18
|
-
stepOrder,
|
|
19
|
-
} as StreamMessage;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function makeDelta(
|
|
23
|
-
streamId: string,
|
|
24
|
-
start: number,
|
|
25
|
-
end: number,
|
|
26
|
-
parts: TextStreamPart[],
|
|
27
|
-
): StreamDelta {
|
|
28
|
-
return {
|
|
29
|
-
streamId,
|
|
30
|
-
start,
|
|
31
|
-
end,
|
|
32
|
-
parts,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
describe("mergeDeltas", () => {
|
|
37
|
-
it("merges a single text-delta into a message", () => {
|
|
38
|
-
const streamId = "s1";
|
|
39
|
-
const streamMessages = [makeStreamMessage(streamId, 1, 0)];
|
|
40
|
-
const deltas = [
|
|
41
|
-
makeDelta(streamId, 0, 5, [{ type: "text-delta", textDelta: "Hello" }]),
|
|
42
|
-
];
|
|
43
|
-
const [messages, newStreams, changed] = mergeDeltas(
|
|
44
|
-
"thread1",
|
|
45
|
-
streamMessages,
|
|
46
|
-
[],
|
|
47
|
-
deltas,
|
|
48
|
-
);
|
|
49
|
-
expect(messages).toHaveLength(1);
|
|
50
|
-
expect(messages[0].text).toBe("Hello");
|
|
51
|
-
expect(messages[0].message?.role).toBe("assistant");
|
|
52
|
-
expect(changed).toBe(true);
|
|
53
|
-
expect(newStreams[0].cursor).toBe(5);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it("merges multiple deltas for the same stream", () => {
|
|
57
|
-
const streamId = "s1";
|
|
58
|
-
const streamMessages = [makeStreamMessage(streamId, 1, 0)];
|
|
59
|
-
const deltas = [
|
|
60
|
-
makeDelta(streamId, 0, 5, [{ type: "text-delta", textDelta: "Hello" }]),
|
|
61
|
-
makeDelta(streamId, 5, 11, [
|
|
62
|
-
{ type: "text-delta", textDelta: " World!" },
|
|
63
|
-
]),
|
|
64
|
-
];
|
|
65
|
-
const [messages, newStreams, changed] = mergeDeltas(
|
|
66
|
-
"thread1",
|
|
67
|
-
streamMessages,
|
|
68
|
-
[],
|
|
69
|
-
deltas,
|
|
70
|
-
);
|
|
71
|
-
expect(messages).toHaveLength(1);
|
|
72
|
-
expect(messages[0].text).toBe("Hello World!");
|
|
73
|
-
expect(changed).toBe(true);
|
|
74
|
-
expect(newStreams[0].cursor).toBe(11);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("handles tool-call and tool-result parts", () => {
|
|
78
|
-
const streamId = "s2";
|
|
79
|
-
const streamMessages = [makeStreamMessage(streamId, 2, 0)];
|
|
80
|
-
const deltas = [
|
|
81
|
-
makeDelta(streamId, 0, 1, [
|
|
82
|
-
{
|
|
83
|
-
type: "tool-call",
|
|
84
|
-
toolCallId: "call1",
|
|
85
|
-
toolName: "myTool",
|
|
86
|
-
args: "",
|
|
87
|
-
},
|
|
88
|
-
]),
|
|
89
|
-
makeDelta(streamId, 1, 2, [
|
|
90
|
-
{
|
|
91
|
-
type: "tool-result",
|
|
92
|
-
toolCallId: "call1",
|
|
93
|
-
toolName: "myTool",
|
|
94
|
-
result: "42",
|
|
95
|
-
},
|
|
96
|
-
]),
|
|
97
|
-
];
|
|
98
|
-
const [messages, _, changed] = mergeDeltas(
|
|
99
|
-
"thread1",
|
|
100
|
-
streamMessages,
|
|
101
|
-
[],
|
|
102
|
-
deltas,
|
|
103
|
-
);
|
|
104
|
-
expect(messages).toHaveLength(2);
|
|
105
|
-
expect(messages[0].message?.role).toBe("assistant");
|
|
106
|
-
expect(messages[0].tool).toBe(true);
|
|
107
|
-
const content = messages[0].message?.content;
|
|
108
|
-
expect(content).toEqual([
|
|
109
|
-
{
|
|
110
|
-
type: "tool-call",
|
|
111
|
-
toolCallId: "call1",
|
|
112
|
-
toolName: "myTool",
|
|
113
|
-
args: "",
|
|
114
|
-
},
|
|
115
|
-
]);
|
|
116
|
-
expect(messages[1].message?.role).toBe("tool");
|
|
117
|
-
expect(messages[1].tool).toBe(true);
|
|
118
|
-
expect(messages[1].message?.content).toEqual([
|
|
119
|
-
{
|
|
120
|
-
type: "tool-result",
|
|
121
|
-
toolCallId: "call1",
|
|
122
|
-
toolName: "myTool",
|
|
123
|
-
result: "42",
|
|
124
|
-
},
|
|
125
|
-
]);
|
|
126
|
-
expect(changed).toBe(true);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it("returns changed=false if no new deltas", () => {
|
|
130
|
-
const streamId = "s3";
|
|
131
|
-
const streamMessages = [makeStreamMessage(streamId, 3, 0)];
|
|
132
|
-
const deltas: StreamDelta[] = [];
|
|
133
|
-
const [messages, newStreams, changed] = mergeDeltas(
|
|
134
|
-
"thread1",
|
|
135
|
-
streamMessages,
|
|
136
|
-
[],
|
|
137
|
-
deltas,
|
|
138
|
-
);
|
|
139
|
-
expect(messages).toHaveLength(0);
|
|
140
|
-
expect(changed).toBe(false);
|
|
141
|
-
expect(newStreams[0].cursor).toBe(0);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("handles multiple streams and sorts by order/stepOrder", () => {
|
|
145
|
-
const s1 = makeStreamMessage("s1", 1, 0);
|
|
146
|
-
const s2 = makeStreamMessage("s2", 2, 0);
|
|
147
|
-
const deltas = [
|
|
148
|
-
makeDelta("s2", 0, 3, [{ type: "text-delta", textDelta: "B" }]),
|
|
149
|
-
makeDelta("s1", 0, 3, [{ type: "text-delta", textDelta: "A" }]),
|
|
150
|
-
];
|
|
151
|
-
const [messages, _, changed] = mergeDeltas("thread1", [s2, s1], [], deltas);
|
|
152
|
-
expect(messages).toHaveLength(2);
|
|
153
|
-
expect(messages[0].text).toBe("A");
|
|
154
|
-
expect(messages[1].text).toBe("B");
|
|
155
|
-
expect(changed).toBe(true);
|
|
156
|
-
// Sorted by order
|
|
157
|
-
expect(messages[0].order).toBe(1);
|
|
158
|
-
expect(messages[1].order).toBe(2);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it("does not duplicate text content when merging sequential text-deltas", () => {
|
|
162
|
-
const streamId = "s4";
|
|
163
|
-
const streamMessages = [makeStreamMessage(streamId, 4, 0)];
|
|
164
|
-
const deltas = [
|
|
165
|
-
makeDelta(streamId, 0, 5, [{ type: "text-delta", textDelta: "Hello" }]),
|
|
166
|
-
makeDelta(streamId, 5, 11, [
|
|
167
|
-
{ type: "text-delta", textDelta: " World!" },
|
|
168
|
-
]),
|
|
169
|
-
makeDelta(streamId, 11, 12, [{ type: "text-delta", textDelta: "!" }]),
|
|
170
|
-
];
|
|
171
|
-
const [messages] = mergeDeltas("thread1", streamMessages, [], deltas);
|
|
172
|
-
expect(messages).toHaveLength(1);
|
|
173
|
-
expect(messages[0].text).toBe("Hello World!!");
|
|
174
|
-
// There should only be one text part per message
|
|
175
|
-
const content = messages[0].message?.content;
|
|
176
|
-
if (Array.isArray(content)) {
|
|
177
|
-
const textParts = content.filter((p) => p.type === "text");
|
|
178
|
-
expect(textParts).toHaveLength(1);
|
|
179
|
-
expect(textParts[0].text).toBe("Hello World!!");
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it("does not duplicate reasoning parts", () => {
|
|
184
|
-
const streamId = "s6";
|
|
185
|
-
const streamMessages = [makeStreamMessage(streamId, 6, 0)];
|
|
186
|
-
const deltas = [
|
|
187
|
-
makeDelta(streamId, 0, 1, [
|
|
188
|
-
{ type: "reasoning", textDelta: "I'm thinking..." },
|
|
189
|
-
]),
|
|
190
|
-
makeDelta(streamId, 1, 2, [
|
|
191
|
-
{ type: "reasoning", textDelta: " Still thinking..." },
|
|
192
|
-
]),
|
|
193
|
-
];
|
|
194
|
-
const [messages] = mergeDeltas("thread1", streamMessages, [], deltas);
|
|
195
|
-
expect(messages).toHaveLength(1);
|
|
196
|
-
if (Array.isArray(messages[0].message?.content)) {
|
|
197
|
-
const reasoningParts = messages[0].message.content.filter(
|
|
198
|
-
(p) => p.type === "reasoning",
|
|
199
|
-
);
|
|
200
|
-
expect(reasoningParts).toHaveLength(1);
|
|
201
|
-
expect(reasoningParts[0].text).toBe("I'm thinking... Still thinking...");
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it("applyDeltasToStreamMessage is idempotent and does not duplicate content", () => {
|
|
206
|
-
const streamId = "s7";
|
|
207
|
-
const streamMessage = makeStreamMessage(streamId, 7, 0);
|
|
208
|
-
const deltas = [
|
|
209
|
-
makeDelta(streamId, 0, 5, [{ type: "text-delta", textDelta: "Hello" }]),
|
|
210
|
-
makeDelta(streamId, 5, 11, [
|
|
211
|
-
{ type: "text-delta", textDelta: " World!" },
|
|
212
|
-
]),
|
|
213
|
-
];
|
|
214
|
-
// First call: apply both deltas
|
|
215
|
-
let [result, changed] = applyDeltasToStreamMessage(
|
|
216
|
-
"thread1",
|
|
217
|
-
streamMessage,
|
|
218
|
-
undefined,
|
|
219
|
-
deltas,
|
|
220
|
-
);
|
|
221
|
-
expect(result.messages).toHaveLength(1);
|
|
222
|
-
expect(result.messages[0].text).toBe("Hello World!");
|
|
223
|
-
// Second call: re-apply the same deltas (should not duplicate)
|
|
224
|
-
[result, changed] = applyDeltasToStreamMessage(
|
|
225
|
-
"thread1",
|
|
226
|
-
streamMessage,
|
|
227
|
-
result,
|
|
228
|
-
deltas,
|
|
229
|
-
);
|
|
230
|
-
expect(result.messages).toHaveLength(1);
|
|
231
|
-
expect(result.messages[0].text).toBe("Hello World!");
|
|
232
|
-
// Third call: add a new delta
|
|
233
|
-
const moreDeltas = [
|
|
234
|
-
...deltas,
|
|
235
|
-
makeDelta(streamId, 11, 12, [{ type: "text-delta", textDelta: "!" }]),
|
|
236
|
-
];
|
|
237
|
-
[result, changed] = applyDeltasToStreamMessage(
|
|
238
|
-
"thread1",
|
|
239
|
-
streamMessage,
|
|
240
|
-
result,
|
|
241
|
-
moreDeltas,
|
|
242
|
-
);
|
|
243
|
-
expect(changed).toBe(true);
|
|
244
|
-
expect(result.messages).toHaveLength(1);
|
|
245
|
-
expect(result.messages[0].text).toBe("Hello World!!");
|
|
246
|
-
// Re-apply all deltas again (should still not duplicate)
|
|
247
|
-
[result, changed] = applyDeltasToStreamMessage(
|
|
248
|
-
"thread1",
|
|
249
|
-
streamMessage,
|
|
250
|
-
result,
|
|
251
|
-
moreDeltas,
|
|
252
|
-
);
|
|
253
|
-
expect(changed).toBe(false);
|
|
254
|
-
expect(result.messages).toHaveLength(1);
|
|
255
|
-
expect(result.messages[0].text).toBe("Hello World!!");
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
it("mergeDeltas is pure and does not mutate inputs", () => {
|
|
259
|
-
const streamId = "s8";
|
|
260
|
-
const streamMessages = [makeStreamMessage(streamId, 8, 0)];
|
|
261
|
-
const deltas = [
|
|
262
|
-
makeDelta(streamId, 0, 5, [{ type: "text-delta", textDelta: "Hello" }]),
|
|
263
|
-
makeDelta(streamId, 5, 11, [
|
|
264
|
-
{ type: "text-delta", textDelta: " World!" },
|
|
265
|
-
]),
|
|
266
|
-
];
|
|
267
|
-
// Deep freeze inputs to catch mutation
|
|
268
|
-
function deepFreeze(obj: unknown): unknown {
|
|
269
|
-
if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
|
|
270
|
-
Object.freeze(obj);
|
|
271
|
-
for (const key of Object.keys(obj)) {
|
|
272
|
-
deepFreeze((obj as Record<string, unknown>)[key]);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return obj;
|
|
276
|
-
}
|
|
277
|
-
deepFreeze(streamMessages);
|
|
278
|
-
deepFreeze(deltas);
|
|
279
|
-
const [messages1, streams1, changed1] = mergeDeltas(
|
|
280
|
-
"thread1",
|
|
281
|
-
streamMessages,
|
|
282
|
-
[],
|
|
283
|
-
deltas,
|
|
284
|
-
);
|
|
285
|
-
const [messages2, streams2, changed2] = mergeDeltas(
|
|
286
|
-
"thread1",
|
|
287
|
-
streamMessages,
|
|
288
|
-
[],
|
|
289
|
-
deltas,
|
|
290
|
-
);
|
|
291
|
-
expect(messages1.map((m) => omit(m, ["_creationTime"]))).toEqual(
|
|
292
|
-
messages2.map((m) => omit(m, ["_creationTime"])),
|
|
293
|
-
);
|
|
294
|
-
expect(
|
|
295
|
-
streams1.map((s) => ({
|
|
296
|
-
...s,
|
|
297
|
-
messages: s.messages.map((m) => omit(m, ["_creationTime"])),
|
|
298
|
-
})),
|
|
299
|
-
).toEqual(
|
|
300
|
-
streams2.map((s) => ({
|
|
301
|
-
...s,
|
|
302
|
-
messages: s.messages.map((m) => omit(m, ["_creationTime"])),
|
|
303
|
-
})),
|
|
304
|
-
);
|
|
305
|
-
expect(changed1).toBe(changed2);
|
|
306
|
-
// Inputs should remain unchanged
|
|
307
|
-
expect(streamMessages).toEqual([makeStreamMessage(streamId, 8, 0)]);
|
|
308
|
-
expect(deltas).toEqual([
|
|
309
|
-
makeDelta(streamId, 0, 5, [{ type: "text-delta", textDelta: "Hello" }]),
|
|
310
|
-
makeDelta(streamId, 5, 11, [
|
|
311
|
-
{ type: "text-delta", textDelta: " World!" },
|
|
312
|
-
]),
|
|
313
|
-
]);
|
|
314
|
-
});
|
|
315
|
-
});
|