@convex-dev/agent 0.1.1-alpha.0 → 0.1.2-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 +9 -3
- package/dist/commonjs/client/createTool.d.ts +49 -0
- package/dist/commonjs/client/createTool.d.ts.map +1 -0
- package/dist/commonjs/client/createTool.js +45 -0
- package/dist/commonjs/client/createTool.js.map +1 -0
- package/dist/commonjs/client/index.d.ts +101 -322
- package/dist/commonjs/client/index.d.ts.map +1 -1
- package/dist/commonjs/client/index.js +142 -194
- package/dist/commonjs/client/index.js.map +1 -1
- package/dist/commonjs/client/streaming.d.ts +54 -0
- package/dist/commonjs/client/streaming.d.ts.map +1 -0
- package/dist/commonjs/client/streaming.js +121 -0
- package/dist/commonjs/client/streaming.js.map +1 -0
- package/dist/commonjs/client/types.d.ts +290 -2
- package/dist/commonjs/client/types.d.ts.map +1 -1
- package/dist/commonjs/component/messages.d.ts +109 -143
- package/dist/commonjs/component/messages.d.ts.map +1 -1
- package/dist/commonjs/component/messages.js +15 -14
- package/dist/commonjs/component/messages.js.map +1 -1
- package/dist/commonjs/component/schema.d.ts +1026 -52
- package/dist/commonjs/component/schema.d.ts.map +1 -1
- package/dist/commonjs/component/schema.js +39 -1
- package/dist/commonjs/component/schema.js.map +1 -1
- package/dist/commonjs/component/streams.d.ts +191 -0
- package/dist/commonjs/component/streams.d.ts.map +1 -0
- package/dist/commonjs/component/streams.js +169 -0
- package/dist/commonjs/component/streams.js.map +1 -0
- package/dist/commonjs/component/threads.d.ts +1 -1
- package/dist/commonjs/component/threads.js +3 -3
- package/dist/commonjs/component/threads.js.map +1 -1
- package/dist/commonjs/component/users.js +2 -2
- package/dist/commonjs/component/users.js.map +1 -1
- package/dist/commonjs/component/vector/index.d.ts +8 -8
- package/dist/commonjs/component/vector/index.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.d.ts +5 -5
- package/dist/commonjs/component/vector/tables.d.ts.map +1 -1
- package/dist/commonjs/component/vector/tables.js +1 -1
- package/dist/commonjs/component/vector/tables.js.map +1 -1
- package/dist/commonjs/mapping.d.ts.map +1 -1
- package/dist/commonjs/mapping.js +3 -1
- package/dist/commonjs/mapping.js.map +1 -1
- package/dist/commonjs/react/index.d.ts +99 -0
- package/dist/commonjs/react/index.d.ts.map +1 -1
- package/dist/commonjs/react/index.js +505 -1
- package/dist/commonjs/react/index.js.map +1 -1
- package/dist/commonjs/react/toUIMessages.d.ts +8 -0
- package/dist/commonjs/react/toUIMessages.d.ts.map +1 -0
- package/dist/commonjs/react/toUIMessages.js +134 -0
- package/dist/commonjs/react/toUIMessages.js.map +1 -0
- package/dist/commonjs/validators.d.ts +513 -11
- package/dist/commonjs/validators.d.ts.map +1 -1
- package/dist/commonjs/validators.js +49 -2
- package/dist/commonjs/validators.js.map +1 -1
- package/dist/esm/client/createTool.d.ts +49 -0
- package/dist/esm/client/createTool.d.ts.map +1 -0
- package/dist/esm/client/createTool.js +45 -0
- package/dist/esm/client/createTool.js.map +1 -0
- package/dist/esm/client/index.d.ts +101 -322
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +142 -194
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/streaming.d.ts +54 -0
- package/dist/esm/client/streaming.d.ts.map +1 -0
- package/dist/esm/client/streaming.js +121 -0
- package/dist/esm/client/streaming.js.map +1 -0
- package/dist/esm/client/types.d.ts +290 -2
- package/dist/esm/client/types.d.ts.map +1 -1
- package/dist/esm/component/messages.d.ts +109 -143
- package/dist/esm/component/messages.d.ts.map +1 -1
- package/dist/esm/component/messages.js +15 -14
- package/dist/esm/component/messages.js.map +1 -1
- package/dist/esm/component/schema.d.ts +1026 -52
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +39 -1
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/streams.d.ts +191 -0
- package/dist/esm/component/streams.d.ts.map +1 -0
- package/dist/esm/component/streams.js +169 -0
- package/dist/esm/component/streams.js.map +1 -0
- package/dist/esm/component/threads.d.ts +1 -1
- package/dist/esm/component/threads.js +3 -3
- package/dist/esm/component/threads.js.map +1 -1
- package/dist/esm/component/users.js +2 -2
- package/dist/esm/component/users.js.map +1 -1
- package/dist/esm/component/vector/index.d.ts +8 -8
- package/dist/esm/component/vector/index.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.d.ts +5 -5
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/component/vector/tables.js +1 -1
- package/dist/esm/component/vector/tables.js.map +1 -1
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +3 -1
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/react/index.d.ts +99 -0
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +505 -1
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/react/toUIMessages.d.ts +8 -0
- package/dist/esm/react/toUIMessages.d.ts.map +1 -0
- package/dist/esm/react/toUIMessages.js +134 -0
- package/dist/esm/react/toUIMessages.js.map +1 -0
- package/dist/esm/validators.d.ts +513 -11
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +49 -2
- package/dist/esm/validators.js.map +1 -1
- package/package.json +6 -2
- package/src/client/createTool.ts +108 -0
- package/src/client/index.ts +270 -689
- package/src/client/streaming.ts +166 -0
- package/src/client/types.ts +430 -5
- package/src/component/_generated/api.d.ts +367 -190
- package/src/component/messages.ts +15 -14
- package/src/component/schema.ts +46 -0
- package/src/component/streams.ts +206 -0
- package/src/component/threads.ts +3 -3
- package/src/component/users.ts +2 -2
- package/src/component/vector/tables.ts +1 -1
- package/src/mapping.ts +3 -1
- package/src/react/index.ts +687 -1
- package/src/react/toUIMessages.ts +153 -0
- package/src/validators.test.ts +18 -0
- package/src/validators.ts +72 -2
- package/dist/commonjs/deltaStreaming.d.ts +0 -2
- package/dist/commonjs/deltaStreaming.d.ts.map +0 -1
- package/dist/commonjs/deltaStreaming.js +0 -2
- package/dist/commonjs/deltaStreaming.js.map +0 -1
- package/dist/esm/deltaStreaming.d.ts +0 -2
- package/dist/esm/deltaStreaming.d.ts.map +0 -1
- package/dist/esm/deltaStreaming.js +0 -2
- package/dist/esm/deltaStreaming.js.map +0 -1
- package/src/deltaStreaming.ts +0 -1
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
isTool,
|
|
9
9
|
} from "../shared.js";
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
vPaginationResult,
|
|
12
12
|
vMessageEmbeddings,
|
|
13
13
|
vMessageStatus,
|
|
14
14
|
vMessageWithMetadata,
|
|
@@ -180,11 +180,12 @@ async function addMessagesHandler(
|
|
|
180
180
|
error: fail ? "Parent message failed" : undefined,
|
|
181
181
|
stepOrder,
|
|
182
182
|
});
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
183
|
+
// Let's just not set the id field and have it set only in explicit cases.
|
|
184
|
+
// if (!message.id) {
|
|
185
|
+
// await ctx.db.patch(messageId, {
|
|
186
|
+
// id: messageId,
|
|
187
|
+
// });
|
|
188
|
+
// }
|
|
188
189
|
for (const { fileId } of message.files ?? []) {
|
|
189
190
|
if (!fileId) continue;
|
|
190
191
|
await ctx.db.patch(fileId, {
|
|
@@ -214,7 +215,7 @@ function orderedMessagesStream(
|
|
|
214
215
|
) {
|
|
215
216
|
return mergedStream(
|
|
216
217
|
[true, false].flatMap((tool) =>
|
|
217
|
-
|
|
218
|
+
messageStatuses.map((status) =>
|
|
218
219
|
stream(ctx.db, schema)
|
|
219
220
|
.query("messages")
|
|
220
221
|
.withIndex("threadId_status_tool_order_stepOrder", (q) => {
|
|
@@ -244,7 +245,7 @@ const addStepArgs = {
|
|
|
244
245
|
|
|
245
246
|
export const addStep = mutation({
|
|
246
247
|
args: addStepArgs,
|
|
247
|
-
returns: v.array(
|
|
248
|
+
returns: v.array(vMessageDoc),
|
|
248
249
|
handler: addStepHandler,
|
|
249
250
|
});
|
|
250
251
|
async function addStepHandler(
|
|
@@ -279,7 +280,7 @@ async function addStepHandler(
|
|
|
279
280
|
status: step.finishReason === "stop" ? "success" : "pending",
|
|
280
281
|
step,
|
|
281
282
|
});
|
|
282
|
-
await addMessagesHandler(ctx, {
|
|
283
|
+
const added = await addMessagesHandler(ctx, {
|
|
283
284
|
userId: args.userId,
|
|
284
285
|
threadId: args.threadId,
|
|
285
286
|
stepId,
|
|
@@ -293,8 +294,7 @@ async function addStepHandler(
|
|
|
293
294
|
if (step.finishReason === "stop") {
|
|
294
295
|
await commitMessageHandler(ctx, { messageId: args.promptMessageId });
|
|
295
296
|
}
|
|
296
|
-
|
|
297
|
-
return steps;
|
|
297
|
+
return added.messages.map(publicMessage);
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
export const rollbackMessage = mutation({
|
|
@@ -388,7 +388,8 @@ export const listMessagesByThreadId = query({
|
|
|
388
388
|
excludeToolMessages: v.optional(v.boolean()),
|
|
389
389
|
/** @deprecated Use excludeToolMessages instead. */
|
|
390
390
|
isTool: v.optional(v.literal("use excludeToolMessages instead of this")),
|
|
391
|
-
order
|
|
391
|
+
/** What order to sort the messages in. To get the latest, use "desc". */
|
|
392
|
+
order: v.union(v.literal("asc"), v.literal("desc")),
|
|
392
393
|
paginationOpts: v.optional(paginationOptsValidator),
|
|
393
394
|
statuses: v.optional(v.array(vMessageStatus)),
|
|
394
395
|
upToAndIncludingMessageId: v.optional(v.id("messages")),
|
|
@@ -439,7 +440,7 @@ export const listMessagesByThreadId = query({
|
|
|
439
440
|
);
|
|
440
441
|
return { ...messages, page: messages.page.map(publicMessage) };
|
|
441
442
|
},
|
|
442
|
-
returns:
|
|
443
|
+
returns: vPaginationResult(vMessageDoc),
|
|
443
444
|
});
|
|
444
445
|
|
|
445
446
|
/** @deprecated Use listMessagesByThreadId instead. */
|
|
@@ -448,7 +449,7 @@ export const getThreadMessages = query({
|
|
|
448
449
|
handler: async () => {
|
|
449
450
|
throw new Error("Use listMessagesByThreadId instead of getThreadMessages");
|
|
450
451
|
},
|
|
451
|
-
returns:
|
|
452
|
+
returns: vPaginationResult(vMessageDoc),
|
|
452
453
|
});
|
|
453
454
|
|
|
454
455
|
export const searchMessages = action({
|
package/src/component/schema.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
vReasoningDetails,
|
|
15
15
|
vFile,
|
|
16
16
|
vFileWithStringId,
|
|
17
|
+
vTextStreamPart,
|
|
17
18
|
} from "../validators.js";
|
|
18
19
|
import { typedV } from "convex-helpers/validators";
|
|
19
20
|
import vectorTables, { vVectorId } from "./vector/tables.js";
|
|
@@ -105,6 +106,51 @@ export const schema = defineSchema({
|
|
|
105
106
|
"stepOrder",
|
|
106
107
|
]),
|
|
107
108
|
|
|
109
|
+
// Status: if it's done, it's deleted, then deltas are vacuumed
|
|
110
|
+
streamingMessages: defineTable({
|
|
111
|
+
// extra metadata?
|
|
112
|
+
userId: v.optional(v.string()),
|
|
113
|
+
agentName: v.optional(v.string()),
|
|
114
|
+
model: v.optional(v.string()),
|
|
115
|
+
provider: v.optional(v.string()),
|
|
116
|
+
providerOptions: v.optional(vProviderOptions), // Sent to model
|
|
117
|
+
|
|
118
|
+
threadId: v.id("threads"),
|
|
119
|
+
order: v.number(),
|
|
120
|
+
/**
|
|
121
|
+
* The step order of the first message in the stream.
|
|
122
|
+
* If the stream ends up with both a tool call and a tool result,
|
|
123
|
+
* the stepOrder of the result will be +1 of the tool call.
|
|
124
|
+
*/
|
|
125
|
+
stepOrder: v.number(),
|
|
126
|
+
state: v.union(
|
|
127
|
+
v.object({
|
|
128
|
+
kind: v.literal("streaming"),
|
|
129
|
+
lastHeartbeat: v.number(),
|
|
130
|
+
timeoutFnId: v.optional(v.id("_scheduled_functions")),
|
|
131
|
+
}),
|
|
132
|
+
v.object({
|
|
133
|
+
kind: v.literal("finished"),
|
|
134
|
+
endedAt: v.number(),
|
|
135
|
+
}),
|
|
136
|
+
v.object({
|
|
137
|
+
kind: v.literal("error"),
|
|
138
|
+
error: v.string(),
|
|
139
|
+
})
|
|
140
|
+
),
|
|
141
|
+
})
|
|
142
|
+
// There should only be one per "order" index
|
|
143
|
+
// If another exists, it's deleted and replaced
|
|
144
|
+
.index("threadId_order_stepOrder", ["threadId", "order", "stepOrder"]),
|
|
145
|
+
|
|
146
|
+
streamDeltas: defineTable({
|
|
147
|
+
streamId: v.id("streamingMessages"),
|
|
148
|
+
// the indexes work like: 0 <first> 1 <second> 2 <third> 3 ...
|
|
149
|
+
start: v.number(), // inclusive
|
|
150
|
+
end: v.number(), // exclusive
|
|
151
|
+
parts: v.array(vTextStreamPart),
|
|
152
|
+
}).index("streamId_start_end", ["streamId", "start", "end"]),
|
|
153
|
+
|
|
108
154
|
memories: defineTable({
|
|
109
155
|
threadId: v.optional(v.id("threads")),
|
|
110
156
|
userId: v.optional(v.string()),
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { v } from "convex/values";
|
|
2
|
+
import {
|
|
3
|
+
internalMutation,
|
|
4
|
+
mutation,
|
|
5
|
+
MutationCtx,
|
|
6
|
+
query,
|
|
7
|
+
} from "./_generated/server";
|
|
8
|
+
import { omit, pick } from "convex-helpers";
|
|
9
|
+
import { StreamDelta, vStreamDelta, vStreamMessage } from "../validators";
|
|
10
|
+
import schema from "./schema";
|
|
11
|
+
import { internal } from "./_generated/api";
|
|
12
|
+
import { Id } from "./_generated/dataModel";
|
|
13
|
+
|
|
14
|
+
const MAX_DELTAS_PER_REQUEST = 1000;
|
|
15
|
+
const MAX_DELTAS_PER_STREAM = 100;
|
|
16
|
+
const TIMEOUT_INTERVAL = 1000 * 60; // 1 minute
|
|
17
|
+
|
|
18
|
+
const deltaValidator = schema.tables.streamDeltas.validator;
|
|
19
|
+
|
|
20
|
+
export const addDelta = mutation({
|
|
21
|
+
args: deltaValidator,
|
|
22
|
+
returns: v.null(),
|
|
23
|
+
handler: async (ctx, args) => {
|
|
24
|
+
await ctx.db.insert("streamDeltas", args);
|
|
25
|
+
await heartbeatStream(ctx, { streamId: args.streamId });
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const listDeltas = query({
|
|
30
|
+
args: {
|
|
31
|
+
threadId: v.id("threads"),
|
|
32
|
+
cursors: v.array(
|
|
33
|
+
v.object({
|
|
34
|
+
streamId: v.id("streamingMessages"),
|
|
35
|
+
cursor: v.number(),
|
|
36
|
+
})
|
|
37
|
+
),
|
|
38
|
+
},
|
|
39
|
+
returns: v.array(vStreamDelta),
|
|
40
|
+
handler: async (ctx, args): Promise<StreamDelta[]> => {
|
|
41
|
+
let totalDeltas = 0;
|
|
42
|
+
const deltas: StreamDelta[] = [];
|
|
43
|
+
for (const cursor of args.cursors) {
|
|
44
|
+
const streamDeltas = await ctx.db
|
|
45
|
+
.query("streamDeltas")
|
|
46
|
+
.withIndex("streamId_start_end", (q) =>
|
|
47
|
+
q.eq("streamId", cursor.streamId).gte("start", cursor.cursor)
|
|
48
|
+
)
|
|
49
|
+
.take(
|
|
50
|
+
Math.min(MAX_DELTAS_PER_STREAM, MAX_DELTAS_PER_REQUEST - totalDeltas)
|
|
51
|
+
);
|
|
52
|
+
totalDeltas += streamDeltas.length;
|
|
53
|
+
deltas.push(
|
|
54
|
+
...streamDeltas.map((d) => ({
|
|
55
|
+
streamId: d.streamId.toString(),
|
|
56
|
+
...pick(d, ["start", "end", "parts"]),
|
|
57
|
+
}))
|
|
58
|
+
);
|
|
59
|
+
if (totalDeltas >= MAX_DELTAS_PER_REQUEST) {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return deltas;
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
export const create = mutation({
|
|
68
|
+
args: omit(schema.tables.streamingMessages.validator.fields, ["state"]),
|
|
69
|
+
returns: v.id("streamingMessages"),
|
|
70
|
+
handler: async (ctx, args) => {
|
|
71
|
+
const state = {
|
|
72
|
+
kind: "streaming" as const,
|
|
73
|
+
lastHeartbeat: Date.now(),
|
|
74
|
+
};
|
|
75
|
+
const streamId = await ctx.db.insert("streamingMessages", {
|
|
76
|
+
...args,
|
|
77
|
+
state,
|
|
78
|
+
});
|
|
79
|
+
const timeoutFnId = await ctx.scheduler.runAfter(
|
|
80
|
+
TIMEOUT_INTERVAL,
|
|
81
|
+
internal.streams.timeoutStream,
|
|
82
|
+
{ streamId }
|
|
83
|
+
);
|
|
84
|
+
await ctx.db.patch(streamId, { state: { ...state, timeoutFnId } });
|
|
85
|
+
return streamId;
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export const list = query({
|
|
90
|
+
args: {
|
|
91
|
+
threadId: v.id("threads"),
|
|
92
|
+
},
|
|
93
|
+
returns: v.array(vStreamMessage),
|
|
94
|
+
handler: async (ctx, args) => {
|
|
95
|
+
return ctx.db
|
|
96
|
+
.query("streamingMessages")
|
|
97
|
+
.withIndex("threadId_order_stepOrder", (q) =>
|
|
98
|
+
q.eq("threadId", args.threadId)
|
|
99
|
+
)
|
|
100
|
+
.order("desc")
|
|
101
|
+
.take(100)
|
|
102
|
+
.then((msgs) =>
|
|
103
|
+
msgs.map((m) => ({
|
|
104
|
+
streamId: m._id,
|
|
105
|
+
...pick(m, [
|
|
106
|
+
"order",
|
|
107
|
+
"stepOrder",
|
|
108
|
+
"userId",
|
|
109
|
+
"agentName",
|
|
110
|
+
"model",
|
|
111
|
+
"provider",
|
|
112
|
+
"providerOptions",
|
|
113
|
+
]),
|
|
114
|
+
}))
|
|
115
|
+
);
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export const finish = mutation({
|
|
120
|
+
args: {
|
|
121
|
+
streamId: v.id("streamingMessages"),
|
|
122
|
+
finalDelta: v.optional(deltaValidator),
|
|
123
|
+
},
|
|
124
|
+
returns: v.null(),
|
|
125
|
+
handler: async (ctx, args) => {
|
|
126
|
+
if (args.finalDelta) {
|
|
127
|
+
await ctx.db.insert("streamDeltas", args.finalDelta);
|
|
128
|
+
}
|
|
129
|
+
const stream = await ctx.db.get(args.streamId);
|
|
130
|
+
if (!stream) {
|
|
131
|
+
throw new Error(`Stream not found: ${args.streamId}`);
|
|
132
|
+
}
|
|
133
|
+
if (stream.state.kind !== "streaming") {
|
|
134
|
+
throw new Error(`Stream is not streaming: ${args.streamId}`);
|
|
135
|
+
}
|
|
136
|
+
if (stream.state.timeoutFnId) {
|
|
137
|
+
const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
|
|
138
|
+
if (timeoutFn?.state.kind === "pending") {
|
|
139
|
+
await ctx.scheduler.cancel(stream.state.timeoutFnId);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
await ctx.db.patch(args.streamId, {
|
|
143
|
+
state: { kind: "finished", endedAt: Date.now() },
|
|
144
|
+
});
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
async function heartbeatStream(
|
|
149
|
+
ctx: MutationCtx,
|
|
150
|
+
args: { streamId: Id<"streamingMessages"> }
|
|
151
|
+
) {
|
|
152
|
+
const stream = await ctx.db.get(args.streamId);
|
|
153
|
+
if (!stream) {
|
|
154
|
+
console.warn("Stream not found", args.streamId);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (stream.state.kind !== "streaming") {
|
|
158
|
+
console.warn("Stream is not streaming", args.streamId);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (Date.now() - stream.state.lastHeartbeat < TIMEOUT_INTERVAL / 4) {
|
|
162
|
+
// Debounce heartbeating.
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (!stream.state.timeoutFnId) {
|
|
166
|
+
throw new Error("Stream has no timeout function");
|
|
167
|
+
}
|
|
168
|
+
const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
|
|
169
|
+
if (!timeoutFn) {
|
|
170
|
+
throw new Error("Timeout function not found");
|
|
171
|
+
}
|
|
172
|
+
if (timeoutFn.state.kind !== "pending") {
|
|
173
|
+
throw new Error("Timeout function is not pending");
|
|
174
|
+
}
|
|
175
|
+
await ctx.scheduler.cancel(stream.state.timeoutFnId);
|
|
176
|
+
const timeoutFnId = await ctx.scheduler.runAfter(
|
|
177
|
+
TIMEOUT_INTERVAL,
|
|
178
|
+
internal.streams.timeoutStream,
|
|
179
|
+
{ streamId: args.streamId }
|
|
180
|
+
);
|
|
181
|
+
await ctx.db.patch(args.streamId, {
|
|
182
|
+
state: {
|
|
183
|
+
kind: "streaming",
|
|
184
|
+
lastHeartbeat: Date.now(),
|
|
185
|
+
timeoutFnId,
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export const timeoutStream = internalMutation({
|
|
191
|
+
args: { streamId: v.id("streamingMessages") },
|
|
192
|
+
returns: v.null(),
|
|
193
|
+
handler: async (ctx, args) => {
|
|
194
|
+
const stream = await ctx.db.get(args.streamId);
|
|
195
|
+
if (!stream) {
|
|
196
|
+
console.warn("Stream not found", args.streamId);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
await ctx.db.patch(args.streamId, {
|
|
200
|
+
state: {
|
|
201
|
+
kind: "finished",
|
|
202
|
+
endedAt: Date.now(),
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
},
|
|
206
|
+
});
|
package/src/component/threads.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { assert, omit, pick } from "convex-helpers";
|
|
|
2
2
|
import { paginator } from "convex-helpers/server/pagination";
|
|
3
3
|
import { partial } from "convex-helpers/validators";
|
|
4
4
|
import { ObjectType } from "convex/values";
|
|
5
|
-
import {
|
|
5
|
+
import { vPaginationResult } from "../validators.js";
|
|
6
6
|
import { api, internal } from "./_generated/api.js";
|
|
7
7
|
import { Doc } from "./_generated/dataModel.js";
|
|
8
8
|
import {
|
|
@@ -38,7 +38,7 @@ export const getThread = query({
|
|
|
38
38
|
|
|
39
39
|
export const listThreadsByUserId = query({
|
|
40
40
|
args: {
|
|
41
|
-
userId: v.string(),
|
|
41
|
+
userId: v.optional(v.string()),
|
|
42
42
|
order: v.optional(v.union(v.literal("asc"), v.literal("desc"))),
|
|
43
43
|
paginationOpts: v.optional(paginationOptsValidator),
|
|
44
44
|
},
|
|
@@ -53,7 +53,7 @@ export const listThreadsByUserId = query({
|
|
|
53
53
|
page: threads.page.map(publicThread),
|
|
54
54
|
};
|
|
55
55
|
},
|
|
56
|
-
returns:
|
|
56
|
+
returns: vPaginationResult(vThreadDoc),
|
|
57
57
|
});
|
|
58
58
|
|
|
59
59
|
const vThread = schema.tables.threads.validator;
|
package/src/component/users.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { schema, v } from "./schema.js";
|
|
|
13
13
|
import { deleteMessage } from "./messages.js";
|
|
14
14
|
import { paginationOptsValidator } from "convex/server";
|
|
15
15
|
import { stream } from "convex-helpers/server/stream";
|
|
16
|
-
import {
|
|
16
|
+
import { vPaginationResult } from "../validators.js";
|
|
17
17
|
import { Id } from "./_generated/dataModel.js";
|
|
18
18
|
|
|
19
19
|
// Note: it only searches for users with threads
|
|
@@ -33,7 +33,7 @@ export const listUsersWithThreads = query({
|
|
|
33
33
|
page: results.page.map((t) => t.userId).filter((t): t is string => !!t),
|
|
34
34
|
};
|
|
35
35
|
},
|
|
36
|
-
returns:
|
|
36
|
+
returns: vPaginationResult(v.string()),
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
export const deleteAllForUserId = action({
|
|
@@ -68,7 +68,7 @@ export type VectorSchema = SchemaDefinition<
|
|
|
68
68
|
>;
|
|
69
69
|
|
|
70
70
|
export const VectorDimensions = [
|
|
71
|
-
128, 256, 512, 768, 1024, 1536, 2048, 3072, 4096,
|
|
71
|
+
128, 256, 512, 768, 1024, 1408, 1536, 2048, 3072, 4096,
|
|
72
72
|
] as const;
|
|
73
73
|
export function validateVectorDimension(
|
|
74
74
|
dimension: number
|
package/src/mapping.ts
CHANGED
|
@@ -108,7 +108,9 @@ export function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
108
108
|
).map(
|
|
109
109
|
(message): MessageWithMetadata => ({
|
|
110
110
|
message: serializeMessage(message),
|
|
111
|
-
|
|
111
|
+
// Let's not store the ID by default here. It's being generated internally
|
|
112
|
+
// and not referenced elsewhere that we know of.
|
|
113
|
+
// id: message.id,
|
|
112
114
|
...(message.role === "tool" ? toolFields : assistantFields),
|
|
113
115
|
text: step.text,
|
|
114
116
|
// fileId: message.fileId,
|