convex-durable-agents 0.1.7 → 0.2.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.
Files changed (130) hide show
  1. package/README.md +30 -39
  2. package/dist/client/api.d.ts +124 -0
  3. package/dist/client/api.d.ts.map +1 -0
  4. package/dist/client/api.js +269 -0
  5. package/dist/client/api.js.map +1 -0
  6. package/dist/client/handler.d.ts +53 -0
  7. package/dist/client/handler.d.ts.map +1 -0
  8. package/dist/client/handler.js +282 -0
  9. package/dist/client/handler.js.map +1 -0
  10. package/dist/client/helpers.d.ts +6 -0
  11. package/dist/client/helpers.d.ts.map +1 -0
  12. package/dist/client/helpers.js +27 -0
  13. package/dist/client/helpers.js.map +1 -0
  14. package/dist/client/index.d.ts +7 -256
  15. package/dist/client/index.d.ts.map +1 -1
  16. package/dist/client/index.js +4 -753
  17. package/dist/client/index.js.map +1 -1
  18. package/dist/client/streamer.d.ts +36 -0
  19. package/dist/client/streamer.d.ts.map +1 -0
  20. package/dist/client/streamer.js +192 -0
  21. package/dist/client/streamer.js.map +1 -0
  22. package/dist/client/tools.d.ts +33 -0
  23. package/dist/client/tools.d.ts.map +1 -0
  24. package/dist/client/tools.js +67 -0
  25. package/dist/client/tools.js.map +1 -0
  26. package/dist/client/types.d.ts +73 -0
  27. package/dist/client/types.d.ts.map +1 -0
  28. package/dist/client/types.js +21 -0
  29. package/dist/client/types.js.map +1 -0
  30. package/dist/client/usage.d.ts +11 -0
  31. package/dist/client/usage.d.ts.map +1 -0
  32. package/dist/client/usage.js +97 -0
  33. package/dist/client/usage.js.map +1 -0
  34. package/dist/client/workpool.d.ts +40 -0
  35. package/dist/client/workpool.d.ts.map +1 -0
  36. package/dist/client/workpool.js +42 -0
  37. package/dist/client/workpool.js.map +1 -0
  38. package/dist/component/_generated/component.d.ts +106 -78
  39. package/dist/component/_generated/component.d.ts.map +1 -1
  40. package/dist/component/_generated/server.d.ts.map +1 -1
  41. package/dist/component/agent.d.ts +10 -62
  42. package/dist/component/agent.d.ts.map +1 -1
  43. package/dist/component/agent.js +49 -305
  44. package/dist/component/agent.js.map +1 -1
  45. package/dist/component/messages.d.ts +40 -30
  46. package/dist/component/messages.d.ts.map +1 -1
  47. package/dist/component/messages.js +97 -33
  48. package/dist/component/messages.js.map +1 -1
  49. package/dist/component/schema.d.ts +98 -41
  50. package/dist/component/schema.d.ts.map +1 -1
  51. package/dist/component/schema.js +49 -18
  52. package/dist/component/schema.js.map +1 -1
  53. package/dist/component/streams.d.ts +98 -89
  54. package/dist/component/streams.d.ts.map +1 -1
  55. package/dist/component/streams.js +304 -181
  56. package/dist/component/streams.js.map +1 -1
  57. package/dist/component/threads.d.ts +26 -4
  58. package/dist/component/threads.d.ts.map +1 -1
  59. package/dist/component/threads.js +153 -9
  60. package/dist/component/threads.js.map +1 -1
  61. package/dist/component/tool_calls.d.ts +105 -5
  62. package/dist/component/tool_calls.d.ts.map +1 -1
  63. package/dist/component/tool_calls.js +580 -11
  64. package/dist/component/tool_calls.js.map +1 -1
  65. package/dist/logger.d.ts +9 -0
  66. package/dist/logger.d.ts.map +1 -0
  67. package/dist/logger.js +22 -0
  68. package/dist/logger.js.map +1 -0
  69. package/dist/react/agent-chat.d.ts +73 -0
  70. package/dist/react/agent-chat.d.ts.map +1 -0
  71. package/dist/react/agent-chat.js +66 -0
  72. package/dist/react/agent-chat.js.map +1 -0
  73. package/dist/react/index.d.ts +5 -299
  74. package/dist/react/index.d.ts.map +1 -1
  75. package/dist/react/index.js +3 -686
  76. package/dist/react/index.js.map +1 -1
  77. package/dist/react/message-utils.d.ts +11 -0
  78. package/dist/react/message-utils.d.ts.map +1 -0
  79. package/dist/react/message-utils.js +29 -0
  80. package/dist/react/message-utils.js.map +1 -0
  81. package/dist/react/smooth-text.d.ts +13 -0
  82. package/dist/react/smooth-text.d.ts.map +1 -0
  83. package/dist/react/smooth-text.js +59 -0
  84. package/dist/react/smooth-text.js.map +1 -0
  85. package/dist/react/types.d.ts +21 -0
  86. package/dist/react/types.d.ts.map +1 -0
  87. package/dist/react/types.js +2 -0
  88. package/dist/react/types.js.map +1 -0
  89. package/dist/react/use-thread-messages.d.ts +41 -0
  90. package/dist/react/use-thread-messages.d.ts.map +1 -0
  91. package/dist/react/use-thread-messages.js +127 -0
  92. package/dist/react/use-thread-messages.js.map +1 -0
  93. package/dist/shared/stream_seq.d.ts +2 -0
  94. package/dist/shared/stream_seq.d.ts.map +1 -0
  95. package/dist/shared/stream_seq.js +4 -0
  96. package/dist/shared/stream_seq.js.map +1 -0
  97. package/dist/streaming.d.ts +3 -0
  98. package/dist/streaming.d.ts.map +1 -0
  99. package/dist/streaming.js +4 -0
  100. package/dist/streaming.js.map +1 -0
  101. package/package.json +19 -18
  102. package/src/client/api.ts +393 -0
  103. package/src/client/handler.ts +413 -0
  104. package/src/client/helpers.ts +27 -0
  105. package/src/client/index.ts +29 -1090
  106. package/src/client/streamer.ts +211 -0
  107. package/src/client/tools.ts +92 -0
  108. package/src/client/types.ts +108 -0
  109. package/src/client/usage.ts +125 -0
  110. package/src/client/workpool.ts +70 -0
  111. package/src/component/_generated/component.ts +164 -109
  112. package/src/component/_generated/server.ts +0 -5
  113. package/src/component/agent.ts +60 -347
  114. package/src/component/messages.ts +105 -47
  115. package/src/component/schema.ts +51 -19
  116. package/src/component/streams.ts +351 -208
  117. package/src/component/threads.ts +180 -9
  118. package/src/component/tool_calls.ts +664 -12
  119. package/src/logger.ts +23 -0
  120. package/src/react/agent-chat.ts +128 -0
  121. package/src/react/index.ts +5 -1080
  122. package/src/react/message-utils.ts +34 -0
  123. package/src/react/smooth-text.ts +78 -0
  124. package/src/react/types.ts +21 -0
  125. package/src/react/use-thread-messages.ts +197 -0
  126. package/src/streaming.ts +4 -0
  127. package/src/client/index.test.ts +0 -49
  128. package/src/client/setup.test.ts +0 -20
  129. package/src/component/component.test.ts +0 -466
  130. package/src/component/setup.test.ts +0 -11
