@convex-dev/agent 0.0.1-alpha.0 → 0.0.1-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +297 -6
  2. package/dist/commonjs/client/index.d.ts +521 -62
  3. package/dist/commonjs/client/index.d.ts.map +1 -1
  4. package/dist/commonjs/client/index.js +230 -118
  5. package/dist/commonjs/client/index.js.map +1 -1
  6. package/dist/commonjs/client/types.d.ts +3 -0
  7. package/dist/commonjs/client/types.d.ts.map +1 -1
  8. package/dist/commonjs/component/messages.d.ts +22 -17
  9. package/dist/commonjs/component/messages.d.ts.map +1 -1
  10. package/dist/commonjs/component/messages.js +107 -47
  11. package/dist/commonjs/component/messages.js.map +1 -1
  12. package/dist/commonjs/component/schema.d.ts +16 -12
  13. package/dist/commonjs/component/schema.d.ts.map +1 -1
  14. package/dist/commonjs/component/schema.js +10 -3
  15. package/dist/commonjs/component/schema.js.map +1 -1
  16. package/dist/commonjs/component/vector/index.d.ts +41 -0
  17. package/dist/commonjs/component/vector/index.d.ts.map +1 -0
  18. package/dist/commonjs/component/vector/index.js +120 -0
  19. package/dist/commonjs/component/vector/index.js.map +1 -0
  20. package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
  21. package/dist/commonjs/component/vector/tables.js +4 -2
  22. package/dist/commonjs/component/vector/tables.js.map +1 -1
  23. package/dist/commonjs/mapping.d.ts +6 -1
  24. package/dist/commonjs/mapping.d.ts.map +1 -1
  25. package/dist/commonjs/mapping.js +25 -0
  26. package/dist/commonjs/mapping.js.map +1 -1
  27. package/dist/commonjs/validators.d.ts +1375 -0
  28. package/dist/commonjs/validators.d.ts.map +1 -1
  29. package/dist/commonjs/validators.js +27 -0
  30. package/dist/commonjs/validators.js.map +1 -1
  31. package/dist/esm/client/index.d.ts +521 -62
  32. package/dist/esm/client/index.d.ts.map +1 -1
  33. package/dist/esm/client/index.js +230 -118
  34. package/dist/esm/client/index.js.map +1 -1
  35. package/dist/esm/client/types.d.ts +3 -0
  36. package/dist/esm/client/types.d.ts.map +1 -1
  37. package/dist/esm/component/messages.d.ts +22 -17
  38. package/dist/esm/component/messages.d.ts.map +1 -1
  39. package/dist/esm/component/messages.js +107 -47
  40. package/dist/esm/component/messages.js.map +1 -1
  41. package/dist/esm/component/schema.d.ts +16 -12
  42. package/dist/esm/component/schema.d.ts.map +1 -1
  43. package/dist/esm/component/schema.js +10 -3
  44. package/dist/esm/component/schema.js.map +1 -1
  45. package/dist/esm/component/vector/index.d.ts +41 -0
  46. package/dist/esm/component/vector/index.d.ts.map +1 -0
  47. package/dist/esm/component/vector/index.js +120 -0
  48. package/dist/esm/component/vector/index.js.map +1 -0
  49. package/dist/esm/component/vector/tables.d.ts.map +1 -1
  50. package/dist/esm/component/vector/tables.js +4 -2
  51. package/dist/esm/component/vector/tables.js.map +1 -1
  52. package/dist/esm/mapping.d.ts +6 -1
  53. package/dist/esm/mapping.d.ts.map +1 -1
  54. package/dist/esm/mapping.js +25 -0
  55. package/dist/esm/mapping.js.map +1 -1
  56. package/dist/esm/validators.d.ts +1375 -0
  57. package/dist/esm/validators.d.ts.map +1 -1
  58. package/dist/esm/validators.js +27 -0
  59. package/dist/esm/validators.js.map +1 -1
  60. package/package.json +2 -2
  61. package/src/client/index.ts +428 -232
  62. package/src/client/types.ts +4 -0
  63. package/src/component/_generated/api.d.ts +138 -11
  64. package/src/component/messages.ts +136 -66
  65. package/src/component/schema.ts +10 -3
  66. package/src/component/vector/index.ts +144 -0
  67. package/src/component/vector/tables.ts +7 -5
  68. package/src/mapping.ts +46 -11
  69. package/src/validators.test.ts +9 -0
  70. package/src/validators.ts +32 -0
