@convex-dev/agent 0.1.16-alpha.0 → 0.1.16-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.
- package/README.md +26 -15
- package/dist/client/createTool.d.ts +2 -2
- package/dist/client/createTool.d.ts.map +1 -1
- package/dist/client/createTool.js.map +1 -1
- package/dist/client/files.js +2 -2
- package/dist/client/files.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +47 -29
- package/dist/client/index.js.map +1 -1
- package/dist/client/search.d.ts +2 -3
- package/dist/client/search.d.ts.map +1 -1
- package/dist/client/search.js +2 -1
- package/dist/client/search.js.map +1 -1
- package/dist/client/types.d.ts +7 -9
- package/dist/client/types.d.ts.map +1 -1
- package/dist/component/messages.d.ts +1 -1
- package/dist/component/messages.d.ts.map +1 -1
- package/dist/component/messages.js +5 -5
- package/dist/component/messages.js.map +1 -1
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js.map +1 -1
- package/dist/mapping.d.ts.map +1 -1
- package/dist/mapping.js +3 -1
- package/dist/mapping.js.map +1 -1
- package/dist/react/deltas.d.ts.map +1 -1
- package/dist/react/deltas.js +6 -5
- package/dist/react/deltas.js.map +1 -1
- package/dist/validators.js +1 -2
- package/dist/validators.js.map +1 -1
- package/package.json +1 -1
- package/src/client/createTool.ts +9 -6
- package/src/client/files.ts +8 -8
- package/src/client/index.test.ts +14 -12
- package/src/client/index.ts +127 -99
- package/src/client/listMessages.ts +1 -1
- package/src/client/search.ts +14 -14
- package/src/client/streaming.ts +7 -7
- package/src/client/types.ts +29 -23
- package/src/component/apiKeys.ts +1 -1
- package/src/component/files.test.ts +1 -1
- package/src/component/files.ts +6 -6
- package/src/component/messages.test.ts +6 -6
- package/src/component/messages.ts +44 -43
- package/src/component/schema.ts +1 -2
- package/src/component/streams.ts +27 -27
- package/src/component/threads.test.ts +4 -4
- package/src/component/threads.ts +4 -4
- package/src/component/users.test.ts +2 -2
- package/src/component/users.ts +4 -4
- package/src/component/vector/index.ts +11 -11
- package/src/component/vector/tables.ts +6 -6
- package/src/mapping.test.ts +4 -4
- package/src/mapping.ts +18 -17
- package/src/react/deltas.test.ts +16 -16
- package/src/react/deltas.ts +19 -18
- package/src/react/index.ts +11 -11
- package/src/react/optimisticallySendMessage.ts +2 -2
- package/src/react/toUIMessages.test.ts +10 -10
- package/src/react/toUIMessages.ts +6 -6
- package/src/react/useSmoothText.ts +6 -6
- package/src/validators.ts +24 -24
package/src/component/schema.ts
CHANGED
|
@@ -118,7 +118,7 @@ export const schema = defineSchema({
|
|
|
118
118
|
v.object({
|
|
119
119
|
kind: v.literal("aborted"),
|
|
120
120
|
reason: v.string(),
|
|
121
|
-
})
|
|
121
|
+
}),
|
|
122
122
|
),
|
|
123
123
|
})
|
|
124
124
|
// There should only be one per "order" index
|
|
@@ -197,5 +197,4 @@ export const vMessageDoc = v.object({
|
|
|
197
197
|
});
|
|
198
198
|
export type MessageDoc = Infer<typeof vMessageDoc>;
|
|
199
199
|
|
|
200
|
-
|
|
201
200
|
export default schema;
|
package/src/component/streams.ts
CHANGED
|
@@ -51,7 +51,7 @@ export const listDeltas = query({
|
|
|
51
51
|
v.object({
|
|
52
52
|
streamId: v.id("streamingMessages"),
|
|
53
53
|
cursor: v.number(),
|
|
54
|
-
})
|
|
54
|
+
}),
|
|
55
55
|
),
|
|
56
56
|
},
|
|
57
57
|
returns: v.array(vStreamDelta),
|
|
@@ -62,16 +62,16 @@ export const listDeltas = query({
|
|
|
62
62
|
const streamDeltas = await ctx.db
|
|
63
63
|
.query("streamDeltas")
|
|
64
64
|
.withIndex("streamId_start_end", (q) =>
|
|
65
|
-
q.eq("streamId", cursor.streamId).gte("start", cursor.cursor)
|
|
65
|
+
q.eq("streamId", cursor.streamId).gte("start", cursor.cursor),
|
|
66
66
|
)
|
|
67
67
|
.take(
|
|
68
|
-
Math.min(MAX_DELTAS_PER_STREAM, MAX_DELTAS_PER_REQUEST - totalDeltas)
|
|
68
|
+
Math.min(MAX_DELTAS_PER_STREAM, MAX_DELTAS_PER_REQUEST - totalDeltas),
|
|
69
69
|
);
|
|
70
70
|
totalDeltas += streamDeltas.length;
|
|
71
71
|
deltas.push(
|
|
72
72
|
...streamDeltas.map((d) =>
|
|
73
|
-
pick(d, ["streamId", "start", "end", "parts"])
|
|
74
|
-
)
|
|
73
|
+
pick(d, ["streamId", "start", "end", "parts"]),
|
|
74
|
+
),
|
|
75
75
|
);
|
|
76
76
|
if (totalDeltas >= MAX_DELTAS_PER_REQUEST) {
|
|
77
77
|
break;
|
|
@@ -96,7 +96,7 @@ export const create = mutation({
|
|
|
96
96
|
const timeoutFnId = await ctx.scheduler.runAfter(
|
|
97
97
|
TIMEOUT_INTERVAL,
|
|
98
98
|
internal.streams.timeoutStream,
|
|
99
|
-
{ streamId }
|
|
99
|
+
{ streamId },
|
|
100
100
|
);
|
|
101
101
|
await ctx.db.patch(streamId, { state: { ...state, timeoutFnId } });
|
|
102
102
|
return streamId;
|
|
@@ -112,9 +112,9 @@ export const list = query({
|
|
|
112
112
|
v.union(
|
|
113
113
|
v.literal("streaming"),
|
|
114
114
|
v.literal("finished"),
|
|
115
|
-
v.literal("aborted")
|
|
116
|
-
)
|
|
117
|
-
)
|
|
115
|
+
v.literal("aborted"),
|
|
116
|
+
),
|
|
117
|
+
),
|
|
118
118
|
),
|
|
119
119
|
},
|
|
120
120
|
returns: v.array(vStreamMessage),
|
|
@@ -128,11 +128,11 @@ export const list = query({
|
|
|
128
128
|
q
|
|
129
129
|
.eq("threadId", args.threadId)
|
|
130
130
|
.eq("state.kind", status)
|
|
131
|
-
.gte("order", args.startOrder ?? 0)
|
|
131
|
+
.gte("order", args.startOrder ?? 0),
|
|
132
132
|
)
|
|
133
|
-
.order("desc")
|
|
133
|
+
.order("desc"),
|
|
134
134
|
),
|
|
135
|
-
["order", "stepOrder"]
|
|
135
|
+
["order", "stepOrder"],
|
|
136
136
|
).take(100);
|
|
137
137
|
|
|
138
138
|
return messages.map((m) => ({
|
|
@@ -165,7 +165,7 @@ export const abortByOrder = mutation({
|
|
|
165
165
|
q
|
|
166
166
|
.eq("threadId", args.threadId)
|
|
167
167
|
.eq("state.kind", "streaming")
|
|
168
|
-
.eq("order", args.order)
|
|
168
|
+
.eq("order", args.order),
|
|
169
169
|
)
|
|
170
170
|
.take(100);
|
|
171
171
|
for (const stream of streams) {
|
|
@@ -189,7 +189,7 @@ export const abort = mutation({
|
|
|
189
189
|
|
|
190
190
|
async function abortById(
|
|
191
191
|
ctx: MutationCtx,
|
|
192
|
-
args: { streamId: Id<"streamingMessages">; reason: string }
|
|
192
|
+
args: { streamId: Id<"streamingMessages">; reason: string },
|
|
193
193
|
) {
|
|
194
194
|
const stream = await ctx.db.get(args.streamId);
|
|
195
195
|
if (!stream) {
|
|
@@ -197,7 +197,7 @@ async function abortById(
|
|
|
197
197
|
}
|
|
198
198
|
if (stream.state.kind !== "streaming") {
|
|
199
199
|
console.warn(
|
|
200
|
-
`Stream trying to abort but not currently streaming (${stream.state.kind}): ${args.streamId}
|
|
200
|
+
`Stream trying to abort but not currently streaming (${stream.state.kind}): ${args.streamId}`,
|
|
201
201
|
);
|
|
202
202
|
return false;
|
|
203
203
|
}
|
|
@@ -210,7 +210,7 @@ async function abortById(
|
|
|
210
210
|
|
|
211
211
|
async function cleanupTimeoutFn(
|
|
212
212
|
ctx: MutationCtx,
|
|
213
|
-
stream: Doc<"streamingMessages"
|
|
213
|
+
stream: Doc<"streamingMessages">,
|
|
214
214
|
) {
|
|
215
215
|
if (stream.state.kind === "streaming" && stream.state.timeoutFnId) {
|
|
216
216
|
const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
|
|
@@ -236,7 +236,7 @@ export const finish = mutation({
|
|
|
236
236
|
}
|
|
237
237
|
if (stream.state.kind !== "streaming") {
|
|
238
238
|
console.warn(
|
|
239
|
-
`Stream trying to finish but not currently streaming: ${args.streamId}
|
|
239
|
+
`Stream trying to finish but not currently streaming: ${args.streamId}`,
|
|
240
240
|
);
|
|
241
241
|
return;
|
|
242
242
|
}
|
|
@@ -244,7 +244,7 @@ export const finish = mutation({
|
|
|
244
244
|
const cleanupFnId = await ctx.scheduler.runAfter(
|
|
245
245
|
DELETE_STREAM_DELAY,
|
|
246
246
|
api.streams.deleteStreamAsync,
|
|
247
|
-
{ streamId: args.streamId }
|
|
247
|
+
{ streamId: args.streamId },
|
|
248
248
|
);
|
|
249
249
|
await ctx.db.patch(args.streamId, {
|
|
250
250
|
state: { kind: "finished", endedAt: Date.now(), cleanupFnId },
|
|
@@ -254,7 +254,7 @@ export const finish = mutation({
|
|
|
254
254
|
|
|
255
255
|
async function heartbeatStream(
|
|
256
256
|
ctx: MutationCtx,
|
|
257
|
-
args: { streamId: Id<"streamingMessages"> }
|
|
257
|
+
args: { streamId: Id<"streamingMessages"> },
|
|
258
258
|
) {
|
|
259
259
|
const stream = await ctx.db.get(args.streamId);
|
|
260
260
|
if (!stream) {
|
|
@@ -283,7 +283,7 @@ async function heartbeatStream(
|
|
|
283
283
|
const timeoutFnId = await ctx.scheduler.runAfter(
|
|
284
284
|
TIMEOUT_INTERVAL,
|
|
285
285
|
internal.streams.timeoutStream,
|
|
286
|
-
{ streamId: args.streamId }
|
|
286
|
+
{ streamId: args.streamId },
|
|
287
287
|
);
|
|
288
288
|
await ctx.db.patch(args.streamId, {
|
|
289
289
|
state: {
|
|
@@ -314,7 +314,7 @@ export const timeoutStream = internalMutation({
|
|
|
314
314
|
|
|
315
315
|
async function deletePageForStreamId(
|
|
316
316
|
ctx: MutationCtx,
|
|
317
|
-
args: { streamId: Id<"streamingMessages">; cursor?: string }
|
|
317
|
+
args: { streamId: Id<"streamingMessages">; cursor?: string },
|
|
318
318
|
) {
|
|
319
319
|
const deltas = await paginator(ctx.db, schema)
|
|
320
320
|
.query("streamDeltas")
|
|
@@ -339,7 +339,7 @@ async function deletePageForStreamId(
|
|
|
339
339
|
|
|
340
340
|
export async function deleteStreamsPageForThreadId(
|
|
341
341
|
ctx: MutationCtx,
|
|
342
|
-
args: { threadId: Id<"threads">; streamOrder?: number; deltaCursor?: string }
|
|
342
|
+
args: { threadId: Id<"threads">; streamOrder?: number; deltaCursor?: string },
|
|
343
343
|
) {
|
|
344
344
|
const allStreamMessages =
|
|
345
345
|
schema.tables.streamingMessages.validator.fields.state.members
|
|
@@ -351,8 +351,8 @@ export async function deleteStreamsPageForThreadId(
|
|
|
351
351
|
q
|
|
352
352
|
.eq("threadId", args.threadId)
|
|
353
353
|
.eq("state.kind", stateKind)
|
|
354
|
-
.gte("order", args.streamOrder ?? 0)
|
|
355
|
-
)
|
|
354
|
+
.gte("order", args.streamOrder ?? 0),
|
|
355
|
+
),
|
|
356
356
|
);
|
|
357
357
|
let deltaCursor = args.deltaCursor;
|
|
358
358
|
const streamMessage = await mergedStream(allStreamMessages, [
|
|
@@ -417,7 +417,7 @@ export const deleteAllStreamsForThreadIdAsync = mutation({
|
|
|
417
417
|
threadId: args.threadId,
|
|
418
418
|
streamOrder: result.streamOrder,
|
|
419
419
|
deltaCursor: result.deltaCursor,
|
|
420
|
-
}
|
|
420
|
+
},
|
|
421
421
|
);
|
|
422
422
|
} else {
|
|
423
423
|
await ctx.db.delete(args.threadId);
|
|
@@ -460,7 +460,7 @@ export const deleteAllStreamsForThreadIdSync = action({
|
|
|
460
460
|
handler: async (ctx, args) => {
|
|
461
461
|
let result = await ctx.runMutation(
|
|
462
462
|
internal.streams.deleteStreamsPageForThreadIdMutation,
|
|
463
|
-
args
|
|
463
|
+
args,
|
|
464
464
|
);
|
|
465
465
|
while (!result.isDone) {
|
|
466
466
|
result = await ctx.runMutation(
|
|
@@ -469,7 +469,7 @@ export const deleteAllStreamsForThreadIdSync = action({
|
|
|
469
469
|
...args,
|
|
470
470
|
streamOrder: result.streamOrder,
|
|
471
471
|
deltaCursor: result.deltaCursor,
|
|
472
|
-
}
|
|
472
|
+
},
|
|
473
473
|
);
|
|
474
474
|
}
|
|
475
475
|
},
|
|
@@ -225,7 +225,7 @@ describe("threads", () => {
|
|
|
225
225
|
t.mutation(api.threads.updateThread, {
|
|
226
226
|
threadId: thread._id as Id<"threads">,
|
|
227
227
|
patch: { title: "New Title" },
|
|
228
|
-
})
|
|
228
|
+
}),
|
|
229
229
|
).rejects.toThrow();
|
|
230
230
|
});
|
|
231
231
|
|
|
@@ -368,7 +368,7 @@ describe("threads", () => {
|
|
|
368
368
|
{
|
|
369
369
|
threadId: thread._id as Id<"threads">,
|
|
370
370
|
cursor: currentResult.cursor,
|
|
371
|
-
}
|
|
371
|
+
},
|
|
372
372
|
);
|
|
373
373
|
iterations++;
|
|
374
374
|
}
|
|
@@ -471,7 +471,7 @@ describe("threads", () => {
|
|
|
471
471
|
await expect(
|
|
472
472
|
t.action(api.threads.deleteAllForThreadIdSync, {
|
|
473
473
|
threadId: thread._id as Id<"threads">,
|
|
474
|
-
})
|
|
474
|
+
}),
|
|
475
475
|
).resolves.not.toThrow();
|
|
476
476
|
|
|
477
477
|
// Thread should be deleted
|
|
@@ -499,7 +499,7 @@ describe("threads", () => {
|
|
|
499
499
|
await expect(
|
|
500
500
|
t.action(api.threads.deleteAllForThreadIdSync, {
|
|
501
501
|
threadId: thread._id as Id<"threads">,
|
|
502
|
-
})
|
|
502
|
+
}),
|
|
503
503
|
).resolves.not.toThrow();
|
|
504
504
|
});
|
|
505
505
|
|
package/src/component/threads.ts
CHANGED
|
@@ -104,7 +104,7 @@ export const searchThreadTitles = query({
|
|
|
104
104
|
.withSearchIndex("title", (q) =>
|
|
105
105
|
args.userId
|
|
106
106
|
? q.search("title", args.query).eq("userId", args.userId ?? undefined)
|
|
107
|
-
: q.search("title", args.query)
|
|
107
|
+
: q.search("title", args.query),
|
|
108
108
|
)
|
|
109
109
|
.take(args.limit);
|
|
110
110
|
return threads.map(publicThread);
|
|
@@ -138,7 +138,7 @@ export const deleteAllForThreadIdSync = action({
|
|
|
138
138
|
while (true) {
|
|
139
139
|
const result: DeleteThreadReturns = await ctx.runMutation(
|
|
140
140
|
internal.threads._deletePageForThreadId,
|
|
141
|
-
{ threadId: args.threadId, cursor, limit: args.limit }
|
|
141
|
+
{ threadId: args.threadId, cursor, limit: args.limit },
|
|
142
142
|
);
|
|
143
143
|
if (result.isDone) {
|
|
144
144
|
break;
|
|
@@ -218,12 +218,12 @@ export const deleteAllForThreadIdAsync = mutation({
|
|
|
218
218
|
|
|
219
219
|
async function deletePageForThreadIdHandler(
|
|
220
220
|
ctx: MutationCtx,
|
|
221
|
-
args: DeleteThreadArgs
|
|
221
|
+
args: DeleteThreadArgs,
|
|
222
222
|
): Promise<DeleteThreadReturns> {
|
|
223
223
|
const messages = await paginator(ctx.db, schema)
|
|
224
224
|
.query("messages")
|
|
225
225
|
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
226
|
-
q.eq("threadId", args.threadId)
|
|
226
|
+
q.eq("threadId", args.threadId),
|
|
227
227
|
)
|
|
228
228
|
.paginate({
|
|
229
229
|
numItems: args.limit ?? 100,
|
|
@@ -60,7 +60,7 @@ describe("users", () => {
|
|
|
60
60
|
// Should not have duplicate users
|
|
61
61
|
console.log(firstPage.page, secondPage.page);
|
|
62
62
|
expect(
|
|
63
|
-
firstPage.page.every((user) => !secondPage.page.includes(user))
|
|
63
|
+
firstPage.page.every((user) => !secondPage.page.includes(user)),
|
|
64
64
|
).toBe(true);
|
|
65
65
|
});
|
|
66
66
|
|
|
@@ -470,7 +470,7 @@ describe("users", () => {
|
|
|
470
470
|
|
|
471
471
|
// Try to delete for a user that doesn't exist
|
|
472
472
|
await expect(
|
|
473
|
-
t.action(api.users.deleteAllForUserId, { userId: "nonexistentUser" })
|
|
473
|
+
t.action(api.users.deleteAllForUserId, { userId: "nonexistentUser" }),
|
|
474
474
|
).resolves.not.toThrow();
|
|
475
475
|
|
|
476
476
|
// Should complete successfully without errors
|
package/src/component/users.ts
CHANGED
|
@@ -59,7 +59,7 @@ export const deleteAllForUserId = action({
|
|
|
59
59
|
streamsInProgress,
|
|
60
60
|
streamOrder,
|
|
61
61
|
deltaCursor,
|
|
62
|
-
}
|
|
62
|
+
},
|
|
63
63
|
);
|
|
64
64
|
messagesCursor = result.messagesCursor;
|
|
65
65
|
threadInProgress = result.threadInProgress;
|
|
@@ -121,7 +121,7 @@ export const _deleteAllForUserIdAsync = internalMutation({
|
|
|
121
121
|
|
|
122
122
|
async function deleteAllForUserIdAsyncHandler(
|
|
123
123
|
ctx: MutationCtx,
|
|
124
|
-
args: DeleteAllArgs
|
|
124
|
+
args: DeleteAllArgs,
|
|
125
125
|
): Promise<boolean> {
|
|
126
126
|
const result = await deletePageForUserId(ctx, args);
|
|
127
127
|
if (!result.isDone) {
|
|
@@ -145,7 +145,7 @@ export const _deletePageForUserId = internalMutation({
|
|
|
145
145
|
});
|
|
146
146
|
async function deletePageForUserId(
|
|
147
147
|
ctx: MutationCtx,
|
|
148
|
-
args: DeleteAllArgs
|
|
148
|
+
args: DeleteAllArgs,
|
|
149
149
|
): Promise<DeleteAllReturns> {
|
|
150
150
|
let threadInProgress: Id<"threads"> | null = args.threadInProgress;
|
|
151
151
|
let threadsCursor: string | null = args.threadsCursor;
|
|
@@ -189,7 +189,7 @@ async function deletePageForUserId(
|
|
|
189
189
|
const messages = await paginator(ctx.db, schema)
|
|
190
190
|
.query("messages")
|
|
191
191
|
.withIndex("threadId_status_tool_order_stepOrder", (q) =>
|
|
192
|
-
q.eq("threadId", threadInProgress!)
|
|
192
|
+
q.eq("threadId", threadInProgress!),
|
|
193
193
|
)
|
|
194
194
|
.order("desc")
|
|
195
195
|
.paginate({
|
|
@@ -40,7 +40,7 @@ export const paginate = query({
|
|
|
40
40
|
args.table
|
|
41
41
|
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42
42
|
(q.eq("model", args.targetModel) as any).eq("table", args.table)
|
|
43
|
-
: q.eq("model", args.targetModel)
|
|
43
|
+
: q.eq("model", args.targetModel),
|
|
44
44
|
)
|
|
45
45
|
.paginate({
|
|
46
46
|
cursor: args.cursor ?? null,
|
|
@@ -77,10 +77,10 @@ export const deleteBatchForThread = mutation({
|
|
|
77
77
|
q
|
|
78
78
|
.eq("model", args.model)
|
|
79
79
|
.eq("table", table)
|
|
80
|
-
.eq("threadId", args.threadId)
|
|
81
|
-
)
|
|
80
|
+
.eq("threadId", args.threadId),
|
|
81
|
+
),
|
|
82
82
|
),
|
|
83
|
-
["threadId"]
|
|
83
|
+
["threadId"],
|
|
84
84
|
).paginate({
|
|
85
85
|
cursor: args.cursor ?? null,
|
|
86
86
|
numItems: args.limit,
|
|
@@ -101,7 +101,7 @@ export const insertBatch = mutation({
|
|
|
101
101
|
v.object({
|
|
102
102
|
...vEmbeddingsWithoutDenormalizedFields.fields,
|
|
103
103
|
messageId: v.optional(v.id("messages")),
|
|
104
|
-
})
|
|
104
|
+
}),
|
|
105
105
|
),
|
|
106
106
|
},
|
|
107
107
|
returns: v.array(vVectorId),
|
|
@@ -113,7 +113,7 @@ export const insertBatch = mutation({
|
|
|
113
113
|
await ctx.db.patch(messageId, { embeddingId });
|
|
114
114
|
}
|
|
115
115
|
return embeddingId;
|
|
116
|
-
})
|
|
116
|
+
}),
|
|
117
117
|
);
|
|
118
118
|
},
|
|
119
119
|
});
|
|
@@ -121,7 +121,7 @@ export const insertBatch = mutation({
|
|
|
121
121
|
export async function insertVector(
|
|
122
122
|
ctx: MutationCtx,
|
|
123
123
|
dimension: VectorDimension,
|
|
124
|
-
v: EmbeddingsWithoutDenormalizedFields
|
|
124
|
+
v: EmbeddingsWithoutDenormalizedFields,
|
|
125
125
|
) {
|
|
126
126
|
return ctx.db.insert(getVectorTableName(dimension), {
|
|
127
127
|
...v,
|
|
@@ -143,7 +143,7 @@ export function searchVectors(
|
|
|
143
143
|
threadId?: Id<"threads">;
|
|
144
144
|
searchAllMessagesForUserId?: string;
|
|
145
145
|
limit?: number;
|
|
146
|
-
}
|
|
146
|
+
},
|
|
147
147
|
) {
|
|
148
148
|
const tableName = getVectorTableName(args.dimension);
|
|
149
149
|
return ctx.vectorSearch(tableName, "vector", {
|
|
@@ -176,7 +176,7 @@ export const updateBatch = mutation({
|
|
|
176
176
|
// deleting from one table and inserting into another.
|
|
177
177
|
// However this requires updating all the messages that reference
|
|
178
178
|
// the vector.
|
|
179
|
-
})
|
|
179
|
+
}),
|
|
180
180
|
),
|
|
181
181
|
},
|
|
182
182
|
returns: v.null(),
|
|
@@ -186,8 +186,8 @@ export const updateBatch = mutation({
|
|
|
186
186
|
ctx.db.patch(embedding.id, {
|
|
187
187
|
model: embedding.model,
|
|
188
188
|
vector: embedding.vector,
|
|
189
|
-
})
|
|
190
|
-
)
|
|
189
|
+
}),
|
|
190
|
+
),
|
|
191
191
|
);
|
|
192
192
|
},
|
|
193
193
|
});
|
|
@@ -31,7 +31,7 @@ const embeddings = {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
export const vEmbeddingsWithoutDenormalizedFields = v.object(
|
|
34
|
-
omit(embeddings, ["model_table_userId", "model_table_threadId"])
|
|
34
|
+
omit(embeddings, ["model_table_userId", "model_table_threadId"]),
|
|
35
35
|
);
|
|
36
36
|
export type EmbeddingsWithoutDenormalizedFields = Infer<
|
|
37
37
|
typeof vEmbeddingsWithoutDenormalizedFields
|
|
@@ -71,17 +71,17 @@ export const VectorDimensions = [
|
|
|
71
71
|
128, 256, 512, 768, 1024, 1408, 1536, 2048, 3072, 4096,
|
|
72
72
|
] as const;
|
|
73
73
|
export function validateVectorDimension(
|
|
74
|
-
dimension: number
|
|
74
|
+
dimension: number,
|
|
75
75
|
): asserts dimension is VectorDimension {
|
|
76
76
|
if (!VectorDimensions.includes(dimension as VectorDimension)) {
|
|
77
77
|
throw new Error(
|
|
78
|
-
`Unsupported vector dimension${dimension}. Supported: ${VectorDimensions.join(", ")}
|
|
78
|
+
`Unsupported vector dimension${dimension}. Supported: ${VectorDimensions.join(", ")}`,
|
|
79
79
|
);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
export type VectorDimension = (typeof VectorDimensions)[number];
|
|
83
83
|
export const VectorTableNames = VectorDimensions.map(
|
|
84
|
-
(d) => `embeddings_${d}
|
|
84
|
+
(d) => `embeddings_${d}`,
|
|
85
85
|
) as `embeddings_${(typeof VectorDimensions)[number]}`[];
|
|
86
86
|
export type VectorTableName = (typeof VectorTableNames)[number];
|
|
87
87
|
export type VectorTableId = GenericId<(typeof VectorTableNames)[number]>;
|
|
@@ -89,7 +89,7 @@ export type VectorTableId = GenericId<(typeof VectorTableNames)[number]>;
|
|
|
89
89
|
export const vVectorDimension = literals(...VectorDimensions);
|
|
90
90
|
export const vVectorTableName = literals(...VectorTableNames);
|
|
91
91
|
export const vVectorId = v.union(
|
|
92
|
-
...VectorTableNames.map((name) => v.id(name))
|
|
92
|
+
...VectorTableNames.map((name) => v.id(name)),
|
|
93
93
|
) as VUnion<
|
|
94
94
|
GenericId<(typeof VectorTableNames)[number]>,
|
|
95
95
|
VId<(typeof VectorTableNames)[number]>[]
|
|
@@ -117,7 +117,7 @@ const tables: {
|
|
|
117
117
|
VectorDimensions.map((dimensions) => [
|
|
118
118
|
`embeddings_${dimensions}`,
|
|
119
119
|
table(dimensions),
|
|
120
|
-
])
|
|
120
|
+
]),
|
|
121
121
|
) as Record<
|
|
122
122
|
`embeddings_${(typeof VectorDimensions)[number]}`,
|
|
123
123
|
VectorTable<(typeof VectorDimensions)[number]>
|
package/src/mapping.test.ts
CHANGED
|
@@ -89,7 +89,7 @@ describe("mapping", () => {
|
|
|
89
89
|
const bigArr = new Uint8Array(1024 * 65).fill(1);
|
|
90
90
|
const ab = bigArr.buffer.slice(
|
|
91
91
|
bigArr.byteOffset,
|
|
92
|
-
bigArr.byteOffset + bigArr.byteLength
|
|
92
|
+
bigArr.byteOffset + bigArr.byteLength,
|
|
93
93
|
);
|
|
94
94
|
let called = false;
|
|
95
95
|
const ctx = {
|
|
@@ -117,7 +117,7 @@ describe("mapping", () => {
|
|
|
117
117
|
const { content: ser, fileIds } = await serializeContent(
|
|
118
118
|
ctx,
|
|
119
119
|
component,
|
|
120
|
-
content
|
|
120
|
+
content,
|
|
121
121
|
);
|
|
122
122
|
expect(called).toBe(true);
|
|
123
123
|
expect(fileIds).toEqual(["file-123"]);
|
|
@@ -125,7 +125,7 @@ describe("mapping", () => {
|
|
|
125
125
|
const serArr = ser as SerializedContent;
|
|
126
126
|
expect(typeof (serArr as { data: unknown }[])[0].data).toBe("string");
|
|
127
127
|
expect((serArr as { data: unknown }[])[0].data as string).toMatch(
|
|
128
|
-
/^https
|
|
128
|
+
/^https?:\/\//,
|
|
129
129
|
);
|
|
130
130
|
});
|
|
131
131
|
|
|
@@ -133,7 +133,7 @@ describe("mapping", () => {
|
|
|
133
133
|
const arr = new Uint8Array([1, 2, 3, 4, 5]);
|
|
134
134
|
const ab = arr.buffer.slice(
|
|
135
135
|
arr.byteOffset,
|
|
136
|
-
arr.byteOffset + arr.byteLength
|
|
136
|
+
arr.byteOffset + arr.byteLength,
|
|
137
137
|
);
|
|
138
138
|
const ctx = {
|
|
139
139
|
runAction: async () => undefined,
|
package/src/mapping.ts
CHANGED
|
@@ -20,7 +20,6 @@ import type { ActionCtx, AgentComponent } from "./client/types.js";
|
|
|
20
20
|
import type { RunMutationCtx } from "./client/types.js";
|
|
21
21
|
import { MAX_FILE_SIZE, storeFile } from "./client/files.js";
|
|
22
22
|
|
|
23
|
-
|
|
24
23
|
export type AIMessageWithoutId = Omit<AIMessage, "id">;
|
|
25
24
|
|
|
26
25
|
export type SerializeUrlsAndUint8Arrays<T> = T extends URL
|
|
@@ -42,13 +41,13 @@ export type SerializedMessage = SerializeUrlsAndUint8Arrays<CoreMessage>;
|
|
|
42
41
|
export async function serializeMessage(
|
|
43
42
|
ctx: ActionCtx | RunMutationCtx,
|
|
44
43
|
component: AgentComponent,
|
|
45
|
-
messageWithId: CoreMessage & { id?: string }
|
|
44
|
+
messageWithId: CoreMessage & { id?: string },
|
|
46
45
|
): Promise<{ message: SerializedMessage; fileIds?: string[] }> {
|
|
47
46
|
const { id: _, experimental_providerMetadata, ...message } = messageWithId;
|
|
48
47
|
const { content, fileIds } = await serializeContent(
|
|
49
48
|
ctx,
|
|
50
49
|
component,
|
|
51
|
-
message.content
|
|
50
|
+
message.content,
|
|
52
51
|
);
|
|
53
52
|
return {
|
|
54
53
|
message: {
|
|
@@ -72,7 +71,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
72
71
|
ctx: ActionCtx,
|
|
73
72
|
component: AgentComponent,
|
|
74
73
|
step: StepResult<TOOLS>,
|
|
75
|
-
metadata: { model: string; provider: string }
|
|
74
|
+
metadata: { model: string; provider: string },
|
|
76
75
|
): Promise<MessageWithMetadata[]> {
|
|
77
76
|
// If there are tool results, there's another message with the tool results
|
|
78
77
|
// ref: https://github.com/vercel/ai/blob/main/packages/ai/core/generate-text/to-response-messages.ts
|
|
@@ -98,7 +97,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
98
97
|
const { message, fileIds } = await serializeMessage(
|
|
99
98
|
ctx,
|
|
100
99
|
component,
|
|
101
|
-
messageWithId
|
|
100
|
+
messageWithId,
|
|
102
101
|
);
|
|
103
102
|
return {
|
|
104
103
|
message,
|
|
@@ -109,7 +108,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
109
108
|
text: step.text,
|
|
110
109
|
fileIds,
|
|
111
110
|
};
|
|
112
|
-
})
|
|
111
|
+
}),
|
|
113
112
|
);
|
|
114
113
|
return messages;
|
|
115
114
|
}
|
|
@@ -118,7 +117,7 @@ export async function serializeObjectResult(
|
|
|
118
117
|
ctx: ActionCtx,
|
|
119
118
|
component: AgentComponent,
|
|
120
119
|
result: GenerateObjectResult<unknown>,
|
|
121
|
-
metadata: { model: string; provider: string }
|
|
120
|
+
metadata: { model: string; provider: string },
|
|
122
121
|
): Promise<{ messages: MessageWithMetadata[] }> {
|
|
123
122
|
const text = JSON.stringify(result.object);
|
|
124
123
|
|
|
@@ -147,7 +146,7 @@ export async function serializeObjectResult(
|
|
|
147
146
|
export async function serializeContent(
|
|
148
147
|
ctx: ActionCtx | RunMutationCtx,
|
|
149
148
|
component: AgentComponent,
|
|
150
|
-
content: Content
|
|
149
|
+
content: Content,
|
|
151
150
|
): Promise<{ content: SerializedContent; fileIds?: string[] }> {
|
|
152
151
|
if (typeof content === "string") {
|
|
153
152
|
return { content };
|
|
@@ -166,7 +165,9 @@ export async function serializeContent(
|
|
|
166
165
|
const { file } = await storeFile(
|
|
167
166
|
ctx,
|
|
168
167
|
component,
|
|
169
|
-
new Blob([image], {
|
|
168
|
+
new Blob([image], {
|
|
169
|
+
type: part.mimeType || guessMimeType(image),
|
|
170
|
+
}),
|
|
170
171
|
);
|
|
171
172
|
image = file.url;
|
|
172
173
|
fileIds.push(file.fileId);
|
|
@@ -179,7 +180,7 @@ export async function serializeContent(
|
|
|
179
180
|
const { file } = await storeFile(
|
|
180
181
|
ctx,
|
|
181
182
|
component,
|
|
182
|
-
new Blob([data], { type: part.mimeType })
|
|
183
|
+
new Blob([data], { type: part.mimeType }),
|
|
183
184
|
);
|
|
184
185
|
data = file.url;
|
|
185
186
|
fileIds.push(file.fileId);
|
|
@@ -192,7 +193,7 @@ export async function serializeContent(
|
|
|
192
193
|
default:
|
|
193
194
|
return part;
|
|
194
195
|
}
|
|
195
|
-
})
|
|
196
|
+
}),
|
|
196
197
|
);
|
|
197
198
|
return {
|
|
198
199
|
content: serialized as SerializedContent,
|
|
@@ -289,7 +290,7 @@ export function guessMimeType(buf: ArrayBuffer | string): string {
|
|
|
289
290
|
* @returns The serialized data as an ArrayBuffer or the URL as a string.
|
|
290
291
|
*/
|
|
291
292
|
export function serializeDataOrUrl(
|
|
292
|
-
dataOrUrl: DataContent | URL
|
|
293
|
+
dataOrUrl: DataContent | URL,
|
|
293
294
|
): ArrayBuffer | string {
|
|
294
295
|
if (typeof dataOrUrl === "string") {
|
|
295
296
|
return dataOrUrl;
|
|
@@ -302,12 +303,12 @@ export function serializeDataOrUrl(
|
|
|
302
303
|
}
|
|
303
304
|
return dataOrUrl.buffer.slice(
|
|
304
305
|
dataOrUrl.byteOffset,
|
|
305
|
-
dataOrUrl.byteOffset + dataOrUrl.byteLength
|
|
306
|
+
dataOrUrl.byteOffset + dataOrUrl.byteLength,
|
|
306
307
|
) as ArrayBuffer;
|
|
307
308
|
}
|
|
308
309
|
|
|
309
310
|
export function deserializeUrl(
|
|
310
|
-
urlOrString: string | ArrayBuffer
|
|
311
|
+
urlOrString: string | ArrayBuffer,
|
|
311
312
|
): URL | DataContent {
|
|
312
313
|
if (typeof urlOrString === "string") {
|
|
313
314
|
if (
|
|
@@ -323,7 +324,7 @@ export function deserializeUrl(
|
|
|
323
324
|
|
|
324
325
|
export function toUIFilePart(part: ImagePart | FilePart): FileUIPart {
|
|
325
326
|
const dataOrUrl = serializeDataOrUrl(
|
|
326
|
-
part.type === "image" ? part.image : part.data
|
|
327
|
+
part.type === "image" ? part.image : part.data,
|
|
327
328
|
);
|
|
328
329
|
|
|
329
330
|
return {
|
|
@@ -346,7 +347,7 @@ export function promptOrMessagesToCoreMessages(args: {
|
|
|
346
347
|
const messages: CoreMessage[] = [];
|
|
347
348
|
assert(
|
|
348
349
|
args.prompt || args.messages || args.promptMessageId,
|
|
349
|
-
"messages or prompt or promptMessageId is required"
|
|
350
|
+
"messages or prompt or promptMessageId is required",
|
|
350
351
|
);
|
|
351
352
|
if (args.messages) {
|
|
352
353
|
if (
|
|
@@ -357,7 +358,7 @@ export function promptOrMessagesToCoreMessages(args: {
|
|
|
357
358
|
(m.role === "data" || // UI-only role
|
|
358
359
|
"toolInvocations" in m || // UI-specific field
|
|
359
360
|
"parts" in m || // UI-specific field
|
|
360
|
-
"experimental_attachments" in m)
|
|
361
|
+
"experimental_attachments" in m),
|
|
361
362
|
)
|
|
362
363
|
) {
|
|
363
364
|
messages.push(...convertToCoreMessages(args.messages as AIMessage[]));
|