deepagentsdk 0.13.0 → 0.14.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.
@@ -6,7 +6,15 @@ let ai = require("ai");
6
6
  * Server-side route handler adapter for AI SDK Elements
7
7
  *
8
8
  * Creates a Next.js/Express-compatible route handler that runs DeepAgent
9
- * and returns UI Message Stream compatible responses for use with useChat.
9
+ * and returns UI Message Stream compatible responses with full event visibility.
10
+ *
11
+ * This handler streams all DeepAgent event types (26+) including:
12
+ * - Text and tool events (standard protocol)
13
+ * - File system operations
14
+ * - Command execution
15
+ * - Web requests and searches
16
+ * - Subagent lifecycle
17
+ * - State changes (todos, checkpoints)
10
18
  *
11
19
  * @example
12
20
  * ```typescript
@@ -26,13 +34,14 @@ let ai = require("ai");
26
34
  */
27
35
  /**
28
36
  * Creates a route handler that processes chat requests using DeepAgent
29
- * and returns UI Message Stream compatible responses.
37
+ * and streams all 26+ event types in UI Message Stream Protocol format.
30
38
  *
31
39
  * The returned handler:
32
40
  * - Accepts POST requests with { messages: UIMessage[] } body
33
41
  * - Runs DeepAgent with the conversation history
34
42
  * - Streams responses in UI Message Stream Protocol format
35
43
  * - Works with useChat hook from @ai-sdk/react
44
+ * - Provides full visibility into agent behavior (file ops, web requests, subagents, etc.)
36
45
  *
37
46
  * @param options - Configuration options
38
47
  * @returns A request handler function compatible with Next.js/Express
@@ -66,8 +75,8 @@ function createElementsRouteHandler(options) {
66
75
  headers: { "Content-Type": "application/json" }
67
76
  });
68
77
  const modelMessages = await (0, ai.convertToModelMessages)(messages);
69
- let currentTextId = null;
70
78
  const genId = generateId || (() => crypto.randomUUID());
79
+ let currentTextId = null;
71
80
  return (0, ai.createUIMessageStreamResponse)({ stream: (0, ai.createUIMessageStream)({
72
81
  originalMessages: messages,
73
82
  generateId: genId,
@@ -78,84 +87,10 @@ function createElementsRouteHandler(options) {
78
87
  state: initialState,
79
88
  threadId,
80
89
  maxSteps
81
- })) switch (event.type) {
82
- case "step-start":
83
- writer.write({ type: "start-step" });
84
- break;
85
- case "step-finish":
86
- writer.write({ type: "finish-step" });
87
- break;
88
- case "text":
89
- if (!currentTextId) {
90
- currentTextId = genId();
91
- writer.write({
92
- type: "text-start",
93
- id: currentTextId
94
- });
95
- }
96
- writer.write({
97
- type: "text-delta",
98
- id: currentTextId,
99
- delta: event.text
100
- });
101
- break;
102
- case "tool-call":
103
- if (currentTextId) {
104
- writer.write({
105
- type: "text-end",
106
- id: currentTextId
107
- });
108
- currentTextId = null;
109
- }
110
- writer.write({
111
- type: "tool-input-available",
112
- toolCallId: event.toolCallId,
113
- toolName: event.toolName,
114
- input: event.args
115
- });
116
- break;
117
- case "tool-result":
118
- if (event.isError) writer.write({
119
- type: "tool-output-error",
120
- toolCallId: event.toolCallId,
121
- errorText: String(event.result)
122
- });
123
- else writer.write({
124
- type: "tool-output-available",
125
- toolCallId: event.toolCallId,
126
- output: event.result
127
- });
128
- break;
129
- case "todos-changed":
130
- writer.write({
131
- type: "data",
132
- name: "todos-changed",
133
- data: { todos: event.todos }
134
- });
135
- break;
136
- case "error":
137
- if (currentTextId) {
138
- writer.write({
139
- type: "text-end",
140
- id: currentTextId
141
- });
142
- currentTextId = null;
143
- }
144
- writer.write({
145
- type: "error",
146
- errorText: event.error.message
147
- });
148
- break;
149
- case "done":
150
- if (currentTextId) {
151
- writer.write({
152
- type: "text-end",
153
- id: currentTextId
154
- });
155
- currentTextId = null;
156
- }
157
- break;
158
- default: break;
90
+ })) {
91
+ const result = mapEventToProtocol(event, writer, genId, currentTextId);
92
+ if (typeof result === "string") currentTextId = result;
93
+ else if (result === null) currentTextId = null;
159
94
  }
160
95
  if (currentTextId) writer.write({
161
96
  type: "text-end",
@@ -175,6 +110,310 @@ function createElementsRouteHandler(options) {
175
110
  }) });
176
111
  };
177
112
  }
113
+ /**
114
+ * Maps a DeepAgent event to a UI Message Stream Protocol event.
115
+ *
116
+ * This function handles all 26+ DeepAgent event types, mapping:
117
+ * - Standard protocol events (text, tools, steps, errors)
118
+ * - Custom data events (file operations, web requests, subagents, execution)
119
+ *
120
+ * @param event - The DeepAgent event to map
121
+ * @param writer - The UI message stream writer
122
+ * @param genId - ID generator function
123
+ * @param currentTextId - The current text part ID (for tracking streaming text)
124
+ * @returns The new currentTextId value (string | null)
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * // Handles text streaming with proper ID tracking
129
+ * let textId: string | null = null;
130
+ * textId = mapEventToProtocol({ type: 'text', text: 'Hello' }, writer, genId, textId);
131
+ * // textId is now the ID of the active text part
132
+ * ```
133
+ */
134
+ function mapEventToProtocol(event, writer, genId, currentTextId) {
135
+ switch (event.type) {
136
+ case "step-start":
137
+ writer.write({ type: "start-step" });
138
+ return currentTextId;
139
+ case "step-finish":
140
+ writer.write({ type: "finish-step" });
141
+ return currentTextId;
142
+ case "text":
143
+ if (!currentTextId) {
144
+ const textId = genId();
145
+ writer.write({
146
+ type: "text-start",
147
+ id: textId
148
+ });
149
+ return textId;
150
+ }
151
+ writer.write({
152
+ type: "text-delta",
153
+ id: currentTextId,
154
+ delta: event.text
155
+ });
156
+ return currentTextId;
157
+ case "tool-call":
158
+ if (currentTextId) {
159
+ writer.write({
160
+ type: "text-end",
161
+ id: currentTextId
162
+ });
163
+ currentTextId = null;
164
+ }
165
+ writer.write({
166
+ type: "tool-input-available",
167
+ toolCallId: event.toolCallId,
168
+ toolName: event.toolName,
169
+ input: event.args
170
+ });
171
+ return null;
172
+ case "tool-result":
173
+ if (event.isError) writer.write({
174
+ type: "tool-output-error",
175
+ toolCallId: event.toolCallId,
176
+ errorText: String(event.result)
177
+ });
178
+ else writer.write({
179
+ type: "tool-output-available",
180
+ toolCallId: event.toolCallId,
181
+ output: event.result
182
+ });
183
+ return currentTextId;
184
+ case "todos-changed":
185
+ writer.write({
186
+ type: "data",
187
+ name: "todos-changed",
188
+ data: { todos: event.todos }
189
+ });
190
+ return currentTextId;
191
+ case "file-write-start":
192
+ writer.write({
193
+ type: "data",
194
+ name: "file-write-start",
195
+ data: {
196
+ path: event.path,
197
+ content: event.content
198
+ }
199
+ });
200
+ return currentTextId;
201
+ case "file-written":
202
+ writer.write({
203
+ type: "data",
204
+ name: "file-written",
205
+ data: {
206
+ path: event.path,
207
+ content: event.content
208
+ }
209
+ });
210
+ return currentTextId;
211
+ case "file-edited":
212
+ writer.write({
213
+ type: "data",
214
+ name: "file-edited",
215
+ data: {
216
+ path: event.path,
217
+ occurrences: event.occurrences
218
+ }
219
+ });
220
+ return currentTextId;
221
+ case "file-read":
222
+ writer.write({
223
+ type: "data",
224
+ name: "file-read",
225
+ data: {
226
+ path: event.path,
227
+ lines: event.lines
228
+ }
229
+ });
230
+ return currentTextId;
231
+ case "ls":
232
+ writer.write({
233
+ type: "data",
234
+ name: "ls",
235
+ data: {
236
+ path: event.path,
237
+ count: event.count
238
+ }
239
+ });
240
+ return currentTextId;
241
+ case "glob":
242
+ writer.write({
243
+ type: "data",
244
+ name: "glob",
245
+ data: {
246
+ pattern: event.pattern,
247
+ count: event.count
248
+ }
249
+ });
250
+ return currentTextId;
251
+ case "grep":
252
+ writer.write({
253
+ type: "data",
254
+ name: "grep",
255
+ data: {
256
+ pattern: event.pattern,
257
+ count: event.count
258
+ }
259
+ });
260
+ return currentTextId;
261
+ case "execute-start":
262
+ writer.write({
263
+ type: "data",
264
+ name: "execute-start",
265
+ data: {
266
+ command: event.command,
267
+ sandboxId: event.sandboxId
268
+ }
269
+ });
270
+ return currentTextId;
271
+ case "execute-finish":
272
+ writer.write({
273
+ type: "data",
274
+ name: "execute-finish",
275
+ data: {
276
+ command: event.command,
277
+ exitCode: event.exitCode,
278
+ truncated: event.truncated,
279
+ sandboxId: event.sandboxId
280
+ }
281
+ });
282
+ return currentTextId;
283
+ case "web-search-start":
284
+ writer.write({
285
+ type: "data",
286
+ name: "web-search-start",
287
+ data: { query: event.query }
288
+ });
289
+ return currentTextId;
290
+ case "web-search-finish":
291
+ writer.write({
292
+ type: "data",
293
+ name: "web-search-finish",
294
+ data: {
295
+ query: event.query,
296
+ resultCount: event.resultCount
297
+ }
298
+ });
299
+ return currentTextId;
300
+ case "http-request-start":
301
+ writer.write({
302
+ type: "data",
303
+ name: "http-request-start",
304
+ data: {
305
+ url: event.url,
306
+ method: event.method
307
+ }
308
+ });
309
+ return currentTextId;
310
+ case "http-request-finish":
311
+ writer.write({
312
+ type: "data",
313
+ name: "http-request-finish",
314
+ data: {
315
+ url: event.url,
316
+ statusCode: event.statusCode
317
+ }
318
+ });
319
+ return currentTextId;
320
+ case "fetch-url-start":
321
+ writer.write({
322
+ type: "data",
323
+ name: "fetch-url-start",
324
+ data: { url: event.url }
325
+ });
326
+ return currentTextId;
327
+ case "fetch-url-finish":
328
+ writer.write({
329
+ type: "data",
330
+ name: "fetch-url-finish",
331
+ data: {
332
+ url: event.url,
333
+ success: event.success
334
+ }
335
+ });
336
+ return currentTextId;
337
+ case "subagent-start":
338
+ writer.write({
339
+ type: "data",
340
+ name: "subagent-start",
341
+ data: {
342
+ name: event.name,
343
+ task: event.task
344
+ }
345
+ });
346
+ return currentTextId;
347
+ case "subagent-finish":
348
+ writer.write({
349
+ type: "data",
350
+ name: "subagent-finish",
351
+ data: {
352
+ name: event.name,
353
+ result: event.result
354
+ }
355
+ });
356
+ return currentTextId;
357
+ case "subagent-step":
358
+ writer.write({
359
+ type: "data",
360
+ name: "subagent-step",
361
+ data: {
362
+ stepIndex: event.stepIndex,
363
+ toolCalls: event.toolCalls
364
+ }
365
+ });
366
+ return currentTextId;
367
+ case "checkpoint-saved":
368
+ writer.write({
369
+ type: "data",
370
+ name: "checkpoint-saved",
371
+ data: {
372
+ threadId: event.threadId,
373
+ step: event.step
374
+ }
375
+ });
376
+ return currentTextId;
377
+ case "checkpoint-loaded":
378
+ writer.write({
379
+ type: "data",
380
+ name: "checkpoint-loaded",
381
+ data: {
382
+ threadId: event.threadId,
383
+ step: event.step,
384
+ messagesCount: event.messagesCount
385
+ }
386
+ });
387
+ return currentTextId;
388
+ case "error":
389
+ if (currentTextId) {
390
+ writer.write({
391
+ type: "text-end",
392
+ id: currentTextId
393
+ });
394
+ currentTextId = null;
395
+ }
396
+ writer.write({
397
+ type: "error",
398
+ errorText: event.error.message
399
+ });
400
+ return null;
401
+ case "done":
402
+ if (currentTextId) {
403
+ writer.write({
404
+ type: "text-end",
405
+ id: currentTextId
406
+ });
407
+ currentTextId = null;
408
+ }
409
+ writer.write({
410
+ type: "finish",
411
+ finishReason: "stop"
412
+ });
413
+ return null;
414
+ default: return currentTextId;
415
+ }
416
+ }
178
417
 
