@dexto/core 1.8.3 → 1.8.4
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/agent/DextoAgent.cjs +3 -1
- package/dist/agent/DextoAgent.d.ts +2 -0
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +7 -2
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/index.browser.cjs +6 -0
- package/dist/index.browser.d.ts +2 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +4 -0
- package/dist/llm/executor/provider-error.cjs +214 -0
- package/dist/llm/executor/provider-error.d.ts +26 -0
- package/dist/llm/executor/provider-error.d.ts.map +1 -0
- package/dist/llm/executor/provider-error.js +190 -0
- package/dist/llm/executor/stream-processor.cjs +34 -5
- package/dist/llm/executor/stream-processor.d.ts +4 -1
- package/dist/llm/executor/stream-processor.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.js +34 -5
- package/dist/llm/executor/turn-executor.cjs +185 -124
- package/dist/llm/executor/turn-executor.d.ts +5 -5
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +184 -120
- package/dist/session/title-generator.cjs +19 -2
- package/dist/session/title-generator.d.ts +8 -0
- package/dist/session/title-generator.d.ts.map +1 -1
- package/dist/session/title-generator.js +19 -2
- package/dist/systemPrompt/contributors.cjs +10 -1
- package/dist/systemPrompt/contributors.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.js +10 -1
- package/dist/telemetry/browser.cjs +138 -0
- package/dist/telemetry/browser.d.ts +30 -0
- package/dist/telemetry/browser.d.ts.map +1 -0
- package/dist/telemetry/browser.js +115 -0
- package/dist/telemetry/index.cjs +5 -2
- package/dist/telemetry/index.d.ts +1 -0
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +3 -1
- package/dist/telemetry/operation-span.cjs +73 -0
- package/dist/telemetry/operation-span.d.ts +13 -0
- package/dist/telemetry/operation-span.d.ts.map +1 -0
- package/dist/telemetry/operation-span.js +50 -0
- package/dist/telemetry/telemetry.cjs +2 -3
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/telemetry/telemetry.js +2 -3
- package/dist/telemetry/utils.cjs +11 -12
- package/dist/telemetry/utils.d.ts.map +1 -1
- package/dist/telemetry/utils.js +11 -12
- package/dist/tools/tool-call-metadata.cjs +118 -6
- package/dist/tools/tool-call-metadata.d.ts.map +1 -1
- package/dist/tools/tool-call-metadata.js +118 -6
- package/package.json +2 -2
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import "../../chunk-C6A6W6XS.js";
|
|
2
|
+
import { APICallError } from "ai";
|
|
3
|
+
import { DextoRuntimeError } from "../../errors/DextoRuntimeError.js";
|
|
4
|
+
import { ErrorScope, ErrorType } from "../../errors/types.js";
|
|
5
|
+
import { LLMErrorCode } from "../error-codes.js";
|
|
6
|
+
function isRecord(value) {
|
|
7
|
+
return typeof value === "object" && value !== null;
|
|
8
|
+
}
|
|
9
|
+
function parseJsonObject(value) {
|
|
10
|
+
if (isRecord(value)) return value;
|
|
11
|
+
if (typeof value !== "string") return null;
|
|
12
|
+
try {
|
|
13
|
+
const parsed = JSON.parse(value);
|
|
14
|
+
return isRecord(parsed) ? parsed : null;
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function readStringOrNumber(value) {
|
|
20
|
+
return typeof value === "string" || typeof value === "number" ? value : void 0;
|
|
21
|
+
}
|
|
22
|
+
function readString(value) {
|
|
23
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
24
|
+
}
|
|
25
|
+
function readRetryAfter(headers) {
|
|
26
|
+
const retryAfter = headers?.["retry-after"];
|
|
27
|
+
if (retryAfter === void 0) return void 0;
|
|
28
|
+
const value = Number(retryAfter);
|
|
29
|
+
return Number.isFinite(value) ? value : void 0;
|
|
30
|
+
}
|
|
31
|
+
function stringifyBody(value) {
|
|
32
|
+
if (typeof value === "string") return value;
|
|
33
|
+
if (value === void 0 || value === null) return void 0;
|
|
34
|
+
try {
|
|
35
|
+
return JSON.stringify(value);
|
|
36
|
+
} catch {
|
|
37
|
+
return String(value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function readErrorEnvelope(body) {
|
|
41
|
+
const error = body?.error;
|
|
42
|
+
return isRecord(error) ? error : null;
|
|
43
|
+
}
|
|
44
|
+
function addOpenRouterDetails(details, responseBody) {
|
|
45
|
+
const body = parseJsonObject(responseBody);
|
|
46
|
+
const errorEnvelope = readErrorEnvelope(body);
|
|
47
|
+
if (errorEnvelope === null) return;
|
|
48
|
+
const code = readStringOrNumber(errorEnvelope.code);
|
|
49
|
+
if (code !== void 0) details.openRouterErrorCode = code;
|
|
50
|
+
const message = readString(errorEnvelope.message);
|
|
51
|
+
if (message !== void 0) details.openRouterErrorMessage = message;
|
|
52
|
+
const metadata = isRecord(errorEnvelope.metadata) ? errorEnvelope.metadata : null;
|
|
53
|
+
if (metadata === null) return;
|
|
54
|
+
const providerName = readString(metadata.provider_name);
|
|
55
|
+
if (providerName !== void 0) details.openRouterProviderName = providerName;
|
|
56
|
+
if (Reflect.has(metadata, "raw")) {
|
|
57
|
+
details.openRouterProviderRaw = metadata.raw;
|
|
58
|
+
}
|
|
59
|
+
const rawObject = parseJsonObject(metadata.raw);
|
|
60
|
+
const rawError = readErrorEnvelope(rawObject);
|
|
61
|
+
const rawMessage = readString(rawError?.message);
|
|
62
|
+
if (rawMessage !== void 0) details.openRouterProviderRawMessage = rawMessage;
|
|
63
|
+
const rawParam = readString(rawError?.param);
|
|
64
|
+
if (rawParam !== void 0) details.openRouterProviderRawParam = rawParam;
|
|
65
|
+
const rawCode = readStringOrNumber(rawError?.code);
|
|
66
|
+
if (rawCode !== void 0) details.openRouterProviderRawCode = rawCode;
|
|
67
|
+
const previousErrors = metadata.previous_errors;
|
|
68
|
+
if (Array.isArray(previousErrors)) {
|
|
69
|
+
details.openRouterPreviousErrorCount = previousErrors.length;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function providerMessage(details, fallback) {
|
|
73
|
+
return details.openRouterProviderRawMessage ?? details.openRouterErrorMessage ?? details.responseBody ?? fallback;
|
|
74
|
+
}
|
|
75
|
+
function messageFromUnknown(value) {
|
|
76
|
+
return value instanceof Error ? value.message : String(value);
|
|
77
|
+
}
|
|
78
|
+
function isInvalidSchemaMessage(message) {
|
|
79
|
+
return message.includes("Invalid schema for function") || message.includes("invalid_function_parameters") || message.includes("schema must have type");
|
|
80
|
+
}
|
|
81
|
+
function readNumericField(value, field) {
|
|
82
|
+
if (!isRecord(value)) return void 0;
|
|
83
|
+
const fieldValue = value[field];
|
|
84
|
+
return typeof fieldValue === "number" && Number.isFinite(fieldValue) ? fieldValue : void 0;
|
|
85
|
+
}
|
|
86
|
+
function extractBalance(value) {
|
|
87
|
+
if (!isRecord(value)) return void 0;
|
|
88
|
+
const direct = readNumericField(value, "balance") ?? readNumericField(value, "balanceUsd") ?? readNumericField(value, "creditsUsd");
|
|
89
|
+
if (direct !== void 0) return direct;
|
|
90
|
+
for (const nested of Object.values(value)) {
|
|
91
|
+
const balance = extractBalance(nested);
|
|
92
|
+
if (balance !== void 0) return balance;
|
|
93
|
+
}
|
|
94
|
+
return void 0;
|
|
95
|
+
}
|
|
96
|
+
function errorTypeForStatus(status) {
|
|
97
|
+
if (status === 402) return ErrorType.PAYMENT_REQUIRED;
|
|
98
|
+
if (status === 403) return ErrorType.FORBIDDEN;
|
|
99
|
+
if (status === 408) return ErrorType.TIMEOUT;
|
|
100
|
+
if (status === 429) return ErrorType.RATE_LIMIT;
|
|
101
|
+
if (status !== void 0 && status >= 400 && status < 500) return ErrorType.USER;
|
|
102
|
+
return ErrorType.THIRD_PARTY;
|
|
103
|
+
}
|
|
104
|
+
function errorCodeForStatus(status, details) {
|
|
105
|
+
if (status === 402) return LLMErrorCode.INSUFFICIENT_CREDITS;
|
|
106
|
+
if (status === 429) return LLMErrorCode.RATE_LIMIT_EXCEEDED;
|
|
107
|
+
if (status === 400 && (details.openRouterProviderRawCode === "invalid_function_parameters" || isInvalidSchemaMessage(providerMessage(details, "")))) {
|
|
108
|
+
return LLMErrorCode.REQUEST_INVALID_SCHEMA;
|
|
109
|
+
}
|
|
110
|
+
return LLMErrorCode.GENERATION_FAILED;
|
|
111
|
+
}
|
|
112
|
+
function buildContext(input, details) {
|
|
113
|
+
return {
|
|
114
|
+
...input.sessionId === void 0 ? {} : { sessionId: input.sessionId },
|
|
115
|
+
provider: input.provider,
|
|
116
|
+
model: input.model,
|
|
117
|
+
...details
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function extractProviderErrorDetails(input) {
|
|
121
|
+
const details = {
|
|
122
|
+
provider: input.provider,
|
|
123
|
+
model: input.model
|
|
124
|
+
};
|
|
125
|
+
if (!APICallError.isInstance?.(input.error)) return details;
|
|
126
|
+
const responseHeaders = input.error.responseHeaders || {};
|
|
127
|
+
const responseBody = stringifyBody(input.error.responseBody);
|
|
128
|
+
if (input.error.statusCode !== void 0) details.statusCode = input.error.statusCode;
|
|
129
|
+
const retryAfter = readRetryAfter(responseHeaders);
|
|
130
|
+
if (retryAfter !== void 0) details.retryAfter = retryAfter;
|
|
131
|
+
if (responseBody !== void 0) details.responseBody = responseBody;
|
|
132
|
+
if (input.error.url !== void 0) details.url = input.error.url;
|
|
133
|
+
details.isRetryable = input.error.isRetryable;
|
|
134
|
+
if (responseBody !== void 0) {
|
|
135
|
+
addOpenRouterDetails(details, responseBody);
|
|
136
|
+
}
|
|
137
|
+
return details;
|
|
138
|
+
}
|
|
139
|
+
function mapProviderError(input) {
|
|
140
|
+
if (input.error instanceof DextoRuntimeError) return input.error;
|
|
141
|
+
if (!APICallError.isInstance?.(input.error)) {
|
|
142
|
+
const message2 = messageFromUnknown(input.error);
|
|
143
|
+
if (isInvalidSchemaMessage(message2)) {
|
|
144
|
+
return new DextoRuntimeError(
|
|
145
|
+
LLMErrorCode.REQUEST_INVALID_SCHEMA,
|
|
146
|
+
ErrorScope.LLM,
|
|
147
|
+
ErrorType.USER,
|
|
148
|
+
message2,
|
|
149
|
+
buildContext(input, extractProviderErrorDetails(input))
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return new DextoRuntimeError(
|
|
153
|
+
LLMErrorCode.GENERATION_FAILED,
|
|
154
|
+
ErrorScope.LLM,
|
|
155
|
+
ErrorType.THIRD_PARTY,
|
|
156
|
+
message2,
|
|
157
|
+
buildContext(input, extractProviderErrorDetails(input))
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
const details = extractProviderErrorDetails(input);
|
|
161
|
+
const status = input.error.statusCode;
|
|
162
|
+
const message = providerMessage(details, input.error.message);
|
|
163
|
+
const code = errorCodeForStatus(status, details);
|
|
164
|
+
const type = errorTypeForStatus(status);
|
|
165
|
+
if (status === 402) {
|
|
166
|
+
const balance = extractBalance(parseJsonObject(details.responseBody));
|
|
167
|
+
return new DextoRuntimeError(
|
|
168
|
+
code,
|
|
169
|
+
ErrorScope.LLM,
|
|
170
|
+
type,
|
|
171
|
+
`Insufficient Dexto credits. Balance: ${balance === void 0 ? "low" : `$${balance.toFixed(2)}`}`,
|
|
172
|
+
{
|
|
173
|
+
...buildContext(input, details),
|
|
174
|
+
...balance === void 0 ? {} : { balance }
|
|
175
|
+
},
|
|
176
|
+
"Run `dexto billing` to check your balance"
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return new DextoRuntimeError(
|
|
180
|
+
code,
|
|
181
|
+
ErrorScope.LLM,
|
|
182
|
+
type,
|
|
183
|
+
status === void 0 ? message : `Provider error ${status}: ${message}`,
|
|
184
|
+
buildContext(input, details)
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
export {
|
|
188
|
+
extractProviderErrorDetails,
|
|
189
|
+
mapProviderError
|
|
190
|
+
};
|
|
@@ -23,6 +23,7 @@ __export(stream_processor_exports, {
|
|
|
23
23
|
module.exports = __toCommonJS(stream_processor_exports);
|
|
24
24
|
var import_types2 = require("../../logger/v2/types.js");
|
|
25
25
|
var import_usage_metadata = require("../usage-metadata.js");
|
|
26
|
+
var import_provider_error = require("./provider-error.js");
|
|
26
27
|
function finiteUsageCount(value) {
|
|
27
28
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
28
29
|
}
|
|
@@ -34,13 +35,16 @@ class StreamProcessor {
|
|
|
34
35
|
* @param config Provider/model configuration
|
|
35
36
|
* @param logger Logger instance
|
|
36
37
|
* @param streaming If true, emits llm:chunk events. Default true.
|
|
38
|
+
* @param emitFatalErrors If true, emits terminal llm:error events. TurnExecutor owns
|
|
39
|
+
* terminal run errors and disables this to avoid duplicate events.
|
|
37
40
|
*/
|
|
38
|
-
constructor(contextManager, eventBus, abortSignal, config, logger, streaming = true) {
|
|
41
|
+
constructor(contextManager, eventBus, abortSignal, config, logger, streaming = true, emitFatalErrors = true) {
|
|
39
42
|
this.contextManager = contextManager;
|
|
40
43
|
this.eventBus = eventBus;
|
|
41
44
|
this.abortSignal = abortSignal;
|
|
42
45
|
this.config = config;
|
|
43
46
|
this.streaming = streaming;
|
|
47
|
+
this.emitFatalErrors = emitFatalErrors;
|
|
44
48
|
this.logger = logger.createChild(import_types2.DextoLogComponent.EXECUTOR);
|
|
45
49
|
this.usageScopeId = config.usageScopeId;
|
|
46
50
|
}
|
|
@@ -267,9 +271,13 @@ class StreamProcessor {
|
|
|
267
271
|
break;
|
|
268
272
|
}
|
|
269
273
|
case "error": {
|
|
270
|
-
const err =
|
|
274
|
+
const err = (0, import_provider_error.mapProviderError)({
|
|
275
|
+
error: event.error,
|
|
276
|
+
provider: this.config.provider,
|
|
277
|
+
model: this.config.model
|
|
278
|
+
});
|
|
271
279
|
await this.persistFailedToolResults(err.message);
|
|
272
|
-
throw
|
|
280
|
+
throw event.error;
|
|
273
281
|
}
|
|
274
282
|
case "abort": {
|
|
275
283
|
this.logger.debug("Stream aborted, emitting partial response");
|
|
@@ -325,8 +333,29 @@ class StreamProcessor {
|
|
|
325
333
|
toolCalls: this.modelToolCalls
|
|
326
334
|
};
|
|
327
335
|
}
|
|
328
|
-
|
|
329
|
-
|
|
336
|
+
const mappedError = (0, import_provider_error.mapProviderError)({
|
|
337
|
+
error,
|
|
338
|
+
provider: this.config.provider,
|
|
339
|
+
model: this.config.model
|
|
340
|
+
});
|
|
341
|
+
if (!this.emitFatalErrors) {
|
|
342
|
+
this.logger.error("Stream processing failed", { error: mappedError });
|
|
343
|
+
throw error;
|
|
344
|
+
}
|
|
345
|
+
if (this.emitFatalErrors) {
|
|
346
|
+
this.eventBus.emit("llm:error", {
|
|
347
|
+
error: mappedError,
|
|
348
|
+
context: "StreamProcessor",
|
|
349
|
+
recoverable: false,
|
|
350
|
+
details: (0, import_provider_error.extractProviderErrorDetails)({
|
|
351
|
+
error,
|
|
352
|
+
provider: this.config.provider,
|
|
353
|
+
model: this.config.model
|
|
354
|
+
})
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
this.logger.error("Stream processing failed", { error: mappedError });
|
|
358
|
+
throw mappedError;
|
|
330
359
|
}
|
|
331
360
|
return {
|
|
332
361
|
text: this.accumulatedText,
|
|
@@ -21,6 +21,7 @@ export declare class StreamProcessor {
|
|
|
21
21
|
private abortSignal;
|
|
22
22
|
private config;
|
|
23
23
|
private streaming;
|
|
24
|
+
private emitFatalErrors;
|
|
24
25
|
private assistantMessageId;
|
|
25
26
|
private actualTokens;
|
|
26
27
|
private finishReason;
|
|
@@ -44,8 +45,10 @@ export declare class StreamProcessor {
|
|
|
44
45
|
* @param config Provider/model configuration
|
|
45
46
|
* @param logger Logger instance
|
|
46
47
|
* @param streaming If true, emits llm:chunk events. Default true.
|
|
48
|
+
* @param emitFatalErrors If true, emits terminal llm:error events. TurnExecutor owns
|
|
49
|
+
* terminal run errors and disables this to avoid duplicate events.
|
|
47
50
|
*/
|
|
48
|
-
constructor(contextManager: ContextManager, eventBus: SessionEventBus, abortSignal: AbortSignal, config: StreamProcessorConfig, logger: Logger, streaming?: boolean);
|
|
51
|
+
constructor(contextManager: ContextManager, eventBus: SessionEventBus, abortSignal: AbortSignal, config: StreamProcessorConfig, logger: Logger, streaming?: boolean, emitFatalErrors?: boolean);
|
|
49
52
|
process(streamFn: () => StreamTextResult<VercelToolSet, unknown>): Promise<StreamProcessorResult>;
|
|
50
53
|
private getCacheTokensFromProviderMetadata;
|
|
51
54
|
private normalizeUsage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-processor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/stream-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,IAAI,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAKvD,OAAO,KAAK,EAAE,WAAW,EAAoB,gBAAgB,EAAc,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"stream-processor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/stream-processor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,IAAI,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAmB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAKvD,OAAO,KAAK,EAAE,WAAW,EAAoB,gBAAgB,EAAc,MAAM,YAAY,CAAC;AAiD9F,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,WAAW,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,qBAAa,eAAe;IA6BpB,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAEd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,eAAe;IAlC3B,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,YAAY,CAAmE;IACvF,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,iBAAiB,CAAsC;IAC/D,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;IAClD,OAAO,CAAC,cAAc,CAAuB;IAC7C;;;OAGG;IACH,OAAO,CAAC,gBAAgB,CAAgD;IACxE,OAAO,CAAC,gBAAgB,CAAkE;IAE1F;;;;;;;;;OASG;gBAES,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,eAAe,EACzB,WAAW,EAAE,WAAW,EACxB,MAAM,EAAE,qBAAqB,EACrC,MAAM,EAAE,MAAM,EACN,SAAS,GAAE,OAAc,EACzB,eAAe,GAAE,OAAc;IAMrC,OAAO,CACT,QAAQ,EAAE,MAAM,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,GACzD,OAAO,CAAC,qBAAqB,CAAC;IAwZjC,OAAO,CAAC,kCAAkC;IAoB1C,OAAO,CAAC,cAAc;IA4CtB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,0BAA0B;IAclC,OAAO,CAAC,eAAe;YA8BT,gCAAgC;IA0B9C,OAAO,CAAC,sBAAsB;YAwChB,sBAAsB;YAKtB,gBAAgB;IAO9B;;;;OAIG;YACW,2BAA2B;IAQzC;;OAEG;YACW,wBAAwB;YAQxB,yBAAyB;CAuC1C"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import "../../chunk-C6A6W6XS.js";
|
|
2
2
|
import { DextoLogComponent } from "../../logger/v2/types.js";
|
|
3
3
|
import { getUsagePricingMetadata } from "../usage-metadata.js";
|
|
4
|
+
import { extractProviderErrorDetails, mapProviderError } from "./provider-error.js";
|
|
4
5
|
function finiteUsageCount(value) {
|
|
5
6
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
6
7
|
}
|
|
@@ -12,13 +13,16 @@ class StreamProcessor {
|
|
|
12
13
|
* @param config Provider/model configuration
|
|
13
14
|
* @param logger Logger instance
|
|
14
15
|
* @param streaming If true, emits llm:chunk events. Default true.
|
|
16
|
+
* @param emitFatalErrors If true, emits terminal llm:error events. TurnExecutor owns
|
|
17
|
+
* terminal run errors and disables this to avoid duplicate events.
|
|
15
18
|
*/
|
|
16
|
-
constructor(contextManager, eventBus, abortSignal, config, logger, streaming = true) {
|
|
19
|
+
constructor(contextManager, eventBus, abortSignal, config, logger, streaming = true, emitFatalErrors = true) {
|
|
17
20
|
this.contextManager = contextManager;
|
|
18
21
|
this.eventBus = eventBus;
|
|
19
22
|
this.abortSignal = abortSignal;
|
|
20
23
|
this.config = config;
|
|
21
24
|
this.streaming = streaming;
|
|
25
|
+
this.emitFatalErrors = emitFatalErrors;
|
|
22
26
|
this.logger = logger.createChild(DextoLogComponent.EXECUTOR);
|
|
23
27
|
this.usageScopeId = config.usageScopeId;
|
|
24
28
|
}
|
|
@@ -245,9 +249,13 @@ class StreamProcessor {
|
|
|
245
249
|
break;
|
|
246
250
|
}
|
|
247
251
|
case "error": {
|
|
248
|
-
const err =
|
|
252
|
+
const err = mapProviderError({
|
|
253
|
+
error: event.error,
|
|
254
|
+
provider: this.config.provider,
|
|
255
|
+
model: this.config.model
|
|
256
|
+
});
|
|
249
257
|
await this.persistFailedToolResults(err.message);
|
|
250
|
-
throw
|
|
258
|
+
throw event.error;
|
|
251
259
|
}
|
|
252
260
|
case "abort": {
|
|
253
261
|
this.logger.debug("Stream aborted, emitting partial response");
|
|
@@ -303,8 +311,29 @@ class StreamProcessor {
|
|
|
303
311
|
toolCalls: this.modelToolCalls
|
|
304
312
|
};
|
|
305
313
|
}
|
|
306
|
-
|
|
307
|
-
|
|
314
|
+
const mappedError = mapProviderError({
|
|
315
|
+
error,
|
|
316
|
+
provider: this.config.provider,
|
|
317
|
+
model: this.config.model
|
|
318
|
+
});
|
|
319
|
+
if (!this.emitFatalErrors) {
|
|
320
|
+
this.logger.error("Stream processing failed", { error: mappedError });
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
if (this.emitFatalErrors) {
|
|
324
|
+
this.eventBus.emit("llm:error", {
|
|
325
|
+
error: mappedError,
|
|
326
|
+
context: "StreamProcessor",
|
|
327
|
+
recoverable: false,
|
|
328
|
+
details: extractProviderErrorDetails({
|
|
329
|
+
error,
|
|
330
|
+
provider: this.config.provider,
|
|
331
|
+
model: this.config.model
|
|
332
|
+
})
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
this.logger.error("Stream processing failed", { error: mappedError });
|
|
336
|
+
throw mappedError;
|
|
308
337
|
}
|
|
309
338
|
return {
|
|
310
339
|
text: this.accumulatedText,
|