deepagentsdk 0.12.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.
- package/dist/adapters/elements/index.cjs +478 -288
- package/dist/adapters/elements/index.cjs.map +1 -1
- package/dist/adapters/elements/index.d.cts +107 -172
- package/dist/adapters/elements/index.d.mts +107 -172
- package/dist/adapters/elements/index.mjs +471 -284
- package/dist/adapters/elements/index.mjs.map +1 -1
- package/dist/{types-4g9UvXal.d.mts → agent-D0bKkNI-.d.mts} +352 -3
- package/dist/{types-IulnvhFg.d.cts → agent-DwAj5emJ.d.cts} +352 -3
- package/dist/{chunk-CbDLau6x.cjs → chunk-C5azi7Hr.cjs} +33 -0
- package/dist/cli/index.cjs +12 -12
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +2 -2
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{agent-Cuks-Idh.cjs → file-saver-BYPKakT4.cjs} +799 -205
- package/dist/file-saver-BYPKakT4.cjs.map +1 -0
- package/dist/{agent-CrH-He58.mjs → file-saver-Hj5so3dV.mjs} +793 -199
- package/dist/file-saver-Hj5so3dV.mjs.map +1 -0
- package/dist/index.cjs +83 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -353
- package/dist/index.d.mts +5 -353
- package/dist/index.mjs +13 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{load-B6CA5js_.mjs → load-BBYEnMwz.mjs} +1 -1
- package/dist/{load-B6CA5js_.mjs.map → load-BBYEnMwz.mjs.map} +1 -1
- package/dist/{load-94gjHorc.mjs → load-BDxe6Cet.mjs} +1 -1
- package/dist/{load-79a2H4m0.cjs → load-BrRAKlO6.cjs} +2 -2
- package/dist/{load-79a2H4m0.cjs.map → load-BrRAKlO6.cjs.map} +1 -1
- package/dist/load-DqllBbDc.cjs +4 -0
- package/package.json +1 -1
- package/dist/agent-CrH-He58.mjs.map +0 -1
- package/dist/agent-Cuks-Idh.cjs.map +0 -1
- package/dist/file-saver-BJCqMIb5.mjs +0 -655
- package/dist/file-saver-BJCqMIb5.mjs.map +0 -1
- package/dist/file-saver-C6O2LAvg.cjs +0 -679
- package/dist/file-saver-C6O2LAvg.cjs.map +0 -1
- package/dist/load-C2qVmZMp.cjs +0 -3
|
@@ -1,324 +1,514 @@
|
|
|
1
|
-
const require_chunk = require('../../chunk-
|
|
2
|
-
|
|
3
|
-
let react = require("react");
|
|
1
|
+
const require_chunk = require('../../chunk-C5azi7Hr.cjs');
|
|
2
|
+
let ai = require("ai");
|
|
4
3
|
|
|
5
|
-
//#region src/adapters/elements/
|
|
4
|
+
//#region src/adapters/elements/createElementsRouteHandler.ts
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
6
|
+
* Server-side route handler adapter for AI SDK Elements
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* @param uiStatus - Current UI status
|
|
12
|
-
* @returns Array of UIMessage objects for Elements Message component
|
|
8
|
+
* Creates a Next.js/Express-compatible route handler that runs DeepAgent
|
|
9
|
+
* and returns UI Message Stream compatible responses with full event visibility.
|
|
13
10
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
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)
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // app/api/chat/route.ts (Next.js App Router)
|
|
22
|
+
* import { createDeepAgent } from 'deepagentsdk';
|
|
23
|
+
* import { createElementsRouteHandler } from 'deepagentsdk/adapters/elements';
|
|
24
|
+
* import { anthropic } from '@ai-sdk/anthropic';
|
|
25
|
+
*
|
|
26
|
+
* const agent = createDeepAgent({
|
|
27
|
+
* model: anthropic('claude-sonnet-4-20250514'),
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* export const POST = createElementsRouteHandler({ agent });
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @see https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol
|
|
19
34
|
*/
|
|
20
|
-
function convertEventsToUIMessages(events, streamingText, uiStatus) {
|
|
21
|
-
const messages = [];
|
|
22
|
-
let currentAssistantParts = [];
|
|
23
|
-
let messageIdCounter = 0;
|
|
24
|
-
const generateMessageId = () => {
|
|
25
|
-
return `msg-${Date.now()}-${++messageIdCounter}`;
|
|
26
|
-
};
|
|
27
|
-
for (const eventLog of events) {
|
|
28
|
-
const event = eventLog.event;
|
|
29
|
-
switch (event.type) {
|
|
30
|
-
case "user-message":
|
|
31
|
-
if (currentAssistantParts.length > 0) {
|
|
32
|
-
messages.push({
|
|
33
|
-
id: generateMessageId(),
|
|
34
|
-
role: "assistant",
|
|
35
|
-
parts: currentAssistantParts,
|
|
36
|
-
status: "ready"
|
|
37
|
-
});
|
|
38
|
-
currentAssistantParts = [];
|
|
39
|
-
}
|
|
40
|
-
messages.push({
|
|
41
|
-
id: eventLog.id,
|
|
42
|
-
role: "user",
|
|
43
|
-
parts: [{
|
|
44
|
-
type: "text",
|
|
45
|
-
text: event.content
|
|
46
|
-
}],
|
|
47
|
-
status: "ready"
|
|
48
|
-
});
|
|
49
|
-
break;
|
|
50
|
-
case "text-segment":
|
|
51
|
-
currentAssistantParts.push({
|
|
52
|
-
type: "text",
|
|
53
|
-
text: event.text
|
|
54
|
-
});
|
|
55
|
-
break;
|
|
56
|
-
case "tool-call":
|
|
57
|
-
currentAssistantParts.push({
|
|
58
|
-
type: "tool-call",
|
|
59
|
-
toolCallId: event.toolCallId,
|
|
60
|
-
toolName: event.toolName,
|
|
61
|
-
args: event.args
|
|
62
|
-
});
|
|
63
|
-
break;
|
|
64
|
-
case "tool-result":
|
|
65
|
-
currentAssistantParts.push({
|
|
66
|
-
type: "tool-result",
|
|
67
|
-
toolCallId: event.toolCallId,
|
|
68
|
-
toolName: event.toolName,
|
|
69
|
-
result: event.result,
|
|
70
|
-
isError: event.isError
|
|
71
|
-
});
|
|
72
|
-
break;
|
|
73
|
-
default: break;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (streamingText || currentAssistantParts.length > 0) {
|
|
77
|
-
if (streamingText) currentAssistantParts.push({
|
|
78
|
-
type: "text",
|
|
79
|
-
text: streamingText
|
|
80
|
-
});
|
|
81
|
-
let messageStatus = "ready";
|
|
82
|
-
if (uiStatus === "streaming") messageStatus = "streaming";
|
|
83
|
-
else if (uiStatus === "submitted") messageStatus = "submitted";
|
|
84
|
-
else if (uiStatus === "error") messageStatus = "error";
|
|
85
|
-
messages.push({
|
|
86
|
-
id: generateMessageId(),
|
|
87
|
-
role: "assistant",
|
|
88
|
-
parts: currentAssistantParts,
|
|
89
|
-
status: messageStatus
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return messages;
|
|
93
|
-
}
|
|
94
35
|
/**
|
|
95
|
-
*
|
|
36
|
+
* Creates a route handler that processes chat requests using DeepAgent
|
|
37
|
+
* and streams all 26+ event types in UI Message Stream Protocol format.
|
|
38
|
+
*
|
|
39
|
+
* The returned handler:
|
|
40
|
+
* - Accepts POST requests with { messages: UIMessage[] } body
|
|
41
|
+
* - Runs DeepAgent with the conversation history
|
|
42
|
+
* - Streams responses in UI Message Stream Protocol format
|
|
43
|
+
* - Works with useChat hook from @ai-sdk/react
|
|
44
|
+
* - Provides full visibility into agent behavior (file ops, web requests, subagents, etc.)
|
|
96
45
|
*
|
|
97
|
-
* @param
|
|
98
|
-
* @returns
|
|
46
|
+
* @param options - Configuration options
|
|
47
|
+
* @returns A request handler function compatible with Next.js/Express
|
|
99
48
|
*/
|
|
100
|
-
function
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
49
|
+
function createElementsRouteHandler(options) {
|
|
50
|
+
const { agent, onRequest, initialState = {
|
|
51
|
+
todos: [],
|
|
52
|
+
files: {}
|
|
53
|
+
}, threadId, maxSteps, generateId } = options;
|
|
54
|
+
return async (req) => {
|
|
55
|
+
if (onRequest) try {
|
|
56
|
+
await onRequest(req);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return new Response(JSON.stringify({ error: error instanceof Error ? error.message : "Request rejected" }), {
|
|
59
|
+
status: 401,
|
|
60
|
+
headers: { "Content-Type": "application/json" }
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
let requestBody;
|
|
64
|
+
try {
|
|
65
|
+
requestBody = await req.json();
|
|
66
|
+
} catch {
|
|
67
|
+
return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
|
|
68
|
+
status: 400,
|
|
69
|
+
headers: { "Content-Type": "application/json" }
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const { messages } = requestBody;
|
|
73
|
+
if (!messages || !Array.isArray(messages)) return new Response(JSON.stringify({ error: "messages array is required" }), {
|
|
74
|
+
status: 400,
|
|
75
|
+
headers: { "Content-Type": "application/json" }
|
|
76
|
+
});
|
|
77
|
+
const modelMessages = await (0, ai.convertToModelMessages)(messages);
|
|
78
|
+
const genId = generateId || (() => crypto.randomUUID());
|
|
79
|
+
let currentTextId = null;
|
|
80
|
+
return (0, ai.createUIMessageStreamResponse)({ stream: (0, ai.createUIMessageStream)({
|
|
81
|
+
originalMessages: messages,
|
|
82
|
+
generateId: genId,
|
|
83
|
+
execute: async ({ writer }) => {
|
|
84
|
+
try {
|
|
85
|
+
for await (const event of agent.streamWithEvents({
|
|
86
|
+
messages: modelMessages,
|
|
87
|
+
state: initialState,
|
|
88
|
+
threadId,
|
|
89
|
+
maxSteps
|
|
90
|
+
})) {
|
|
91
|
+
const result = mapEventToProtocol(event, writer, genId, currentTextId);
|
|
92
|
+
if (typeof result === "string") currentTextId = result;
|
|
93
|
+
else if (result === null) currentTextId = null;
|
|
94
|
+
}
|
|
95
|
+
if (currentTextId) writer.write({
|
|
96
|
+
type: "text-end",
|
|
97
|
+
id: currentTextId
|
|
98
|
+
});
|
|
99
|
+
} catch (error) {
|
|
100
|
+
if (currentTextId) writer.write({
|
|
101
|
+
type: "text-end",
|
|
102
|
+
id: currentTextId
|
|
103
|
+
});
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
onError: (error) => {
|
|
108
|
+
return error instanceof Error ? error.message : "Unknown error";
|
|
109
|
+
}
|
|
110
|
+
}) });
|
|
111
|
+
};
|
|
118
112
|
}
|
|
119
|
-
|
|
120
|
-
//#endregion
|
|
121
|
-
//#region src/adapters/elements/statusAdapter.ts
|
|
122
113
|
/**
|
|
123
|
-
* Maps
|
|
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)
|
|
124
119
|
*
|
|
125
|
-
* @param
|
|
126
|
-
* @
|
|
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)
|
|
127
125
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
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
133
|
*/
|
|
134
|
-
function
|
|
135
|
-
switch (
|
|
136
|
-
case "
|
|
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;
|
|
137
157
|
case "tool-call":
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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;
|
|
142
401
|
case "done":
|
|
143
|
-
|
|
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;
|
|
144
415
|
}
|
|
145
416
|
}
|
|
146
417
|
|
|
147
418
|
//#endregion
|
|
148
|
-
//#region src/adapters/elements/
|
|
419
|
+
//#region src/adapters/elements/messageConverters.ts
|
|
149
420
|
/**
|
|
150
|
-
*
|
|
421
|
+
* Message conversion utilities for AI SDK Elements adapter
|
|
151
422
|
*
|
|
152
|
-
* Provides
|
|
423
|
+
* Provides utilities for converting between UI message formats and model message formats.
|
|
424
|
+
* The primary conversion is handled by AI SDK's `convertToModelMessages`, but these
|
|
425
|
+
* utilities provide additional helpers for DeepAgent-specific needs.
|
|
153
426
|
*/
|
|
154
|
-
let eventCounter = 0;
|
|
155
|
-
function createEventId() {
|
|
156
|
-
return `event-${++eventCounter}`;
|
|
157
|
-
}
|
|
158
427
|
/**
|
|
159
|
-
*
|
|
428
|
+
* Re-export AI SDK's convertToModelMessages for convenience.
|
|
160
429
|
*
|
|
161
|
-
*
|
|
162
|
-
*
|
|
430
|
+
* This function converts UIMessage[] (from useChat) to ModelMessage[]
|
|
431
|
+
* (for agent consumption), handling:
|
|
432
|
+
* - Role mapping (user/assistant)
|
|
433
|
+
* - Tool call/result parts
|
|
434
|
+
* - Text content extraction
|
|
163
435
|
*
|
|
164
436
|
* @example
|
|
165
|
-
* ```
|
|
166
|
-
* import {
|
|
167
|
-
* import { Conversation, Message, PromptInput } from '@/components/ai-elements';
|
|
168
|
-
*
|
|
169
|
-
* function Chat() {
|
|
170
|
-
* const { uiMessages, sendMessage } = useElementsAdapter({
|
|
171
|
-
* model,
|
|
172
|
-
* backend
|
|
173
|
-
* });
|
|
437
|
+
* ```typescript
|
|
438
|
+
* import { convertUIMessagesToModelMessages } from 'deepagentsdk/adapters/elements';
|
|
174
439
|
*
|
|
175
|
-
*
|
|
176
|
-
* <Conversation>
|
|
177
|
-
* {uiMessages.map(msg => <Message key={msg.id} from={msg.role} />)}
|
|
178
|
-
* <PromptInput onSubmit={sendMessage} />
|
|
179
|
-
* </Conversation>
|
|
180
|
-
* );
|
|
181
|
-
* }
|
|
440
|
+
* const modelMessages = await convertUIMessagesToModelMessages(uiMessages);
|
|
182
441
|
* ```
|
|
183
442
|
*/
|
|
184
|
-
function
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
tools
|
|
201
|
-
}));
|
|
202
|
-
const addEvent = (0, react.useCallback)((event) => {
|
|
203
|
-
setEvents((prev) => [...prev, {
|
|
204
|
-
id: createEventId(),
|
|
205
|
-
type: event.type,
|
|
206
|
-
event,
|
|
207
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
208
|
-
}]);
|
|
209
|
-
}, []);
|
|
210
|
-
const flushTextSegment = (0, react.useCallback)(() => {
|
|
211
|
-
if (accumulatedTextRef.current.trim()) {
|
|
212
|
-
addEvent({
|
|
213
|
-
type: "text-segment",
|
|
214
|
-
text: accumulatedTextRef.current
|
|
215
|
-
});
|
|
216
|
-
accumulatedTextRef.current = "";
|
|
217
|
-
setStreamingText("");
|
|
218
|
-
}
|
|
219
|
-
}, [addEvent]);
|
|
220
|
-
const sendMessage = async (message) => {
|
|
221
|
-
if (!message.text.trim()) return;
|
|
222
|
-
setStatus("thinking");
|
|
223
|
-
setStreamingText("");
|
|
224
|
-
accumulatedTextRef.current = "";
|
|
225
|
-
addEvent({
|
|
226
|
-
type: "user-message",
|
|
227
|
-
content: message.text
|
|
228
|
-
});
|
|
229
|
-
abortControllerRef.current = new AbortController();
|
|
230
|
-
try {
|
|
231
|
-
for await (const event of agentRef.current.streamWithEvents({
|
|
232
|
-
messages: [{
|
|
233
|
-
role: "user",
|
|
234
|
-
content: message.text
|
|
235
|
-
}],
|
|
236
|
-
state,
|
|
237
|
-
abortSignal: abortControllerRef.current.signal
|
|
238
|
-
})) switch (event.type) {
|
|
239
|
-
case "text":
|
|
240
|
-
setStatus("streaming");
|
|
241
|
-
accumulatedTextRef.current += event.text;
|
|
242
|
-
setStreamingText(accumulatedTextRef.current);
|
|
243
|
-
break;
|
|
244
|
-
case "step-start":
|
|
245
|
-
if (event.stepNumber > 1) addEvent(event);
|
|
246
|
-
break;
|
|
247
|
-
case "tool-call":
|
|
248
|
-
flushTextSegment();
|
|
249
|
-
setStatus("tool-call");
|
|
250
|
-
addEvent(event);
|
|
251
|
-
break;
|
|
252
|
-
case "tool-result":
|
|
253
|
-
addEvent(event);
|
|
254
|
-
break;
|
|
255
|
-
case "todos-changed":
|
|
256
|
-
flushTextSegment();
|
|
257
|
-
setStatus("tool-call");
|
|
258
|
-
setState((prev) => ({
|
|
259
|
-
...prev,
|
|
260
|
-
todos: event.todos
|
|
261
|
-
}));
|
|
262
|
-
addEvent(event);
|
|
263
|
-
break;
|
|
264
|
-
case "done":
|
|
265
|
-
flushTextSegment();
|
|
266
|
-
setStatus("done");
|
|
267
|
-
setState(event.state);
|
|
268
|
-
addEvent(event);
|
|
269
|
-
break;
|
|
270
|
-
case "error":
|
|
271
|
-
flushTextSegment();
|
|
272
|
-
setStatus("error");
|
|
273
|
-
addEvent(event);
|
|
274
|
-
break;
|
|
275
|
-
default:
|
|
276
|
-
addEvent(event);
|
|
277
|
-
break;
|
|
278
|
-
}
|
|
279
|
-
setStatus("idle");
|
|
280
|
-
} catch (err) {
|
|
281
|
-
if (err.name === "AbortError") {
|
|
282
|
-
flushTextSegment();
|
|
283
|
-
setStatus("idle");
|
|
284
|
-
} else {
|
|
285
|
-
flushTextSegment();
|
|
286
|
-
setStatus("error");
|
|
287
|
-
}
|
|
288
|
-
} finally {
|
|
289
|
-
abortControllerRef.current = null;
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
const abort = (0, react.useCallback)(() => {
|
|
293
|
-
if (abortControllerRef.current) {
|
|
294
|
-
abortControllerRef.current.abort();
|
|
295
|
-
setStatus("idle");
|
|
443
|
+
async function convertUIMessagesToModelMessages(messages) {
|
|
444
|
+
return await (0, ai.convertToModelMessages)(messages);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Extract the last user message text from a UIMessage array.
|
|
448
|
+
* Useful for extracting the prompt from a conversation.
|
|
449
|
+
*
|
|
450
|
+
* @param messages - Array of UI messages
|
|
451
|
+
* @returns The text content of the last user message, or undefined if none
|
|
452
|
+
*/
|
|
453
|
+
function extractLastUserMessage(messages) {
|
|
454
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
455
|
+
const msg = messages[i];
|
|
456
|
+
if (msg && msg.role === "user" && msg.parts) {
|
|
457
|
+
const textParts = msg.parts.filter((p) => p.type === "text");
|
|
458
|
+
if (textParts.length > 0) return textParts.map((p) => p.text).join("");
|
|
296
459
|
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Check if the messages contain any tool parts.
|
|
464
|
+
* This is a simplified helper that checks for any tool-related parts.
|
|
465
|
+
*
|
|
466
|
+
* @param messages - Array of UI messages
|
|
467
|
+
* @returns True if there are any tool-related parts in the messages
|
|
468
|
+
*/
|
|
469
|
+
function hasToolParts(messages) {
|
|
470
|
+
for (const msg of messages) {
|
|
471
|
+
if (!msg.parts) continue;
|
|
472
|
+
for (const part of msg.parts) if (part.type.startsWith("tool-") || part.type === "dynamic-tool") return true;
|
|
473
|
+
}
|
|
474
|
+
return false;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Count the number of messages by role.
|
|
478
|
+
*
|
|
479
|
+
* @param messages - Array of UI messages
|
|
480
|
+
* @returns Object with counts by role
|
|
481
|
+
*/
|
|
482
|
+
function countMessagesByRole(messages) {
|
|
483
|
+
let user = 0;
|
|
484
|
+
let assistant = 0;
|
|
485
|
+
let system = 0;
|
|
486
|
+
for (const msg of messages) if (msg.role === "user") user++;
|
|
487
|
+
else if (msg.role === "assistant") assistant++;
|
|
488
|
+
else if (msg.role === "system") system++;
|
|
309
489
|
return {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
sendMessage,
|
|
314
|
-
abort,
|
|
315
|
-
clear
|
|
490
|
+
user,
|
|
491
|
+
assistant,
|
|
492
|
+
system
|
|
316
493
|
};
|
|
317
494
|
}
|
|
495
|
+
/**
|
|
496
|
+
* Extract all text content from a message.
|
|
497
|
+
*
|
|
498
|
+
* @param message - A UI message
|
|
499
|
+
* @returns Combined text from all text parts
|
|
500
|
+
*/
|
|
501
|
+
function extractTextFromMessage(message) {
|
|
502
|
+
if (!message.parts) return "";
|
|
503
|
+
return message.parts.filter((p) => p.type === "text").map((p) => p.text).join("");
|
|
504
|
+
}
|
|
318
505
|
|
|
319
506
|
//#endregion
|
|
320
|
-
exports.
|
|
321
|
-
exports.
|
|
322
|
-
exports.
|
|
323
|
-
exports.
|
|
507
|
+
exports.convertUIMessagesToModelMessages = convertUIMessagesToModelMessages;
|
|
508
|
+
exports.countMessagesByRole = countMessagesByRole;
|
|
509
|
+
exports.createElementsRouteHandler = createElementsRouteHandler;
|
|
510
|
+
exports.extractLastUserMessage = extractLastUserMessage;
|
|
511
|
+
exports.extractTextFromMessage = extractTextFromMessage;
|
|
512
|
+
exports.hasToolParts = hasToolParts;
|
|
513
|
+
exports.mapEventToProtocol = mapEventToProtocol;
|
|
324
514
|
//# sourceMappingURL=index.cjs.map
|