179
418
  //#endregion
180
419
  //#region src/adapters/elements/messageConverters.ts
@@ -271,4 +510,5 @@ exports.createElementsRouteHandler = createElementsRouteHandler;
271
510
  exports.extractLastUserMessage = extractLastUserMessage;
272
511
  exports.extractTextFromMessage = extractTextFromMessage;
273
512
  exports.hasToolParts = hasToolParts;
513
+ exports.mapEventToProtocol = mapEventToProtocol;
274
514
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/adapters/elements/createElementsRouteHandler.ts","../../../src/adapters/elements/messageConverters.ts"],"sourcesContent":["/**\n * Server-side route handler adapter for AI SDK Elements\n *\n * Creates a Next.js/Express-compatible route handler that runs DeepAgent\n * and returns UI Message Stream compatible responses for use with useChat.\n *\n * @example\n * ```typescript\n * // app/api/chat/route.ts (Next.js App Router)\n * import { createDeepAgent } from 'deepagentsdk';\n * import { createElementsRouteHandler } from 'deepagentsdk/adapters/elements';\n * import { anthropic } from '@ai-sdk/anthropic';\n *\n * const agent = createDeepAgent({\n * model: anthropic('claude-sonnet-4-20250514'),\n * });\n *\n * export const POST = createElementsRouteHandler({ agent });\n * ```\n *\n * @see https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol\n */\n\nimport {\n createUIMessageStream,\n createUIMessageStreamResponse,\n convertToModelMessages,\n type UIMessage,\n} from \"ai\";\nimport type { DeepAgent } from \"../../agent\";\nimport type { DeepAgentState, ModelMessage } from \"../../types\";\n\n/**\n * Options for creating an Elements route handler\n */\nexport interface CreateElementsRouteHandlerOptions {\n /**\n * The DeepAgent instance to use for handling requests\n */\n agent: DeepAgent;\n\n /**\n * Optional callback before processing a request.\n * Use for authentication, logging, rate limiting, etc.\n *\n * @example\n * ```typescript\n * onRequest: async (req) => {\n * const token = req.headers.get('Authorization');\n * if (!validateToken(token)) {\n * throw new Error('Unauthorized');\n * }\n * }\n * ```\n */\n onRequest?: (req: Request) => Promise<void> | void;\n\n /**\n * Optional initial state to provide to the agent.\n * If not provided, uses empty state { todos: [], files: {} }\n */\n initialState?: DeepAgentState;\n\n /**\n * Optional thread ID for checkpointing.\n * If provided, enables conversation persistence.\n */\n threadId?: string;\n\n /**\n * Optional maximum number of steps for the agent loop.\n */\n maxSteps?: number;\n\n /**\n * Custom ID generator for message IDs.\n * Defaults to crypto.randomUUID if available.\n */\n generateId?: () => string;\n}\n\n/**\n * Creates a route handler that processes chat requests using DeepAgent\n * and returns UI Message Stream compatible responses.\n *\n * The returned handler:\n * - Accepts POST requests with { messages: UIMessage[] } body\n * - Runs DeepAgent with the conversation history\n * - Streams responses in UI Message Stream Protocol format\n * - Works with useChat hook from @ai-sdk/react\n *\n * @param options - Configuration options\n * @returns A request handler function compatible with Next.js/Express\n */\nexport function createElementsRouteHandler(\n options: CreateElementsRouteHandlerOptions\n): (req: Request) => Promise<Response> {\n const {\n agent,\n onRequest,\n initialState = { todos: [], files: {} },\n threadId,\n maxSteps,\n generateId,\n } = options;\n\n return async (req: Request): Promise<Response> => {\n // Run optional request hook (auth, logging, etc.)\n if (onRequest) {\n try {\n await onRequest(req);\n } catch (error) {\n return new Response(\n JSON.stringify({\n error: error instanceof Error ? error.message : \"Request rejected\",\n }),\n { status: 401, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n }\n\n // Parse request body\n let requestBody: { messages: UIMessage[] };\n try {\n requestBody = await req.json();\n } catch {\n return new Response(\n JSON.stringify({ error: \"Invalid JSON body\" }),\n { status: 400, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n\n const { messages } = requestBody;\n\n if (!messages || !Array.isArray(messages)) {\n return new Response(\n JSON.stringify({ error: \"messages array is required\" }),\n { status: 400, headers: { \"Content-Type\": \"application/json\" } }\n );\n }\n\n // Convert UI messages to model messages using AI SDK's converter\n const modelMessages = await convertToModelMessages(messages) as ModelMessage[];\n\n // Track current text part ID for proper text streaming\n let currentTextId: string | null = null;\n const genId = generateId || (() => crypto.randomUUID());\n\n // Create the UI message stream\n const stream = createUIMessageStream({\n originalMessages: messages,\n generateId: genId,\n execute: async ({ writer }) => {\n try {\n for await (const event of agent.streamWithEvents({\n messages: modelMessages,\n state: initialState,\n threadId,\n maxSteps,\n })) {\n switch (event.type) {\n case \"step-start\":\n // Emit step start for UI progress tracking\n writer.write({ type: \"start-step\" });\n break;\n\n case \"step-finish\":\n // Emit step finish\n writer.write({ type: \"finish-step\" });\n break;\n\n case \"text\":\n // Handle text streaming\n if (!currentTextId) {\n // Start a new text part\n currentTextId = genId();\n writer.write({\n type: \"text-start\",\n id: currentTextId,\n });\n }\n // Stream text delta\n writer.write({\n type: \"text-delta\",\n id: currentTextId,\n delta: event.text,\n });\n break;\n\n case \"tool-call\":\n // End any in-progress text before tool call\n if (currentTextId) {\n writer.write({ type: \"text-end\", id: currentTextId });\n currentTextId = null;\n }\n // Emit tool input available\n writer.write({\n type: \"tool-input-available\",\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n input: event.args,\n });\n break;\n\n case \"tool-result\":\n // Emit tool output\n if (event.isError) {\n writer.write({\n type: \"tool-output-error\",\n toolCallId: event.toolCallId,\n errorText: String(event.result),\n });\n } else {\n writer.write({\n type: \"tool-output-available\",\n toolCallId: event.toolCallId,\n output: event.result,\n });\n }\n break;\n\n case \"todos-changed\":\n // Emit as custom data part for UI to handle\n // Note: This requires UI to handle custom data types\n writer.write({\n type: \"data\" as any,\n name: \"todos-changed\",\n data: { todos: event.todos },\n } as any);\n break;\n\n case \"error\":\n // End any in-progress text\n if (currentTextId) {\n writer.write({ type: \"text-end\", id: currentTextId });\n currentTextId = null;\n }\n // Emit error\n writer.write({\n type: \"error\",\n errorText: event.error.message,\n });\n break;\n\n case \"done\":\n // End any in-progress text\n if (currentTextId) {\n writer.write({ type: \"text-end\", id: currentTextId });\n currentTextId = null;\n }\n // Done event is handled automatically by the stream\n break;\n\n // Other events (file operations, subagents, etc.) can be\n // emitted as custom data parts if needed by the UI\n default:\n // Optionally emit other events as data parts\n // writer.write({\n // type: \"data\" as any,\n // name: event.type,\n // data: event,\n // } as any);\n break;\n }\n }\n\n // Ensure text is ended if stream completes\n if (currentTextId) {\n writer.write({ type: \"text-end\", id: currentTextId });\n }\n } catch (error) {\n // End any in-progress text on error\n if (currentTextId) {\n writer.write({ type: \"text-end\", id: currentTextId });\n }\n // Re-throw to let the stream handle the error\n throw error;\n }\n },\n onError: (error) => {\n // Return error message for the stream\n return error instanceof Error ? error.message : \"Unknown error\";\n },\n });\n\n // Return the stream response\n return createUIMessageStreamResponse({ stream });\n };\n}\n\n/**\n * Type for the request handler returned by createElementsRouteHandler\n */\nexport type ElementsRouteHandler = (req: Request) => Promise<Response>;\n","/**\n * Message conversion utilities for AI SDK Elements adapter\n *\n * Provides utilities for converting between UI message formats and model message formats.\n * The primary conversion is handled by AI SDK's `convertToModelMessages`, but these\n * utilities provide additional helpers for DeepAgent-specific needs.\n */\n\nimport {\n convertToModelMessages,\n type UIMessage,\n} from \"ai\";\nimport type { ModelMessage } from \"../../types\";\n\n/**\n * Re-export AI SDK's convertToModelMessages for convenience.\n *\n * This function converts UIMessage[] (from useChat) to ModelMessage[]\n * (for agent consumption), handling:\n * - Role mapping (user/assistant)\n * - Tool call/result parts\n * - Text content extraction\n *\n * @example\n * ```typescript\n * import { convertUIMessagesToModelMessages } from 'deepagentsdk/adapters/elements';\n *\n * const modelMessages = await convertUIMessagesToModelMessages(uiMessages);\n * ```\n */\nexport async function convertUIMessagesToModelMessages(\n messages: UIMessage[]\n): Promise<ModelMessage[]> {\n return await convertToModelMessages(messages) as ModelMessage[];\n}\n\n/**\n * Extract the last user message text from a UIMessage array.\n * Useful for extracting the prompt from a conversation.\n *\n * @param messages - Array of UI messages\n * @returns The text content of the last user message, or undefined if none\n */\nexport function extractLastUserMessage(messages: UIMessage[]): string | undefined {\n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg && msg.role === \"user\" && msg.parts) {\n // Extract text parts\n const textParts = msg.parts.filter(\n (p): p is { type: \"text\"; text: string } => p.type === \"text\"\n );\n if (textParts.length > 0) {\n return textParts.map(p => p.text).join(\"\");\n }\n }\n }\n return undefined;\n}\n\n/**\n * Check if the messages contain any tool parts.\n * This is a simplified helper that checks for any tool-related parts.\n *\n * @param messages - Array of UI messages\n * @returns True if there are any tool-related parts in the messages\n */\nexport function hasToolParts(messages: UIMessage[]): boolean {\n for (const msg of messages) {\n if (!msg.parts) continue;\n for (const part of msg.parts) {\n // Tool parts have type starting with \"tool-\" or \"dynamic-tool\"\n if (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Count the number of messages by role.\n *\n * @param messages - Array of UI messages\n * @returns Object with counts by role\n */\nexport function countMessagesByRole(\n messages: UIMessage[]\n): { user: number; assistant: number; system: number } {\n let user = 0;\n let assistant = 0;\n let system = 0;\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n user++;\n } else if (msg.role === \"assistant\") {\n assistant++;\n } else if (msg.role === \"system\") {\n system++;\n }\n }\n\n return { user, assistant, system };\n}\n\n/**\n * Extract all text content from a message.\n *\n * @param message - A UI message\n * @returns Combined text from all text parts\n */\nexport function extractTextFromMessage(message: UIMessage): string {\n if (!message.parts) return \"\";\n\n return message.parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map(p => p.text)\n .join(\"\");\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../../src/adapters/elements/createElementsRouteHandler.ts","../../../src/adapters/elements/messageConverters.ts"],"sourcesContent":["/**\n * Server-side route handler adapter for AI SDK Elements\n *\n * Creates a Next.js/Express-compatible route handler that runs DeepAgent\n * and returns UI Message Stream compatible responses with full event visibility.\n *\n * This handler streams all DeepAgent event types (26+) including:\n * - Text and tool events (standard protocol)\n * - File system operations\n * - Command execution\n * - Web requests and searches\n * - Subagent lifecycle\n * - State changes (todos, checkpoints)\n *\n * @example\n * ```typescript\n * // app/api/chat/route.ts (Next.js App Router)\n * import { createDeepAgent } from 'deepagentsdk';\n * import { createElementsRouteHandler } from 'deepagentsdk/adapters/elements';\n * import { anthropic } from '@ai-sdk/anthropic';\n *\n * const agent = createDeepAgent({\n * model: anthropic('claude-sonnet-4-20250514'),\n * });\n *\n * export const POST = createElementsRouteHandler({ agent });\n * ```\n *\n * @see https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol\n */\n\nimport {\n createUIMessageStream,\n createUIMessageStreamResponse,\n convertToModelMessages,\n} from \"ai\";\nimport type { DeepAgent } from \"../../agent\";\nimport type { DeepAgentState, DeepAgentEvent } from \"../../types\";\n\n/**\n * Options for creating an Elements route handler\n */\nexport interface CreateElementsRouteHandlerOptions {\n /**\n * The DeepAgent instance to use for handling requests\n */\n agent: DeepAgent;\n\n /**\n * Optional callback before processing a request.\n * Use for authentication, logging, rate limiting, etc.\n *\n * @example\n * ```typescript\n * onRequest: async (req) => {\n * const token = req.headers.get('Authorization');\n * if (!validateToken(token)) {\n * throw new Error('Unauthorized');\n * }\n * }\n * ```\n */\n onRequest?: (req: Request) => Promise<void> | void;\n\n /**\n * Optional initial state to provide to the agent.\n * If not provided, uses empty state { todos: [], files: {} }\n */\n initialState?: DeepAgentState;\n\n /**\n * Optional thread ID for checkpointing.\n * If provided, enables conversation persistence.\n */\n threadId?: string;\n\n /**\n * Optional maximum number of steps for the agent loop.\n */\n maxSteps?: number;\n\n /**\n * Custom ID generator for message IDs.\n * Defaults to crypto.randomUUID if available.\n */\n generateId?: () => string;\n}\n\n/**\n * Creates a route handler that processes chat requests using DeepAgent\n * and streams all 26+ event types in UI Message Stream Protocol format.\n *\n * The returned handler:\n * - Accepts POST requests with { messages: UIMessage[] } body\n * - Runs DeepAgent with the conversation history\n * - Streams responses in UI Message Stream Protocol format\n * - Works with useChat hook from @ai-sdk/react\n * - Provides full visibility into agent behavior (file ops, web requests, subagents, etc.)\n *\n * @param options - Configuration options\n * @returns A request handler function compatible with Next.js/Express\n */\nexport function createElementsRouteHandler(\n options: CreateElementsRouteHandlerOptions\n): (req: Request) => Promise<Response> {\n const {\n agent,\n onRequest,\n initialState = {\n todos: [],\n files: {}\n },\n threadId,\n maxSteps,\n generateId\n } = options;\n\n return async (req: Request): Promise<Response> => {\n // 1. Handle onRequest hook (auth, logging, rate limiting)\n if (onRequest) {\n try {\n await onRequest(req);\n } catch (error) {\n return new Response(\n JSON.stringify({\n error: error instanceof Error ? error.message : 'Request rejected'\n }),\n {\n status: 401,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n }\n }\n\n // 2. Parse request body\n let requestBody;\n try {\n requestBody = await req.json();\n } catch {\n return new Response(\n JSON.stringify({ error: 'Invalid JSON body' }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n }\n\n const { messages } = requestBody;\n if (!messages || !Array.isArray(messages)) {\n return new Response(\n JSON.stringify({ error: 'messages array is required' }),\n {\n status: 400,\n headers: { 'Content-Type': 'application/json' }\n }\n );\n }\n\n // 3. Convert UI messages to model messages\n const modelMessages = await convertToModelMessages(messages);\n\n // 4. Setup ID generator\n const genId = generateId || (() => crypto.randomUUID());\n\n // 5. Track current text ID for text-start/text-end\n let currentTextId: string | null = null;\n\n // 6. Create UI message stream response\n return createUIMessageStreamResponse({\n stream: createUIMessageStream({\n originalMessages: messages,\n generateId: genId,\n execute: async ({ writer }) => {\n try {\n // Stream all events from DeepAgent\n for await (const event of agent.streamWithEvents({\n messages: modelMessages,\n state: initialState,\n threadId,\n maxSteps\n })) {\n // Update currentTextId from the returned value\n const result = mapEventToProtocol(event, writer, genId, currentTextId);\n if (typeof result === 'string') {\n currentTextId = result;\n } else if (result === null) {\n currentTextId = null;\n }\n }\n\n // Ensure text is properly closed\n if (currentTextId) {\n writer.write({\n type: 'text-end',\n id: currentTextId\n });\n }\n } catch (error) {\n // Close text if error occurs mid-stream\n if (currentTextId) {\n writer.write({\n type: 'text-end',\n id: currentTextId\n });\n }\n throw error;\n }\n },\n onError: (error) => {\n return error instanceof Error ? error.message : 'Unknown error';\n }\n })\n });\n };\n}\n\n/**\n * Maps a DeepAgent event to a UI Message Stream Protocol event.\n *\n * This function handles all 26+ DeepAgent event types, mapping:\n * - Standard protocol events (text, tools, steps, errors)\n * - Custom data events (file operations, web requests, subagents, execution)\n *\n * @param event - The DeepAgent event to map\n * @param writer - The UI message stream writer\n * @param genId - ID generator function\n * @param currentTextId - The current text part ID (for tracking streaming text)\n * @returns The new currentTextId value (string | null)\n *\n * @example\n * ```typescript\n * // Handles text streaming with proper ID tracking\n * let textId: string | null = null;\n * textId = mapEventToProtocol({ type: 'text', text: 'Hello' }, writer, genId, textId);\n * // textId is now the ID of the active text part\n * ```\n */\nexport function mapEventToProtocol(\n event: DeepAgentEvent,\n writer: { write: (chunk: any) => void },\n genId: () => string,\n currentTextId: string | null\n): string | null {\n switch (event.type) {\n // ============================================================================\n // TEXT & FLOW EVENTS (Required for compatibility)\n // ============================================================================\n\n case 'step-start':\n writer.write({ type: 'start-step' });\n return currentTextId;\n\n case 'step-finish':\n writer.write({ type: 'finish-step' });\n return currentTextId;\n\n case 'text':\n // Start text if not already started\n if (!currentTextId) {\n const textId = genId();\n writer.write({\n type: 'text-start',\n id: textId\n });\n return textId;\n }\n writer.write({\n type: 'text-delta',\n id: currentTextId,\n delta: event.text\n });\n return currentTextId;\n\n // ============================================================================\n // TOOL EVENTS (Standard protocol events)\n // ============================================================================\n\n case 'tool-call':\n // End text before tool call\n if (currentTextId) {\n writer.write({\n type: 'text-end',\n id: currentTextId\n });\n currentTextId = null;\n }\n writer.write({\n type: 'tool-input-available',\n toolCallId: event.toolCallId,\n toolName: event.toolName,\n input: event.args\n });\n return null;\n\n case 'tool-result':\n if (event.isError) {\n writer.write({\n type: 'tool-output-error',\n toolCallId: event.toolCallId,\n errorText: String(event.result)\n });\n } else {\n writer.write({\n type: 'tool-output-available',\n toolCallId: event.toolCallId,\n output: event.result\n });\n }\n return currentTextId;\n\n // ============================================================================\n // TODO & PLANNING EVENTS\n // ============================================================================\n\n case 'todos-changed':\n writer.write({\n type: 'data',\n name: 'todos-changed',\n data: { todos: event.todos }\n });\n return currentTextId;\n\n // ============================================================================\n // FILE SYSTEM EVENTS (Custom data events)\n // ============================================================================\n\n case 'file-write-start':\n writer.write({\n type: 'data',\n name: 'file-write-start',\n data: {\n path: event.path,\n content: event.content\n }\n });\n return currentTextId;\n\n case 'file-written':\n writer.write({\n type: 'data',\n name: 'file-written',\n data: {\n path: event.path,\n content: event.content\n }\n });\n return currentTextId;\n\n case 'file-edited':\n writer.write({\n type: 'data',\n name: 'file-edited',\n data: {\n path: event.path,\n occurrences: event.occurrences\n }\n });\n return currentTextId;\n\n case 'file-read':\n writer.write({\n type: 'data',\n name: 'file-read',\n data: {\n path: event.path,\n lines: event.lines\n }\n });\n return currentTextId;\n\n case 'ls':\n writer.write({\n type: 'data',\n name: 'ls',\n data: {\n path: event.path,\n count: event.count\n }\n });\n return currentTextId;\n\n case 'glob':\n writer.write({\n type: 'data',\n name: 'glob',\n data: {\n pattern: event.pattern,\n count: event.count\n }\n });\n return currentTextId;\n\n case 'grep':\n writer.write({\n type: 'data',\n name: 'grep',\n data: {\n pattern: event.pattern,\n count: event.count\n }\n });\n return currentTextId;\n\n // ============================================================================\n // EXECUTION EVENTS (Custom data events)\n // ============================================================================\n\n case 'execute-start':\n writer.write({\n type: 'data',\n name: 'execute-start',\n data: {\n command: event.command,\n sandboxId: event.sandboxId\n }\n });\n return currentTextId;\n\n case 'execute-finish':\n writer.write({\n type: 'data',\n name: 'execute-finish',\n data: {\n command: event.command,\n exitCode: event.exitCode,\n truncated: event.truncated,\n sandboxId: event.sandboxId\n }\n });\n return currentTextId;\n\n // ============================================================================\n // WEB EVENTS (Custom data events)\n // ============================================================================\n\n case 'web-search-start':\n writer.write({\n type: 'data',\n name: 'web-search-start',\n data: {\n query: event.query\n }\n });\n return currentTextId;\n\n case 'web-search-finish':\n writer.write({\n type: 'data',\n name: 'web-search-finish',\n data: {\n query: event.query,\n resultCount: event.resultCount\n }\n });\n return currentTextId;\n\n case 'http-request-start':\n writer.write({\n type: 'data',\n name: 'http-request-start',\n data: {\n url: event.url,\n method: event.method\n }\n });\n return currentTextId;\n\n case 'http-request-finish':\n writer.write({\n type: 'data',\n name: 'http-request-finish',\n data: {\n url: event.url,\n statusCode: event.statusCode\n }\n });\n return currentTextId;\n\n case 'fetch-url-start':\n writer.write({\n type: 'data',\n name: 'fetch-url-start',\n data: {\n url: event.url\n }\n });\n return currentTextId;\n\n case 'fetch-url-finish':\n writer.write({\n type: 'data',\n name: 'fetch-url-finish',\n data: {\n url: event.url,\n success: event.success\n }\n });\n return currentTextId;\n\n // ============================================================================\n // SUBAGENT EVENTS (Custom data events)\n // ============================================================================\n\n case 'subagent-start':\n writer.write({\n type: 'data',\n name: 'subagent-start',\n data: {\n name: event.name,\n task: event.task\n }\n });\n return currentTextId;\n\n case 'subagent-finish':\n writer.write({\n type: 'data',\n name: 'subagent-finish',\n data: {\n name: event.name,\n result: event.result\n }\n });\n return currentTextId;\n\n case 'subagent-step':\n writer.write({\n type: 'data',\n name: 'subagent-step',\n data: {\n stepIndex: event.stepIndex,\n toolCalls: event.toolCalls\n }\n });\n return currentTextId;\n\n // ============================================================================\n // CHECKPOINT EVENTS (Custom data events)\n // ============================================================================\n\n case 'checkpoint-saved':\n writer.write({\n type: 'data',\n name: 'checkpoint-saved',\n data: {\n threadId: event.threadId,\n step: event.step\n }\n });\n return currentTextId;\n\n case 'checkpoint-loaded':\n writer.write({\n type: 'data',\n name: 'checkpoint-loaded',\n data: {\n threadId: event.threadId,\n step: event.step,\n messagesCount: event.messagesCount\n }\n });\n return currentTextId;\n\n // ============================================================================\n // CONTROL EVENTS\n // ============================================================================\n\n case 'error':\n // End text before error\n if (currentTextId) {\n writer.write({\n type: 'text-end',\n id: currentTextId\n });\n currentTextId = null;\n }\n writer.write({\n type: 'error',\n errorText: event.error.message\n });\n return null;\n\n case 'done':\n // End text before completion\n if (currentTextId) {\n writer.write({\n type: 'text-end',\n id: currentTextId\n });\n currentTextId = null;\n }\n // The finish event is auto-emitted by createUIMessageStream\n // We explicitly emit it here for clarity\n writer.write({\n type: 'finish',\n finishReason: 'stop',\n });\n return null;\n\n // Ignore unhandled events (text-segment, user-message, approval events)\n default:\n return currentTextId;\n }\n}\n\n/**\n * Type for the request handler returned by createElementsRouteHandler\n */\nexport type ElementsRouteHandler = (req: Request) => Promise<Response>;\n","/**\n * Message conversion utilities for AI SDK Elements adapter\n *\n * Provides utilities for converting between UI message formats and model message formats.\n * The primary conversion is handled by AI SDK's `convertToModelMessages`, but these\n * utilities provide additional helpers for DeepAgent-specific needs.\n */\n\nimport {\n convertToModelMessages,\n type UIMessage,\n} from \"ai\";\nimport type { ModelMessage } from \"../../types\";\n\n/**\n * Re-export AI SDK's convertToModelMessages for convenience.\n *\n * This function converts UIMessage[] (from useChat) to ModelMessage[]\n * (for agent consumption), handling:\n * - Role mapping (user/assistant)\n * - Tool call/result parts\n * - Text content extraction\n *\n * @example\n * ```typescript\n * import { convertUIMessagesToModelMessages } from 'deepagentsdk/adapters/elements';\n *\n * const modelMessages = await convertUIMessagesToModelMessages(uiMessages);\n * ```\n */\nexport async function convertUIMessagesToModelMessages(\n messages: UIMessage[]\n): Promise<ModelMessage[]> {\n return await convertToModelMessages(messages) as ModelMessage[];\n}\n\n/**\n * Extract the last user message text from a UIMessage array.\n * Useful for extracting the prompt from a conversation.\n *\n * @param messages - Array of UI messages\n * @returns The text content of the last user message, or undefined if none\n */\nexport function extractLastUserMessage(messages: UIMessage[]): string | undefined {\n // Find the last user message\n for (let i = messages.length - 1; i >= 0; i--) {\n const msg = messages[i];\n if (msg && msg.role === \"user\" && msg.parts) {\n // Extract text parts\n const textParts = msg.parts.filter(\n (p): p is { type: \"text\"; text: string } => p.type === \"text\"\n );\n if (textParts.length > 0) {\n return textParts.map(p => p.text).join(\"\");\n }\n }\n }\n return undefined;\n}\n\n/**\n * Check if the messages contain any tool parts.\n * This is a simplified helper that checks for any tool-related parts.\n *\n * @param messages - Array of UI messages\n * @returns True if there are any tool-related parts in the messages\n */\nexport function hasToolParts(messages: UIMessage[]): boolean {\n for (const msg of messages) {\n if (!msg.parts) continue;\n for (const part of msg.parts) {\n // Tool parts have type starting with \"tool-\" or \"dynamic-tool\"\n if (part.type.startsWith(\"tool-\") || part.type === \"dynamic-tool\") {\n return true;\n }\n }\n }\n return false;\n}\n\n/**\n * Count the number of messages by role.\n *\n * @param messages - Array of UI messages\n * @returns Object with counts by role\n */\nexport function countMessagesByRole(\n messages: UIMessage[]\n): { user: number; assistant: number; system: number } {\n let user = 0;\n let assistant = 0;\n let system = 0;\n\n for (const msg of messages) {\n if (msg.role === \"user\") {\n user++;\n } else if (msg.role === \"assistant\") {\n assistant++;\n } else if (msg.role === \"system\") {\n system++;\n }\n }\n\n return { user, assistant, system };\n}\n\n/**\n * Extract all text content from a message.\n *\n * @param message - A UI message\n * @returns Combined text from all text parts\n */\nexport function extractTextFromMessage(message: UIMessage): string {\n if (!message.parts) return \"\";\n\n return message.parts\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map(p => p.text)\n .join(\"\");\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { r as ModelMessage$1, t as DeepAgent, yt as DeepAgentState } from "../../agent-DToEVxs-.cjs";
1
+ import { p as DeepAgentEvent, r as ModelMessage$1, t as DeepAgent, yt as DeepAgentState } from "../../agent-DwAj5emJ.cjs";
2
2
  import { UIMessage, UIMessage as UIMessage$1, UIMessagePart } from "ai";
3
3
 
4
4
  //#region src/adapters/elements/createElementsRouteHandler.d.ts
@@ -48,18 +48,43 @@ interface CreateElementsRouteHandlerOptions {
48
48
  }
49
49
  /**
50
50
  * Creates a route handler that processes chat requests using DeepAgent
51
- * and returns UI Message Stream compatible responses.
51
+ * and streams all 26+ event types in UI Message Stream Protocol format.
52
52
  *
53
53
  * The returned handler:
54
54
  * - Accepts POST requests with { messages: UIMessage[] } body
55
55
  * - Runs DeepAgent with the conversation history
56
56
  * - Streams responses in UI Message Stream Protocol format
57
57
  * - Works with useChat hook from @ai-sdk/react
58
+ * - Provides full visibility into agent behavior (file ops, web requests, subagents, etc.)
58
59
  *
59
60
  * @param options - Configuration options
60
61
  * @returns A request handler function compatible with Next.js/Express
61
62
  */
62
63
  declare function createElementsRouteHandler(options: CreateElementsRouteHandlerOptions): (req: Request) => Promise<Response>;
64
+ /**
65
+ * Maps a DeepAgent event to a UI Message Stream Protocol event.
66
+ *
67
+ * This function handles all 26+ DeepAgent event types, mapping:
68
+ * - Standard protocol events (text, tools, steps, errors)
69
+ * - Custom data events (file operations, web requests, subagents, execution)
70
+ *
71
+ * @param event - The DeepAgent event to map
72
+ * @param writer - The UI message stream writer
73
+ * @param genId - ID generator function
74
+ * @param currentTextId - The current text part ID (for tracking streaming text)
75
+ * @returns The new currentTextId value (string | null)
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Handles text streaming with proper ID tracking
80
+ * let textId: string | null = null;
81
+ * textId = mapEventToProtocol({ type: 'text', text: 'Hello' }, writer, genId, textId);
82
+ * // textId is now the ID of the active text part
83
+ * ```
84
+ */
85
+ declare function mapEventToProtocol(event: DeepAgentEvent, writer: {
86
+ write: (chunk: any) => void;
87
+ }, genId: () => string, currentTextId: string | null): string | null;
63
88
  /**
64
89
  * Type for the request handler returned by createElementsRouteHandler
65
90
  */
@@ -118,5 +143,5 @@ declare function countMessagesByRole(messages: UIMessage$1[]): {
118
143
  */
119
144
  declare function extractTextFromMessage(message: UIMessage$1): string;
120
145
  //#endregion
121
- export { type CreateElementsRouteHandlerOptions, type ElementsRouteHandler, type UIMessage, type UIMessagePart, convertUIMessagesToModelMessages, countMessagesByRole, createElementsRouteHandler, extractLastUserMessage, extractTextFromMessage, hasToolParts };
146
+ export { type CreateElementsRouteHandlerOptions, type ElementsRouteHandler, type UIMessage, type UIMessagePart, convertUIMessagesToModelMessages, countMessagesByRole, createElementsRouteHandler, extractLastUserMessage, extractTextFromMessage, hasToolParts, mapEventToProtocol };
122
147
  //# sourceMappingURL=index.d.cts.map
@@ -1,4 +1,4 @@
1
- import { r as ModelMessage$1, t as DeepAgent, yt as DeepAgentState } from "../../agent-BDM-PIu8.mjs";
1
+ import { p as DeepAgentEvent, r as ModelMessage$1, t as DeepAgent, yt as DeepAgentState } from "../../agent-D0bKkNI-.mjs";
2
2
  import { UIMessage, UIMessage as UIMessage$1, UIMessagePart } from "ai";
3
3
 
4
4
  //#region src/adapters/elements/createElementsRouteHandler.d.ts
@@ -48,18 +48,43 @@ interface CreateElementsRouteHandlerOptions {
48
48
  }
49
49
  /**
50
50
  * Creates a route handler that processes chat requests using DeepAgent
51
- * and returns UI Message Stream compatible responses.
51
+ * and streams all 26+ event types in UI Message Stream Protocol format.
52
52
  *
53
53
  * The returned handler:
54
54
  * - Accepts POST requests with { messages: UIMessage[] } body
55
55
  * - Runs DeepAgent with the conversation history
56
56
  * - Streams responses in UI Message Stream Protocol format
57
57
  * - Works with useChat hook from @ai-sdk/react
58
+ * - Provides full visibility into agent behavior (file ops, web requests, subagents, etc.)
58
59
  *
59
60
  * @param options - Configuration options
60
61
  * @returns A request handler function compatible with Next.js/Express
61
62
  */
62
63
  declare function createElementsRouteHandler(options: CreateElementsRouteHandlerOptions): (req: Request) => Promise<Response>;
64
+ /**
65
+ * Maps a DeepAgent event to a UI Message Stream Protocol event.
66
+ *
67
+ * This function handles all 26+ DeepAgent event types, mapping:
68
+ * - Standard protocol events (text, tools, steps, errors)
69
+ * - Custom data events (file operations, web requests, subagents, execution)
70
+ *
71
+ * @param event - The DeepAgent event to map
72
+ * @param writer - The UI message stream writer
73
+ * @param genId - ID generator function
74
+ * @param currentTextId - The current text part ID (for tracking streaming text)
75
+ * @returns The new currentTextId value (string | null)
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // Handles text streaming with proper ID tracking
80
+ * let textId: string | null = null;
81
+ * textId = mapEventToProtocol({ type: 'text', text: 'Hello' }, writer, genId, textId);
82
+ * // textId is now the ID of the active text part
83
+ * ```
84
+ */
85
+ declare function mapEventToProtocol(event: DeepAgentEvent, writer: {
86
+ write: (chunk: any) => void;
87
+ }, genId: () => string, currentTextId: string | null): string | null;
63
88
  /**
64
89
  * Type for the request handler returned by createElementsRouteHandler
65
90
  */
@@ -118,5 +143,5 @@ declare function countMessagesByRole(messages: UIMessage$1[]): {
118
143
  */
119
144
  declare function extractTextFromMessage(message: UIMessage$1): string;
120
145
  //#endregion
121
- export { type CreateElementsRouteHandlerOptions, type ElementsRouteHandler, type UIMessage, type UIMessagePart, convertUIMessagesToModelMessages, countMessagesByRole, createElementsRouteHandler, extractLastUserMessage, extractTextFromMessage, hasToolParts };
146
+ export { type CreateElementsRouteHandlerOptions, type ElementsRouteHandler, type UIMessage, type UIMessagePart, convertUIMessagesToModelMessages, countMessagesByRole, createElementsRouteHandler, extractLastUserMessage, extractTextFromMessage, hasToolParts, mapEventToProtocol };
122
147
  //# sourceMappingURL=index.d.mts.map