@@ -0,0 +1,144 @@
1
+ import { paginator } from "convex-helpers/server/pagination";
2
+ import { v } from "convex/values";
3
+ import { mutation, query } from "../_generated/server";
4
+ import { getVectorTableName, vVectorDimension, vVectorId } from "./tables";
5
+ import schema from "../schema";
6
+ import { mergedStream } from "convex-helpers/server/stream";
7
+ import { stream } from "convex-helpers/server/stream";
8
+
9
+ export const paginate = query({
10
+ args: {
11
+ vectorDimension: vVectorDimension,
12
+ targetModel: v.string(),
13
+ cursor: v.optional(v.string()),
14
+ limit: v.number(),
15
+ },
16
+ returns: v.object({
17
+ ids: v.array(vVectorId),
18
+ isDone: v.boolean(),
19
+ continueCursor: v.string(),
20
+ }),
21
+ handler: async (ctx, args) => {
22
+ const tableName = getVectorTableName(args.vectorDimension);
23
+ const vectors = await paginator(ctx.db, schema)
24
+ .query(tableName)
25
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
26
+ .withIndex("model_kind_chatId" as any, (q) =>
27
+ q.eq("model", args.targetModel)
28
+ )
29
+ .paginate({
30
+ cursor: args.cursor ?? null,
31
+ numItems: args.limit,
32
+ maximumRowsRead: 300,
33
+ });
34
+ return {
35
+ ids: vectors.page.map((v) => v._id),
36
+ isDone: vectors.isDone,
37
+ continueCursor: vectors.continueCursor,
38
+ };
39
+ },
40
+ });
41
+
42
+ export const deleteBatchForChat = mutation({
43
+ args: {
44
+ vectorDimension: vVectorDimension,
45
+ model: v.string(),
46
+ chatId: v.string(),
47
+ cursor: v.optional(v.string()),
48
+ limit: v.number(),
49
+ },
50
+ returns: v.object({
51
+ isDone: v.boolean(),
52
+ continueCursor: v.string(),
53
+ }),
54
+ handler: async (ctx, args) => {
55
+ const tableName = getVectorTableName(args.vectorDimension);
56
+ const vectors = await mergedStream(
57
+ ["chat", "memory"].map((kind) =>
58
+ stream(ctx.db, schema)
59
+ .query(tableName)
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
61
+ .withIndex("model_kind_chatId" as any, (q) =>
62
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
+ (q.eq("model", args.model) as any)
64
+ .eq("kind", kind)
65
+ .eq("chatId", args.chatId)
66
+ )
67
+ ),
68
+ ["chatId"]
69
+ ).paginate({
70
+ cursor: args.cursor ?? null,
71
+ numItems: args.limit,
72
+ maximumRowsRead: 300,
73
+ });
74
+ await Promise.all(vectors.page.map((v) => ctx.db.delete(v._id)));
75
+ return {
76
+ isDone: vectors.isDone,
77
+ continueCursor: vectors.continueCursor,
78
+ };
79
+ },
80
+ });
81
+
82
+ export const insertBatch = mutation({
83
+ args: {
84
+ vectorDimension: vVectorDimension,
85
+ vectors: v.array(
86
+ v.object({
87
+ model: v.string(),
88
+ kind: v.union(v.literal("chat"), v.literal("memory")),
89
+ userId: v.optional(v.string()),
90
+ chatId: v.optional(v.string()),
91
+ vector: v.array(v.number()),
92
+ })
93
+ ),
94
+ },
95
+ returns: v.null(),
96
+ handler: async (ctx, args) => {
97
+ await Promise.all(
98
+ args.vectors.map((v) =>
99
+ ctx.db.insert(getVectorTableName(args.vectorDimension), {
100
+ model: v.model,
101
+ kind: v.kind,
102
+ userId: v.userId,
103
+ chatId: v.chatId,
104
+ vector: v.vector,
105
+ model_kind_userId: v.userId ? [v.model, v.kind, v.userId] : undefined,
106
+ model_kind_chatId: v.chatId ? [v.model, v.kind, v.chatId] : undefined,
107
+ })
108
+ )
109
+ );
110
+ },
111
+ });
112
+
113
+ export const updateBatch = mutation({
114
+ args: {
115
+ vectors: v.array(
116
+ v.object({
117
+ model: v.string(),
118
+ id: vVectorId,
119
+ vector: v.array(v.number()),
120
+ })
121
+ ),
122
+ },
123
+ returns: v.null(),
124
+ handler: async (ctx, args) => {
125
+ await Promise.all(
126
+ args.vectors.map((v) =>
127
+ ctx.db.patch(v.id, {
128
+ model: v.model,
129
+ vector: v.vector,
130
+ })
131
+ )
132
+ );
133
+ },
134
+ });
135
+
136
+ export const deleteBatch = mutation({
137
+ args: {
138
+ ids: v.array(vVectorId),
139
+ },
140
+ returns: v.null(),
141
+ handler: async (ctx, args) => {
142
+ await Promise.all(args.ids.map((id) => ctx.db.delete(id)));
143
+ },
144
+ });
@@ -20,11 +20,13 @@ const embeddings = {
20
20
  };
