@convex-dev/agent 0.3.0 → 0.3.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 (54) hide show
  1. package/dist/client/files.d.ts +5 -2
  2. package/dist/client/files.d.ts.map +1 -1
  3. package/dist/client/files.js.map +1 -1
  4. package/dist/client/index.d.ts.map +1 -1
  5. package/dist/client/index.js +16 -90
  6. package/dist/client/index.js.map +1 -1
  7. package/dist/client/messages.d.ts +2 -2
  8. package/dist/client/messages.d.ts.map +1 -1
  9. package/dist/client/messages.js.map +1 -1
  10. package/dist/client/saveInputMessages.d.ts.map +1 -1
  11. package/dist/client/saveInputMessages.js +1 -0
  12. package/dist/client/saveInputMessages.js.map +1 -1
  13. package/dist/client/search.d.ts +1 -1
  14. package/dist/client/search.d.ts.map +1 -1
  15. package/dist/client/start.d.ts +1 -1
  16. package/dist/client/start.d.ts.map +1 -1
  17. package/dist/client/start.js +2 -1
  18. package/dist/client/start.js.map +1 -1
  19. package/dist/client/streamText.d.ts +46 -0
  20. package/dist/client/streamText.d.ts.map +1 -0
  21. package/dist/client/streamText.js +93 -0
  22. package/dist/client/streamText.js.map +1 -0
  23. package/dist/client/streaming.d.ts +3 -3
  24. package/dist/client/streaming.d.ts.map +1 -1
  25. package/dist/client/streaming.js.map +1 -1
  26. package/dist/client/threads.d.ts +2 -2
  27. package/dist/client/threads.d.ts.map +1 -1
  28. package/dist/client/threads.js.map +1 -1
  29. package/dist/client/types.d.ts +4 -16
  30. package/dist/client/types.d.ts.map +1 -1
  31. package/dist/client/utils.d.ts +4 -0
  32. package/dist/client/utils.d.ts.map +1 -0
  33. package/dist/client/utils.js +21 -0
  34. package/dist/client/utils.js.map +1 -0
  35. package/dist/component/messages.d.ts.map +1 -1
  36. package/dist/component/messages.js +22 -7
  37. package/dist/component/messages.js.map +1 -1
  38. package/dist/deltas.js +1 -1
  39. package/dist/deltas.js.map +1 -1
  40. package/package.json +4 -3
  41. package/src/client/files.ts +3 -2
  42. package/src/client/index.ts +24 -131
  43. package/src/client/messages.ts +2 -2
  44. package/src/client/saveInputMessages.ts +1 -0
  45. package/src/client/search.ts +1 -1
  46. package/src/client/start.ts +6 -10
  47. package/src/client/streamText.ts +163 -0
  48. package/src/client/streaming.ts +2 -2
  49. package/src/client/threads.ts +2 -2
  50. package/src/client/types.ts +11 -28
  51. package/src/client/utils.ts +27 -0
  52. package/src/component/messages.test.ts +7 -5
  53. package/src/component/messages.ts +26 -14
  54. package/src/deltas.ts +1 -1
@@ -0,0 +1,27 @@
1
+ import type { StepResult, StopCondition } from "ai";
2
+
3
+ export async function willContinue(
4
+ steps: StepResult<any>[],
5
+
6
+ stopWhen: StopCondition<any> | Array<StopCondition<any>> | undefined,
7
+ ): Promise<boolean> {
8
+ const step = steps.at(-1)!;
9
+ // we aren't doing another round after a tool result
10
+ // TODO: whether to handle continuing after too much context used..
11
+ if (step.finishReason !== "tool-calls") return false;
12
+ // we don't have a tool result, so we'll wait for more
13
+ if (step.toolCalls.length > step.toolResults.length) return false;
14
+ if (Array.isArray(stopWhen)) {
15
+ return (await Promise.all(stopWhen.map(async (s) => s({ steps })))).every(
16
+ (stop) => !stop,
17
+ );
18
+ }
19
+ return !!stopWhen && !(await stopWhen({ steps }));
20
+ }
21
+
22
+ export function errorToString(error: unknown): string {
23
+ if (error instanceof Error) {
24
+ return error.message;
25
+ }
26
+ return String(error);
27
+ }
@@ -536,21 +536,23 @@ describe("agent", () => {
536
536
  const result = await t.mutation(api.messages.deleteByOrder, {
537
537
  threadId: thread._id as Id<"threads">,
538
538
  startOrder: 0,
539
- endOrder: 1,
539
+ endOrder: 2,
540
540
  });
541
541
 
542
542
  expect(result.isDone).toBe(true);
543
- expect(result.lastOrder).toBe(0);
543
+ expect(result.lastOrder).toBe(1);
544
544
  expect(result.lastStepOrder).toBe(1);
545
545
 
546
- // Verify only messages from order 0 were deleted
546
+ // Verify only messages from order 0 & 1 were deleted
547
547
  const remainingMessages = await t.query(
548
548
  api.messages.listMessagesByThreadId,
549
549
  { threadId: thread._id as Id<"threads">, order: "asc" },
550
550
  );
551
551
 
552
- expect(remainingMessages.page).toHaveLength(3); // Should have messages from order 1 and 2
553
- expect(remainingMessages.page.map((m) => m.order)).toEqual([1, 1, 2]);
552
+ expect(remainingMessages.page).toHaveLength(1); // Should have messages from order 2
553
+ expect(remainingMessages.page[0].message!.content).toBe(
554
+ "message order 2, step 0",
555
+ );
554
556
  });
