@convex-dev/agent 0.1.6-alpha.1 → 0.1.7-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 +23 -12
- package/dist/commonjs/client/_generated/_ignore.d.ts +1 -0
- package/dist/commonjs/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/commonjs/client/_generated/_ignore.js +3 -0
- package/dist/commonjs/client/_generated/_ignore.js.map +1 -0
- package/dist/commonjs/client/files.d.ts +57 -0
- package/dist/commonjs/client/files.d.ts.map +1 -0
- package/dist/commonjs/client/files.js +124 -0
- package/dist/commonjs/client/files.js.map +1 -0
- package/dist/commonjs/client/index.d.ts +489 -318
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +652 -550
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/client/types.d.ts +35 -5
- package/dist/commonjs/client/types.d.ts.map +1 -1
- package/dist/commonjs/component/_generated/api.d.ts +53 -711
- package/dist/commonjs/component/files.d.ts +66 -21
- package/dist/commonjs/component/files.d.ts.map +1 -1
- package/dist/commonjs/component/files.js +71 -26
- package/dist/commonjs/component/files.js.map +1 -1
- package/dist/commonjs/component/messages.d.ts +37 -499
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +44 -124
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +951 -3785
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +8 -25
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/streams.d.ts +3 -3
- package/dist/commonjs/mapping.d.ts +28 -19
- package/dist/commonjs/mapping.d.ts.map +1 -1
- package/dist/commonjs/mapping.js +136 -81
- package/dist/commonjs/mapping.js.map +1 -1
- package/dist/commonjs/react/index.d.ts.map +1 -1
- package/dist/commonjs/react/index.js +2 -1
- package/dist/commonjs/react/index.js.map +1 -1
- package/dist/commonjs/react/toUIMessages.d.ts.map +1 -1
- package/dist/commonjs/react/toUIMessages.js +12 -6
- package/dist/commonjs/react/toUIMessages.js.map +1 -1
- package/dist/commonjs/react/usePaginatedQuery.d.ts +241 -0
- package/dist/commonjs/react/usePaginatedQuery.d.ts.map +1 -0
- package/dist/commonjs/react/usePaginatedQuery.js +647 -0
- package/dist/commonjs/react/usePaginatedQuery.js.map +1 -0
- package/dist/commonjs/validators.d.ts +851 -3388
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +11 -37
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/commonjs.tsbuildinfo +1 -1
- package/dist/esm/client/_generated/_ignore.d.ts +1 -0
- package/dist/esm/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/esm/client/_generated/_ignore.js +3 -0
- package/dist/esm/client/_generated/_ignore.js.map +1 -0
- package/dist/esm/client/files.d.ts +57 -0
- package/dist/esm/client/files.d.ts.map +1 -0
- package/dist/esm/client/files.js +124 -0
- package/dist/esm/client/files.js.map +1 -0
- package/dist/esm/client/index.d.ts +489 -318
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +652 -550
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/types.d.ts +35 -5
- package/dist/esm/client/types.d.ts.map +1 -1
- package/dist/esm/component/_generated/api.d.ts +53 -711
- package/dist/esm/component/files.d.ts +66 -21
- package/dist/esm/component/files.d.ts.map +1 -1
- package/dist/esm/component/files.js +71 -26
- package/dist/esm/component/files.js.map +1 -1
- package/dist/esm/component/messages.d.ts +37 -499
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +44 -124
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +951 -3785
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +8 -25
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/streams.d.ts +3 -3
- package/dist/esm/mapping.d.ts +28 -19
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +136 -81
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +2 -1
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/react/toUIMessages.d.ts.map +1 -1
- package/dist/esm/react/toUIMessages.js +12 -6
- package/dist/esm/react/toUIMessages.js.map +1 -1
- package/dist/esm/react/usePaginatedQuery.d.ts +241 -0
- package/dist/esm/react/usePaginatedQuery.d.ts.map +1 -0
- package/dist/esm/react/usePaginatedQuery.js +647 -0
- package/dist/esm/react/usePaginatedQuery.js.map +1 -0
- package/dist/esm/validators.d.ts +851 -3388
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +11 -37
- package/dist/esm/validators.js.map +1 -1
- package/dist/esm.tsbuildinfo +1 -1
- package/package.json +11 -9
- package/src/client/_generated/_ignore.ts +1 -0
- package/src/client/files.ts +167 -0
- package/src/client/index.test.ts +127 -1
- package/src/client/index.ts +970 -812
- package/src/client/setup.test.ts +29 -0
- package/src/client/types.ts +41 -3
- package/src/component/_generated/api.d.ts +53 -711
- package/src/component/files.test.ts +130 -0
- package/src/component/files.ts +83 -27
- package/src/component/messages.test.ts +2 -1
- package/src/component/messages.ts +46 -136
- package/src/component/schema.ts +7 -28
- package/src/mapping.test.ts +163 -0
- package/src/mapping.ts +173 -103
- package/src/react/deltas.test.ts +4 -1
- package/src/react/index.ts +2 -1
- package/src/react/toUIMessages.ts +12 -6
- package/src/react/usePaginatedQuery.ts +933 -0
- package/src/validators.ts +33 -47
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"email": "support@convex.dev",
|
|
8
8
|
"url": "https://github.com/get-convex/agent/issues"
|
|
9
9
|
},
|
|
10
|
-
"version": "0.1.
|
|
10
|
+
"version": "0.1.7-alpha.0",
|
|
11
11
|
"license": "Apache-2.0",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"convex",
|
|
@@ -18,16 +18,15 @@
|
|
|
18
18
|
"type": "module",
|
|
19
19
|
"scripts": {
|
|
20
20
|
"example": "npm run setup && cd example && npm run dev",
|
|
21
|
-
"dev": "run-p 'build:watch'
|
|
22
|
-
"setup": "
|
|
21
|
+
"dev": "run-p 'example' 'build:watch'",
|
|
22
|
+
"setup": "node setup.cjs",
|
|
23
23
|
"build": "npm run build:esm && npm run build:cjs",
|
|
24
24
|
"build:watch": "cd src && npx chokidar '../tsconfig.json' '*.ts' 'react/**/*.ts' 'component/**/*.ts' 'client/**/*.ts' -c 'npm run build' --initial",
|
|
25
25
|
"build:esm": "tsc --project ./esm.json && npm run copy:dts:esm && echo '{\\n \"type\": \"module\"\\n}' > dist/esm/package.json",
|
|
26
26
|
"build:cjs": "tsc --project ./commonjs.json && npm run copy:dts:cjs && echo '{\\n \"type\": \"commonjs\"\\n}' > dist/commonjs/package.json",
|
|
27
|
-
"copy:dts:esm": "
|
|
28
|
-
"copy:dts:cjs": "
|
|
27
|
+
"copy:dts:esm": "cpy 'src/**/*.d.ts' 'dist/esm/' --parents",
|
|
28
|
+
"copy:dts:cjs": "cpy 'src/**/*.d.ts' 'dist/commonjs/' --parents",
|
|
29
29
|
"typecheck": "tsc --noEmit",
|
|
30
|
-
"prepare": "npm run build",
|
|
31
30
|
"prepack": "node node10stubs.mjs",
|
|
32
31
|
"postpack": "node node10stubs.mjs --cleanup",
|
|
33
32
|
"alpha": "rm -rf dist && npm run build && npm run test && npm version prerelease --preid alpha && npm publish --tag alpha && git push --tags",
|
|
@@ -90,9 +89,9 @@
|
|
|
90
89
|
}
|
|
91
90
|
},
|
|
92
91
|
"peerDependencies": {
|
|
93
|
-
"ai": "^4.3.
|
|
92
|
+
"ai": "^4.3.16",
|
|
94
93
|
"convex": "^1.23.0",
|
|
95
|
-
"convex-helpers": "^0.1.
|
|
94
|
+
"convex-helpers": "^0.1.91",
|
|
96
95
|
"react": "^18.3.1 || ^19.0.0"
|
|
97
96
|
},
|
|
98
97
|
"peerDependenciesMeta": {
|
|
@@ -101,12 +100,15 @@
|
|
|
101
100
|
}
|
|
102
101
|
},
|
|
103
102
|
"devDependencies": {
|
|
103
|
+
"@edge-runtime/vm": "^5.0.0",
|
|
104
104
|
"@eslint/js": "^9.9.1",
|
|
105
105
|
"@types/node": "^18.19.86",
|
|
106
106
|
"@types/react": "^19.1.1",
|
|
107
107
|
"chokidar-cli": "^3.0.0",
|
|
108
|
-
"convex
|
|
108
|
+
"convex": "^1.24.8",
|
|
109
|
+
"convex-helpers": "^0.1.92",
|
|
109
110
|
"convex-test": "^0.0.37",
|
|
111
|
+
"cpy-cli": "^5.0.0",
|
|
110
112
|
"eslint": "^9.24.0",
|
|
111
113
|
"eslint-plugin-jsx-a11y": "^6.8.0",
|
|
112
114
|
"eslint-plugin-react": "^7.34.0",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
// This is only here so convex-test can detect a _generated folder
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import type { FilePart, ImagePart } from "ai";
|
|
2
|
+
import type { Id } from "../component/_generated/dataModel.js";
|
|
3
|
+
import type { ActionCtx, AgentComponent, QueryCtx } from "./types.js";
|
|
4
|
+
import type { RunMutationCtx } from "@convex-dev/prosemirror-sync";
|
|
5
|
+
|
|
6
|
+
export const MAX_FILE_SIZE = 1024 * 64;
|
|
7
|
+
|
|
8
|
+
type File = {
|
|
9
|
+
url: string;
|
|
10
|
+
fileId: string;
|
|
11
|
+
storageId: Id<"_storage">;
|
|
12
|
+
hash: string;
|
|
13
|
+
filename: string | undefined;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Store a file in the file storage and return the URL and fileId.
|
|
18
|
+
* @param ctx A ctx object from an action.
|
|
19
|
+
* @param component The agent component.
|
|
20
|
+
* @param blob The blob to store.
|
|
21
|
+
* @param filename The filename to store.
|
|
22
|
+
* @param sha256 The sha256 hash of the file. If not provided, it will be
|
|
23
|
+
* computed. However, to ensure no corruption during transfer, you can
|
|
24
|
+
* calculate this on the client to enforce integrity.
|
|
25
|
+
* @returns The URL, fileId, and storageId of the stored file.
|
|
26
|
+
*/
|
|
27
|
+
export async function storeFile(
|
|
28
|
+
ctx: ActionCtx | RunMutationCtx,
|
|
29
|
+
component: AgentComponent,
|
|
30
|
+
blob: Blob,
|
|
31
|
+
filename?: string,
|
|
32
|
+
sha256?: string
|
|
33
|
+
): Promise<{
|
|
34
|
+
file: File;
|
|
35
|
+
filePart: FilePart;
|
|
36
|
+
imagePart: ImagePart | undefined;
|
|
37
|
+
}> {
|
|
38
|
+
if (!("runAction" in ctx)) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
"You're trying to save a file that's too large in a mutation. " +
|
|
41
|
+
"You can store the file in file storage from an action first, then pass a URL instead. " +
|
|
42
|
+
"To have the agent component track the file, you can use `saveFile` from an action then use the fileId with getFile in the mutation. " +
|
|
43
|
+
"Read more in the docs."
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
const hash =
|
|
47
|
+
sha256 ||
|
|
48
|
+
Array.from(
|
|
49
|
+
new Uint8Array(
|
|
50
|
+
await crypto.subtle.digest("SHA-256", await blob.arrayBuffer())
|
|
51
|
+
)
|
|
52
|
+
)
|
|
53
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
54
|
+
.join("");
|
|
55
|
+
const reused = await ctx.runMutation(component.files.useExistingFile, {
|
|
56
|
+
hash,
|
|
57
|
+
filename,
|
|
58
|
+
});
|
|
59
|
+
if (reused) {
|
|
60
|
+
const url = (await ctx.storage.getUrl(reused.storageId))!;
|
|
61
|
+
return {
|
|
62
|
+
...getParts(url, blob.type, filename),
|
|
63
|
+
file: {
|
|
64
|
+
url,
|
|
65
|
+
fileId: reused.fileId,
|
|
66
|
+
storageId: reused.storageId as Id<"_storage">,
|
|
67
|
+
hash,
|
|
68
|
+
filename,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const newStorageId = await ctx.storage.store(blob);
|
|
73
|
+
if (sha256) {
|
|
74
|
+
const metadata = await ctx.storage.getMetadata(newStorageId);
|
|
75
|
+
if (metadata?.sha256 !== sha256) {
|
|
76
|
+
throw new Error("Hash mismatch: " + metadata?.sha256 + " != " + sha256);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const { fileId, storageId } = await ctx.runMutation(component.files.addFile, {
|
|
80
|
+
storageId: newStorageId,
|
|
81
|
+
hash,
|
|
82
|
+
filename,
|
|
83
|
+
mimeType: blob.type,
|
|
84
|
+
});
|
|
85
|
+
const url = (await ctx.storage.getUrl(storageId as Id<"_storage">))!;
|
|
86
|
+
if (storageId !== newStorageId) {
|
|
87
|
+
// We're re-using another file's storageId
|
|
88
|
+
// Because we try to reuse the file above, this should be very very rare
|
|
89
|
+
// and only in the case of racing to check then store the file.
|
|
90
|
+
await ctx.storage.delete(newStorageId);
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
...getParts(url, blob.type, filename),
|
|
94
|
+
file: {
|
|
95
|
+
url,
|
|
96
|
+
fileId,
|
|
97
|
+
storageId: storageId as Id<"_storage">,
|
|
98
|
+
hash,
|
|
99
|
+
filename,
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get file metadata from the component.
|
|
106
|
+
* This also returns filePart (and imagePart if the file is an image),
|
|
107
|
+
* which are useful to construct a CoreMessage like
|
|
108
|
+
* ```ts
|
|
109
|
+
* const { filePart, imagePart } = await getFile(ctx, components.agent, fileId);
|
|
110
|
+
* const message: UserMessage = {
|
|
111
|
+
* role: "user",
|
|
112
|
+
* content: [imagePart ?? filePart],
|
|
113
|
+
* };
|
|
114
|
+
* ```
|
|
115
|
+
* @param ctx A ctx object from an action or query.
|
|
116
|
+
* @param component The agent component, usually `components.agent`.
|
|
117
|
+
* @param fileId The fileId of the file to get.
|
|
118
|
+
* @returns The file metadata and content parts.
|
|
119
|
+
*/
|
|
120
|
+
export async function getFile(
|
|
121
|
+
ctx: ActionCtx | QueryCtx,
|
|
122
|
+
component: AgentComponent,
|
|
123
|
+
fileId: string
|
|
124
|
+
) {
|
|
125
|
+
const file = await ctx.runQuery(component.files.get, { fileId });
|
|
126
|
+
if (!file) {
|
|
127
|
+
throw new Error(`File not found in component: ${fileId}`);
|
|
128
|
+
}
|
|
129
|
+
const url = await ctx.storage.getUrl(file.storageId as Id<"_storage">);
|
|
130
|
+
if (!url) {
|
|
131
|
+
throw new Error(`File not found in storage: ${file.storageId}`);
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
...getParts(url, file.mimeType, file.filename),
|
|
135
|
+
file: {
|
|
136
|
+
fileId,
|
|
137
|
+
url,
|
|
138
|
+
storageId: file.storageId as Id<"_storage">,
|
|
139
|
+
hash: file.hash,
|
|
140
|
+
filename: file.filename,
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function getParts(
|
|
146
|
+
url: string,
|
|
147
|
+
mimeType: string,
|
|
148
|
+
filename: string | undefined
|
|
149
|
+
): {
|
|
150
|
+
filePart: FilePart;
|
|
151
|
+
imagePart: ImagePart | undefined;
|
|
152
|
+
} {
|
|
153
|
+
const filePart: FilePart = {
|
|
154
|
+
type: "file",
|
|
155
|
+
data: new URL(url),
|
|
156
|
+
mimeType,
|
|
157
|
+
filename,
|
|
158
|
+
};
|
|
159
|
+
const imagePart: ImagePart | undefined = mimeType.startsWith("image/")
|
|
160
|
+
? {
|
|
161
|
+
type: "image",
|
|
162
|
+
image: new URL(url),
|
|
163
|
+
mimeType,
|
|
164
|
+
}
|
|
165
|
+
: undefined;
|
|
166
|
+
return { filePart, imagePart };
|
|
167
|
+
}
|
package/src/client/index.test.ts
CHANGED
|
@@ -1,5 +1,98 @@
|
|
|
1
1
|
import { describe, expect, test } from "vitest";
|
|
2
|
-
import { filterOutOrphanedToolMessages, type MessageDoc } from ".";
|
|
2
|
+
import { Agent, filterOutOrphanedToolMessages, type MessageDoc } from ".";
|
|
3
|
+
import type { DataModelFromSchemaDefinition } from "convex/server";
|
|
4
|
+
import {
|
|
5
|
+
anyApi,
|
|
6
|
+
queryGeneric,
|
|
7
|
+
mutationGeneric,
|
|
8
|
+
actionGeneric,
|
|
9
|
+
} from "convex/server";
|
|
10
|
+
import type {
|
|
11
|
+
ApiFromModules,
|
|
12
|
+
ActionBuilder,
|
|
13
|
+
MutationBuilder,
|
|
14
|
+
QueryBuilder,
|
|
15
|
+
} from "convex/server";
|
|
16
|
+
import { v } from "convex/values";
|
|
17
|
+
import { defineSchema } from "convex/server";
|
|
18
|
+
import { MockLanguageModelV1 } from "ai/test";
|
|
19
|
+
import type { LanguageModelV1, LanguageModelV1StreamPart } from "ai";
|
|
20
|
+
import { simulateReadableStream } from "ai";
|
|
21
|
+
import { components, initConvexTest } from "./setup.test";
|
|
22
|
+
|
|
23
|
+
const schema = defineSchema({});
|
|
24
|
+
type DataModel = DataModelFromSchemaDefinition<typeof schema>;
|
|
25
|
+
// type DatabaseReader = GenericDatabaseReader<DataModel>;
|
|
26
|
+
const query = queryGeneric as QueryBuilder<DataModel, "public">;
|
|
27
|
+
const mutation = mutationGeneric as MutationBuilder<DataModel, "public">;
|
|
28
|
+
const action = actionGeneric as ActionBuilder<DataModel, "public">;
|
|
29
|
+
|
|
30
|
+
const agent = new Agent(components.agent, {
|
|
31
|
+
name: "test",
|
|
32
|
+
instructions: "You are a test agent",
|
|
33
|
+
// TODO: get mock model that works in v8
|
|
34
|
+
chat: mockModel(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const testQuery = query({
|
|
38
|
+
args: { threadId: v.string() },
|
|
39
|
+
handler: async (ctx, args) => {
|
|
40
|
+
return await agent.listMessages(ctx, {
|
|
41
|
+
threadId: args.threadId,
|
|
42
|
+
paginationOpts: {
|
|
43
|
+
cursor: null,
|
|
44
|
+
numItems: 10,
|
|
45
|
+
},
|
|
46
|
+
excludeToolMessages: true,
|
|
47
|
+
statuses: ["success"],
|
|
48
|
+
});
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export const createThread = mutation({
|
|
53
|
+
args: {},
|
|
54
|
+
handler: async (ctx) => {
|
|
55
|
+
return await agent.createThread(ctx, {
|
|
56
|
+
userId: "1",
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export const createAndGenerate = action({
|
|
62
|
+
args: {},
|
|
63
|
+
handler: async (ctx) => {
|
|
64
|
+
const { thread } = await agent.createThread(ctx, {
|
|
65
|
+
userId: "1",
|
|
66
|
+
});
|
|
67
|
+
const result = await thread.generateText({
|
|
68
|
+
messages: [{ role: "user", content: "Hello" }],
|
|
69
|
+
});
|
|
70
|
+
return result.text;
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const testApi: ApiFromModules<{
|
|
75
|
+
fns: {
|
|
76
|
+
createAndGenerate: typeof createAndGenerate;
|
|
77
|
+
createThread: typeof createThread;
|
|
78
|
+
testQuery: typeof testQuery;
|
|
79
|
+
};
|
|
80
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
81
|
+
}>["fns"] = anyApi["index.test"] as any;
|
|
82
|
+
|
|
83
|
+
describe("Agent thick client", () => {
|
|
84
|
+
test("should create a thread", async () => {
|
|
85
|
+
const t = initConvexTest(schema);
|
|
86
|
+
const result = await t.mutation(testApi.createThread, {});
|
|
87
|
+
expect(result.threadId).toBeTypeOf("string");
|
|
88
|
+
});
|
|
89
|
+
test("should create a thread and generate text", async () => {
|
|
90
|
+
const t = initConvexTest(schema);
|
|
91
|
+
const result = await t.action(testApi.createAndGenerate, {});
|
|
92
|
+
expect(result).toBeDefined();
|
|
93
|
+
expect(result).toMatch("This is a sample response");
|
|
94
|
+
});
|
|
95
|
+
});
|
|
3
96
|
|
|
4
97
|
describe("filterOutOrphanedToolMessages", () => {
|
|
5
98
|
const call1: MessageDoc = {
|
|
@@ -66,3 +159,36 @@ describe("filterOutOrphanedToolMessages", () => {
|
|
|
66
159
|
expect(filterOutOrphanedToolMessages([response1, call2])).toEqual([call2]);
|
|
67
160
|
});
|
|
68
161
|
});
|
|
162
|
+
|
|
163
|
+
function mockModel(): LanguageModelV1 {
|
|
164
|
+
return new MockLanguageModelV1({
|
|
165
|
+
provider: "mock",
|
|
166
|
+
modelId: "mock",
|
|
167
|
+
doGenerate: async ({ prompt }) => ({
|
|
168
|
+
finishReason: "stop",
|
|
169
|
+
usage: { completionTokens: 10, promptTokens: 3 },
|
|
170
|
+
logprobs: undefined,
|
|
171
|
+
rawCall: { rawPrompt: null, rawSettings: {} },
|
|
172
|
+
text: `This is a sample response to ${JSON.stringify(prompt)}`,
|
|
173
|
+
}),
|
|
174
|
+
doStream: async ({ prompt }) => ({
|
|
175
|
+
stream: simulateReadableStream({
|
|
176
|
+
chunkDelayInMs: 50,
|
|
177
|
+
initialDelayInMs: 100,
|
|
178
|
+
chunks: [
|
|
179
|
+
{
|
|
180
|
+
type: "text-delta",
|
|
181
|
+
textDelta: `This is a sample response to ${JSON.stringify(prompt)}`,
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: "finish",
|
|
185
|
+
finishReason: "stop",
|
|
186
|
+
logprobs: undefined,
|
|
187
|
+
usage: { completionTokens: 10, promptTokens: 3 },
|
|
188
|
+
},
|
|
189
|
+
] as LanguageModelV1StreamPart[],
|
|
190
|
+
}),
|
|
191
|
+
rawCall: { rawPrompt: null, rawSettings: {} },
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
}
|