21
21
 
22
22
  function table<D extends number>(dimensions: D): Table<D> {
23
- return defineTable(embeddings).vectorIndex("vector", {
24
- vectorField: "vector",
25
- dimensions,
26
- filterFields: ["model_kind_userId", "model_kind_chatId"],
27
- });
23
+ return defineTable(embeddings)
24
+ .vectorIndex("vector", {
25
+ vectorField: "vector",
26
+ dimensions,
27
+ filterFields: ["model_kind_userId", "model_kind_chatId"],
28
+ })
29
+ .index("model_kind_chatId", ["model", "kind", "chatId"]);
28
30
  }
29
31
 
30
32
  export const VectorDimensions = [
package/src/mapping.ts CHANGED
@@ -1,16 +1,20 @@
1
- import type {
2
- AssistantContent,
3
- CoreAssistantMessage,
4
- CoreMessage,
5
- CoreToolMessage,
6
- DataContent,
7
- GenerateTextResult,
8
- StepResult,
9
- ToolContent,
10
- ToolSet,
11
- UserContent,
1
+ import {
2
+ convertToCoreMessages,
3
+ coreMessageSchema,
4
+ type AssistantContent,
5
+ type CoreAssistantMessage,
6
+ type CoreMessage,
7
+ type CoreToolMessage,
8
+ type DataContent,
9
+ type GenerateTextResult,
10
+ type StepResult,
11
+ type ToolContent,
12
+ type ToolSet,
13
+ type Message as UIMessage,
14
+ type UserContent,
12
15
  } from "ai";
13
16
  import { MessageWithFileAndId, Step } from "./validators";
17
+ import { assert } from "convex-helpers";
14
18
 
15
19
  export type SerializeUrlsAndUint8Arrays<T> = T extends URL
16
20
  ? string
@@ -158,3 +162,34 @@ function deserializeUrl(urlOrString: string | ArrayBuffer): URL | DataContent {
158
162
  }
159
163
  return urlOrString;
160
164
  }
165
+
166
+ export function promptOrMessagesToCoreMessages(args: {
167
+ system?: string;
168
+ prompt?: string;
169
+ messages?: CoreMessage[] | Omit<UIMessage, "id">[];
170
+ }): CoreMessage[] {
171
+ const messages: CoreMessage[] = [];
172
+ if (args.system) {
173
+ messages.push({ role: "system", content: args.system });
174
+ }
175
+ if (!args.messages) {
176
+ assert(args.prompt, "messages or prompt is required");
177
+ messages.push({ role: "user", content: args.prompt });
178
+ } else if (
179
+ args.messages.some(
180
+ (m) =>
181
+ typeof m === "object" &&
182
+ m !== null &&
183
+ (m.role === "data" || // UI-only role
184
+ "toolInvocations" in m || // UI-specific field
185
+ "parts" in m || // UI-specific field
186
+ "experimental_attachments" in m)
187
+ )
188
+ ) {
189
+ messages.push(...convertToCoreMessages(args.messages as UIMessage[]));
190
+ } else {
191
+ messages.push(...coreMessageSchema.array().parse(args.messages));
192
+ }
193
+ assert(messages.length > 0, "Messages must contain at least one message");
194
+ return messages;
195
+ }
@@ -3,11 +3,13 @@ import { expectTypeOf, test } from "vitest";
3
3
  import {
4
4
  vAssistantContent,
5
5
  vAssistantMessage,
6
+ vContextOptions,
6
7
  vFilePart,
7
8
  vImagePart,
8
9
  vMessage,
9
10
  vReasoningPart,
10
11
  vRedactedReasoningPart,
12
+ vStorageOptions,
11
13
  vSystemMessage,
12
14
  vTextPart,
13
15
  vToolCallPart,
@@ -31,6 +33,7 @@ import {
31
33
  UserContent,
32
34
  } from "ai";
33
35
  import { SerializeUrlsAndUint8Arrays } from "./mapping";
36
+ import { ContextOptions, StorageOptions } from "./client";
34
37
 
35
38
  // type assertion
36
39
  type OurUserContent = SerializeUrlsAndUint8Arrays<UserContent>;
@@ -98,4 +101,10 @@ type OurMessage = SerializeUrlsAndUint8Arrays<CoreMessage>;
98
101
  expectTypeOf<OurMessage>().toExtend<Infer<typeof vMessage>>();
99
102
  expectTypeOf<Infer<typeof vMessage>>().toExtend<OurMessage>();
100
103
 
104
+ expectTypeOf<Infer<typeof vContextOptions>>().toExtend<ContextOptions>();
105
+ expectTypeOf<ContextOptions>().toExtend<Infer<typeof vContextOptions>>();
106
+
107
+ expectTypeOf<Infer<typeof vStorageOptions>>().toExtend<StorageOptions>();
108
+ expectTypeOf<StorageOptions>().toExtend<Infer<typeof vStorageOptions>>();
109
+
101
110
  test("noop", () => { });
package/src/validators.ts CHANGED
@@ -256,3 +256,35 @@ export const vSearchOptions = v.object({
256
256
  messageRange: v.optional(v.object({ before: v.number(), after: v.number() })),
257
257
  });
258
258
  export type SearchOptions = Infer<typeof vSearchOptions>;
259
+
260
+ export const vContextOptionsSearchOptions = v.object({
261
+ limit: v.number(),
262
+ textSearch: v.optional(v.boolean()),
263
+ vectorSearch: v.optional(v.boolean()),
264
+ messageRange: v.optional(v.object({ before: v.number(), after: v.number() })),
265
+ });
266
+
267
+ export const vContextOptions = v.object({
268
+ includeToolCalls: v.optional(v.boolean()),
269
+ recentMessages: v.optional(v.number()),
270
+ searchOptions: v.optional(vContextOptionsSearchOptions),
271
+ searchOtherChats: v.optional(v.boolean()),
272
+ });
273
+
274
+ export const vStorageOptions = v.object({
275
+ saveAllInputMessages: v.optional(v.boolean()),
276
+ saveAllOutputMessages: v.optional(v.boolean()),
277
+ });
278
+
279
+ export const vChatArgs = v.object({
280
+ maxSteps: v.optional(v.number()),
281
+ prompt: v.optional(v.string()),
282
+ messages: v.optional(v.array(vMessage)),
283
+ });
284
+
285
+ export const vObjectArgs = v.object({
286
+ output: v.optional(v.any()),
287
+ mode: v.optional(v.literal("json")),
288
+ prompt: v.optional(v.string()),
289
+ messages: v.optional(v.array(vMessage)),
290
+ });