@convex-dev/agent 0.1.10-alpha.1 → 0.1.11
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 +1 -1
- package/dist/esm/client/index.d.ts +10 -11
- package/dist/esm/client/index.d.ts.map +1 -1
- package/dist/esm/client/index.js +27 -28
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/client/streaming.d.ts.map +1 -1
- package/dist/esm/client/streaming.js +1 -7
- package/dist/esm/client/streaming.js.map +1 -1
- package/dist/esm/component/_generated/api.d.ts +2 -13
- package/dist/esm/component/files.d.ts +1 -1
- package/dist/esm/component/files.d.ts.map +1 -1
- package/dist/esm/component/files.js +6 -4
- package/dist/esm/component/files.js.map +1 -1
- package/dist/esm/component/messages.d.ts +30 -30
- package/dist/esm/component/schema.d.ts +74 -84
- package/dist/esm/component/schema.d.ts.map +1 -1
- package/dist/esm/component/schema.js +2 -3
- package/dist/esm/component/schema.js.map +1 -1
- package/dist/esm/component/streams.d.ts +0 -7
- package/dist/esm/component/streams.d.ts.map +1 -1
- package/dist/esm/component/streams.js +22 -49
- package/dist/esm/component/streams.js.map +1 -1
- package/dist/esm/component/threads.d.ts +8 -8
- package/dist/esm/component/vector/tables.d.ts +3 -5
- package/dist/esm/component/vector/tables.d.ts.map +1 -1
- package/dist/esm/mapping.d.ts +4 -3
- package/dist/esm/mapping.d.ts.map +1 -1
- package/dist/esm/mapping.js +7 -5
- package/dist/esm/mapping.js.map +1 -1
- package/dist/esm/react/deltas.d.ts.map +1 -1
- package/dist/esm/react/deltas.js +2 -2
- package/dist/esm/react/deltas.js.map +1 -1
- package/dist/esm/react/index.d.ts +2 -4
- package/dist/esm/react/index.d.ts.map +1 -1
- package/dist/esm/react/index.js +9 -22
- package/dist/esm/react/index.js.map +1 -1
- package/dist/esm/react/optimisticallySendMessage.js +1 -1
- package/dist/esm/react/optimisticallySendMessage.js.map +1 -1
- package/dist/esm/validators.d.ts +10 -15
- package/dist/esm/validators.d.ts.map +1 -1
- package/dist/esm/validators.js +0 -2
- package/dist/esm/validators.js.map +1 -1
- package/dist/esm.tsbuildinfo +1 -1
- package/package.json +24 -49
- package/src/client/index.ts +42 -39
- package/src/client/streaming.ts +1 -7
- package/src/component/_generated/api.d.ts +2 -13
- package/src/component/files.ts +6 -4
- package/src/component/schema.ts +2 -3
- package/src/component/streams.ts +39 -85
- package/src/component/vector/tables.ts +1 -1
- package/src/mapping.ts +17 -6
- package/src/react/deltas.ts +2 -4
- package/src/react/index.ts +11 -23
- package/src/react/optimisticallySendMessage.ts +1 -1
- package/src/validators.ts +0 -6
- package/dist/commonjs/client/_generated/_ignore.d.ts +0 -1
- package/dist/commonjs/client/_generated/_ignore.d.ts.map +0 -1
- package/dist/commonjs/client/_generated/_ignore.js +0 -3
- package/dist/commonjs/client/_generated/_ignore.js.map +0 -1
- package/dist/commonjs/client/createTool.d.ts +0 -47
- package/dist/commonjs/client/createTool.d.ts.map +0 -1
- package/dist/commonjs/client/createTool.js +0 -46
- package/dist/commonjs/client/createTool.js.map +0 -1
- package/dist/commonjs/client/files.d.ts +0 -56
- package/dist/commonjs/client/files.d.ts.map +0 -1
- package/dist/commonjs/client/files.js +0 -124
- package/dist/commonjs/client/files.js.map +0 -1
- package/dist/commonjs/client/index.d.ts +0 -1356
- package/dist/commonjs/client/index.d.ts.map +0 -1
- package/dist/commonjs/client/index.js +0 -1148
- package/dist/commonjs/client/index.js.map +0 -1
- package/dist/commonjs/client/streaming.d.ts +0 -57
- package/dist/commonjs/client/streaming.d.ts.map +0 -1
- package/dist/commonjs/client/streaming.js +0 -149
- package/dist/commonjs/client/streaming.js.map +0 -1
- package/dist/commonjs/client/types.d.ts +0 -352
- package/dist/commonjs/client/types.d.ts.map +0 -1
- package/dist/commonjs/client/types.js +0 -2
- package/dist/commonjs/client/types.js.map +0 -1
- package/dist/commonjs/component/_generated/api.d.ts +0 -1949
- package/dist/commonjs/component/_generated/api.d.ts.map +0 -1
- package/dist/commonjs/component/_generated/api.js +0 -22
- package/dist/commonjs/component/_generated/api.js.map +0 -1
- package/dist/commonjs/component/_generated/dataModel.d.ts +0 -60
- package/dist/commonjs/component/_generated/server.d.ts +0 -149
- package/dist/commonjs/component/_generated/server.d.ts.map +0 -1
- package/dist/commonjs/component/_generated/server.js +0 -74
- package/dist/commonjs/component/_generated/server.js.map +0 -1
- package/dist/commonjs/component/apiKeys.d.ts +0 -11
- package/dist/commonjs/component/apiKeys.d.ts.map +0 -1
- package/dist/commonjs/component/apiKeys.js +0 -69
- package/dist/commonjs/component/apiKeys.js.map +0 -1
- package/dist/commonjs/component/convex.config.d.ts +0 -3
- package/dist/commonjs/component/convex.config.d.ts.map +0 -1
- package/dist/commonjs/component/convex.config.js +0 -3
- package/dist/commonjs/component/convex.config.js.map +0 -1
- package/dist/commonjs/component/files.d.ts +0 -90
- package/dist/commonjs/component/files.d.ts.map +0 -1
- package/dist/commonjs/component/files.js +0 -150
- package/dist/commonjs/component/files.js.map +0 -1
- package/dist/commonjs/component/messages.d.ts +0 -1479
- package/dist/commonjs/component/messages.d.ts.map +0 -1
- package/dist/commonjs/component/messages.js +0 -478
- package/dist/commonjs/component/messages.js.map +0 -1
- package/dist/commonjs/component/schema.d.ts +0 -4592
- package/dist/commonjs/component/schema.d.ts.map +0 -1
- package/dist/commonjs/component/schema.js +0 -165
- package/dist/commonjs/component/schema.js.map +0 -1
- package/dist/commonjs/component/streams.d.ts +0 -249
- package/dist/commonjs/component/streams.d.ts.map +0 -1
- package/dist/commonjs/component/streams.js +0 -346
- package/dist/commonjs/component/streams.js.map +0 -1
- package/dist/commonjs/component/threads.d.ts +0 -101
- package/dist/commonjs/component/threads.d.ts.map +0 -1
- package/dist/commonjs/component/threads.js +0 -185
- package/dist/commonjs/component/threads.js.map +0 -1
- package/dist/commonjs/component/users.d.ts +0 -52
- package/dist/commonjs/component/users.d.ts.map +0 -1
- package/dist/commonjs/component/users.js +0 -230
- package/dist/commonjs/component/users.js.map +0 -1
- package/dist/commonjs/component/vector/index.d.ts +0 -61
- package/dist/commonjs/component/vector/index.d.ts.map +0 -1
- package/dist/commonjs/component/vector/index.js +0 -148
- package/dist/commonjs/component/vector/index.js.map +0 -1
- package/dist/commonjs/component/vector/tables.d.ts +0 -60
- package/dist/commonjs/component/vector/tables.d.ts.map +0 -1
- package/dist/commonjs/component/vector/tables.js +0 -56
- package/dist/commonjs/component/vector/tables.js.map +0 -1
- package/dist/commonjs/mapping.d.ts +0 -50
- package/dist/commonjs/mapping.d.ts.map +0 -1
- package/dist/commonjs/mapping.js +0 -257
- package/dist/commonjs/mapping.js.map +0 -1
- package/dist/commonjs/package.json +0 -3
- package/dist/commonjs/react/deltas.d.ts +0 -29
- package/dist/commonjs/react/deltas.d.ts.map +0 -1
- package/dist/commonjs/react/deltas.js +0 -268
- package/dist/commonjs/react/deltas.js.map +0 -1
- package/dist/commonjs/react/index.d.ts +0 -97
- package/dist/commonjs/react/index.d.ts.map +0 -1
- package/dist/commonjs/react/index.js +0 -224
- package/dist/commonjs/react/index.js.map +0 -1
- package/dist/commonjs/react/optimisticallySendMessage.d.ts +0 -8
- package/dist/commonjs/react/optimisticallySendMessage.d.ts.map +0 -1
- package/dist/commonjs/react/optimisticallySendMessage.js +0 -40
- package/dist/commonjs/react/optimisticallySendMessage.js.map +0 -1
- package/dist/commonjs/react/toUIMessages.d.ts +0 -13
- package/dist/commonjs/react/toUIMessages.d.ts.map +0 -1
- package/dist/commonjs/react/toUIMessages.js +0 -146
- package/dist/commonjs/react/toUIMessages.js.map +0 -1
- package/dist/commonjs/react/types.d.ts +0 -26
- package/dist/commonjs/react/types.d.ts.map +0 -1
- package/dist/commonjs/react/types.js +0 -2
- package/dist/commonjs/react/types.js.map +0 -1
- package/dist/commonjs/react/useSmoothText.d.ts +0 -20
- package/dist/commonjs/react/useSmoothText.d.ts.map +0 -1
- package/dist/commonjs/react/useSmoothText.js +0 -51
- package/dist/commonjs/react/useSmoothText.js.map +0 -1
- package/dist/commonjs/shared.d.ts +0 -10
- package/dist/commonjs/shared.d.ts.map +0 -1
- package/dist/commonjs/shared.js +0 -30
- package/dist/commonjs/shared.js.map +0 -1
- package/dist/commonjs/validators.d.ts +0 -5721
- package/dist/commonjs/validators.d.ts.map +0 -1
- package/dist/commonjs/validators.js +0 -317
- package/dist/commonjs/validators.js.map +0 -1
- package/dist/commonjs/vitest.config.d.ts +0 -3
- package/dist/commonjs/vitest.config.d.ts.map +0 -1
- package/dist/commonjs/vitest.config.js +0 -7
- package/dist/commonjs/vitest.config.js.map +0 -1
- package/dist/commonjs.tsbuildinfo +0 -1
- package/dist/esm/vitest.config.d.ts +0 -3
- package/dist/esm/vitest.config.d.ts.map +0 -1
- package/dist/esm/vitest.config.js +0 -7
- package/dist/esm/vitest.config.js.map +0 -1
package/src/client/index.ts
CHANGED
|
@@ -624,7 +624,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
624
624
|
* to a thread (and optionally userId).
|
|
625
625
|
*/
|
|
626
626
|
async generateObject<T>(
|
|
627
|
-
ctx:
|
|
627
|
+
ctx: ActionCtx,
|
|
628
628
|
{
|
|
629
629
|
userId: argsUserId,
|
|
630
630
|
threadId,
|
|
@@ -705,7 +705,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
705
705
|
* to a thread (and optionally userId).
|
|
706
706
|
*/
|
|
707
707
|
async streamObject<T>(
|
|
708
|
-
ctx:
|
|
708
|
+
ctx: ActionCtx,
|
|
709
709
|
{
|
|
710
710
|
userId: argsUserId,
|
|
711
711
|
threadId,
|
|
@@ -994,8 +994,6 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
994
994
|
args: {
|
|
995
995
|
threadId: string;
|
|
996
996
|
streamArgs: StreamArgs | undefined;
|
|
997
|
-
// By default, only streaming messages are included.
|
|
998
|
-
includeStatuses?: ("streaming" | "finished" | "aborted")[];
|
|
999
997
|
}
|
|
1000
998
|
): Promise<SyncStreamsReturnValue | undefined> {
|
|
1001
999
|
if (!args.streamArgs) return undefined;
|
|
@@ -1004,8 +1002,6 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1004
1002
|
kind: "list",
|
|
1005
1003
|
messages: await ctx.runQuery(this.component.streams.list, {
|
|
1006
1004
|
threadId: args.threadId,
|
|
1007
|
-
startOrder: args.streamArgs.startOrder,
|
|
1008
|
-
statuses: args.includeStatuses,
|
|
1009
1005
|
}),
|
|
1010
1006
|
};
|
|
1011
1007
|
} else {
|
|
@@ -1075,9 +1071,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1075
1071
|
const targetMessage = contextMessages.find(
|
|
1076
1072
|
(m) => m._id === args.upToAndIncludingMessageId
|
|
1077
1073
|
)?.message;
|
|
1078
|
-
const messagesToSearch = targetMessage
|
|
1079
|
-
? [targetMessage, ...args.messages]
|
|
1080
|
-
: args.messages;
|
|
1074
|
+
const messagesToSearch = targetMessage ? [targetMessage] : args.messages;
|
|
1081
1075
|
if (!("runAction" in ctx)) {
|
|
1082
1076
|
throw new Error("searchUserMessages only works in an action");
|
|
1083
1077
|
}
|
|
@@ -1351,7 +1345,7 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1351
1345
|
* @param args The arguments to the saveObject function.
|
|
1352
1346
|
*/
|
|
1353
1347
|
async saveObject(
|
|
1354
|
-
ctx:
|
|
1348
|
+
ctx: ActionCtx,
|
|
1355
1349
|
args: {
|
|
1356
1350
|
userId: string | undefined;
|
|
1357
1351
|
threadId: string;
|
|
@@ -1360,10 +1354,15 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1360
1354
|
metadata?: Omit<MessageWithMetadata, "message">;
|
|
1361
1355
|
}
|
|
1362
1356
|
): Promise<void> {
|
|
1363
|
-
const { messages } = serializeObjectResult(
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1357
|
+
const { messages } = await serializeObjectResult(
|
|
1358
|
+
ctx,
|
|
1359
|
+
this.component,
|
|
1360
|
+
args.result,
|
|
1361
|
+
{
|
|
1362
|
+
model: this.options.chat.modelId,
|
|
1363
|
+
provider: this.options.chat.provider,
|
|
1364
|
+
}
|
|
1365
|
+
);
|
|
1367
1366
|
const embeddings = await this.generateEmbeddings(
|
|
1368
1367
|
ctx,
|
|
1369
1368
|
{ userId: args.userId, threadId: args.threadId },
|
|
@@ -1442,18 +1441,16 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1442
1441
|
}> {
|
|
1443
1442
|
contextOptions ||= this.options.contextOptions;
|
|
1444
1443
|
storageOptions ||= this.options.storageOptions;
|
|
1445
|
-
// If only a
|
|
1446
|
-
const messages = args
|
|
1447
|
-
? []
|
|
1448
|
-
: promptOrMessagesToCoreMessages(args);
|
|
1444
|
+
// If only a promptMessageId is provided, this will be empty.
|
|
1445
|
+
const messages = promptOrMessagesToCoreMessages(args);
|
|
1449
1446
|
const userId =
|
|
1450
1447
|
argsUserId ??
|
|
1451
1448
|
(threadId &&
|
|
1452
1449
|
(await ctx.runQuery(this.component.threads.getThread, { threadId }))
|
|
1453
1450
|
?.userId);
|
|
1454
1451
|
assert(
|
|
1455
|
-
!args.promptMessageId || !
|
|
1456
|
-
"you can't specify a prompt
|
|
1452
|
+
!args.promptMessageId || !args.prompt,
|
|
1453
|
+
"you can't specify a prompt if you specify a promptMessageId"
|
|
1457
1454
|
);
|
|
1458
1455
|
// If only a messageId is provided, this will add that message to the end.
|
|
1459
1456
|
const contextMessages = await this.fetchContextMessages(ctx, {
|
|
@@ -1463,29 +1460,33 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1463
1460
|
messages,
|
|
1464
1461
|
contextOptions,
|
|
1465
1462
|
});
|
|
1466
|
-
//
|
|
1467
|
-
//
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
args.promptMessageId
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
) {
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1463
|
+
// If it was a promptMessageId, pop it off context messages
|
|
1464
|
+
// and add to the end of messages.
|
|
1465
|
+
const promptMessage =
|
|
1466
|
+
!!args.promptMessageId &&
|
|
1467
|
+
contextMessages.at(-1)?._id === args.promptMessageId
|
|
1468
|
+
? contextMessages.pop()
|
|
1469
|
+
: undefined;
|
|
1470
|
+
if (promptMessage?.message) {
|
|
1471
|
+
messages.push(deserializeMessage(promptMessage.message));
|
|
1472
|
+
// Lazily generate embeddings for the prompt message, if it doesn't have
|
|
1473
|
+
// embeddings yet. This can happen if the message was saved in a mutation
|
|
1474
|
+
// where the LLM is not available.
|
|
1475
|
+
if (!promptMessage.embeddingId && this.options.textEmbedding) {
|
|
1476
|
+
await this.generateAndSaveEmbeddings(ctx, {
|
|
1477
|
+
messageIds: [promptMessage._id],
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1477
1480
|
}
|
|
1478
|
-
let messageId =
|
|
1479
|
-
let order =
|
|
1480
|
-
|
|
1481
|
-
: undefined;
|
|
1482
|
-
let stepOrder = args.promptMessageId
|
|
1483
|
-
? contextMessages.at(-1)?.stepOrder
|
|
1484
|
-
: undefined;
|
|
1481
|
+
let messageId = promptMessage?._id;
|
|
1482
|
+
let order = promptMessage?.order;
|
|
1483
|
+
let stepOrder = promptMessage?.stepOrder;
|
|
1485
1484
|
if (
|
|
1486
1485
|
threadId &&
|
|
1487
1486
|
messages.length &&
|
|
1488
1487
|
storageOptions?.saveMessages !== "none" &&
|
|
1488
|
+
// If it was a promptMessageId, we don't want to save it again.
|
|
1489
|
+
(!args.promptMessageId || storageOptions?.saveMessages === "all") &&
|
|
1489
1490
|
storageOptions?.saveAnyInputMessages !== false
|
|
1490
1491
|
) {
|
|
1491
1492
|
const saveAll = storageOptions?.saveMessages === "all";
|
|
@@ -1494,7 +1495,9 @@ export class Agent<AgentTools extends ToolSet> {
|
|
|
1494
1495
|
threadId,
|
|
1495
1496
|
userId,
|
|
1496
1497
|
messages: coreMessages,
|
|
1497
|
-
metadata: coreMessages.
|
|
1498
|
+
metadata: coreMessages.map((_, i) =>
|
|
1499
|
+
i === coreMessages.length - 1 ? { id: args.id } : {}
|
|
1500
|
+
),
|
|
1498
1501
|
pending: true,
|
|
1499
1502
|
failPendingSteps: true,
|
|
1500
1503
|
});
|
package/src/client/streaming.ts
CHANGED
|
@@ -96,13 +96,7 @@ export class DeltaStreamer {
|
|
|
96
96
|
this.#nextStepOrder = (metadata.stepOrder ?? 0) + 1;
|
|
97
97
|
this.abortController = new AbortController();
|
|
98
98
|
if (metadata.abortSignal) {
|
|
99
|
-
metadata.abortSignal.addEventListener("abort",
|
|
100
|
-
if (this.streamId) {
|
|
101
|
-
await this.ctx.runMutation(this.component.streams.abort, {
|
|
102
|
-
streamId: this.streamId,
|
|
103
|
-
reason: "abortSignal",
|
|
104
|
-
});
|
|
105
|
-
}
|
|
99
|
+
metadata.abortSignal.addEventListener("abort", () => {
|
|
106
100
|
this.abortController.abort();
|
|
107
101
|
});
|
|
108
102
|
}
|
|
@@ -67,7 +67,7 @@ export type Mounts = {
|
|
|
67
67
|
"mutation",
|
|
68
68
|
"public",
|
|
69
69
|
{ fileIds: Array<string>; force?: boolean },
|
|
70
|
-
|
|
70
|
+
Array<string>
|
|
71
71
|
>;
|
|
72
72
|
get: FunctionReference<
|
|
73
73
|
"query",
|
|
@@ -1414,12 +1414,6 @@ export type Mounts = {
|
|
|
1414
1414
|
>;
|
|
1415
1415
|
};
|
|
1416
1416
|
streams: {
|
|
1417
|
-
abort: FunctionReference<
|
|
1418
|
-
"mutation",
|
|
1419
|
-
"public",
|
|
1420
|
-
{ reason: string; streamId: string },
|
|
1421
|
-
null
|
|
1422
|
-
>;
|
|
1423
1417
|
addDelta: FunctionReference<
|
|
1424
1418
|
"mutation",
|
|
1425
1419
|
"public",
|
|
@@ -1575,18 +1569,13 @@ export type Mounts = {
|
|
|
1575
1569
|
list: FunctionReference<
|
|
1576
1570
|
"query",
|
|
1577
1571
|
"public",
|
|
1578
|
-
{
|
|
1579
|
-
startOrder?: number;
|
|
1580
|
-
statuses?: Array<"streaming" | "finished" | "aborted">;
|
|
1581
|
-
threadId: string;
|
|
1582
|
-
},
|
|
1572
|
+
{ threadId: string },
|
|
1583
1573
|
Array<{
|
|
1584
1574
|
agentName?: string;
|
|
1585
1575
|
model?: string;
|
|
1586
1576
|
order: number;
|
|
1587
1577
|
provider?: string;
|
|
1588
1578
|
providerOptions?: Record<string, Record<string, any>>;
|
|
1589
|
-
status: "streaming" | "finished" | "aborted";
|
|
1590
1579
|
stepOrder: number;
|
|
1591
1580
|
streamId: string;
|
|
1592
1581
|
userId?: string;
|
package/src/component/files.ts
CHANGED
|
@@ -149,25 +149,27 @@ export const deleteFiles = mutation({
|
|
|
149
149
|
fileIds: v.array(v.id("files")),
|
|
150
150
|
force: v.optional(v.boolean()),
|
|
151
151
|
},
|
|
152
|
+
returns: v.array(v.id("files")),
|
|
152
153
|
handler: async (ctx, args) => {
|
|
153
|
-
await Promise.all(
|
|
154
|
+
const deletedFileIds = await Promise.all(
|
|
154
155
|
args.fileIds.map(async (fileId) => {
|
|
155
156
|
const file = await ctx.db.get(fileId);
|
|
156
157
|
if (!file) {
|
|
157
158
|
console.error(`File ${fileId} not found when deleting, skipping...`);
|
|
158
|
-
return;
|
|
159
|
+
return null;
|
|
159
160
|
}
|
|
160
161
|
if (file.refcount && file.refcount > 0) {
|
|
161
162
|
if (!args.force) {
|
|
162
163
|
console.error(
|
|
163
164
|
`File ${fileId} has refcount ${file.refcount} > 0, skipping...`
|
|
164
165
|
);
|
|
165
|
-
return;
|
|
166
|
+
return null;
|
|
166
167
|
}
|
|
167
168
|
}
|
|
168
169
|
await ctx.db.delete(fileId);
|
|
170
|
+
return fileId;
|
|
169
171
|
})
|
|
170
172
|
);
|
|
173
|
+
return deletedFileIds.filter((fileId) => fileId !== null);
|
|
171
174
|
},
|
|
172
|
-
returns: v.null(),
|
|
173
175
|
});
|
package/src/component/schema.ts
CHANGED
|
@@ -108,11 +108,10 @@ export const schema = defineSchema({
|
|
|
108
108
|
v.object({
|
|
109
109
|
kind: v.literal("finished"),
|
|
110
110
|
endedAt: v.number(),
|
|
111
|
-
cleanupFnId: v.optional(v.id("_scheduled_functions")),
|
|
112
111
|
}),
|
|
113
112
|
v.object({
|
|
114
|
-
kind: v.literal("
|
|
115
|
-
|
|
113
|
+
kind: v.literal("error"),
|
|
114
|
+
error: v.string(),
|
|
116
115
|
})
|
|
117
116
|
),
|
|
118
117
|
})
|
package/src/component/streams.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
vStreamMessage,
|
|
7
7
|
} from "../validators.js";
|
|
8
8
|
import { api, internal } from "./_generated/api.js";
|
|
9
|
-
import type {
|
|
9
|
+
import type { Id } from "./_generated/dataModel.js";
|
|
10
10
|
import {
|
|
11
11
|
internalMutation,
|
|
12
12
|
mutation,
|
|
@@ -106,87 +106,33 @@ export const create = mutation({
|
|
|
106
106
|
export const list = query({
|
|
107
107
|
args: {
|
|
108
108
|
threadId: v.id("threads"),
|
|
109
|
-
startOrder: v.optional(v.number()),
|
|
110
|
-
statuses: v.optional(
|
|
111
|
-
v.array(
|
|
112
|
-
v.union(
|
|
113
|
-
v.literal("streaming"),
|
|
114
|
-
v.literal("finished"),
|
|
115
|
-
v.literal("aborted")
|
|
116
|
-
)
|
|
117
|
-
)
|
|
118
|
-
),
|
|
119
109
|
},
|
|
120
110
|
returns: v.array(vStreamMessage),
|
|
121
111
|
handler: async (ctx, args) => {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
"order",
|
|
143
|
-
"stepOrder",
|
|
144
|
-
"userId",
|
|
145
|
-
"agentName",
|
|
146
|
-
"model",
|
|
147
|
-
"provider",
|
|
148
|
-
"providerOptions",
|
|
149
|
-
]),
|
|
150
|
-
}));
|
|
151
|
-
},
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
export const abort = mutation({
|
|
155
|
-
args: {
|
|
156
|
-
streamId: v.id("streamingMessages"),
|
|
157
|
-
reason: v.string(),
|
|
158
|
-
},
|
|
159
|
-
returns: v.null(),
|
|
160
|
-
handler: async (ctx, args) => {
|
|
161
|
-
const stream = await ctx.db.get(args.streamId);
|
|
162
|
-
if (!stream) {
|
|
163
|
-
throw new Error(`Stream not found: ${args.streamId}`);
|
|
164
|
-
}
|
|
165
|
-
if (stream.state.kind !== "streaming") {
|
|
166
|
-
console.warn(
|
|
167
|
-
`Stream trying to abort but not currently streaming (${stream.state.kind}): ${args.streamId}`
|
|
112
|
+
return ctx.db
|
|
113
|
+
.query("streamingMessages")
|
|
114
|
+
.withIndex("threadId_state_order_stepOrder", (q) =>
|
|
115
|
+
q.eq("threadId", args.threadId).eq("state.kind", "streaming")
|
|
116
|
+
)
|
|
117
|
+
.order("desc")
|
|
118
|
+
.take(100)
|
|
119
|
+
.then((msgs) =>
|
|
120
|
+
msgs.map((m) => ({
|
|
121
|
+
streamId: m._id,
|
|
122
|
+
...pick(m, [
|
|
123
|
+
"order",
|
|
124
|
+
"stepOrder",
|
|
125
|
+
"userId",
|
|
126
|
+
"agentName",
|
|
127
|
+
"model",
|
|
128
|
+
"provider",
|
|
129
|
+
"providerOptions",
|
|
130
|
+
]),
|
|
131
|
+
}))
|
|
168
132
|
);
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
await cleanupTimeoutFn(ctx, stream);
|
|
172
|
-
await ctx.db.patch(args.streamId, {
|
|
173
|
-
state: { kind: "aborted", reason: args.reason },
|
|
174
|
-
});
|
|
175
133
|
},
|
|
176
134
|
});
|
|
177
135
|
|
|
178
|
-
async function cleanupTimeoutFn(
|
|
179
|
-
ctx: MutationCtx,
|
|
180
|
-
stream: Doc<"streamingMessages">
|
|
181
|
-
) {
|
|
182
|
-
if (stream.state.kind === "streaming" && stream.state.timeoutFnId) {
|
|
183
|
-
const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
|
|
184
|
-
if (timeoutFn?.state.kind === "pending") {
|
|
185
|
-
await ctx.scheduler.cancel(stream.state.timeoutFnId);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
136
|
export const finish = mutation({
|
|
191
137
|
args: {
|
|
192
138
|
streamId: v.id("streamingMessages"),
|
|
@@ -207,15 +153,20 @@ export const finish = mutation({
|
|
|
207
153
|
);
|
|
208
154
|
return;
|
|
209
155
|
}
|
|
210
|
-
|
|
211
|
-
|
|
156
|
+
if (stream.state.timeoutFnId) {
|
|
157
|
+
const timeoutFn = await ctx.db.system.get(stream.state.timeoutFnId);
|
|
158
|
+
if (timeoutFn?.state.kind === "pending") {
|
|
159
|
+
await ctx.scheduler.cancel(stream.state.timeoutFnId);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
await ctx.db.patch(args.streamId, {
|
|
163
|
+
state: { kind: "finished", endedAt: Date.now() },
|
|
164
|
+
});
|
|
165
|
+
await ctx.scheduler.runAfter(
|
|
212
166
|
DELETE_STREAM_DELAY,
|
|
213
167
|
api.streams.deleteStreamAsync,
|
|
214
168
|
{ streamId: args.streamId }
|
|
215
169
|
);
|
|
216
|
-
await ctx.db.patch(args.streamId, {
|
|
217
|
-
state: { kind: "finished", endedAt: Date.now(), cleanupFnId },
|
|
218
|
-
});
|
|
219
170
|
},
|
|
220
171
|
});
|
|
221
172
|
|
|
@@ -272,8 +223,8 @@ export const timeoutStream = internalMutation({
|
|
|
272
223
|
}
|
|
273
224
|
await ctx.db.patch(args.streamId, {
|
|
274
225
|
state: {
|
|
275
|
-
kind: "
|
|
276
|
-
|
|
226
|
+
kind: "finished",
|
|
227
|
+
endedAt: Date.now(),
|
|
277
228
|
},
|
|
278
229
|
});
|
|
279
230
|
},
|
|
@@ -294,9 +245,12 @@ async function deletePageForStreamId(
|
|
|
294
245
|
if (deltas.isDone) {
|
|
295
246
|
const stream = await ctx.db.get(args.streamId);
|
|
296
247
|
if (stream) {
|
|
297
|
-
|
|
298
|
-
if (
|
|
299
|
-
await ctx.
|
|
248
|
+
const state = stream.state;
|
|
249
|
+
if (state.kind === "streaming" && state.timeoutFnId) {
|
|
250
|
+
const timeoutFn = await ctx.db.system.get(state.timeoutFnId);
|
|
251
|
+
if (timeoutFn?.state.kind === "pending") {
|
|
252
|
+
await ctx.scheduler.cancel(state.timeoutFnId);
|
|
253
|
+
}
|
|
300
254
|
}
|
|
301
255
|
await ctx.db.delete(args.streamId);
|
|
302
256
|
}
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
type VObject,
|
|
16
16
|
type VUnion,
|
|
17
17
|
} from "convex/values";
|
|
18
|
-
import type { QueryCtx } from "../_generated/server";
|
|
18
|
+
import type { QueryCtx } from "../_generated/server.js";
|
|
19
19
|
|
|
20
20
|
// We only generate embeddings for non-tool, non-system messages
|
|
21
21
|
const embeddings = {
|
package/src/mapping.ts
CHANGED
|
@@ -85,6 +85,7 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
85
85
|
usage: step.usage,
|
|
86
86
|
warnings: step.warnings,
|
|
87
87
|
finishReason: step.finishReason,
|
|
88
|
+
sources: step.stepType === "tool-result" ? undefined : step.sources,
|
|
88
89
|
};
|
|
89
90
|
const toolFields = {
|
|
90
91
|
sources: step.sources,
|
|
@@ -113,17 +114,19 @@ export async function serializeNewMessagesInStep<TOOLS extends ToolSet>(
|
|
|
113
114
|
return messages;
|
|
114
115
|
}
|
|
115
116
|
|
|
116
|
-
export function serializeObjectResult(
|
|
117
|
+
export async function serializeObjectResult(
|
|
118
|
+
ctx: ActionCtx,
|
|
119
|
+
component: AgentComponent,
|
|
117
120
|
result: GenerateObjectResult<unknown>,
|
|
118
121
|
metadata: { model: string; provider: string }
|
|
119
|
-
): { messages: MessageWithMetadata[] } {
|
|
122
|
+
): Promise<{ messages: MessageWithMetadata[] }> {
|
|
120
123
|
const text = JSON.stringify(result.object);
|
|
121
124
|
|
|
122
|
-
const message = {
|
|
125
|
+
const { message, fileIds } = await serializeMessage(ctx, component, {
|
|
123
126
|
role: "assistant" as const,
|
|
124
127
|
content: text,
|
|
125
128
|
id: result.response.id,
|
|
126
|
-
};
|
|
129
|
+
});
|
|
127
130
|
return {
|
|
128
131
|
messages: [
|
|
129
132
|
{
|
|
@@ -136,6 +139,7 @@ export function serializeObjectResult(
|
|
|
136
139
|
text,
|
|
137
140
|
usage: result.usage,
|
|
138
141
|
warnings: result.warnings,
|
|
142
|
+
fileIds,
|
|
139
143
|
},
|
|
140
144
|
],
|
|
141
145
|
};
|
|
@@ -330,9 +334,17 @@ function encodeBase64(data: ArrayBuffer): string {
|
|
|
330
334
|
export function promptOrMessagesToCoreMessages(args: {
|
|
331
335
|
prompt?: string;
|
|
332
336
|
messages?: CoreMessage[] | AIMessageWithoutId[];
|
|
337
|
+
promptMessageId?: string;
|
|
333
338
|
}): CoreMessage[] {
|
|
334
339
|
const messages: CoreMessage[] = [];
|
|
335
|
-
assert(
|
|
340
|
+
assert(
|
|
341
|
+
args.prompt || args.messages || args.promptMessageId,
|
|
342
|
+
"messages or prompt or promptMessageId is required"
|
|
343
|
+
);
|
|
344
|
+
assert(
|
|
345
|
+
!args.promptMessageId || !args.prompt,
|
|
346
|
+
"you can't specify a prompt if you specify a promptMessageId. use messages instead."
|
|
347
|
+
);
|
|
336
348
|
if (args.messages) {
|
|
337
349
|
if (
|
|
338
350
|
args.messages.some(
|
|
@@ -353,6 +365,5 @@ export function promptOrMessagesToCoreMessages(args: {
|
|
|
353
365
|
if (args.prompt) {
|
|
354
366
|
messages.push({ role: "user", content: args.prompt });
|
|
355
367
|
}
|
|
356
|
-
assert(messages.length > 0, "Messages must contain at least one message");
|
|
357
368
|
return messages;
|
|
358
369
|
}
|
package/src/react/deltas.ts
CHANGED
|
@@ -256,14 +256,12 @@ export function createStreamingMessage(
|
|
|
256
256
|
): MessageDoc {
|
|
257
257
|
const { streamId, ...rest } = message;
|
|
258
258
|
const metadata: MessageDoc = {
|
|
259
|
-
...rest,
|
|
260
259
|
_id: `${streamId}-${index}`,
|
|
261
260
|
_creationTime: Date.now(),
|
|
262
|
-
status:
|
|
263
|
-
{ streaming: "pending", finished: "success", aborted: "failed" } as const
|
|
264
|
-
)[message.status],
|
|
261
|
+
status: "pending",
|
|
265
262
|
threadId,
|
|
266
263
|
tool: false,
|
|
264
|
+
...rest,
|
|
267
265
|
};
|
|
268
266
|
switch (part.type) {
|
|
269
267
|
case "text-delta":
|
package/src/react/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
2
|
+
import type { ErrorMessage } from "convex-helpers";
|
|
3
3
|
import {
|
|
4
4
|
type PaginatedQueryArgs,
|
|
5
5
|
type UsePaginatedQueryResult,
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "convex/react";
|
|
8
8
|
import { usePaginatedQuery } from "convex-helpers/react";
|
|
9
9
|
import type { FunctionArgs } from "convex/server";
|
|
10
|
-
import { useMemo,
|
|
10
|
+
import { useMemo, useState } from "react";
|
|
11
11
|
import type { MessageDoc } from "../client/index.js";
|
|
12
12
|
import type { SyncStreamsReturnValue } from "../client/types.js";
|
|
13
13
|
import type { StreamArgs } from "../validators.js";
|
|
@@ -103,18 +103,14 @@ export function useThreadMessages<
|
|
|
103
103
|
ThreadMessagesArgs<Query>,
|
|
104
104
|
ThreadMessagesResult<Query>
|
|
105
105
|
>,
|
|
106
|
-
!options.stream
|
|
107
|
-
args === "skip" ||
|
|
108
|
-
paginated.status === "LoadingFirstPage"
|
|
109
|
-
? "skip"
|
|
110
|
-
: { ...args, startOrder: paginated.results.at(-1)?.order }
|
|
106
|
+
!options.stream ? "skip" : args
|
|
111
107
|
);
|
|
112
108
|
|
|
113
109
|
const merged = useMemo(() => {
|
|
114
110
|
const streamListMessages =
|
|
115
111
|
streamMessages?.map((m) => ({
|
|
116
112
|
...m,
|
|
117
|
-
streaming:
|
|
113
|
+
streaming: true,
|
|
118
114
|
})) ?? [];
|
|
119
115
|
return {
|
|
120
116
|
...paginated,
|
|
@@ -154,7 +150,7 @@ export function useStreamingThreadMessages<
|
|
|
154
150
|
Query extends ThreadStreamQuery<any, any>,
|
|
155
151
|
>(
|
|
156
152
|
query: Query,
|
|
157
|
-
args:
|
|
153
|
+
args: ThreadMessagesArgs<Query> | "skip"
|
|
158
154
|
): Array<ThreadMessagesResult<Query>> | undefined {
|
|
159
155
|
// Invariant: streamMessages[streamId] is comprised of all deltas up to the
|
|
160
156
|
// cursor. There can be multiple messages in the same stream, e.g. for tool
|
|
@@ -162,23 +158,15 @@ export function useStreamingThreadMessages<
|
|
|
162
158
|
const [streams, setStreams] = useState<
|
|
163
159
|
Array<{ streamId: string; cursor: number; messages: MessageDoc[] }>
|
|
164
160
|
>([]);
|
|
165
|
-
const startOrderRef = useRef<number>(0);
|
|
166
|
-
const queryArgs = args === "skip" ? args : omit(args, ["startOrder"]);
|
|
167
|
-
if (args !== "skip" && !startOrderRef.current && args.startOrder) {
|
|
168
|
-
startOrderRef.current = args.startOrder;
|
|
169
|
-
}
|
|
170
161
|
// Get all the active streams
|
|
171
162
|
const streamList = useQuery(
|
|
172
163
|
query,
|
|
173
|
-
|
|
174
|
-
?
|
|
164
|
+
args === "skip"
|
|
165
|
+
? args
|
|
175
166
|
: ({
|
|
176
|
-
...
|
|
167
|
+
...args,
|
|
177
168
|
paginationOpts: { cursor: null, numItems: 0 },
|
|
178
|
-
streamArgs: {
|
|
179
|
-
kind: "list",
|
|
180
|
-
startOrder: startOrderRef.current,
|
|
181
|
-
} as StreamArgs,
|
|
169
|
+
streamArgs: { kind: "list" } as StreamArgs,
|
|
182
170
|
} as FunctionArgs<Query>)
|
|
183
171
|
) as
|
|
184
172
|
| { streams: Extract<SyncStreamsReturnValue, { kind: "list" }> }
|
|
@@ -198,10 +186,10 @@ export function useStreamingThreadMessages<
|
|
|
198
186
|
// Get the deltas for all the active streams, if any.
|
|
199
187
|
const cursorQuery = useQuery(
|
|
200
188
|
query,
|
|
201
|
-
|
|
189
|
+
args === "skip" || !streamList
|
|
202
190
|
? ("skip" as const)
|
|
203
191
|
: ({
|
|
204
|
-
...
|
|
192
|
+
...args,
|
|
205
193
|
paginationOpts: { cursor: null, numItems: 0 },
|
|
206
194
|
streamArgs: { kind: "deltas", cursors } as StreamArgs,
|
|
207
195
|
} as FunctionArgs<Query>)
|
|
@@ -11,7 +11,7 @@ export function optimisticallySendMessage(
|
|
|
11
11
|
) => void {
|
|
12
12
|
return (store, args) => {
|
|
13
13
|
const queries = store.getAllQueries(query);
|
|
14
|
-
let maxOrder =
|
|
14
|
+
let maxOrder = 0;
|
|
15
15
|
let maxStepOrder = 0;
|
|
16
16
|
for (const q of queries) {
|
|
17
17
|
if (q.args?.threadId !== args.threadId) continue;
|
package/src/validators.ts
CHANGED
|
@@ -460,7 +460,6 @@ export const vStreamArgs = v.optional(
|
|
|
460
460
|
v.union(
|
|
461
461
|
v.object({
|
|
462
462
|
kind: v.literal("list"),
|
|
463
|
-
startOrder: v.optional(v.number()),
|
|
464
463
|
}),
|
|
465
464
|
v.object({
|
|
466
465
|
kind: v.literal("deltas"),
|
|
@@ -472,11 +471,6 @@ export type StreamArgs = Infer<typeof vStreamArgs>;
|
|
|
472
471
|
|
|
473
472
|
export const vStreamMessage = v.object({
|
|
474
473
|
streamId: v.string(),
|
|
475
|
-
status: v.union(
|
|
476
|
-
v.literal("streaming"),
|
|
477
|
-
v.literal("finished"),
|
|
478
|
-
v.literal("aborted")
|
|
479
|
-
),
|
|
480
474
|
order: v.number(),
|
|
481
475
|
stepOrder: v.number(),
|
|
482
476
|
// metadata
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=_ignore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_ignore.d.ts","sourceRoot":"","sources":["../../../../src/client/_generated/_ignore.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"_ignore.js","sourceRoot":"","sources":["../../../../src/client/_generated/_ignore.ts"],"names":[],"mappings":";AAAA,kEAAkE"}
|