veryfront 0.1.260 → 0.1.261
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/esm/cli/templates/manifest.d.ts +473 -473
- package/esm/cli/templates/manifest.js +521 -521
- package/esm/deno.js +1 -1
- package/esm/src/agent/ag-ui-runtime-chat-stream-encoder.d.ts +17 -0
- package/esm/src/agent/ag-ui-runtime-chat-stream-encoder.d.ts.map +1 -0
- package/esm/src/agent/ag-ui-runtime-chat-stream-encoder.js +304 -0
- package/esm/src/agent/index.d.ts +1 -0
- package/esm/src/agent/index.d.ts.map +1 -1
- package/esm/src/agent/index.js +1 -0
- package/esm/src/server/dev-ui/manifest.d.ts +17 -17
- package/esm/src/server/dev-ui/manifest.js +17 -17
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/cli/templates/manifest.js +521 -521
- package/src/deno.js +1 -1
- package/src/src/agent/ag-ui-runtime-chat-stream-encoder.ts +359 -0
- package/src/src/agent/index.ts +6 -0
- package/src/src/server/dev-ui/manifest.js +17 -17
- package/src/src/utils/version-constant.ts +1 -1
package/src/deno.js
CHANGED
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import {
|
|
3
|
+
mergeToolInputDelta,
|
|
4
|
+
parseToolInputObject,
|
|
5
|
+
stripLeadingEmptyObjectPlaceholder,
|
|
6
|
+
} from "./data-stream.js";
|
|
7
|
+
import type { AgUiRuntimeStreamEvent } from "./ag-ui-browser-encoder.js";
|
|
8
|
+
import type { ChatFinishReason, ChatStreamEvent } from "../chat/protocol.js";
|
|
9
|
+
|
|
10
|
+
export interface AgUiRuntimeChatStreamEncoderState {
|
|
11
|
+
isStepOpen: boolean;
|
|
12
|
+
finishReason: ChatFinishReason;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface AgUiRuntimeChatStreamEncoder {
|
|
16
|
+
state: AgUiRuntimeChatStreamEncoderState;
|
|
17
|
+
encode: (event: AgUiRuntimeStreamEvent) => ChatStreamEvent[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface CreateAgUiRuntimeChatStreamEncoderOptions {
|
|
21
|
+
responseMessageId: string;
|
|
22
|
+
sendReasoning?: boolean;
|
|
23
|
+
onError?: (error: unknown) => string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type ToolPart = {
|
|
27
|
+
toolName: string;
|
|
28
|
+
inputText: string;
|
|
29
|
+
input: Record<string, unknown>;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
type PendingToolDelta = {
|
|
33
|
+
inputText: string;
|
|
34
|
+
chunks: string[];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function getStringField(event: AgUiRuntimeStreamEvent, key: string): string | undefined {
|
|
38
|
+
const value = event[key];
|
|
39
|
+
return typeof value === "string" ? value : undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
43
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getDataRecord(event: AgUiRuntimeStreamEvent): Record<string, unknown> | undefined {
|
|
47
|
+
return isRecord(event.data) ? event.data : undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function getToolInput(event: AgUiRuntimeStreamEvent): Record<string, unknown> {
|
|
51
|
+
return parseToolInputObject(event.input);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function parseStreamedToolInput(inputText: string): Record<string, unknown> | null {
|
|
55
|
+
const normalizedInputText = stripLeadingEmptyObjectPlaceholder(inputText).trim();
|
|
56
|
+
if (normalizedInputText.length === 0) {
|
|
57
|
+
return {};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(normalizedInputText);
|
|
62
|
+
return isRecord(parsed) ? Object.fromEntries(Object.entries(parsed)) : {};
|
|
63
|
+
} catch {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isEmptyRecord(value: Record<string, unknown>): boolean {
|
|
69
|
+
return Object.keys(value).length === 0;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function formatErrorText(error: unknown, onError?: (error: unknown) => string): string {
|
|
73
|
+
return onError ? onError(error) : error instanceof Error ? error.message : String(error);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function createAgUiRuntimeChatStreamEncoder(
|
|
77
|
+
options: CreateAgUiRuntimeChatStreamEncoderOptions,
|
|
78
|
+
): AgUiRuntimeChatStreamEncoder {
|
|
79
|
+
const state: AgUiRuntimeChatStreamEncoderState = {
|
|
80
|
+
isStepOpen: false,
|
|
81
|
+
finishReason: "stop",
|
|
82
|
+
};
|
|
83
|
+
const startedTextBlockIds = new Set<string>();
|
|
84
|
+
const seenTextBlockIds = new Set<string>();
|
|
85
|
+
const emittedToolInputStartIds = new Set<string>();
|
|
86
|
+
const toolParts = new Map<string, ToolPart>();
|
|
87
|
+
const pendingToolDeltas = new Map<string, PendingToolDelta>();
|
|
88
|
+
|
|
89
|
+
const ensureStepStarted = (events: ChatStreamEvent[]) => {
|
|
90
|
+
if (state.isStepOpen) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
state.isStepOpen = true;
|
|
94
|
+
events.push({ type: "start-step" });
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const appendPendingToolDelta = (toolCallId: string, inputTextDelta: string) => {
|
|
98
|
+
const existing = pendingToolDeltas.get(toolCallId);
|
|
99
|
+
if (existing) {
|
|
100
|
+
existing.inputText = mergeToolInputDelta(existing.inputText, inputTextDelta);
|
|
101
|
+
existing.chunks.push(inputTextDelta);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
pendingToolDeltas.set(toolCallId, {
|
|
106
|
+
inputText: inputTextDelta,
|
|
107
|
+
chunks: [inputTextDelta],
|
|
108
|
+
});
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const flushPendingToolDeltas = (toolCallId: string): ChatStreamEvent[] => {
|
|
112
|
+
const pending = pendingToolDeltas.get(toolCallId);
|
|
113
|
+
if (!pending) {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
pendingToolDeltas.delete(toolCallId);
|
|
117
|
+
return pending.chunks.map((inputTextDelta) => ({
|
|
118
|
+
type: "tool-input-delta",
|
|
119
|
+
toolCallId,
|
|
120
|
+
inputTextDelta,
|
|
121
|
+
}));
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
state,
|
|
126
|
+
encode: (event) => {
|
|
127
|
+
const events: ChatStreamEvent[] = [];
|
|
128
|
+
|
|
129
|
+
switch (event.type) {
|
|
130
|
+
case "message-start":
|
|
131
|
+
case "message-finish":
|
|
132
|
+
return events;
|
|
133
|
+
case "step-start":
|
|
134
|
+
ensureStepStarted(events);
|
|
135
|
+
return events;
|
|
136
|
+
case "step-end":
|
|
137
|
+
if (state.isStepOpen) {
|
|
138
|
+
state.isStepOpen = false;
|
|
139
|
+
events.push({ type: "finish-step" });
|
|
140
|
+
}
|
|
141
|
+
return events;
|
|
142
|
+
case "text-start": {
|
|
143
|
+
ensureStepStarted(events);
|
|
144
|
+
const id = getStringField(event, "id") ?? options.responseMessageId;
|
|
145
|
+
if (!seenTextBlockIds.has(id)) {
|
|
146
|
+
seenTextBlockIds.add(id);
|
|
147
|
+
} else if (startedTextBlockIds.has(id)) {
|
|
148
|
+
events.push({ type: "text-start", id: options.responseMessageId });
|
|
149
|
+
}
|
|
150
|
+
return events;
|
|
151
|
+
}
|
|
152
|
+
case "text-delta": {
|
|
153
|
+
ensureStepStarted(events);
|
|
154
|
+
const id = getStringField(event, "id") ?? options.responseMessageId;
|
|
155
|
+
const delta = getStringField(event, "delta") ?? "";
|
|
156
|
+
if (delta.length === 0) {
|
|
157
|
+
return events;
|
|
158
|
+
}
|
|
159
|
+
if (!startedTextBlockIds.has(id)) {
|
|
160
|
+
startedTextBlockIds.add(id);
|
|
161
|
+
seenTextBlockIds.add(id);
|
|
162
|
+
events.push({ type: "text-start", id: options.responseMessageId });
|
|
163
|
+
}
|
|
164
|
+
events.push({ type: "text-delta", id: options.responseMessageId, delta });
|
|
165
|
+
return events;
|
|
166
|
+
}
|
|
167
|
+
case "text-end": {
|
|
168
|
+
const id = getStringField(event, "id") ?? options.responseMessageId;
|
|
169
|
+
if (startedTextBlockIds.has(id)) {
|
|
170
|
+
startedTextBlockIds.delete(id);
|
|
171
|
+
events.push({ type: "text-end", id: options.responseMessageId });
|
|
172
|
+
}
|
|
173
|
+
return events;
|
|
174
|
+
}
|
|
175
|
+
case "reasoning-start": {
|
|
176
|
+
ensureStepStarted(events);
|
|
177
|
+
const id = getStringField(event, "id") ?? dntShim.crypto.randomUUID();
|
|
178
|
+
events.push({ type: "reasoning-start", id });
|
|
179
|
+
return events;
|
|
180
|
+
}
|
|
181
|
+
case "reasoning-delta": {
|
|
182
|
+
ensureStepStarted(events);
|
|
183
|
+
if (options.sendReasoning === false) {
|
|
184
|
+
return events;
|
|
185
|
+
}
|
|
186
|
+
const id = getStringField(event, "id") ?? dntShim.crypto.randomUUID();
|
|
187
|
+
const delta = getStringField(event, "delta") ?? "";
|
|
188
|
+
if (delta.length > 0) {
|
|
189
|
+
events.push({ type: "reasoning-delta", id, delta });
|
|
190
|
+
}
|
|
191
|
+
return events;
|
|
192
|
+
}
|
|
193
|
+
case "reasoning-end": {
|
|
194
|
+
const id = getStringField(event, "id");
|
|
195
|
+
if (id) {
|
|
196
|
+
events.push({ type: "reasoning-end", id });
|
|
197
|
+
}
|
|
198
|
+
return events;
|
|
199
|
+
}
|
|
200
|
+
case "tool-input-start": {
|
|
201
|
+
ensureStepStarted(events);
|
|
202
|
+
const toolCallId = getStringField(event, "toolCallId");
|
|
203
|
+
const toolName = getStringField(event, "toolName");
|
|
204
|
+
if (!toolCallId || !toolName) {
|
|
205
|
+
return events;
|
|
206
|
+
}
|
|
207
|
+
const toolPart = toolParts.get(toolCallId);
|
|
208
|
+
if (!toolPart) {
|
|
209
|
+
toolParts.set(toolCallId, {
|
|
210
|
+
toolName,
|
|
211
|
+
inputText: "",
|
|
212
|
+
input: {},
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (!emittedToolInputStartIds.has(toolCallId)) {
|
|
216
|
+
emittedToolInputStartIds.add(toolCallId);
|
|
217
|
+
events.push({ type: "tool-input-start", toolCallId, toolName });
|
|
218
|
+
}
|
|
219
|
+
const pendingEvents = flushPendingToolDeltas(toolCallId);
|
|
220
|
+
const existingToolPart = toolParts.get(toolCallId);
|
|
221
|
+
if (existingToolPart) {
|
|
222
|
+
for (const pendingEvent of pendingEvents) {
|
|
223
|
+
if (pendingEvent.type === "tool-input-delta") {
|
|
224
|
+
existingToolPart.inputText = mergeToolInputDelta(
|
|
225
|
+
existingToolPart.inputText,
|
|
226
|
+
pendingEvent.inputTextDelta,
|
|
227
|
+
);
|
|
228
|
+
const parsedInput = parseStreamedToolInput(existingToolPart.inputText);
|
|
229
|
+
if (parsedInput) {
|
|
230
|
+
existingToolPart.input = parsedInput;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
events.push(...pendingEvents);
|
|
236
|
+
return events;
|
|
237
|
+
}
|
|
238
|
+
case "tool-input-delta": {
|
|
239
|
+
ensureStepStarted(events);
|
|
240
|
+
const toolCallId = getStringField(event, "toolCallId");
|
|
241
|
+
const inputTextDelta = getStringField(event, "inputTextDelta") ??
|
|
242
|
+
getStringField(event, "delta") ?? "";
|
|
243
|
+
if (!toolCallId || inputTextDelta.length === 0) {
|
|
244
|
+
return events;
|
|
245
|
+
}
|
|
246
|
+
const toolPart = toolParts.get(toolCallId);
|
|
247
|
+
if (!toolPart) {
|
|
248
|
+
appendPendingToolDelta(toolCallId, inputTextDelta);
|
|
249
|
+
return events;
|
|
250
|
+
}
|
|
251
|
+
toolPart.inputText = mergeToolInputDelta(toolPart.inputText, inputTextDelta);
|
|
252
|
+
const parsedInput = parseStreamedToolInput(toolPart.inputText);
|
|
253
|
+
if (parsedInput) {
|
|
254
|
+
toolPart.input = parsedInput;
|
|
255
|
+
}
|
|
256
|
+
events.push({ type: "tool-input-delta", toolCallId, inputTextDelta });
|
|
257
|
+
return events;
|
|
258
|
+
}
|
|
259
|
+
case "tool-input-available": {
|
|
260
|
+
ensureStepStarted(events);
|
|
261
|
+
const toolCallId = getStringField(event, "toolCallId");
|
|
262
|
+
const toolName = getStringField(event, "toolName");
|
|
263
|
+
if (!toolCallId || !toolName) {
|
|
264
|
+
return events;
|
|
265
|
+
}
|
|
266
|
+
const inputRecord = getToolInput(event);
|
|
267
|
+
const existingToolPart = toolParts.get(toolCallId);
|
|
268
|
+
const pendingToolDelta = pendingToolDeltas.get(toolCallId);
|
|
269
|
+
const pendingInputText = pendingToolDelta?.inputText ?? "";
|
|
270
|
+
const parsedPendingInput = pendingInputText.length > 0
|
|
271
|
+
? parseStreamedToolInput(pendingInputText)
|
|
272
|
+
: null;
|
|
273
|
+
const resolvedInputRecord = isEmptyRecord(inputRecord)
|
|
274
|
+
? existingToolPart && !isEmptyRecord(existingToolPart.input)
|
|
275
|
+
? existingToolPart.input
|
|
276
|
+
: parsedPendingInput && !isEmptyRecord(parsedPendingInput)
|
|
277
|
+
? parsedPendingInput
|
|
278
|
+
: inputRecord
|
|
279
|
+
: inputRecord;
|
|
280
|
+
|
|
281
|
+
if (existingToolPart) {
|
|
282
|
+
existingToolPart.toolName = toolName;
|
|
283
|
+
existingToolPart.inputText = pendingInputText;
|
|
284
|
+
existingToolPart.input = resolvedInputRecord;
|
|
285
|
+
} else {
|
|
286
|
+
toolParts.set(toolCallId, {
|
|
287
|
+
toolName,
|
|
288
|
+
inputText: pendingInputText,
|
|
289
|
+
input: resolvedInputRecord,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (!emittedToolInputStartIds.has(toolCallId)) {
|
|
294
|
+
emittedToolInputStartIds.add(toolCallId);
|
|
295
|
+
events.push({ type: "tool-input-start", toolCallId, toolName });
|
|
296
|
+
}
|
|
297
|
+
events.push(...flushPendingToolDeltas(toolCallId));
|
|
298
|
+
events.push({
|
|
299
|
+
type: "tool-input-available",
|
|
300
|
+
toolCallId,
|
|
301
|
+
toolName,
|
|
302
|
+
input: resolvedInputRecord,
|
|
303
|
+
});
|
|
304
|
+
return events;
|
|
305
|
+
}
|
|
306
|
+
case "tool-output-available": {
|
|
307
|
+
ensureStepStarted(events);
|
|
308
|
+
const toolCallId = getStringField(event, "toolCallId");
|
|
309
|
+
if (!toolCallId) {
|
|
310
|
+
return events;
|
|
311
|
+
}
|
|
312
|
+
events.push({ type: "tool-output-available", toolCallId, output: event.output });
|
|
313
|
+
return events;
|
|
314
|
+
}
|
|
315
|
+
case "tool-output-error": {
|
|
316
|
+
ensureStepStarted(events);
|
|
317
|
+
const toolCallId = getStringField(event, "toolCallId");
|
|
318
|
+
if (!toolCallId) {
|
|
319
|
+
return events;
|
|
320
|
+
}
|
|
321
|
+
const errorText = getStringField(event, "errorText") ?? "Tool execution failed";
|
|
322
|
+
events.push({ type: "tool-output-error", toolCallId, errorText });
|
|
323
|
+
return events;
|
|
324
|
+
}
|
|
325
|
+
case "data": {
|
|
326
|
+
const data = getDataRecord(event);
|
|
327
|
+
const name = typeof data?.name === "string" && data.name.length > 0
|
|
328
|
+
? data.name
|
|
329
|
+
: undefined;
|
|
330
|
+
if (name) {
|
|
331
|
+
const dataValue = data && Object.hasOwn(data, "value") ? data.value : undefined;
|
|
332
|
+
events.push({
|
|
333
|
+
type: `data-${name}`,
|
|
334
|
+
data: dataValue,
|
|
335
|
+
});
|
|
336
|
+
return events;
|
|
337
|
+
}
|
|
338
|
+
if (data && typeof data.model === "string") {
|
|
339
|
+
events.push({ type: "message-metadata", messageMetadata: { modelId: data.model } });
|
|
340
|
+
}
|
|
341
|
+
return events;
|
|
342
|
+
}
|
|
343
|
+
case "error": {
|
|
344
|
+
state.finishReason = "error";
|
|
345
|
+
events.push({
|
|
346
|
+
type: "error",
|
|
347
|
+
errorText: formatErrorText(
|
|
348
|
+
getStringField(event, "error") ?? "Framework stream failed",
|
|
349
|
+
options.onError,
|
|
350
|
+
),
|
|
351
|
+
});
|
|
352
|
+
return events;
|
|
353
|
+
}
|
|
354
|
+
default:
|
|
355
|
+
return events;
|
|
356
|
+
}
|
|
357
|
+
},
|
|
358
|
+
};
|
|
359
|
+
}
|
package/src/src/agent/index.ts
CHANGED
|
@@ -184,6 +184,12 @@ export {
|
|
|
184
184
|
createAgUiRuntimeEventEncoder,
|
|
185
185
|
type CreateAgUiRuntimeEventEncoderOptions,
|
|
186
186
|
} from "./ag-ui-runtime-event-encoder.js";
|
|
187
|
+
export {
|
|
188
|
+
type AgUiRuntimeChatStreamEncoder,
|
|
189
|
+
type AgUiRuntimeChatStreamEncoderState,
|
|
190
|
+
createAgUiRuntimeChatStreamEncoder,
|
|
191
|
+
type CreateAgUiRuntimeChatStreamEncoderOptions,
|
|
192
|
+
} from "./ag-ui-runtime-chat-stream-encoder.js";
|
|
187
193
|
export {
|
|
188
194
|
type AgUiBrowserFinalizeTracker,
|
|
189
195
|
createAgUiBrowserFinalizeTracker,
|