veryfront 0.1.288 → 0.1.289
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/deno.d.ts +4 -0
- package/esm/deno.js +7 -3
- package/esm/src/chat/final-step-fallback.d.ts +48 -0
- package/esm/src/chat/final-step-fallback.d.ts.map +1 -0
- package/esm/src/chat/final-step-fallback.js +678 -0
- package/esm/src/chat/provider-errors.d.ts +17 -0
- package/esm/src/chat/provider-errors.d.ts.map +1 -0
- package/esm/src/chat/provider-errors.js +170 -0
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +9 -1
- package/src/deno.js +7 -3
- package/src/src/chat/final-step-fallback.ts +957 -0
- package/src/src/chat/provider-errors.ts +218 -0
- package/src/src/utils/version-constant.ts +1 -1
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
import * as dntShim from "../../_dnt.shims.js";
|
|
2
|
+
import { isRecord, isTextPart, isToolCallPart, isToolResultPart } from "./conversation.js";
|
|
3
|
+
import { parseKnownProblemBody, safeJsonParse } from "./provider-errors.js";
|
|
4
|
+
function toToolInput(value) {
|
|
5
|
+
return isRecord(value) ? Object.fromEntries(Object.entries(value)) : {};
|
|
6
|
+
}
|
|
7
|
+
const STREAM_PROMISE_TIMEOUT_TOKEN = Symbol("stream-promise-timeout");
|
|
8
|
+
export const DEFAULT_STREAM_PROMISE_TIMEOUT_MS = 10_000;
|
|
9
|
+
function isToolUiPart(part) {
|
|
10
|
+
return isRecord(part) && typeof Reflect.get(part, "toolCallId") === "string" && "state" in part;
|
|
11
|
+
}
|
|
12
|
+
// --- Ordered-part building ---
|
|
13
|
+
function buildOrderedFallbackPartsFromContentMessages(messages) {
|
|
14
|
+
const orderedParts = [];
|
|
15
|
+
const toolCallsById = new Map();
|
|
16
|
+
const toolResultsById = new Map();
|
|
17
|
+
for (const toolCall of messages.flatMap((message) => {
|
|
18
|
+
if (!isRecord(message) || !Array.isArray(message.content)) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
return message.content.flatMap((part) => isToolCallPart(part)
|
|
22
|
+
? [
|
|
23
|
+
{
|
|
24
|
+
toolCallId: part.toolCallId,
|
|
25
|
+
toolName: part.toolName,
|
|
26
|
+
input: part.input,
|
|
27
|
+
},
|
|
28
|
+
]
|
|
29
|
+
: []);
|
|
30
|
+
})) {
|
|
31
|
+
toolCallsById.set(toolCall.toolCallId, toolCall);
|
|
32
|
+
}
|
|
33
|
+
for (const toolResult of messages.flatMap((message) => {
|
|
34
|
+
if (!isRecord(message) || !Array.isArray(message.content)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return message.content.flatMap((part) => isToolResultPart(part)
|
|
38
|
+
? [
|
|
39
|
+
{
|
|
40
|
+
toolCallId: part.toolCallId,
|
|
41
|
+
toolName: part.toolName,
|
|
42
|
+
input: toolCallsById.get(part.toolCallId)?.input ?? {},
|
|
43
|
+
output: part.output,
|
|
44
|
+
},
|
|
45
|
+
]
|
|
46
|
+
: []);
|
|
47
|
+
})) {
|
|
48
|
+
toolResultsById.set(toolResult.toolCallId, toolResult);
|
|
49
|
+
}
|
|
50
|
+
for (const message of messages) {
|
|
51
|
+
if (!isRecord(message) || message.role !== "assistant" || !Array.isArray(message.content)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
for (const part of message.content) {
|
|
55
|
+
if (isTextPart(part)) {
|
|
56
|
+
const text = part.text.trim();
|
|
57
|
+
if (text.length > 0) {
|
|
58
|
+
orderedParts.push({
|
|
59
|
+
type: "text",
|
|
60
|
+
text,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (isToolCallPart(part)) {
|
|
66
|
+
const toolResult = toolResultsById.get(part.toolCallId);
|
|
67
|
+
const toolCall = toolCallsById.get(part.toolCallId);
|
|
68
|
+
orderedParts.push({
|
|
69
|
+
type: "dynamic-tool",
|
|
70
|
+
toolName: part.toolName,
|
|
71
|
+
toolCallId: part.toolCallId,
|
|
72
|
+
input: toToolInput(toolCall?.input ?? part.input),
|
|
73
|
+
state: toolResult ? "output-available" : "input-available",
|
|
74
|
+
...(toolResult ? { output: toolResult.output } : {}),
|
|
75
|
+
});
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (isToolResultPart(part)) {
|
|
79
|
+
const existingIndex = orderedParts.findIndex((existingPart) => isToolUiPart(existingPart) && existingPart.toolCallId === part.toolCallId);
|
|
80
|
+
if (existingIndex >= 0) {
|
|
81
|
+
const existingPart = orderedParts[existingIndex];
|
|
82
|
+
if (!isToolUiPart(existingPart)) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
orderedParts[existingIndex] = {
|
|
86
|
+
...existingPart,
|
|
87
|
+
state: "output-available",
|
|
88
|
+
output: part.output,
|
|
89
|
+
};
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const toolCall = toolCallsById.get(part.toolCallId);
|
|
93
|
+
orderedParts.push({
|
|
94
|
+
type: "dynamic-tool",
|
|
95
|
+
toolName: part.toolName,
|
|
96
|
+
toolCallId: part.toolCallId,
|
|
97
|
+
input: toToolInput(toolCall?.input ?? part.output),
|
|
98
|
+
state: "output-available",
|
|
99
|
+
output: part.output,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return orderedParts;
|
|
105
|
+
}
|
|
106
|
+
function buildOrderedFallbackPartsFromUiMessages(messages) {
|
|
107
|
+
const orderedParts = [];
|
|
108
|
+
for (const message of messages) {
|
|
109
|
+
if (!isRecord(message) || !Array.isArray(message.parts)) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (message.role === "assistant") {
|
|
113
|
+
for (const part of message.parts) {
|
|
114
|
+
if (!isRecord(part) || typeof part.type !== "string") {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if (part.type === "text" && typeof part.text === "string" && part.text.trim().length > 0) {
|
|
118
|
+
orderedParts.push({
|
|
119
|
+
type: "text",
|
|
120
|
+
text: part.text.trim(),
|
|
121
|
+
});
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
const toolCallId = typeof part.toolCallId === "string" ? part.toolCallId : null;
|
|
125
|
+
if (!toolCallId) {
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
const explicitToolName = typeof part.toolName === "string" ? part.toolName : null;
|
|
129
|
+
const derivedToolName = explicitToolName ??
|
|
130
|
+
(part.type.startsWith("tool-")
|
|
131
|
+
? part.type.slice(5)
|
|
132
|
+
: part.type === "dynamic-tool"
|
|
133
|
+
? null
|
|
134
|
+
: null);
|
|
135
|
+
if (!derivedToolName) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
orderedParts.push({
|
|
139
|
+
type: "dynamic-tool",
|
|
140
|
+
toolName: derivedToolName,
|
|
141
|
+
toolCallId,
|
|
142
|
+
input: toToolInput("args" in part ? part.args : "input" in part ? part.input : {}),
|
|
143
|
+
state: "input-available",
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (message.role === "tool") {
|
|
149
|
+
for (const part of message.parts) {
|
|
150
|
+
if (!isRecord(part) || part.type !== "tool-result" || typeof part.toolCallId !== "string") {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
const existingIndex = orderedParts.findIndex((existingPart) => isToolUiPart(existingPart) && existingPart.toolCallId === part.toolCallId);
|
|
154
|
+
if (existingIndex < 0) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
const existingPart = orderedParts[existingIndex];
|
|
158
|
+
if (!isToolUiPart(existingPart)) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
orderedParts[existingIndex] = {
|
|
162
|
+
...existingPart,
|
|
163
|
+
state: "output-available",
|
|
164
|
+
output: "result" in part ? part.result : null,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return orderedParts;
|
|
170
|
+
}
|
|
171
|
+
// --- Part extraction ---
|
|
172
|
+
function extractTextFromAssistantContent(content) {
|
|
173
|
+
if (typeof content === "string") {
|
|
174
|
+
return content.trim();
|
|
175
|
+
}
|
|
176
|
+
if (!Array.isArray(content)) {
|
|
177
|
+
return "";
|
|
178
|
+
}
|
|
179
|
+
return content
|
|
180
|
+
.flatMap((part) => isRecord(part) && part.type === "text" && typeof part.text === "string" &&
|
|
181
|
+
part.text.trim().length > 0
|
|
182
|
+
? [part.text.trim()]
|
|
183
|
+
: [])
|
|
184
|
+
.join("\n")
|
|
185
|
+
.trim();
|
|
186
|
+
}
|
|
187
|
+
function extractTextFromResponseMessages(step) {
|
|
188
|
+
if (!isRecord(step) || !isRecord(step.response) || !Array.isArray(step.response.messages)) {
|
|
189
|
+
return "";
|
|
190
|
+
}
|
|
191
|
+
const assistantTexts = step.response.messages
|
|
192
|
+
.flatMap((message) => isRecord(message) && message.role === "assistant"
|
|
193
|
+
? [extractTextFromAssistantContent(message.content)]
|
|
194
|
+
: [])
|
|
195
|
+
.filter((text) => text.length > 0);
|
|
196
|
+
return assistantTexts.join("\n").trim();
|
|
197
|
+
}
|
|
198
|
+
function buildOrderedFallbackPartsFromResponseMessages(step) {
|
|
199
|
+
if (!isRecord(step) || !isRecord(step.response) || !Array.isArray(step.response.messages)) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
return buildOrderedFallbackPartsFromContentMessages(step.response.messages);
|
|
203
|
+
}
|
|
204
|
+
function buildOrderedFallbackPartsFromUiResponseMessages(step) {
|
|
205
|
+
if (!isRecord(step) || !isRecord(step.response) || !Array.isArray(step.response.messages)) {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
return buildOrderedFallbackPartsFromUiMessages(step.response.messages);
|
|
209
|
+
}
|
|
210
|
+
function buildFallbackUiMessagePartsFromInput(input) {
|
|
211
|
+
const orderedResponseParts = buildOrderedFallbackPartsFromResponseMessages(input.step);
|
|
212
|
+
if (orderedResponseParts.length > 0) {
|
|
213
|
+
return orderedResponseParts;
|
|
214
|
+
}
|
|
215
|
+
if (isRecord(input.step) && Array.isArray(input.step.messages)) {
|
|
216
|
+
const orderedTopLevelContentParts = buildOrderedFallbackPartsFromContentMessages(input.step.messages);
|
|
217
|
+
if (orderedTopLevelContentParts.length > 0) {
|
|
218
|
+
return orderedTopLevelContentParts;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
const orderedUiResponseParts = buildOrderedFallbackPartsFromUiResponseMessages(input.step);
|
|
222
|
+
if (orderedUiResponseParts.length > 0) {
|
|
223
|
+
return orderedUiResponseParts;
|
|
224
|
+
}
|
|
225
|
+
if (isRecord(input.step) && Array.isArray(input.step.messages)) {
|
|
226
|
+
const orderedUiTopLevelParts = buildOrderedFallbackPartsFromUiMessages(input.step.messages);
|
|
227
|
+
if (orderedUiTopLevelParts.length > 0) {
|
|
228
|
+
return orderedUiTopLevelParts;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
const parts = [];
|
|
232
|
+
const toolCalls = input.extractFinalStepToolCalls(input.step);
|
|
233
|
+
const toolResults = new Map(input.extractFinalStepToolResults(input.step).map((toolResult) => [toolResult.toolCallId, toolResult]));
|
|
234
|
+
const handledToolCallIds = new Set();
|
|
235
|
+
for (const toolCall of toolCalls) {
|
|
236
|
+
const toolResult = toolResults.get(toolCall.toolCallId);
|
|
237
|
+
handledToolCallIds.add(toolCall.toolCallId);
|
|
238
|
+
if (toolResult) {
|
|
239
|
+
parts.push({
|
|
240
|
+
type: "dynamic-tool",
|
|
241
|
+
toolName: toolCall.toolName,
|
|
242
|
+
toolCallId: toolCall.toolCallId,
|
|
243
|
+
input: toToolInput(toolCall.input),
|
|
244
|
+
state: "output-available",
|
|
245
|
+
output: toolResult.output,
|
|
246
|
+
});
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
parts.push({
|
|
250
|
+
type: "dynamic-tool",
|
|
251
|
+
toolName: toolCall.toolName,
|
|
252
|
+
toolCallId: toolCall.toolCallId,
|
|
253
|
+
input: toToolInput(toolCall.input),
|
|
254
|
+
state: "input-available",
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
for (const toolResult of toolResults.values()) {
|
|
258
|
+
if (handledToolCallIds.has(toolResult.toolCallId)) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
parts.push({
|
|
262
|
+
type: "dynamic-tool",
|
|
263
|
+
toolName: toolResult.toolName,
|
|
264
|
+
toolCallId: toolResult.toolCallId,
|
|
265
|
+
input: toToolInput(toolResult.input),
|
|
266
|
+
state: "output-available",
|
|
267
|
+
output: toolResult.output,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
const text = input.extractFinalStepText(input.step);
|
|
271
|
+
if (text.length > 0) {
|
|
272
|
+
parts.push({
|
|
273
|
+
type: "text",
|
|
274
|
+
text,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
return parts;
|
|
278
|
+
}
|
|
279
|
+
// --- Text diffing ---
|
|
280
|
+
function hasEquivalentTextPart(parts, text) {
|
|
281
|
+
const normalized = text.trim();
|
|
282
|
+
if (normalized.length === 0) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
return parts.some((part) => isRecord(part) && part.type === "text" && typeof part.text === "string" &&
|
|
286
|
+
part.text.trim() === normalized);
|
|
287
|
+
}
|
|
288
|
+
function collectExistingTextParts(parts) {
|
|
289
|
+
return parts.flatMap((part) => isRecord(part) && part.type === "text" && typeof part.text === "string" &&
|
|
290
|
+
part.text.trim().length > 0
|
|
291
|
+
? [part.text.trim()]
|
|
292
|
+
: []);
|
|
293
|
+
}
|
|
294
|
+
function extractMissingFallbackText(input) {
|
|
295
|
+
const finalText = input.extractFinalStepText(input.step);
|
|
296
|
+
if (finalText.length === 0 || hasEquivalentTextPart(input.parts, finalText)) {
|
|
297
|
+
return "";
|
|
298
|
+
}
|
|
299
|
+
const existingTexts = collectExistingTextParts(input.parts);
|
|
300
|
+
if (existingTexts.length === 0) {
|
|
301
|
+
return finalText;
|
|
302
|
+
}
|
|
303
|
+
const prefixCandidates = [
|
|
304
|
+
existingTexts.join("\n\n").trim(),
|
|
305
|
+
existingTexts.join("\n").trim(),
|
|
306
|
+
existingTexts.join("").trim(),
|
|
307
|
+
].filter((candidate) => candidate.length > 0);
|
|
308
|
+
const matchedPrefix = prefixCandidates
|
|
309
|
+
.filter((candidate) => finalText.startsWith(candidate))
|
|
310
|
+
.sort((left, right) => right.length - left.length)[0];
|
|
311
|
+
if (!matchedPrefix) {
|
|
312
|
+
return finalText;
|
|
313
|
+
}
|
|
314
|
+
return finalText.slice(matchedPrefix.length).replace(/^\s+/, "").trim();
|
|
315
|
+
}
|
|
316
|
+
function appendMissingFallbackTextPartFromInput(input) {
|
|
317
|
+
const text = extractMissingFallbackText(input);
|
|
318
|
+
if (text.length === 0) {
|
|
319
|
+
return [...input.parts];
|
|
320
|
+
}
|
|
321
|
+
return [
|
|
322
|
+
...input.parts,
|
|
323
|
+
{
|
|
324
|
+
type: "text",
|
|
325
|
+
text,
|
|
326
|
+
},
|
|
327
|
+
];
|
|
328
|
+
}
|
|
329
|
+
function buildMissingFallbackTextChunksFromInput(input) {
|
|
330
|
+
const text = extractMissingFallbackText(input);
|
|
331
|
+
if (text.length === 0) {
|
|
332
|
+
return [];
|
|
333
|
+
}
|
|
334
|
+
return [
|
|
335
|
+
{
|
|
336
|
+
type: "text-start",
|
|
337
|
+
id: input.messageId,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
type: "text-delta",
|
|
341
|
+
id: input.messageId,
|
|
342
|
+
delta: text,
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
type: "text-end",
|
|
346
|
+
id: input.messageId,
|
|
347
|
+
},
|
|
348
|
+
];
|
|
349
|
+
}
|
|
350
|
+
// --- Tool-chunk assembly ---
|
|
351
|
+
function createFallbackToolChunkState(state) {
|
|
352
|
+
return {
|
|
353
|
+
startedToolCallIds: state?.startedToolCallIds ?? new Set(),
|
|
354
|
+
inputAvailableToolCallIds: state?.inputAvailableToolCallIds ?? new Set(),
|
|
355
|
+
outputAvailableToolCallIds: state?.outputAvailableToolCallIds ?? new Set(),
|
|
356
|
+
outputErrorToolCallIds: state?.outputErrorToolCallIds ?? new Set(),
|
|
357
|
+
outputDeniedToolCallIds: state?.outputDeniedToolCallIds ?? new Set(),
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function buildToolChunkDescriptorsFromStep(input) {
|
|
361
|
+
const descriptors = [];
|
|
362
|
+
const toolCalls = input.extractFinalStepToolCalls(input.step);
|
|
363
|
+
const toolResults = new Map(input.extractFinalStepToolResults(input.step).map((toolResult) => [toolResult.toolCallId, toolResult]));
|
|
364
|
+
const handledToolCallIds = new Set();
|
|
365
|
+
for (const toolCall of toolCalls) {
|
|
366
|
+
const toolResult = toolResults.get(toolCall.toolCallId);
|
|
367
|
+
handledToolCallIds.add(toolCall.toolCallId);
|
|
368
|
+
descriptors.push({
|
|
369
|
+
toolCallId: toolCall.toolCallId,
|
|
370
|
+
toolName: toolCall.toolName,
|
|
371
|
+
input: toToolInput(toolCall.input),
|
|
372
|
+
outputState: toolResult ? "output-available" : "input-available",
|
|
373
|
+
...(toolResult ? { output: toolResult.output } : {}),
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
for (const toolResult of toolResults.values()) {
|
|
377
|
+
if (handledToolCallIds.has(toolResult.toolCallId)) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
descriptors.push({
|
|
381
|
+
toolCallId: toolResult.toolCallId,
|
|
382
|
+
toolName: toolResult.toolName,
|
|
383
|
+
input: toToolInput(toolResult.input),
|
|
384
|
+
outputState: "output-available",
|
|
385
|
+
output: toolResult.output,
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return descriptors;
|
|
389
|
+
}
|
|
390
|
+
function buildToolChunkDescriptorsFromParts(parts) {
|
|
391
|
+
const descriptors = [];
|
|
392
|
+
for (const part of parts) {
|
|
393
|
+
if (!isRecord(part)) {
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (part.type !== "dynamic-tool" && part.type !== "tool_call" && part.type !== "tool-call") {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
if (!("toolCallId" in part) || typeof part.toolCallId !== "string") {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
if (!("toolName" in part) || typeof part.toolName !== "string") {
|
|
403
|
+
continue;
|
|
404
|
+
}
|
|
405
|
+
if (!("input" in part) || !("state" in part) || typeof part.state !== "string") {
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
const toolCallId = part.toolCallId;
|
|
409
|
+
const toolName = part.toolName;
|
|
410
|
+
const input = toToolInput(part.input);
|
|
411
|
+
const state = part.state;
|
|
412
|
+
switch (state) {
|
|
413
|
+
case "pending":
|
|
414
|
+
case "input-streaming":
|
|
415
|
+
descriptors.push({ toolCallId, toolName, input, outputState: "started" });
|
|
416
|
+
break;
|
|
417
|
+
case "input-available":
|
|
418
|
+
case "approval-requested":
|
|
419
|
+
case "approval-responded":
|
|
420
|
+
descriptors.push({ toolCallId, toolName, input, outputState: "input-available" });
|
|
421
|
+
break;
|
|
422
|
+
case "output-available":
|
|
423
|
+
case "completed":
|
|
424
|
+
descriptors.push({
|
|
425
|
+
toolCallId,
|
|
426
|
+
toolName,
|
|
427
|
+
input,
|
|
428
|
+
outputState: "output-available",
|
|
429
|
+
output: "output" in part ? part.output : undefined,
|
|
430
|
+
});
|
|
431
|
+
break;
|
|
432
|
+
case "output-error":
|
|
433
|
+
case "error":
|
|
434
|
+
descriptors.push({
|
|
435
|
+
toolCallId,
|
|
436
|
+
toolName,
|
|
437
|
+
input,
|
|
438
|
+
outputState: "output-error",
|
|
439
|
+
...("errorText" in part && typeof part.errorText === "string"
|
|
440
|
+
? { errorText: part.errorText }
|
|
441
|
+
: {}),
|
|
442
|
+
});
|
|
443
|
+
break;
|
|
444
|
+
case "output-denied":
|
|
445
|
+
descriptors.push({ toolCallId, toolName, input, outputState: "output-denied" });
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
return descriptors;
|
|
450
|
+
}
|
|
451
|
+
function buildToolFallbackChunks(descriptors, state) {
|
|
452
|
+
const normalizedState = createFallbackToolChunkState(state);
|
|
453
|
+
const chunks = [];
|
|
454
|
+
for (const descriptor of descriptors) {
|
|
455
|
+
if (!normalizedState.startedToolCallIds.has(descriptor.toolCallId)) {
|
|
456
|
+
chunks.push({
|
|
457
|
+
type: "tool-input-start",
|
|
458
|
+
toolCallId: descriptor.toolCallId,
|
|
459
|
+
toolName: descriptor.toolName,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
if (descriptor.outputState !== "started" &&
|
|
463
|
+
!normalizedState.inputAvailableToolCallIds.has(descriptor.toolCallId)) {
|
|
464
|
+
chunks.push({
|
|
465
|
+
type: "tool-input-available",
|
|
466
|
+
toolCallId: descriptor.toolCallId,
|
|
467
|
+
toolName: descriptor.toolName,
|
|
468
|
+
input: descriptor.input,
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
switch (descriptor.outputState) {
|
|
472
|
+
case "output-available":
|
|
473
|
+
if (!normalizedState.outputAvailableToolCallIds.has(descriptor.toolCallId)) {
|
|
474
|
+
chunks.push({
|
|
475
|
+
type: "tool-output-available",
|
|
476
|
+
toolCallId: descriptor.toolCallId,
|
|
477
|
+
output: descriptor.output,
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
break;
|
|
481
|
+
case "output-error":
|
|
482
|
+
if (!normalizedState.outputErrorToolCallIds?.has(descriptor.toolCallId)) {
|
|
483
|
+
chunks.push({
|
|
484
|
+
type: "tool-output-error",
|
|
485
|
+
toolCallId: descriptor.toolCallId,
|
|
486
|
+
errorText: descriptor.errorText ?? "Tool execution failed",
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
break;
|
|
490
|
+
case "output-denied":
|
|
491
|
+
if (!normalizedState.outputDeniedToolCallIds?.has(descriptor.toolCallId)) {
|
|
492
|
+
chunks.push({
|
|
493
|
+
type: "tool-output-denied",
|
|
494
|
+
toolCallId: descriptor.toolCallId,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
return chunks;
|
|
501
|
+
}
|
|
502
|
+
function buildMissingFallbackToolChunksFromInput(input) {
|
|
503
|
+
return buildToolFallbackChunks(buildToolChunkDescriptorsFromStep({
|
|
504
|
+
step: input.step,
|
|
505
|
+
extractFinalStepToolCalls: input.extractFinalStepToolCalls,
|
|
506
|
+
extractFinalStepToolResults: input.extractFinalStepToolResults,
|
|
507
|
+
}), input.state);
|
|
508
|
+
}
|
|
509
|
+
function buildMissingFallbackToolChunksFromPartsFromInput(parts, state) {
|
|
510
|
+
return buildToolFallbackChunks(buildToolChunkDescriptorsFromParts(parts), state);
|
|
511
|
+
}
|
|
512
|
+
async function resolveStreamPromiseWithTimeout(promise, timeoutMs, fallback) {
|
|
513
|
+
let timeoutId = null;
|
|
514
|
+
try {
|
|
515
|
+
const resolved = await Promise.race([
|
|
516
|
+
Promise.resolve(promise),
|
|
517
|
+
new Promise((resolve) => {
|
|
518
|
+
timeoutId = dntShim.setTimeout(() => resolve(STREAM_PROMISE_TIMEOUT_TOKEN), timeoutMs);
|
|
519
|
+
}),
|
|
520
|
+
]);
|
|
521
|
+
if (resolved === STREAM_PROMISE_TIMEOUT_TOKEN) {
|
|
522
|
+
return fallback;
|
|
523
|
+
}
|
|
524
|
+
return resolved;
|
|
525
|
+
}
|
|
526
|
+
catch {
|
|
527
|
+
return fallback;
|
|
528
|
+
}
|
|
529
|
+
finally {
|
|
530
|
+
if (timeoutId) {
|
|
531
|
+
clearTimeout(timeoutId);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
export async function getLastStreamStep(result, timeoutMs = DEFAULT_STREAM_PROMISE_TIMEOUT_MS) {
|
|
536
|
+
const steps = await resolveStreamPromiseWithTimeout(result.steps, timeoutMs, []);
|
|
537
|
+
return steps.at(-1) ?? null;
|
|
538
|
+
}
|
|
539
|
+
export async function getStreamSteps(result, timeoutMs = DEFAULT_STREAM_PROMISE_TIMEOUT_MS) {
|
|
540
|
+
const steps = await resolveStreamPromiseWithTimeout(result.steps, timeoutMs, []);
|
|
541
|
+
return { steps, lastStep: steps.at(-1) ?? null };
|
|
542
|
+
}
|
|
543
|
+
export function extractFinalStepFinishReason(step) {
|
|
544
|
+
if (!isRecord(step) || typeof step.finishReason !== "string") {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
return step.finishReason;
|
|
548
|
+
}
|
|
549
|
+
export function extractFinalStepText(step) {
|
|
550
|
+
if (isRecord(step) && typeof step.text === "string" && step.text.trim().length > 0) {
|
|
551
|
+
return step.text.trim();
|
|
552
|
+
}
|
|
553
|
+
return extractTextFromResponseMessages(step);
|
|
554
|
+
}
|
|
555
|
+
export function extractFinalStepToolCalls(step) {
|
|
556
|
+
if (!isRecord(step) || !Array.isArray(step.toolCalls)) {
|
|
557
|
+
return [];
|
|
558
|
+
}
|
|
559
|
+
return step.toolCalls.flatMap((toolCall) => {
|
|
560
|
+
if (!isRecord(toolCall) || typeof toolCall.toolCallId !== "string" ||
|
|
561
|
+
typeof toolCall.toolName !== "string") {
|
|
562
|
+
return [];
|
|
563
|
+
}
|
|
564
|
+
return [
|
|
565
|
+
{
|
|
566
|
+
toolCallId: toolCall.toolCallId,
|
|
567
|
+
toolName: toolCall.toolName,
|
|
568
|
+
input: "input" in toolCall ? toolCall.input : {},
|
|
569
|
+
},
|
|
570
|
+
];
|
|
571
|
+
});
|
|
572
|
+
}
|
|
573
|
+
export function extractFinalStepToolResults(step) {
|
|
574
|
+
if (!isRecord(step) || !Array.isArray(step.toolResults)) {
|
|
575
|
+
return [];
|
|
576
|
+
}
|
|
577
|
+
const toolInputs = new Map(extractFinalStepToolCalls(step).map((toolCall) => [toolCall.toolCallId, toolCall.input]));
|
|
578
|
+
return step.toolResults.flatMap((toolResult) => {
|
|
579
|
+
if (!isRecord(toolResult) || typeof toolResult.toolCallId !== "string" ||
|
|
580
|
+
typeof toolResult.toolName !== "string") {
|
|
581
|
+
return [];
|
|
582
|
+
}
|
|
583
|
+
return [
|
|
584
|
+
{
|
|
585
|
+
toolCallId: toolResult.toolCallId,
|
|
586
|
+
toolName: toolResult.toolName,
|
|
587
|
+
input: "input" in toolResult
|
|
588
|
+
? toolResult.input
|
|
589
|
+
: (toolInputs.get(toolResult.toolCallId) ?? {}),
|
|
590
|
+
output: "output" in toolResult ? toolResult.output : null,
|
|
591
|
+
},
|
|
592
|
+
];
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
function parseFinalStepResponseBody(step) {
|
|
596
|
+
if (!isRecord(step) || !isRecord(step.response) || !("body" in step.response)) {
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
return step.response.body ?? null;
|
|
600
|
+
}
|
|
601
|
+
function parseProblemBody(body) {
|
|
602
|
+
const match = parseKnownProblemBody(body);
|
|
603
|
+
if (!match) {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
return { code: match.code, message: match.message };
|
|
607
|
+
}
|
|
608
|
+
export function extractFinalStepTerminalError(step) {
|
|
609
|
+
const responseBody = parseFinalStepResponseBody(step);
|
|
610
|
+
if (responseBody == null) {
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
if (typeof responseBody === "string") {
|
|
614
|
+
const parsedResponseBody = safeJsonParse(responseBody);
|
|
615
|
+
if (!parsedResponseBody.ok) {
|
|
616
|
+
return null;
|
|
617
|
+
}
|
|
618
|
+
return parseProblemBody(parsedResponseBody.value);
|
|
619
|
+
}
|
|
620
|
+
return parseProblemBody(responseBody);
|
|
621
|
+
}
|
|
622
|
+
export function buildFallbackUiMessageParts(step) {
|
|
623
|
+
return buildFallbackUiMessagePartsFromInput({
|
|
624
|
+
step,
|
|
625
|
+
extractFinalStepText,
|
|
626
|
+
extractFinalStepToolCalls,
|
|
627
|
+
extractFinalStepToolResults,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
export function appendMissingFallbackTextPart(parts, step) {
|
|
631
|
+
return appendMissingFallbackTextPartFromInput({
|
|
632
|
+
parts,
|
|
633
|
+
step,
|
|
634
|
+
extractFinalStepText,
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
export function buildFallbackUiMessageChunks(step, messageId) {
|
|
638
|
+
const chunks = buildMissingFallbackToolChunks(step);
|
|
639
|
+
const text = extractFinalStepText(step);
|
|
640
|
+
if (text.length > 0) {
|
|
641
|
+
chunks.push({
|
|
642
|
+
type: "text-start",
|
|
643
|
+
id: messageId,
|
|
644
|
+
});
|
|
645
|
+
chunks.push({
|
|
646
|
+
type: "text-delta",
|
|
647
|
+
id: messageId,
|
|
648
|
+
delta: text,
|
|
649
|
+
});
|
|
650
|
+
chunks.push({
|
|
651
|
+
type: "text-end",
|
|
652
|
+
id: messageId,
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
return chunks;
|
|
656
|
+
}
|
|
657
|
+
export function buildMissingFallbackToolChunks(step, state) {
|
|
658
|
+
return buildMissingFallbackToolChunksFromInput({
|
|
659
|
+
step,
|
|
660
|
+
state,
|
|
661
|
+
extractFinalStepToolCalls,
|
|
662
|
+
extractFinalStepToolResults,
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
export function buildMissingFallbackToolChunksFromParts(parts, state) {
|
|
666
|
+
if (parts.length === 0 && (!state || Object.keys(state).length === 0)) {
|
|
667
|
+
return [];
|
|
668
|
+
}
|
|
669
|
+
return buildMissingFallbackToolChunksFromPartsFromInput(parts, state);
|
|
670
|
+
}
|
|
671
|
+
export function buildMissingFallbackTextChunks(parts, step, messageId) {
|
|
672
|
+
return buildMissingFallbackTextChunksFromInput({
|
|
673
|
+
parts,
|
|
674
|
+
step,
|
|
675
|
+
messageId,
|
|
676
|
+
extractFinalStepText,
|
|
677
|
+
});
|
|
678
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface ParsedProviderError {
|
|
2
|
+
code: string;
|
|
3
|
+
message: string;
|
|
4
|
+
status?: number;
|
|
5
|
+
}
|
|
6
|
+
export type SafeJsonParseResult = {
|
|
7
|
+
ok: true;
|
|
8
|
+
value: unknown;
|
|
9
|
+
} | {
|
|
10
|
+
ok: false;
|
|
11
|
+
error: Error;
|
|
12
|
+
};
|
|
13
|
+
export declare function safeJsonParse(value: string): SafeJsonParseResult;
|
|
14
|
+
export declare function parseKnownProblemBody(body: unknown): ParsedProviderError | null;
|
|
15
|
+
export declare function isCreditLimitMessage(normalizedMessage: string): boolean;
|
|
16
|
+
export declare function parseProviderError(error: unknown): ParsedProviderError;
|
|
17
|
+
//# sourceMappingURL=provider-errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-errors.d.ts","sourceRoot":"","sources":["../../../src/src/chat/provider-errors.ts"],"names":[],"mappings":"AAAA,OAAO,yBAAyB,CAAC;AACjC,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAWD,MAAM,MAAM,mBAAmB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAE7F,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAMhE;AAOD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,GAAG,mBAAmB,GAAG,IAAI,CA0B/E;AAED,wBAAgB,oBAAoB,CAAC,iBAAiB,EAAE,MAAM,GAAG,OAAO,CAOvE;AAgFD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAEtE"}
|