555
557
 
556
558
  test("deleteByOrder handles step order boundaries correctly", async () => {
@@ -102,12 +102,12 @@ export const deleteByOrder = mutation({
102
102
  lastOrder?: number;
103
103
  lastStepOrder?: number;
104
104
  }> => {
105
- const messages = await orderedMessagesStream(
106
- ctx,
107
- args.threadId,
108
- "asc",
109
- args.startOrder,
110
- )
105
+ const messages = await orderedMessagesStream(ctx, {
106
+ threadId: args.threadId,
107
+ sortOrder: "asc",
108
+ startOrder: args.startOrder,
109
+ startOrderBound: "gte",
110
+ })
111
111
  .narrow({
112
112
  lowerBound: args.startStepOrder
113
113
  ? [args.startOrder, args.startStepOrder]
@@ -312,14 +312,22 @@ export async function getMaxMessage(
312
312
  threadId: Id<"threads">,
313
313
  order?: number,
314
314
  ) {
315
- return orderedMessagesStream(ctx, threadId, "desc", order).first();
315
+ return orderedMessagesStream(ctx, {
316
+ threadId,
317
+ sortOrder: "desc",
318
+ startOrder: order,
319
+ startOrderBound: "eq",
320
+ }).first();
316
321
  }
317
322
 
318
323
  function orderedMessagesStream(
319
324
  ctx: QueryCtx,
320
- threadId: Id<"threads">,
321
- sortOrder: "asc" | "desc",
322
- order?: number,
325
+ args: {
326
+ threadId: Id<"threads">;
327
+ sortOrder: "asc" | "desc";
328
+ startOrder?: number;
329
+ startOrderBound?: "gte" | "eq";
330
+ },
323
331
  ) {
324
332
  return mergedStream(
325
333
  [true, false].flatMap((tool) =>
@@ -328,15 +336,19 @@ function orderedMessagesStream(
328
336
  .query("messages")
329
337
  .withIndex("threadId_status_tool_order_stepOrder", (q) => {
330
338
  const qq = q
331
- .eq("threadId", threadId)
339
+ .eq("threadId", args.threadId)
332
340
  .eq("status", status)
333
341
  .eq("tool", tool);
334
- if (order !== undefined) {
335
- return qq.eq("order", order);
342
+ if (args.startOrder !== undefined) {
343
+ if (args.startOrderBound === "gte") {
344
+ return qq.gte("order", args.startOrder);
345
+ } else {
346
+ return qq.eq("order", args.startOrder);
347
+ }
336
348
  }
337
349
  return qq;
338
350
  })
339
- .order(sortOrder),
351
+ .order(args.sortOrder),
340
352
  ),
341
353
  ),
342
354
  ["order", "stepOrder"],
package/src/deltas.ts CHANGED
@@ -79,7 +79,7 @@ export async function updateFromUIMessageChunks(
79
79
  for await (const messagePart of messageStream) {
80
80
  assert(
81
81
  messagePart.id === message.id,
82
- `Expecting to only make one UIMessage in a stream, but have ${JSON.stringify(message)} and created ${JSON.stringify(messagePart)}`,
82
+ `Expecting to only make one UIMessage in a stream`,
83
83
  );
84
84
  message = messagePart;
85
85
  }