package/README.md CHANGED
@@ -56,7 +56,6 @@ Create a chat handler with your AI model and tools:
56
56
  import { z } from "zod";
57
57
  import { components, internal } from "./_generated/api";
58
58
  import { createActionTool, defineAgentApi, streamHandlerAction } from "convex-durable-agents";
59
- import { openai } from "@ai-sdk/openai";
60
59
 
61
60
  // Define the stream handler with your model and tools
62
61
  export const chatAgentHandler = streamHandlerAction(components.durableAgents, {
@@ -78,7 +77,7 @@ export const {
78
77
  sendMessage,
79
78
  getThread,
80
79
  listMessages,
81
- listMessagesWithStreams,
80
+ streamUpdates,
82
81
  listThreads,
83
82
  deleteThread,
84
83
  resumeThread,
@@ -165,12 +164,13 @@ export const getWeather = internalAction({
165
164
  Use the React hooks to build your chat interface:
166
165
 
167
166
  ```tsx
168
- import { useAgentChat, getMessageKey } from "convex-durable-agents/react";
167
+ import { useAgentChat } from "convex-durable-agents/react";
169
168
  import { api } from "../convex/_generated/api";
170
169
 
171
170
  function ChatView({ threadId }: { threadId: string }) {
172
171
  const { messages, status, isRunning, sendMessage, stop } = useAgentChat({
173
- listMessages: api.chat.listMessagesWithStreams,
172
+ listMessages: api.chat.listMessages,
173
+ streamUpdates: api.chat.streamUpdates,
174
174
  getThread: api.chat.getThread,
175
175
  sendMessage: api.chat.sendMessage,
176
176
  stopThread: api.chat.stopThread,
@@ -181,7 +181,7 @@ function ChatView({ threadId }: { threadId: string }) {
181
181
  return (
182
182
  <div>
183
183
  {messages.map((msg) => (
184
- <div key={getMessageKey(msg)}>
184
+ <div key={msg.metadata?.key}>
185
185
  <strong>{msg.role}:</strong> {msg.parts.map((p) => (p.type === "text" ? p.text : null))}
186
186
  </div>
187
187
  ))}
@@ -210,17 +210,18 @@ function ChatView({ threadId }: { threadId: string }) {
210
210
 
211
211
  Creates the full agent API with **public** functions that can be called directly from clients:
212
212
 
213
- - `createThread({ prompt? })` - Create a new conversation thread
213
+ - `createThread({ prompt?, messages?, autoStart? })` - Create a new conversation thread
214
214
  - `sendMessage({ threadId, prompt })` - Send a message to a thread
215
+ - `addMessage({ threadId, msg })` - Add a message to a thread without triggering the agent
215
216
  - `resumeThread({ threadId, prompt? })` - Resume a stopped/failed thread
216
217
  - `stopThread({ threadId })` - Stop a running thread
217
218
  - `getThread({ threadId })` - Get thread details
218
219
  - `listMessages({ threadId })` - List messages in a thread
219
- - `listMessagesWithStreams({ threadId, streamArgs? })` - List messages with streaming support
220
+ - `streamUpdates({ threadId, fromSeq? })` - Get streaming message updates for real-time UI
220
221
  - `listThreads({ limit? })` - List all threads
221
222
  - `deleteThread({ threadId })` - Delete a thread
222
- - `addToolResult({ toolCallId, result })` - Add result for async tool
223
- - `addToolError({ toolCallId, error })` - Add error for async tool
223
+ - `addToolResult({ threadId, toolCallId, result })` - Add result for async tool
224
+ - `addToolError({ threadId, toolCallId, error })` - Add error for async tool
224
225
 
225
226
  **Options:**
226
227
 
@@ -229,6 +230,8 @@ type AgentApiOptions = {
229
230
  authorizationCallback?: (ctx: QueryCtx | MutationCtx | ActionCtx, threadId: string) => Promise<void> | void;
230
231
  workpoolEnqueueAction?: FunctionReference<"mutation", "internal">;
231
232
  toolExecutionWorkpoolEnqueueAction?: FunctionReference<"mutation", "internal">;
233
+ onStatusChange?: FunctionReference<"mutation", "internal">;
234
+ excludeSystemMessages?: boolean;
232
235
  };
233
236
  ```
234
237
 
@@ -237,9 +240,10 @@ type AgentApiOptions = {
237
240
  - `workpoolEnqueueAction` - Route agent and tool execution through a workpool for parallelism control
238
241
  - `toolExecutionWorkpoolEnqueueAction` - Override workpool for tool execution only (falls back to
239
242
  `workpoolEnqueueAction` if not set)
243
+ - `onStatusChange` - Mutation callback invoked when thread status changes
244
+ - `excludeSystemMessages` - Whether to exclude system messages from message lists (defaults to `true`)
240
245
 
241
- **Protected endpoints:** `sendMessage`, `resumeThread`, `stopThread`, `getThread`, `listMessages`,
242
- `listMessagesWithStreams`, `deleteThread`
246
+ **Protected endpoints:** `sendMessage`, `resumeThread`, `stopThread`, `getThread`, `listMessages`, `deleteThread`
243
247
 
244
248
  **Example with ownership check:**
245
249
 
@@ -310,7 +314,7 @@ All-in-one hook for chat functionality that combines thread state with mutations
310
314
 
311
315
  ```ts
312
316
  const {
313
- messages, // UIMessage[]
317
+ messages, // UIMessageWithConvexMetadata[]
314
318
  thread, // ThreadDoc | null
315
319
  status, // ThreadStatus
316
320
  isLoading, // boolean
@@ -322,13 +326,13 @@ const {
322
326
  stop, // () => Promise<null>
323
327
  resume, // (prompt?: string) => Promise<null>
324
328
  } = useAgentChat({
325
- listMessages: api.chat.listMessagesWithStreams,
329
+ listMessages: api.chat.listMessages,
330
+ streamUpdates: api.chat.streamUpdates,
326
331
  getThread: api.chat.getThread,
327
332
  sendMessage: api.chat.sendMessage,
328
333
  stopThread: api.chat.stopThread,
329
334
  resumeThread: api.chat.resumeThread,
330
335
  threadId,
331
- stream: true, // optional, defaults to true
332
336
  });
333
337
 
334
338
  // Send a message (threadId is automatically included)
@@ -341,13 +345,13 @@ await stop();
341
345
  await resume();
342
346
  ```
343
347
 
344
- #### `useThread(messagesQuery, threadQuery, args, options?)`
348
+ #### `useThreadMessages(options)`
345
349
 
346
- Lower-level hook for thread status and messages (use `useAgentChat` for most cases):
350
+ Lower-level hook for thread messages with streaming support (use `useAgentChat` for most cases):
347
351
 
348
352
  ```ts
349
353
  const {
350
- messages, // UIMessage[]
354
+ messages, // UIMessageWithConvexMetadata[]
351
355
  thread, // ThreadDoc | null
352
356
  status, // ThreadStatus
353
357
  isLoading, // boolean
@@ -355,7 +359,12 @@ const {
355
359
  isComplete, // boolean
356
360
  isFailed, // boolean
357
361
  isStopped, // boolean
358
- } = useThread(api.chat.listMessagesWithStreams, api.chat.getThread, { threadId }, { stream: true });
362
+ } = useThreadMessages({
363
+ messagesQuery: api.chat.listMessages,
364
+ streamingMessageUpdatesQuery: api.chat.streamUpdates,
365
+ threadQuery: api.chat.getThread,
366
+ threadId,
367
+ });
359
368
  ```
360
369
 
361
370
  #### `useSmoothText(text, options?)`
@@ -369,24 +378,6 @@ const [visibleText, { cursor, isStreaming }] = useSmoothText(text, {
369
378
  });
370
379
  ```
371
380
 
372
- #### `useThreadStatus(query, args)`
373
-
374
- Subscribe to thread status changes:
375
-
376
- ```ts
377
- const { thread, status, isRunning, isComplete, isFailed, isStopped } = useThreadStatus(api.chat.getThread, {
378
- threadId,
379
- });
380
- ```
381
-
382
- #### `useMessages(query, threadQuery, args)`
383
-
384
- Fetch and transform messages:
385
-
386
- ```ts
387
- const { messages, isLoading, thread } = useMessages(api.chat.listMessages, api.chat.getThread, { threadId });
388
- ```
389
-
390
381
  ## Thread Status
391
382
 
392
383
  Threads can be in one of these states:
@@ -479,9 +470,9 @@ defineAgentApi(components.durableAgents, internal.chat.chatAgentHandler, {
479
470
  ├─────────────────────────────────────────────────────────────┤
480
471
  │ defineAgentApi() │ React Hooks │
481
472
  │ - createThread │ - useAgentChat │
482
- │ - sendMessage │ - useThread
483
- │ - stopThread │ - useMessages
484
- │ - resumeThread │ - useSmoothText
473
+ │ - sendMessage │ - useThreadMessages
474
+ │ - stopThread │ - useSmoothText
475
+ │ - resumeThread │
485
476
  ├─────────────────────────────────────────────────────────────┤
486
477
  │ Durable Agent Component │
487
478
  ├──────────────┬──────────────┬──────────────┬────────────────┤
@@ -0,0 +1,124 @@
1
+ import { type FunctionReference, type FunctionVisibility, type RegisteredMutation, type RegisteredQuery } from "convex/server";
2
+ import { type Infer } from "convex/values";
3
+ import type { ComponentApi } from "../component/_generated/component.js";
4
+ import { vUIMessageOptId } from "../component/messages.js";
5
+ import type { StreamingMessageUpdates } from "../component/streams.js";
6
+ import { type ActionCtx, type MessageDoc, type MutationCtx, type QueryCtx, type ThreadDoc } from "./types.js";
7
+ export type StreamArgs = {
8
+ kind: "list";
9
+ } | {
10
+ kind: "deltas";
11
+ cursors: Array<{
12
+ streamId: string;
13
+ cursor: number;
14
+ }>;
15
+ };
16
+ export type StreamMessage = {
17
+ streamId: string;
18
+ status: "streaming" | "finished" | "aborted";
19
+ msgId: string;
20
+ threadId: string;
21
+ _creationTime: number;
22
+ baseMessageCreationTime?: number;
23
+ streamVersion: number;
24
+ };
25
+ export type StreamDelta = {
26
+ streamId: string;
27
+ seq: number;
28
+ start: number;
29
+ end: number;
30
+ parts: Array<unknown>;
31
+ _creationTime: number;
32
+ messageId?: string;
33
+ chunkCount: number;
34
+ schemaVersion: number;
35
+ ops?: Array<{
36
+ op: "append_part" | "replace_tool_call_part" | "skip_duplicate_step_start" | "skip_tail_duplicate_text";
37
+ partType?: string;
38
+ toolCallId?: string;
39
+ targetPartKey?: string;
40
+ targetIndexHint?: number;
41
+ reason?: string;
42
+ }>;
43
+ };
44
+ export type MessagesWithStreamsResult = {
45
+ messages: MessageDoc[];
46
+ streams?: {
47
+ kind: "list";
48
+ messages: StreamMessage[];
49
+ } | {
50
+ kind: "deltas";
51
+ deltas: StreamDelta[];
52
+ };
53
+ };
54
+ export type AgentApi<V extends FunctionVisibility = "public"> = {
55
+ createThread: RegisteredMutation<V, {
56
+ prompt?: string;
57
+ }, string>;
58
+ sendMessage: RegisteredMutation<V, {
59
+ threadId: string;
60
+ prompt: string;
61
+ }, null>;
62
+ addMessage: RegisteredMutation<V, {
63
+ threadId: string;
64
+ msg: Infer<typeof vUIMessageOptId>;
65
+ }, null>;
66
+ resumeThread: RegisteredMutation<V, {
67
+ threadId: string;
68
+ prompt?: string;
69
+ }, null>;
70
+ stopThread: RegisteredMutation<V, {
71
+ threadId: string;
72
+ }, null>;
73
+ getThread: RegisteredQuery<V, {
74
+ threadId: string;
75
+ }, ThreadDoc | null>;
76
+ listMessages: RegisteredQuery<V, {
77
+ threadId: string;
78
+ }, MessageDoc[]>;
79
+ streamUpdates: RegisteredQuery<V, {
80
+ threadId: string;
81
+ fromSeq?: number;
82
+ }, StreamingMessageUpdates>;
83
+ listThreads: RegisteredQuery<V, {
84
+ limit?: number;
85
+ }, ThreadDoc[]>;
86
+ deleteThread: RegisteredMutation<V, {
87
+ threadId: string;
88
+ }, null>;
89
+ addToolResult: RegisteredMutation<V, {
90
+ threadId: string;
91
+ toolCallId: string;
92
+ result: unknown;
93
+ }, null>;
94
+ addToolError: RegisteredMutation<V, {
95
+ threadId: string;
96
+ toolCallId: string;
97
+ error: string;
98
+ }, null>;
99
+ };
100
+ export type AgentApiOptions = {
101
+ /** Optional authorization callback for thread access control */
102
+ authorizationCallback?: (ctx: QueryCtx | MutationCtx | ActionCtx, threadId: string) => Promise<void> | void;
103
+ /** Optional: Function to enqueue actions via workpool (used for both stream handler and tools unless overridden) */
104
+ workpoolEnqueueAction?: FunctionReference<"mutation", "internal">;
105
+ /** Optional: Override workpool for tool execution only */
106
+ toolExecutionWorkpoolEnqueueAction?: FunctionReference<"mutation", "internal">;
107
+ /** Optional: Callback invoked when thread status changes */
108
+ onStatusChange?: FunctionReference<"mutation", "internal">;
109
+ /** Optional: Whether to exclude system messages from message lists */
110
+ excludeSystemMessages?: boolean;
111
+ };
112
+ /**
113
+ * Define a public agent API that can be called from clients.
114
+ */
115
+ export declare function defineAgentApi(component: ComponentApi, ref: FunctionReference<"action", "internal" | "public", {
116
+ threadId: string;
117
+ }>, options?: AgentApiOptions): AgentApi<"public">;
118
+ /**
119
+ * Define an internal agent API that can only be called from other Convex functions.
120
+ */
121
+ export declare function defineInternalAgentApi(component: ComponentApi, ref: FunctionReference<"action", "internal" | "public", {
122
+ threadId: string;
123
+ }>, options?: AgentApiOptions): AgentApi<"internal">;
124
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/client/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,269 @@
1
+ import { actionGeneric, createFunctionHandle, internalActionGeneric, internalMutationGeneric, internalQueryGeneric, mutationGeneric, queryGeneric, } from "convex/server";
2
+ import { v } from "convex/values";
3
+ import { vUIMessageOptId } from "../component/messages.js";
4
+ import { vMessageContent, vMessageRole } from "../component/schema.js";
5
+ import { _vClientThreadDoc, } from "./types.js";
6
+ // ============================================================================
7
+ // Agent API Definition
8
+ // ============================================================================
9
+ async function checkThreadIsIdle(component, ctx, threadId) {
10
+ const thread = await ctx.runQuery(component.threads.get, { threadId });
11
+ if (!thread) {
12
+ throw new Error(`Thread ${threadId} not found`);
13
+ }
14
+ switch (thread.status) {
15
+ case "awaiting_tool_results":
16
+ case "streaming":
17
+ throw new Error(`Thread ${threadId} status=${thread.status}, cannot resume`);
18
+ }
19
+ }
20
+ async function serializeThreadOptions(options) {
21
+ const result = {};
22
+ if (options?.workpoolEnqueueAction) {
23
+ const handle = await createFunctionHandle(options.workpoolEnqueueAction);
24
+ result.workpoolEnqueueAction = handle.toString();
25
+ }
26
+ if (options?.toolExecutionWorkpoolEnqueueAction) {
27
+ const handle = await createFunctionHandle(options.toolExecutionWorkpoolEnqueueAction);
28
+ result.toolExecutionWorkpoolEnqueueAction = handle.toString();
29
+ }
30
+ if (options?.onStatusChange) {
31
+ const handle = await createFunctionHandle(options.onStatusChange);
32
+ result.onStatusChangeHandle = handle.toString();
33
+ }
34
+ return result;
35
+ }
36
+ function createAgentApi(component, ref, _action, query, mutation, options) {
37
+ const authorize = options?.authorizationCallback;
38
+ return {
39
+ createThread: mutation({
40
+ args: {
41
+ prompt: v.optional(v.string()),
42
+ messages: v.optional(v.array(v.object({ role: vMessageRole, content: vMessageContent }))),
43
+ autoStart: v.optional(v.boolean()),
44
+ },
45
+ returns: v.string(),
46
+ handler: async (ctx, args) => {
47
+ // Create a function handle that can be scheduled from within the component
48
+ const handle = await createFunctionHandle(ref);
49
+ // Serialize thread options (workpool + status callback)
50
+ const serializedOptions = await serializeThreadOptions(options);
51
+ const thread = await ctx.runMutation(component.threads.create, {
52
+ streamFnHandle: handle,
53
+ ...serializedOptions,
54
+ });
55
+ if (args.messages) {
56
+ for (const message of args.messages) {
57
+ await ctx.runMutation(component.messages.add, {
58
+ threadId: thread._id,
59
+ msg: {
60
+ role: message.role,
61
+ parts: message.content,
62
+ },
63
+ });
64
+ }
65
+ }
66
+ if (args.prompt) {
67
+ await ctx.runMutation(component.messages.add, {
68
+ threadId: thread._id,
69
+ msg: { role: "user", parts: [{ type: "text", text: args.prompt }] },
70
+ });
71
+ }
72
+ if (args.autoStart || (args.autoStart == null && args.prompt != null)) {
73
+ await ctx.runMutation(component.agent.continueStream, {
74
+ threadId: thread._id,
75
+ });
76
+ }
77
+ return thread._id;
78
+ },
79
+ }),
80
+ sendMessage: mutation({
81
+ args: {
82
+ threadId: v.string(),
83
+ prompt: v.string(),
84
+ },
85
+ returns: v.null(),
86
+ handler: async (ctx, args) => {
87
+ if (authorize)
88
+ await authorize(ctx, args.threadId);
89
+ await checkThreadIsIdle(component, ctx, args.threadId);
90
+ await ctx.runMutation(component.messages.add, {
91
+ threadId: args.threadId,
92
+ msg: { role: "user", parts: [{ type: "text", text: args.prompt }] },
93
+ });
94
+ await ctx.runMutation(component.threads.resume, {
95
+ threadId: args.threadId,
96
+ });
97
+ await ctx.scheduler.runAfter(0, component.agent.continueStream, {
98
+ threadId: args.threadId,
99
+ });
100
+ return null;
101
+ },
102
+ }),
103
+ addMessage: mutation({
104
+ args: {
105
+ threadId: v.string(),
106
+ msg: vUIMessageOptId,
107
+ },
108
+ returns: v.union(v.string(), v.null()),
109
+ handler: async (ctx, args) => {
110
+ if (authorize)
111
+ await authorize(ctx, args.threadId);
112
+ const msgId = await ctx.runMutation(component.messages.add, {
113
+ threadId: args.threadId,
114
+ msg: args.msg,
115
+ overwrite: false,
116
+ });
117
+ return msgId ?? null;
118
+ },
119
+ }),
120
+ resumeThread: mutation({
121
+ args: {
122
+ threadId: v.string(),
123
+ prompt: v.optional(v.string()),
124
+ },
125
+ returns: v.null(),
126
+ handler: async (ctx, args) => {
127
+ if (authorize)
128
+ await authorize(ctx, args.threadId);
129
+ const threadId = args.threadId;
130
+ await checkThreadIsIdle(component, ctx, threadId);
131
+ if (args.prompt) {
132
+ await ctx.runMutation(component.messages.add, {
133
+ threadId,
134
+ msg: { role: "user", parts: [{ type: "text", text: args.prompt }] },
135
+ });
136
+ }
137
+ await ctx.runMutation(component.threads.setStopSignal, {
138
+ threadId,
139
+ stopSignal: false,
140
+ });
141
+ await ctx.scheduler.runAfter(0, component.agent.continueStream, {
142
+ threadId,
143
+ });
144
+ return null;
145
+ },
146
+ }),
147
+ stopThread: mutation({
148
+ args: {
149
+ threadId: v.string(),
150
+ },
151
+ returns: v.null(),
152
+ handler: async (ctx, args) => {
153
+ if (authorize)
154
+ await authorize(ctx, args.threadId);
155
+ await ctx.runMutation(component.threads.setStopSignal, {
156
+ threadId: args.threadId,
157
+ stopSignal: true,
158
+ });
159
+ return null;
160
+ },
161
+ }),
162
+ getThread: query({
163
+ args: {
164
+ threadId: v.string(),
165
+ },
166
+ returns: v.union(_vClientThreadDoc, v.null()),
167
+ handler: async (ctx, args) => {
168
+ if (authorize)
169
+ await authorize(ctx, args.threadId);
170
+ return ctx.runQuery(component.threads.get, {
171
+ threadId: args.threadId,
172
+ });
173
+ },
174
+ }),
175
+ listMessages: query({
176
+ args: {
177
+ threadId: v.string(),
178
+ },
179
+ handler: async (ctx, args) => {
180
+ if (authorize)
181
+ await authorize(ctx, args.threadId);
182
+ const messages = await ctx.runQuery(component.messages.list, {
183
+ threadId: args.threadId,
184
+ excludeSystemMessages: options?.excludeSystemMessages ?? true,
185
+ });
186
+ return messages;
187
+ },
188
+ }),
189
+ streamUpdates: query({
190
+ args: {
191
+ threadId: v.string(),
192
+ fromSeq: v.optional(v.number()),
193
+ },
194
+ handler: async (ctx, args) => {
195
+ return ctx.runQuery(component.streams.queryStreamingMessageUpdates, {
196
+ threadId: args.threadId,
197
+ fromSeq: args.fromSeq,
198
+ });
199
+ },
200
+ }),
201
+ listThreads: query({
202
+ args: {
203
+ limit: v.optional(v.number()),
204
+ },
205
+ handler: async (ctx, args) => {
206
+ return ctx.runQuery(component.threads.list, { limit: args.limit });
207
+ },
208
+ }),
209
+ deleteThread: mutation({
210
+ args: {
211
+ threadId: v.string(),
212
+ },
213
+ returns: v.null(),
214
+ handler: async (ctx, args) => {
215
+ if (authorize)
216
+ await authorize(ctx, args.threadId);
217
+ await ctx.runMutation(component.threads.remove, {
218
+ threadId: args.threadId,
219
+ });
220
+ return null;
221
+ },
222
+ }),
223
+ addToolResult: mutation({
224
+ args: {
225
+ threadId: v.string(),
226
+ toolCallId: v.string(),
227
+ result: v.any(),
228
+ },
229
+ returns: v.null(),
230
+ handler: async (ctx, args) => {
231
+ await ctx.runMutation(component.tool_calls.addToolResult, {
232
+ threadId: args.threadId,
233
+ toolCallId: args.toolCallId,
234
+ result: args.result,
235
+ });
236
+ return null;
237
+ },
238
+ }),
239
+ addToolError: mutation({
240
+ args: {
241
+ threadId: v.string(),
242
+ toolCallId: v.string(),
243
+ error: v.string(),
244
+ },
245
+ returns: v.null(),
246
+ handler: async (ctx, args) => {
247
+ await ctx.runMutation(component.tool_calls.addToolError, {
248
+ threadId: args.threadId,
249
+ toolCallId: args.toolCallId,
250
+ error: args.error,
251
+ });
252
+ return null;
253
+ },
254
+ }),
255
+ };
256
+ }
257
+ /**
258
+ * Define a public agent API that can be called from clients.
259
+ */
260
+ export function defineAgentApi(component, ref, options) {
261
+ return createAgentApi(component, ref, actionGeneric, queryGeneric, mutationGeneric, options);
262
+ }
263
+ /**
264
+ * Define an internal agent API that can only be called from other Convex functions.
265
+ */
266
+ export function defineInternalAgentApi(component, ref, options) {
267
+ return createAgentApi(component, ref, internalActionGeneric, internalQueryGeneric, internalMutationGeneric, options);
268
+ }
269
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/client/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { type ModelMessage, streamText, type UIMessage } from "ai";
2
+ import { type FunctionReference } from "convex/server";
3
+ import type { ComponentApi } from "../component/_generated/component.js";
4
+ import { type ActionCtx, type DurableTool } from "./types.js";
5
+ import { type UsageInfo } from "./usage.js";
6
+ export type StreamingOptions = {
7
+ throttleMs?: number;
8
+ returnImmediately?: boolean;
9
+ };
10
+ export type MessageReceivedCallbackArgs = {
11
+ threadId: string;
12
+ streamId: string;
13
+ message: UIMessage;
14
+ usage: UsageInfo;
15
+ providerMetadata?: unknown;
16
+ };
17
+ export type MessageReceivedCallback = (ctx: ActionCtx, args: MessageReceivedCallbackArgs) => void | Promise<void>;
18
+ export type TurnCompleteArgs = {
19
+ threadId: string;
20
+ streamId: string;
21
+ providerMetadata?: unknown;
22
+ finishReason?: string;
23
+ };
24
+ export type TurnCompleteCallback = (ctx: ActionCtx, args: TurnCompleteArgs) => void | Promise<void>;
25
+ export type ErrorHandlerArgs = {
26
+ threadId: string;
27
+ streamId: string;
28
+ error: string;
29
+ };
30
+ export type ErrorHandlerCallback = (ctx: ActionCtx, args: ErrorHandlerArgs) => void | Promise<void>;
31
+ export type StreamHandlerArgs = Omit<Parameters<typeof streamText>[0], "tools" | "messages" | "prompt"> & {
32
+ tools: Record<string, DurableTool<unknown, unknown>>;
33
+ /** Optional: Save streaming deltas to the database for real-time client updates */
34
+ saveStreamDeltas?: boolean | StreamingOptions;
35
+ /** Optional: Transform the messages before sending them to the model */
36
+ transformMessages?: (messages: ModelMessage[]) => ModelMessage[];
37
+ /** Optional: Callback invoked once per stream handler invocation with token usage (best-effort) */
38
+ onMessageComplete?: MessageReceivedCallback;
39
+ /** Optional: Callback when the LLM response is complete (LLM signaled end or turn or stop condition is met) */
40
+ onTurnComplete?: TurnCompleteCallback;
41
+ /** Optional: Callback when an error occurs during the stream handler invocation */
42
+ onError?: ErrorHandlerCallback;
43
+ /** Optional: Function to enqueue actions via workpool (used for both stream handler and tools unless overridden) */
44
+ workpoolEnqueueAction?: FunctionReference<"mutation", "internal">;
45
+ /** Optional: Override workpool for tool execution only */
46
+ toolExecutionWorkpoolEnqueueAction?: FunctionReference<"mutation", "internal">;
47
+ };
48
+ export type StreamHandlerArgsFactory = (ctx: ActionCtx, threadId: string) => StreamHandlerArgs | Promise<StreamHandlerArgs>;
49
+ export declare function streamHandlerAction(component: ComponentApi, argsOrFactory: StreamHandlerArgs | StreamHandlerArgsFactory): import("convex/server").RegisteredAction<"internal", {
50
+ threadId: string;
51
+ streamId: string;
52
+ }, Promise<null | undefined>>;
53
+ //# sourceMappingURL=handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../src/client/handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EACjB,UAAU,EAGV,KAAK,SAAS,EACf,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,KAAK,iBAAiB,EAAgD,MAAM,eAAe,CAAC;AAErG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sCAAsC,CAAC;AAOzE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAA0C,MAAM,YAAY,CAAC;AACtG,OAAO,EAAqD,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAM/F,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,CAAC;AAWF,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,SAAS,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,2BAA2B,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAElH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpG,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpG,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC,GAAG;IACxG,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACrD,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAC;IAC9C,wEAAwE;IACxE,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,CAAC;IACjE,mGAAmG;IACnG,iBAAiB,CAAC,EAAE,uBAAuB,CAAC;IAC5C,+GAA+G;IAC/G,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC,mFAAmF;IACnF,OAAO,CAAC,EAAE,oBAAoB,CAAC;IAC/B,oHAAoH;IACpH,qBAAqB,CAAC,EAAE,iBAAiB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAClE,0DAA0D;IAC1D,kCAAkC,CAAC,EAAE,iBAAiB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;CAChF,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,CACrC,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,MAAM,KACb,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAEpD,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,YAAY,EACvB,aAAa,EAAE,iBAAiB,GAAG,wBAAwB;;;8BAgU5D"}