@openclaw/ai 2026.7.2-beta.2 → 2026.7.2-beta.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/README.md +6 -5
- package/dist/{anthropic-BIRSg5x9.mjs → anthropic-CrUDIBpM.mjs} +173 -47
- package/dist/{api-registry-Byvoz8Ha.d.mts → api-registry-BMphkFf1.d.mts} +1 -2
- package/dist/{azure-openai-responses-CHi7Wo4A.mjs → azure-openai-responses-CbrpVeEv.mjs} +9 -11
- package/dist/{env-api-keys-DnhYpc27.mjs → env-api-keys-DrgeBuva.mjs} +1 -1
- package/dist/{event-stream-uQspnL8S.d.mts → event-stream-Douf9dob.d.mts} +1 -1
- package/dist/event-stream.d.mts +1 -1
- package/dist/{google-BmsqsNwR.mjs → google-Cs62KA7t.mjs} +4 -4
- package/dist/{google-shared-Dx2aba47.mjs → google-shared-CMLI-tCZ.mjs} +4 -3
- package/dist/{google-vertex-HZ_0rTwS.mjs → google-vertex-B4SD3U0f.mjs} +3 -3
- package/dist/host-WvWBo4h8.d.mts +173 -0
- package/dist/host-XYGZcgO8.mjs +98 -0
- package/dist/index-BVVgDSdq.d.mts +1 -0
- package/dist/index.d.mts +7 -50
- package/dist/index.mjs +1 -1
- package/dist/internal/anthropic.d.mts +9 -3
- package/dist/internal/anthropic.mjs +3 -3
- package/dist/internal/openai.d.mts +2 -279
- package/dist/internal/openai.mjs +5 -5
- package/dist/internal/runtime.d.mts +8 -5
- package/dist/internal/runtime.mjs +22 -12
- package/dist/internal/shared.d.mts +4 -2
- package/dist/internal/shared.mjs +2 -2
- package/dist/{mistral-DxMPt9q9.mjs → mistral-D5Ps7Led.mjs} +26 -10
- package/dist/{model-utils-Q1LSRIdo.mjs → model-utils-1GiZ2_rr.mjs} +3 -1
- package/dist/openai-CoGicoDt.d.mts +332 -0
- package/dist/{openai-chatgpt-responses-BuH2NvsR.mjs → openai-chatgpt-responses-h0o5yV8Y.mjs} +47 -48
- package/dist/{openai-completions-DPR_O2RW.mjs → openai-completions-exO8NFQf.mjs} +342 -102
- package/dist/{openai-responses-Cov-Vdc2.mjs → openai-responses-BHpmtUKo.mjs} +5 -5
- package/dist/{openai-responses-shared-Befb4D6R.mjs → openai-responses-shared-CzCurmY1.mjs} +527 -268
- package/dist/{openai-tool-projection-CFqm42J2.mjs → openai-tool-projection-ITOU9bG1.mjs} +1 -1
- package/dist/provider-error-C4VvV_3t.mjs +41 -0
- package/dist/providers.d.mts +1 -1
- package/dist/providers.mjs +8 -8
- package/dist/{stream-first-event-timeout-RjWszj8c.mjs → stream-first-event-timeout-DP4xEyBY.mjs} +45 -1
- package/dist/{transform-messages-BmS70CP5.mjs → system-prompt-cache-boundary-CbHeV4_l.mjs} +171 -161
- package/dist/transports.d.mts +590 -0
- package/dist/transports.mjs +5701 -0
- package/dist/{types-Cx2zJtyz.d.mts → types-AFwwWium.d.mts} +7 -0
- package/dist/types.d.mts +4 -4
- package/dist/{validation-Cej7htKc.d.mts → validation-sxvxC8J-.d.mts} +1 -1
- package/dist/validation.d.mts +1 -1
- package/npm-shrinkwrap.json +43 -50
- package/package.json +36 -10
- package/dist/host-4t713IeR.mjs +0 -37
- /package/dist/{index-BoTnz8cv.d.mts → anthropic-BoTnz8cv.d.mts} +0 -0
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { n as getAiTransportHost } from "./host-
|
|
2
|
-
import {
|
|
1
|
+
import { n as getAiTransportHost } from "./host-XYGZcgO8.mjs";
|
|
2
|
+
import { C as isImageWithMediaPayload, T as isRecord, _ as normalizeOptionalString, a as stripSystemPromptCacheBoundary, c as transformMessages, g as normalizeLowercaseStringOrEmpty, x as extractToolResultText, y as describeToolResultMediaPlaceholder } from "./system-prompt-cache-boundary-CbHeV4_l.mjs";
|
|
3
|
+
import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
|
|
4
|
+
import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-1GiZ2_rr.mjs";
|
|
3
5
|
import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
|
|
4
6
|
import { n as parseStreamingJson } from "./json-parse-BvXNt1-7.mjs";
|
|
5
|
-
import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
|
|
6
|
-
import { C as stripSystemPromptCacheBoundary, D as normalizeOptionalString, E as normalizeLowercaseStringOrEmpty, d as isRecord, i as extractToolResultText, n as describeToolResultMediaPlaceholder, o as isImageWithMediaPayload, t as transformMessages } from "./transform-messages-BmS70CP5.mjs";
|
|
7
|
-
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-RjWszj8c.mjs";
|
|
8
|
-
import { t as projectOpenAITools } from "./openai-tool-projection-CFqm42J2.mjs";
|
|
9
7
|
import { t as shortHash } from "./hash-CHgqbJmD.mjs";
|
|
8
|
+
import { a as withFirstStreamEventTimeout, i as getFirstStreamEventTimeoutMs, r as getFirstStreamEventTimeoutHandler, t as createFirstStreamEventAbortController } from "./stream-first-event-timeout-DP4xEyBY.mjs";
|
|
9
|
+
import { t as projectOpenAITools } from "./openai-tool-projection-ITOU9bG1.mjs";
|
|
10
10
|
import { createHash, randomUUID } from "node:crypto";
|
|
11
11
|
//#region packages/normalization-core/src/string-normalization.ts
|
|
12
12
|
/** Coerces entries to strings, trims them, and drops empty results. */
|
|
@@ -1076,6 +1076,66 @@ function resolveResponsesMessageSnapshotCollapse(params) {
|
|
|
1076
1076
|
return { kind: "keep" };
|
|
1077
1077
|
}
|
|
1078
1078
|
//#endregion
|
|
1079
|
+
//#region packages/ai/src/providers/openai-responses-terminal-usage.ts
|
|
1080
|
+
function readCount(value) {
|
|
1081
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
1082
|
+
}
|
|
1083
|
+
/**
|
|
1084
|
+
* Split a terminal usage payload into the priced buckets.
|
|
1085
|
+
*
|
|
1086
|
+
* OpenAI includes cache reads and writes in `input_tokens`, so both are subtracted out of the
|
|
1087
|
+
* billable input bucket. `total_tokens` comes from the payload, but never below the sum of the
|
|
1088
|
+
* split buckets: proxies routinely omit it (reporting 0 would understate the turn), and a payload
|
|
1089
|
+
* whose `cached_tokens` exceeds `input_tokens` clamps the input bucket, leaving the reported total
|
|
1090
|
+
* short of what the buckets actually price.
|
|
1091
|
+
*/
|
|
1092
|
+
function mapResponsesTerminalUsage(usage) {
|
|
1093
|
+
if (!usage) return;
|
|
1094
|
+
const cacheRead = readCount(usage.input_tokens_details?.cached_tokens);
|
|
1095
|
+
const cacheWrite = readCount(usage.input_tokens_details?.cache_write_tokens);
|
|
1096
|
+
const input = Math.max(0, readCount(usage.input_tokens) - cacheRead - cacheWrite);
|
|
1097
|
+
const output = readCount(usage.output_tokens);
|
|
1098
|
+
const bucketTotal = input + output + cacheRead + cacheWrite;
|
|
1099
|
+
return {
|
|
1100
|
+
input,
|
|
1101
|
+
output,
|
|
1102
|
+
cacheRead,
|
|
1103
|
+
cacheWrite,
|
|
1104
|
+
totalTokens: Math.max(bucketTotal, readCount(usage.total_tokens))
|
|
1105
|
+
};
|
|
1106
|
+
}
|
|
1107
|
+
/** Reasoning tokens are reported by the agent path only; the package path does not track them. */
|
|
1108
|
+
function readResponsesReasoningTokens(usage) {
|
|
1109
|
+
const reasoningTokens = usage?.output_tokens_details?.reasoning_tokens;
|
|
1110
|
+
return typeof reasoningTokens === "number" && Number.isFinite(reasoningTokens) ? reasoningTokens : void 0;
|
|
1111
|
+
}
|
|
1112
|
+
function mapResponsesTerminalStopReason(status) {
|
|
1113
|
+
if (!status) return "stop";
|
|
1114
|
+
switch (status) {
|
|
1115
|
+
case "completed": return "stop";
|
|
1116
|
+
case "incomplete": return "length";
|
|
1117
|
+
case "failed":
|
|
1118
|
+
case "cancelled": return "error";
|
|
1119
|
+
case "in_progress":
|
|
1120
|
+
case "queued": return "stop";
|
|
1121
|
+
default: throw new Error(`Unhandled stop reason: ${String(status)}`);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* Resolve the terminal stop reason, including the two overrides every Responses path shares: a
|
|
1126
|
+
* content-filtered turn is a provider error rather than a truncated answer, and a turn that
|
|
1127
|
+
* produced tool calls reports `toolUse` instead of a plain stop.
|
|
1128
|
+
*/
|
|
1129
|
+
function resolveResponsesTerminalStopReason(params) {
|
|
1130
|
+
if (params.status === "incomplete" && params.incompleteReason === "content_filter") return {
|
|
1131
|
+
stopReason: "error",
|
|
1132
|
+
errorMessage: "Provider incomplete_reason: content_filter"
|
|
1133
|
+
};
|
|
1134
|
+
const stopReason = mapResponsesTerminalStopReason(params.status);
|
|
1135
|
+
if (stopReason === "stop" && params.hasToolCall) return { stopReason: "toolUse" };
|
|
1136
|
+
return { stopReason };
|
|
1137
|
+
}
|
|
1138
|
+
//#endregion
|
|
1079
1139
|
//#region packages/ai/src/providers/openai-responses-tool-call-tracker.ts
|
|
1080
1140
|
function readIdentityValue(value) {
|
|
1081
1141
|
return (typeof value === "string" ? value.trim() : "") || void 0;
|
|
@@ -1152,6 +1212,151 @@ function createResponsesToolCallTracker() {
|
|
|
1152
1212
|
};
|
|
1153
1213
|
}
|
|
1154
1214
|
//#endregion
|
|
1215
|
+
//#region packages/ai/src/providers/openai-tool-schema-compat.ts
|
|
1216
|
+
const OPENAI_STRICT_COMPAT_SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
|
|
1217
|
+
"$defs",
|
|
1218
|
+
"definitions",
|
|
1219
|
+
"dependentSchemas",
|
|
1220
|
+
"dependencies",
|
|
1221
|
+
"patternProperties",
|
|
1222
|
+
"properties"
|
|
1223
|
+
]);
|
|
1224
|
+
const OPENAI_NULLABLE_ANNOTATION_KEYS = /* @__PURE__ */ new Set([
|
|
1225
|
+
"default",
|
|
1226
|
+
"description",
|
|
1227
|
+
"examples",
|
|
1228
|
+
"format",
|
|
1229
|
+
"title"
|
|
1230
|
+
]);
|
|
1231
|
+
const OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS = /* @__PURE__ */ new Set([
|
|
1232
|
+
"additionalItems",
|
|
1233
|
+
"additionalProperties",
|
|
1234
|
+
"allOf",
|
|
1235
|
+
"anyOf",
|
|
1236
|
+
"contains",
|
|
1237
|
+
"contentSchema",
|
|
1238
|
+
"else",
|
|
1239
|
+
"if",
|
|
1240
|
+
"items",
|
|
1241
|
+
"not",
|
|
1242
|
+
"oneOf",
|
|
1243
|
+
"prefixItems",
|
|
1244
|
+
"propertyNames",
|
|
1245
|
+
"then",
|
|
1246
|
+
"unevaluatedItems",
|
|
1247
|
+
"unevaluatedProperties"
|
|
1248
|
+
]);
|
|
1249
|
+
function normalizeOpenAIStrictCompatSchemaMap(schema) {
|
|
1250
|
+
if (!schema || typeof schema !== "object" || Array.isArray(schema)) return schema;
|
|
1251
|
+
let changed = false;
|
|
1252
|
+
const normalized = {};
|
|
1253
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
1254
|
+
const next = normalizeOpenAIStrictCompatSchemaRecursive(value, { promoteEmptyObject: false });
|
|
1255
|
+
normalized[key] = next;
|
|
1256
|
+
changed ||= next !== value;
|
|
1257
|
+
}
|
|
1258
|
+
return changed ? normalized : schema;
|
|
1259
|
+
}
|
|
1260
|
+
function normalizeOpenAIStrictCompatSchemaRecursive(schema, options) {
|
|
1261
|
+
if (Array.isArray(schema)) {
|
|
1262
|
+
let changed = false;
|
|
1263
|
+
const normalized = schema.map((entry) => {
|
|
1264
|
+
const next = normalizeOpenAIStrictCompatSchemaRecursive(entry, { promoteEmptyObject: false });
|
|
1265
|
+
changed ||= next !== entry;
|
|
1266
|
+
return next;
|
|
1267
|
+
});
|
|
1268
|
+
return changed ? normalized : schema;
|
|
1269
|
+
}
|
|
1270
|
+
if (!schema || typeof schema !== "object") return schema;
|
|
1271
|
+
const record = schema;
|
|
1272
|
+
let changed = false;
|
|
1273
|
+
let hadNullType = false;
|
|
1274
|
+
const normalized = {};
|
|
1275
|
+
for (const [key, value] of Object.entries(record)) {
|
|
1276
|
+
if (value === null && OPENAI_NULLABLE_ANNOTATION_KEYS.has(key)) {
|
|
1277
|
+
changed = true;
|
|
1278
|
+
continue;
|
|
1279
|
+
}
|
|
1280
|
+
if (value === null && key === "type") {
|
|
1281
|
+
hadNullType = true;
|
|
1282
|
+
changed = true;
|
|
1283
|
+
continue;
|
|
1284
|
+
}
|
|
1285
|
+
const next = OPENAI_STRICT_COMPAT_SCHEMA_MAP_KEYS.has(key) ? normalizeOpenAIStrictCompatSchemaMap(value) : OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS.has(key) ? normalizeOpenAIStrictCompatSchemaRecursive(value, { promoteEmptyObject: false }) : value;
|
|
1286
|
+
normalized[key] = next;
|
|
1287
|
+
changed ||= next !== value;
|
|
1288
|
+
}
|
|
1289
|
+
if (Object.keys(normalized).length === 0) {
|
|
1290
|
+
if (!options.promoteEmptyObject) return schema;
|
|
1291
|
+
return {
|
|
1292
|
+
type: "object",
|
|
1293
|
+
properties: {},
|
|
1294
|
+
required: [],
|
|
1295
|
+
additionalProperties: false
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
const hasObjectShapeHints = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) || Array.isArray(normalized.required);
|
|
1299
|
+
const hasArrayShapeHints = "items" in normalized;
|
|
1300
|
+
if (!("type" in normalized) && hasObjectShapeHints !== hasArrayShapeHints) {
|
|
1301
|
+
normalized.type = hasObjectShapeHints ? "object" : "array";
|
|
1302
|
+
changed = true;
|
|
1303
|
+
} else if (hadNullType && !("type" in normalized)) normalized.type = null;
|
|
1304
|
+
if (normalized.type === "object" && !("properties" in normalized)) {
|
|
1305
|
+
normalized.properties = {};
|
|
1306
|
+
changed = true;
|
|
1307
|
+
}
|
|
1308
|
+
const hasEmptyProperties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) && Object.keys(normalized.properties).length === 0;
|
|
1309
|
+
if (normalized.type === "object" && !Array.isArray(normalized.required) && hasEmptyProperties) {
|
|
1310
|
+
normalized.required = [];
|
|
1311
|
+
changed = true;
|
|
1312
|
+
}
|
|
1313
|
+
if (normalized.type === "object" && hasEmptyProperties && !("additionalProperties" in normalized)) {
|
|
1314
|
+
normalized.additionalProperties = false;
|
|
1315
|
+
changed = true;
|
|
1316
|
+
}
|
|
1317
|
+
return changed ? normalized : schema;
|
|
1318
|
+
}
|
|
1319
|
+
/** Repairs recoverable OpenAI tool-schema shapes before canonical normalization. */
|
|
1320
|
+
function normalizeOpenAIStrictCompatSchema(schema) {
|
|
1321
|
+
return normalizeOpenAIStrictCompatSchemaRecursive(schema, { promoteEmptyObject: true });
|
|
1322
|
+
}
|
|
1323
|
+
/** Finds schema paths that violate OpenAI strict tool-schema requirements. */
|
|
1324
|
+
function findOpenAIStrictSchemaViolations(schema, path, options) {
|
|
1325
|
+
if (Array.isArray(schema)) {
|
|
1326
|
+
if (options?.requireObjectRoot) return [`${path}.type`];
|
|
1327
|
+
return schema.flatMap((item, index) => findOpenAIStrictSchemaViolations(item, `${path}[${index}]`));
|
|
1328
|
+
}
|
|
1329
|
+
if (!schema || typeof schema !== "object") return options?.requireObjectRoot ? [`${path}.type`] : [];
|
|
1330
|
+
const record = schema;
|
|
1331
|
+
const violations = [];
|
|
1332
|
+
for (const key of [
|
|
1333
|
+
"anyOf",
|
|
1334
|
+
"oneOf",
|
|
1335
|
+
"allOf"
|
|
1336
|
+
]) if (key in record) violations.push(`${path}.${key}`);
|
|
1337
|
+
if (Array.isArray(record.type)) violations.push(`${path}.type`);
|
|
1338
|
+
const properties = record.properties && typeof record.properties === "object" && !Array.isArray(record.properties) ? record.properties : void 0;
|
|
1339
|
+
if (record.type === "object") {
|
|
1340
|
+
if (record.additionalProperties !== false) violations.push(`${path}.additionalProperties`);
|
|
1341
|
+
const required = Array.isArray(record.required) ? record.required.filter((entry) => typeof entry === "string") : void 0;
|
|
1342
|
+
if (!required) violations.push(`${path}.required`);
|
|
1343
|
+
else if (properties) {
|
|
1344
|
+
const requiredSet = new Set(required);
|
|
1345
|
+
for (const key of Object.keys(properties)) if (!requiredSet.has(key)) violations.push(`${path}.required.${key}`);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
for (const key of OPENAI_STRICT_COMPAT_SCHEMA_MAP_KEYS) {
|
|
1349
|
+
const schemaMap = record[key];
|
|
1350
|
+
if (!schemaMap || typeof schemaMap !== "object" || Array.isArray(schemaMap)) continue;
|
|
1351
|
+
for (const [entryKey, value] of Object.entries(schemaMap)) violations.push(...findOpenAIStrictSchemaViolations(value, `${path}.${key}.${entryKey}`));
|
|
1352
|
+
}
|
|
1353
|
+
for (const key of OPENAI_STRICT_COMPAT_SCHEMA_NESTED_KEYS) {
|
|
1354
|
+
const value = record[key];
|
|
1355
|
+
if (value && typeof value === "object") violations.push(...findOpenAIStrictSchemaViolations(value, `${path}.${key}`));
|
|
1356
|
+
}
|
|
1357
|
+
return violations;
|
|
1358
|
+
}
|
|
1359
|
+
//#endregion
|
|
1155
1360
|
//#region packages/ai/src/providers/openai-tool-schema.ts
|
|
1156
1361
|
/**
|
|
1157
1362
|
* OpenAI strict JSON-schema normalization for tool inventories and request payloads.
|
|
@@ -1245,7 +1450,7 @@ function findOpenAIStrictToolProjectionDiagnostics(projection) {
|
|
|
1245
1450
|
...diagnostic.toolName ? { toolName: diagnostic.toolName } : {},
|
|
1246
1451
|
violations: [...diagnostic.violations]
|
|
1247
1452
|
})), ...projection.tools.flatMap((tool) => {
|
|
1248
|
-
const violations =
|
|
1453
|
+
const violations = findOpenAIStrictSchemaViolations(normalizeStrictOpenAIJsonSchema(tool.parameters), `${tool.name}.parameters`);
|
|
1249
1454
|
return violations.length > 0 ? [{
|
|
1250
1455
|
toolIndex: tool.toolIndex,
|
|
1251
1456
|
toolName: tool.name,
|
|
@@ -1272,34 +1477,6 @@ function isStrictOpenAIJsonSchemaCompatibleRecursive(schema) {
|
|
|
1272
1477
|
return isStrictOpenAIJsonSchemaCompatibleRecursive(entry);
|
|
1273
1478
|
});
|
|
1274
1479
|
}
|
|
1275
|
-
function findStrictOpenAIJsonSchemaViolations(schema, path) {
|
|
1276
|
-
if (Array.isArray(schema)) return schema.flatMap((entry, index) => findStrictOpenAIJsonSchemaViolations(entry, `${path}[${index}]`));
|
|
1277
|
-
if (!schema || typeof schema !== "object") return [];
|
|
1278
|
-
const record = schema;
|
|
1279
|
-
const violations = [];
|
|
1280
|
-
for (const key of [
|
|
1281
|
-
"anyOf",
|
|
1282
|
-
"oneOf",
|
|
1283
|
-
"allOf"
|
|
1284
|
-
]) if (key in record) violations.push(`${path}.${key}`);
|
|
1285
|
-
if (Array.isArray(record.type)) violations.push(`${path}.type`);
|
|
1286
|
-
if (record.type === "object") {
|
|
1287
|
-
if (record.additionalProperties !== false) violations.push(`${path}.additionalProperties`);
|
|
1288
|
-
const properties = record.properties && typeof record.properties === "object" && !Array.isArray(record.properties) ? record.properties : {};
|
|
1289
|
-
const required = Array.isArray(record.required) ? record.required.filter((entry) => typeof entry === "string") : void 0;
|
|
1290
|
-
if (!required) violations.push(`${path}.required`);
|
|
1291
|
-
else {
|
|
1292
|
-
const requiredSet = new Set(required);
|
|
1293
|
-
for (const key of Object.keys(properties)) if (!requiredSet.has(key)) violations.push(`${path}.required.${key}`);
|
|
1294
|
-
}
|
|
1295
|
-
}
|
|
1296
|
-
if (record.properties && typeof record.properties === "object" && !Array.isArray(record.properties)) for (const [key, value] of Object.entries(record.properties)) violations.push(...findStrictOpenAIJsonSchemaViolations(value, `${path}.properties.${key}`));
|
|
1297
|
-
for (const [key, value] of Object.entries(record)) {
|
|
1298
|
-
if (key === "properties") continue;
|
|
1299
|
-
if (value && typeof value === "object") violations.push(...findStrictOpenAIJsonSchemaViolations(value, `${path}.${key}`));
|
|
1300
|
-
}
|
|
1301
|
-
return violations;
|
|
1302
|
-
}
|
|
1303
1480
|
/** Resolves strict mode for the projected tools that will be emitted in the request payload. */
|
|
1304
1481
|
function resolveOpenAIProjectedToolsStrictToolFlag(projection, strict) {
|
|
1305
1482
|
if (strict !== true) return strict === false ? false : void 0;
|
|
@@ -1462,7 +1639,8 @@ function convertResponsesMessages(model, context, allowedToolCallProviders, opti
|
|
|
1462
1639
|
};
|
|
1463
1640
|
const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
|
|
1464
1641
|
if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) {
|
|
1465
|
-
const
|
|
1642
|
+
const compat = model.compat;
|
|
1643
|
+
const role = model.reasoning && compat?.supportsDeveloperRole !== false ? "developer" : "system";
|
|
1466
1644
|
messages.push({
|
|
1467
1645
|
type: "message",
|
|
1468
1646
|
role,
|
|
@@ -1631,7 +1809,7 @@ function resolveResponsesReasoningEffort(model, reasoning) {
|
|
|
1631
1809
|
return clampedReasoning;
|
|
1632
1810
|
}
|
|
1633
1811
|
function applyCommonResponsesParams(params, model, context, options, config) {
|
|
1634
|
-
if (options?.maxTokens) params.max_output_tokens = options.maxTokens;
|
|
1812
|
+
if (options?.maxTokens) params.max_output_tokens = Math.max(options.maxTokens, 16);
|
|
1635
1813
|
if (options?.temperature !== void 0 && supportsOpenAITemperature(model)) params.temperature = options.temperature;
|
|
1636
1814
|
if (context.tools) {
|
|
1637
1815
|
const converted = convertResponsesToolPayload(context.tools, { model });
|
|
@@ -1650,7 +1828,7 @@ function buildResponsesRequestOptions(options) {
|
|
|
1650
1828
|
return {
|
|
1651
1829
|
...options?.signal ? { signal: options.signal } : {},
|
|
1652
1830
|
...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
|
|
1653
|
-
|
|
1831
|
+
maxRetries: options?.maxRetries ?? 0
|
|
1654
1832
|
};
|
|
1655
1833
|
}
|
|
1656
1834
|
function cleanStreamingScratchBuffers(output) {
|
|
@@ -1689,7 +1867,7 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
1689
1867
|
onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout
|
|
1690
1868
|
} : void 0);
|
|
1691
1869
|
if (options?.signal?.aborted) throw new Error("Request was aborted");
|
|
1692
|
-
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
|
|
1870
|
+
if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error(output.errorMessage ?? "An unknown error occurred");
|
|
1693
1871
|
stream.push({
|
|
1694
1872
|
type: "done",
|
|
1695
1873
|
reason: output.stopReason,
|
|
@@ -1711,13 +1889,49 @@ async function runResponsesStreamLifecycle(params) {
|
|
|
1711
1889
|
}
|
|
1712
1890
|
}
|
|
1713
1891
|
async function processResponsesStream(openaiStream, output, stream, model, options) {
|
|
1714
|
-
let currentItem = null;
|
|
1715
|
-
let currentBlock = null;
|
|
1716
1892
|
const streamingToolCalls = createResponsesToolCallTracker();
|
|
1893
|
+
const outputSlots = /* @__PURE__ */ new Map();
|
|
1894
|
+
const reasoningBlocksById = /* @__PURE__ */ new Map();
|
|
1895
|
+
let unindexedOutputSlot;
|
|
1896
|
+
let terminalResponseEvent;
|
|
1717
1897
|
let lastTextBlock = null;
|
|
1718
|
-
let pendingMessageText = null;
|
|
1719
1898
|
const blocks = output.content;
|
|
1720
1899
|
const blockIndex = () => blocks.length - 1;
|
|
1900
|
+
const readOutputIndex = (event) => {
|
|
1901
|
+
const outputIndex = event.output_index;
|
|
1902
|
+
return typeof outputIndex === "number" && Number.isInteger(outputIndex) && outputIndex >= 0 ? outputIndex : void 0;
|
|
1903
|
+
};
|
|
1904
|
+
const registerOutputSlot = (event, slot) => {
|
|
1905
|
+
const outputIndex = readOutputIndex(event);
|
|
1906
|
+
if (outputIndex === void 0) {
|
|
1907
|
+
if (unindexedOutputSlot) throw new Error("Responses stream added overlapping unindexed output items");
|
|
1908
|
+
unindexedOutputSlot = slot;
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
if (outputSlots.has(outputIndex)) throw new Error(`Responses stream reused active output index ${outputIndex}`);
|
|
1912
|
+
outputSlots.set(outputIndex, slot);
|
|
1913
|
+
};
|
|
1914
|
+
const resolveOutputSlot = (event, type) => {
|
|
1915
|
+
const outputIndex = readOutputIndex(event);
|
|
1916
|
+
let slot = outputIndex === void 0 ? unindexedOutputSlot : outputSlots.get(outputIndex);
|
|
1917
|
+
if (outputIndex === void 0 && !slot) {
|
|
1918
|
+
const matchingSlots = [...outputSlots.values()].filter((candidate) => candidate.type === type);
|
|
1919
|
+
slot = matchingSlots.length === 1 ? matchingSlots[0] : void 0;
|
|
1920
|
+
}
|
|
1921
|
+
return slot?.type === type ? slot : void 0;
|
|
1922
|
+
};
|
|
1923
|
+
const forgetOutputSlot = (event, slot) => {
|
|
1924
|
+
const outputIndex = readOutputIndex(event);
|
|
1925
|
+
if (outputIndex === void 0) {
|
|
1926
|
+
if (unindexedOutputSlot === slot) unindexedOutputSlot = void 0;
|
|
1927
|
+
else for (const [indexedOutput, indexedSlot] of outputSlots) if (indexedSlot === slot) outputSlots.delete(indexedOutput);
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
1930
|
+
if (outputSlots.get(outputIndex) === slot) outputSlots.delete(outputIndex);
|
|
1931
|
+
};
|
|
1932
|
+
const forgetToolCallOutputSlot = (toolCall) => {
|
|
1933
|
+
for (const [outputIndex, slot] of outputSlots) if (slot.type === "toolCall" && slot.toolCall === toolCall) outputSlots.delete(outputIndex);
|
|
1934
|
+
};
|
|
1721
1935
|
const readIdentityValue = (value) => {
|
|
1722
1936
|
return (typeof value === "string" ? value.trim() : "") || void 0;
|
|
1723
1937
|
};
|
|
@@ -1729,28 +1943,137 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1729
1943
|
if (!name) throw new Error("Responses stream completed tool call without a function name");
|
|
1730
1944
|
return name;
|
|
1731
1945
|
};
|
|
1732
|
-
const
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1946
|
+
const createOutputSlot = (event, item) => {
|
|
1947
|
+
if (item.type === "reasoning") {
|
|
1948
|
+
const block = {
|
|
1949
|
+
type: "thinking",
|
|
1950
|
+
thinking: ""
|
|
1951
|
+
};
|
|
1952
|
+
const slot = {
|
|
1953
|
+
type: "thinking",
|
|
1954
|
+
item,
|
|
1955
|
+
block,
|
|
1956
|
+
contentIndex: blocks.length
|
|
1957
|
+
};
|
|
1958
|
+
blocks.push(block);
|
|
1959
|
+
registerOutputSlot(event, slot);
|
|
1960
|
+
stream.push({
|
|
1961
|
+
type: "thinking_start",
|
|
1962
|
+
contentIndex: slot.contentIndex,
|
|
1963
|
+
partial: output
|
|
1964
|
+
});
|
|
1965
|
+
return slot;
|
|
1966
|
+
}
|
|
1967
|
+
if (item.type === "message") {
|
|
1968
|
+
const messageItem = item;
|
|
1969
|
+
const collapseCandidate = lastTextBlock;
|
|
1970
|
+
const block = collapseCandidate ? null : {
|
|
1971
|
+
type: "text",
|
|
1972
|
+
text: "",
|
|
1973
|
+
...messageItem.phase ? { textSignature: encodeTextSignatureV1(messageItem.id, messageItem.phase) } : {}
|
|
1974
|
+
};
|
|
1975
|
+
const slot = {
|
|
1976
|
+
type: "text",
|
|
1977
|
+
item: messageItem,
|
|
1978
|
+
block,
|
|
1979
|
+
contentIndex: block ? blocks.length : void 0,
|
|
1980
|
+
pendingText: collapseCandidate ? "" : null,
|
|
1981
|
+
collapseCandidate
|
|
1982
|
+
};
|
|
1983
|
+
if (block) blocks.push(block);
|
|
1984
|
+
registerOutputSlot(event, slot);
|
|
1985
|
+
if (slot.contentIndex !== void 0) stream.push({
|
|
1986
|
+
type: "text_start",
|
|
1987
|
+
contentIndex: slot.contentIndex,
|
|
1988
|
+
partial: output
|
|
1989
|
+
});
|
|
1990
|
+
return slot;
|
|
1991
|
+
}
|
|
1992
|
+
};
|
|
1993
|
+
const resolveOutputItemSlot = (event, item) => {
|
|
1994
|
+
if (item.type === "reasoning") return resolveOutputSlot(event, "thinking");
|
|
1995
|
+
if (item.type === "message") return resolveOutputSlot(event, "text");
|
|
1996
|
+
const outputIndex = readOutputIndex(event);
|
|
1997
|
+
return outputIndex === void 0 ? void 0 : outputSlots.get(outputIndex);
|
|
1998
|
+
};
|
|
1999
|
+
const getOrCreateOutputSlot = (event, item) => {
|
|
2000
|
+
return resolveOutputItemSlot(event, item) ?? createOutputSlot(event, item);
|
|
2001
|
+
};
|
|
2002
|
+
const materializeDeferredTextSlot = (slot) => {
|
|
2003
|
+
if (slot.block || slot.pendingText === null) return;
|
|
2004
|
+
const text = slot.pendingText;
|
|
2005
|
+
slot.block = {
|
|
1737
2006
|
type: "text",
|
|
1738
|
-
text
|
|
1739
|
-
...
|
|
2007
|
+
text,
|
|
2008
|
+
...slot.item.phase ? { textSignature: encodeTextSignatureV1(slot.item.id, slot.item.phase) } : {}
|
|
1740
2009
|
};
|
|
1741
|
-
blocks.push(
|
|
2010
|
+
blocks.push(slot.block);
|
|
2011
|
+
slot.contentIndex = blockIndex();
|
|
1742
2012
|
stream.push({
|
|
1743
2013
|
type: "text_start",
|
|
1744
|
-
contentIndex:
|
|
2014
|
+
contentIndex: slot.contentIndex,
|
|
1745
2015
|
partial: output
|
|
1746
2016
|
});
|
|
1747
|
-
stream.push({
|
|
2017
|
+
if (text) stream.push({
|
|
1748
2018
|
type: "text_delta",
|
|
1749
|
-
contentIndex:
|
|
1750
|
-
delta:
|
|
2019
|
+
contentIndex: slot.contentIndex,
|
|
2020
|
+
delta: text,
|
|
1751
2021
|
partial: output
|
|
1752
2022
|
});
|
|
1753
|
-
|
|
2023
|
+
if (lastTextBlock === slot.collapseCandidate) lastTextBlock = null;
|
|
2024
|
+
slot.pendingText = null;
|
|
2025
|
+
slot.collapseCandidate = null;
|
|
2026
|
+
};
|
|
2027
|
+
const materializeDeferredTextSlots = (except) => {
|
|
2028
|
+
for (const slot of outputSlots.values()) if (slot !== except && slot.type === "text") materializeDeferredTextSlot(slot);
|
|
2029
|
+
if (unindexedOutputSlot !== except && unindexedOutputSlot?.type === "text") materializeDeferredTextSlot(unindexedOutputSlot);
|
|
2030
|
+
};
|
|
2031
|
+
const appendPendingMessageDelta = (slot, delta) => {
|
|
2032
|
+
slot.pendingText = `${slot.pendingText ?? ""}${delta}`;
|
|
2033
|
+
const priorText = slot.collapseCandidate?.block.text ?? "";
|
|
2034
|
+
if (priorText.startsWith(slot.pendingText) || slot.pendingText.startsWith(priorText)) return;
|
|
2035
|
+
materializeDeferredTextSlot(slot);
|
|
2036
|
+
};
|
|
2037
|
+
const backfillReasoningSignatures = (responseOutput) => {
|
|
2038
|
+
for (const item of responseOutput) {
|
|
2039
|
+
if (item.type !== "reasoning" || !item.encrypted_content) continue;
|
|
2040
|
+
const block = reasoningBlocksById.get(item.id);
|
|
2041
|
+
if (!block?.thinkingSignature) continue;
|
|
2042
|
+
const storedItem = JSON.parse(block.thinkingSignature);
|
|
2043
|
+
if (storedItem.encrypted_content) continue;
|
|
2044
|
+
block.thinkingSignature = JSON.stringify({
|
|
2045
|
+
...storedItem,
|
|
2046
|
+
encrypted_content: item.encrypted_content
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
};
|
|
2050
|
+
const finalizeResponse = (response) => {
|
|
2051
|
+
terminalResponseEvent = "finalized";
|
|
2052
|
+
backfillReasoningSignatures(response.output ?? []);
|
|
2053
|
+
if (response.id) output.responseId = response.id;
|
|
2054
|
+
const mappedUsage = mapResponsesTerminalUsage(response.usage);
|
|
2055
|
+
if (mappedUsage) output.usage = {
|
|
2056
|
+
...mappedUsage,
|
|
2057
|
+
cost: {
|
|
2058
|
+
input: 0,
|
|
2059
|
+
output: 0,
|
|
2060
|
+
cacheRead: 0,
|
|
2061
|
+
cacheWrite: 0,
|
|
2062
|
+
total: 0
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
2065
|
+
calculateCost(model, output.usage);
|
|
2066
|
+
if (options?.applyServiceTierPricing) {
|
|
2067
|
+
const serviceTier = options.resolveServiceTier ? options.resolveServiceTier(response.service_tier, options.serviceTier) : response.service_tier ?? options.serviceTier;
|
|
2068
|
+
options.applyServiceTierPricing(output.usage, serviceTier);
|
|
2069
|
+
}
|
|
2070
|
+
const terminal = resolveResponsesTerminalStopReason({
|
|
2071
|
+
status: response.status,
|
|
2072
|
+
incompleteReason: response.incomplete_details?.reason,
|
|
2073
|
+
hasToolCall: output.content.some((block) => block.type === "toolCall")
|
|
2074
|
+
});
|
|
2075
|
+
output.stopReason = terminal.stopReason;
|
|
2076
|
+
if (terminal.errorMessage) output.errorMessage = terminal.errorMessage;
|
|
1754
2077
|
};
|
|
1755
2078
|
const guardedStream = withFirstStreamEventTimeout(openaiStream, {
|
|
1756
2079
|
provider: model.provider,
|
|
@@ -1764,42 +2087,11 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1764
2087
|
});
|
|
1765
2088
|
for await (const event of guardedStream) if (event.type === "response.created") output.responseId = event.response.id;
|
|
1766
2089
|
else if (event.type === "response.output_item.added") {
|
|
2090
|
+
materializeDeferredTextSlots();
|
|
1767
2091
|
const item = event.item;
|
|
1768
|
-
if (item.type !== "message")
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
}
|
|
1772
|
-
if (item.type === "reasoning") {
|
|
1773
|
-
currentItem = item;
|
|
1774
|
-
currentBlock = {
|
|
1775
|
-
type: "thinking",
|
|
1776
|
-
thinking: ""
|
|
1777
|
-
};
|
|
1778
|
-
output.content.push(currentBlock);
|
|
1779
|
-
stream.push({
|
|
1780
|
-
type: "thinking_start",
|
|
1781
|
-
contentIndex: blockIndex(),
|
|
1782
|
-
partial: output
|
|
1783
|
-
});
|
|
1784
|
-
} else if (item.type === "message") {
|
|
1785
|
-
currentItem = item;
|
|
1786
|
-
if (lastTextBlock) {
|
|
1787
|
-
currentBlock = null;
|
|
1788
|
-
pendingMessageText = "";
|
|
1789
|
-
} else {
|
|
1790
|
-
currentBlock = {
|
|
1791
|
-
type: "text",
|
|
1792
|
-
text: "",
|
|
1793
|
-
...item.phase ? { textSignature: encodeTextSignatureV1(item.id, item.phase) } : {}
|
|
1794
|
-
};
|
|
1795
|
-
output.content.push(currentBlock);
|
|
1796
|
-
stream.push({
|
|
1797
|
-
type: "text_start",
|
|
1798
|
-
contentIndex: blockIndex(),
|
|
1799
|
-
partial: output
|
|
1800
|
-
});
|
|
1801
|
-
}
|
|
1802
|
-
} else if (item.type === "function_call") {
|
|
2092
|
+
if (item.type !== "message") lastTextBlock = null;
|
|
2093
|
+
if (item.type === "reasoning" || item.type === "message") createOutputSlot(event, item);
|
|
2094
|
+
else if (item.type === "function_call") {
|
|
1803
2095
|
const toolCallBlock = {
|
|
1804
2096
|
type: "toolCall",
|
|
1805
2097
|
id: resolveResponsesToolCallId(item),
|
|
@@ -1815,8 +2107,10 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1815
2107
|
...readResponsesToolCallItemIdentity(item)
|
|
1816
2108
|
};
|
|
1817
2109
|
streamingToolCalls.register(event, toolCallState);
|
|
1818
|
-
|
|
1819
|
-
|
|
2110
|
+
if (readOutputIndex(event) !== void 0) registerOutputSlot(event, {
|
|
2111
|
+
type: "toolCall",
|
|
2112
|
+
toolCall: toolCallState
|
|
2113
|
+
});
|
|
1820
2114
|
output.content.push(toolCallBlock);
|
|
1821
2115
|
stream.push({
|
|
1822
2116
|
type: "toolcall_start",
|
|
@@ -1825,113 +2119,107 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1825
2119
|
});
|
|
1826
2120
|
}
|
|
1827
2121
|
} else if (event.type === "response.reasoning_summary_part.added") {
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
2122
|
+
const slot = resolveOutputSlot(event, "thinking");
|
|
2123
|
+
if (!slot) continue;
|
|
2124
|
+
slot.item.summary = slot.item.summary || [];
|
|
2125
|
+
slot.item.summary.push(event.part);
|
|
1832
2126
|
} else if (event.type === "response.reasoning_summary_text.delta") {
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
}
|
|
2127
|
+
const slot = resolveOutputSlot(event, "thinking");
|
|
2128
|
+
if (!slot) continue;
|
|
2129
|
+
slot.item.summary = slot.item.summary || [];
|
|
2130
|
+
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
2131
|
+
if (!lastPart) continue;
|
|
2132
|
+
slot.block.thinking += event.delta;
|
|
2133
|
+
lastPart.text += event.delta;
|
|
2134
|
+
stream.push({
|
|
2135
|
+
type: "thinking_delta",
|
|
2136
|
+
contentIndex: slot.contentIndex,
|
|
2137
|
+
delta: event.delta,
|
|
2138
|
+
partial: output
|
|
2139
|
+
});
|
|
1847
2140
|
} else if (event.type === "response.reasoning_summary_part.done") {
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
}
|
|
2141
|
+
const slot = resolveOutputSlot(event, "thinking");
|
|
2142
|
+
if (!slot) continue;
|
|
2143
|
+
slot.item.summary = slot.item.summary || [];
|
|
2144
|
+
const lastPart = slot.item.summary[slot.item.summary.length - 1];
|
|
2145
|
+
if (!lastPart) continue;
|
|
2146
|
+
slot.block.thinking += "\n\n";
|
|
2147
|
+
lastPart.text += "\n\n";
|
|
2148
|
+
stream.push({
|
|
2149
|
+
type: "thinking_delta",
|
|
2150
|
+
contentIndex: slot.contentIndex,
|
|
2151
|
+
delta: "\n\n",
|
|
2152
|
+
partial: output
|
|
2153
|
+
});
|
|
1862
2154
|
} else if (event.type === "response.reasoning_text.delta") {
|
|
1863
|
-
|
|
1864
|
-
|
|
2155
|
+
const slot = resolveOutputSlot(event, "thinking");
|
|
2156
|
+
if (!slot) continue;
|
|
2157
|
+
slot.block.thinking += event.delta;
|
|
2158
|
+
stream.push({
|
|
2159
|
+
type: "thinking_delta",
|
|
2160
|
+
contentIndex: slot.contentIndex,
|
|
2161
|
+
delta: event.delta,
|
|
2162
|
+
partial: output
|
|
2163
|
+
});
|
|
2164
|
+
} else if (event.type === "response.content_part.added") {
|
|
2165
|
+
const slot = resolveOutputSlot(event, "text");
|
|
2166
|
+
if (!slot) continue;
|
|
2167
|
+
slot.item.content = slot.item.content || [];
|
|
2168
|
+
if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") slot.item.content.push(event.part);
|
|
2169
|
+
} else if (event.type === "response.output_text.delta") {
|
|
2170
|
+
const slot = resolveOutputSlot(event, "text");
|
|
2171
|
+
if (!slot?.item.content || slot.item.content.length === 0) continue;
|
|
2172
|
+
const lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2173
|
+
if (!isResponsesTextContentPartType(lastPart?.type)) continue;
|
|
2174
|
+
lastPart.text += event.delta;
|
|
2175
|
+
if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
|
|
2176
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2177
|
+
slot.block.text += event.delta;
|
|
1865
2178
|
stream.push({
|
|
1866
|
-
type: "
|
|
1867
|
-
contentIndex:
|
|
2179
|
+
type: "text_delta",
|
|
2180
|
+
contentIndex: slot.contentIndex,
|
|
1868
2181
|
delta: event.delta,
|
|
1869
2182
|
partial: output
|
|
1870
2183
|
});
|
|
1871
2184
|
}
|
|
1872
|
-
} else if (event.type === "response.content_part.added") {
|
|
1873
|
-
if (currentItem?.type === "message") {
|
|
1874
|
-
currentItem.content = currentItem.content || [];
|
|
1875
|
-
if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") currentItem.content.push(event.part);
|
|
1876
|
-
}
|
|
1877
|
-
} else if (event.type === "response.output_text.delta") {
|
|
1878
|
-
if (currentItem?.type === "message") {
|
|
1879
|
-
if (!currentItem.content || currentItem.content.length === 0) continue;
|
|
1880
|
-
const lastPart = currentItem.content[currentItem.content.length - 1];
|
|
1881
|
-
if (isResponsesTextContentPartType(lastPart?.type)) {
|
|
1882
|
-
lastPart.text += event.delta;
|
|
1883
|
-
if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
|
|
1884
|
-
else if (currentBlock?.type === "text") {
|
|
1885
|
-
currentBlock.text += event.delta;
|
|
1886
|
-
stream.push({
|
|
1887
|
-
type: "text_delta",
|
|
1888
|
-
contentIndex: blockIndex(),
|
|
1889
|
-
delta: event.delta,
|
|
1890
|
-
partial: output
|
|
1891
|
-
});
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
2185
|
} else if (isAzureResponsesTextDeltaEvent(event)) {
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
}
|
|
2186
|
+
const slot = resolveOutputSlot(event, "text");
|
|
2187
|
+
if (!slot) continue;
|
|
2188
|
+
slot.item.content = slot.item.content || [];
|
|
2189
|
+
let lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2190
|
+
if (lastPart?.type !== "text") {
|
|
2191
|
+
lastPart = {
|
|
2192
|
+
type: "text",
|
|
2193
|
+
text: ""
|
|
2194
|
+
};
|
|
2195
|
+
slot.item.content.push(lastPart);
|
|
2196
|
+
}
|
|
2197
|
+
lastPart.text += event.delta;
|
|
2198
|
+
if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
|
|
2199
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2200
|
+
slot.block.text += event.delta;
|
|
2201
|
+
stream.push({
|
|
2202
|
+
type: "text_delta",
|
|
2203
|
+
contentIndex: slot.contentIndex,
|
|
2204
|
+
delta: event.delta,
|
|
2205
|
+
partial: output
|
|
2206
|
+
});
|
|
1917
2207
|
}
|
|
1918
2208
|
} else if (event.type === "response.refusal.delta") {
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
2209
|
+
const slot = resolveOutputSlot(event, "text");
|
|
2210
|
+
if (!slot?.item.content || slot.item.content.length === 0) continue;
|
|
2211
|
+
const lastPart = slot.item.content[slot.item.content.length - 1];
|
|
2212
|
+
if (lastPart?.type !== "refusal") continue;
|
|
2213
|
+
lastPart.refusal += event.delta;
|
|
2214
|
+
if (slot.pendingText !== null) appendPendingMessageDelta(slot, event.delta);
|
|
2215
|
+
else if (slot.block && slot.contentIndex !== void 0) {
|
|
2216
|
+
slot.block.text += event.delta;
|
|
2217
|
+
stream.push({
|
|
2218
|
+
type: "text_delta",
|
|
2219
|
+
contentIndex: slot.contentIndex,
|
|
2220
|
+
delta: event.delta,
|
|
2221
|
+
partial: output
|
|
2222
|
+
});
|
|
1935
2223
|
}
|
|
1936
2224
|
} else if (event.type === "response.function_call_arguments.delta") {
|
|
1937
2225
|
const toolCall = streamingToolCalls.resolve(event);
|
|
@@ -1967,72 +2255,78 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
1967
2255
|
} else if (streamingToolCalls.hasActive()) streamingToolCalls.markArgumentsUnreliable();
|
|
1968
2256
|
} else if (event.type === "response.output_item.done") {
|
|
1969
2257
|
const item = event.item;
|
|
1970
|
-
if (item.type !== "message")
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
if (item.type === "reasoning" &&
|
|
2258
|
+
if (item.type !== "message") lastTextBlock = null;
|
|
2259
|
+
const existingOutputSlot = resolveOutputItemSlot(event, item);
|
|
2260
|
+
materializeDeferredTextSlots(existingOutputSlot);
|
|
2261
|
+
const outputSlot = existingOutputSlot ?? getOrCreateOutputSlot(event, item);
|
|
2262
|
+
if (item.type === "reasoning" && outputSlot?.type === "thinking") {
|
|
1975
2263
|
const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
|
|
1976
2264
|
const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
|
|
1977
|
-
|
|
1978
|
-
|
|
2265
|
+
outputSlot.block.thinking = summaryText || contentText || outputSlot.block.thinking;
|
|
2266
|
+
outputSlot.block.thinkingSignature = JSON.stringify(item);
|
|
2267
|
+
if (typeof item.id === "string") reasoningBlocksById.set(item.id, outputSlot.block);
|
|
1979
2268
|
stream.push({
|
|
1980
2269
|
type: "thinking_end",
|
|
1981
|
-
contentIndex:
|
|
1982
|
-
content:
|
|
2270
|
+
contentIndex: outputSlot.contentIndex,
|
|
2271
|
+
content: outputSlot.block.thinking,
|
|
1983
2272
|
partial: output
|
|
1984
2273
|
});
|
|
1985
|
-
|
|
1986
|
-
} else if (item.type === "message" &&
|
|
1987
|
-
const
|
|
2274
|
+
forgetOutputSlot(event, outputSlot);
|
|
2275
|
+
} else if (item.type === "message" && outputSlot?.type === "text" && (outputSlot.block || outputSlot.pendingText !== null)) {
|
|
2276
|
+
const streamedText = outputSlot.pendingText ?? outputSlot.block?.text ?? "";
|
|
2277
|
+
const finalText = item.content == null ? streamedText : item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
|
|
1988
2278
|
const phase = item.phase ?? void 0;
|
|
1989
|
-
const collapse =
|
|
1990
|
-
prior:
|
|
1991
|
-
text:
|
|
1992
|
-
phase:
|
|
2279
|
+
const collapse = outputSlot.pendingText !== null ? resolveResponsesMessageSnapshotCollapse({
|
|
2280
|
+
prior: outputSlot.collapseCandidate && {
|
|
2281
|
+
text: outputSlot.collapseCandidate.block.text,
|
|
2282
|
+
phase: outputSlot.collapseCandidate.phase
|
|
1993
2283
|
},
|
|
1994
2284
|
nextText: finalText,
|
|
1995
2285
|
nextPhase: phase
|
|
1996
2286
|
}) : { kind: "keep" };
|
|
1997
|
-
|
|
1998
|
-
if (collapse.kind === "extend" &&
|
|
1999
|
-
|
|
2000
|
-
|
|
2287
|
+
outputSlot.pendingText = null;
|
|
2288
|
+
if (collapse.kind === "extend" && outputSlot.collapseCandidate) {
|
|
2289
|
+
outputSlot.collapseCandidate.block.text = collapse.text;
|
|
2290
|
+
outputSlot.collapseCandidate.block.textSignature = encodeTextSignatureV1(item.id, phase);
|
|
2001
2291
|
stream.push({
|
|
2002
2292
|
type: "text_end",
|
|
2003
|
-
contentIndex:
|
|
2293
|
+
contentIndex: outputSlot.collapseCandidate.index,
|
|
2004
2294
|
content: collapse.text,
|
|
2005
2295
|
partial: output
|
|
2006
2296
|
});
|
|
2297
|
+
lastTextBlock = outputSlot.collapseCandidate;
|
|
2007
2298
|
} else {
|
|
2008
|
-
if (
|
|
2009
|
-
|
|
2299
|
+
if (!outputSlot.block) {
|
|
2300
|
+
outputSlot.block = {
|
|
2010
2301
|
type: "text",
|
|
2011
2302
|
text: "",
|
|
2012
2303
|
...phase ? { textSignature: encodeTextSignatureV1(item.id, phase) } : {}
|
|
2013
2304
|
};
|
|
2014
|
-
blocks.push(
|
|
2305
|
+
blocks.push(outputSlot.block);
|
|
2306
|
+
outputSlot.contentIndex = blockIndex();
|
|
2015
2307
|
stream.push({
|
|
2016
2308
|
type: "text_start",
|
|
2017
|
-
contentIndex:
|
|
2309
|
+
contentIndex: outputSlot.contentIndex,
|
|
2018
2310
|
partial: output
|
|
2019
2311
|
});
|
|
2020
2312
|
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2313
|
+
outputSlot.block.text = finalText;
|
|
2314
|
+
outputSlot.block.textSignature = encodeTextSignatureV1(item.id, phase);
|
|
2315
|
+
const contentIndex = outputSlot.contentIndex;
|
|
2316
|
+
if (contentIndex === void 0) throw new Error("Responses stream finalized text without a content index");
|
|
2023
2317
|
lastTextBlock = {
|
|
2024
|
-
block:
|
|
2025
|
-
index:
|
|
2318
|
+
block: outputSlot.block,
|
|
2319
|
+
index: contentIndex,
|
|
2026
2320
|
phase
|
|
2027
2321
|
};
|
|
2028
2322
|
stream.push({
|
|
2029
2323
|
type: "text_end",
|
|
2030
|
-
contentIndex
|
|
2031
|
-
content:
|
|
2324
|
+
contentIndex,
|
|
2325
|
+
content: outputSlot.block.text,
|
|
2032
2326
|
partial: output
|
|
2033
2327
|
});
|
|
2034
2328
|
}
|
|
2035
|
-
|
|
2329
|
+
forgetOutputSlot(event, outputSlot);
|
|
2036
2330
|
} else if (item.type === "function_call") {
|
|
2037
2331
|
const streamingToolCall = streamingToolCalls.resolve(event, readResponsesToolCallItemIdentity(item));
|
|
2038
2332
|
if (!streamingToolCall && streamingToolCalls.hasActive()) continue;
|
|
@@ -2066,10 +2360,9 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2066
2360
|
partial: output
|
|
2067
2361
|
});
|
|
2068
2362
|
}
|
|
2069
|
-
if (streamingToolCall)
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
currentItem = null;
|
|
2363
|
+
if (streamingToolCall) {
|
|
2364
|
+
streamingToolCalls.forget(streamingToolCall);
|
|
2365
|
+
forgetToolCallOutputSlot(streamingToolCall);
|
|
2073
2366
|
}
|
|
2074
2367
|
stream.push({
|
|
2075
2368
|
type: "toolcall_end",
|
|
@@ -2078,56 +2371,22 @@ async function processResponsesStream(openaiStream, output, stream, model, optio
|
|
|
2078
2371
|
partial: output
|
|
2079
2372
|
});
|
|
2080
2373
|
}
|
|
2081
|
-
} else if (event.type === "response.completed") {
|
|
2374
|
+
} else if (event.type === "response.completed" || event.type === "response.incomplete") {
|
|
2082
2375
|
if (streamingToolCalls.hasActive()) throw new Error("Responses stream completed with unresolved tool calls");
|
|
2083
|
-
|
|
2084
|
-
if (response?.id) output.responseId = response.id;
|
|
2085
|
-
if (response?.usage) {
|
|
2086
|
-
const inputTokenDetails = response.usage.input_tokens_details;
|
|
2087
|
-
const cachedTokens = inputTokenDetails?.cached_tokens || 0;
|
|
2088
|
-
const cacheWriteTokens = inputTokenDetails?.cache_write_tokens || 0;
|
|
2089
|
-
output.usage = {
|
|
2090
|
-
input: Math.max(0, (response.usage.input_tokens || 0) - cachedTokens - cacheWriteTokens),
|
|
2091
|
-
output: response.usage.output_tokens || 0,
|
|
2092
|
-
cacheRead: cachedTokens,
|
|
2093
|
-
cacheWrite: cacheWriteTokens,
|
|
2094
|
-
totalTokens: response.usage.total_tokens || 0,
|
|
2095
|
-
cost: {
|
|
2096
|
-
input: 0,
|
|
2097
|
-
output: 0,
|
|
2098
|
-
cacheRead: 0,
|
|
2099
|
-
cacheWrite: 0,
|
|
2100
|
-
total: 0
|
|
2101
|
-
}
|
|
2102
|
-
};
|
|
2103
|
-
}
|
|
2104
|
-
calculateCost(model, output.usage);
|
|
2105
|
-
if (options?.applyServiceTierPricing) {
|
|
2106
|
-
const serviceTier = options.resolveServiceTier ? options.resolveServiceTier(response?.service_tier, options.serviceTier) : response?.service_tier ?? options.serviceTier;
|
|
2107
|
-
options.applyServiceTierPricing(output.usage, serviceTier);
|
|
2108
|
-
}
|
|
2109
|
-
output.stopReason = mapStopReason(response?.status);
|
|
2110
|
-
if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") output.stopReason = "toolUse";
|
|
2376
|
+
finalizeResponse(event.response);
|
|
2111
2377
|
} else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
|
|
2112
2378
|
else if (event.type === "response.failed") {
|
|
2113
2379
|
const error = event.response?.error;
|
|
2114
2380
|
const details = event.response?.incomplete_details;
|
|
2115
|
-
|
|
2116
|
-
|
|
2381
|
+
output.responseId = event.response.id;
|
|
2382
|
+
output.stopReason = "error";
|
|
2383
|
+
output.errorMessage = error ? `${error.code || "unknown"}: ${error.message || "no message"}` : details?.reason ? `incomplete: ${details.reason}` : "Unknown error (no error details in response)";
|
|
2384
|
+
terminalResponseEvent = "failed";
|
|
2385
|
+
break;
|
|
2117
2386
|
}
|
|
2387
|
+
if (terminalResponseEvent === "failed") return;
|
|
2118
2388
|
if (streamingToolCalls.hasActive()) throw new Error("Responses stream ended with unresolved tool calls");
|
|
2119
|
-
|
|
2120
|
-
function mapStopReason(status) {
|
|
2121
|
-
if (!status) return "stop";
|
|
2122
|
-
switch (status) {
|
|
2123
|
-
case "completed": return "stop";
|
|
2124
|
-
case "incomplete": return "length";
|
|
2125
|
-
case "failed":
|
|
2126
|
-
case "cancelled": return "error";
|
|
2127
|
-
case "in_progress":
|
|
2128
|
-
case "queued": return "stop";
|
|
2129
|
-
default: throw new Error(`Unhandled stop reason: ${String(status)}`);
|
|
2130
|
-
}
|
|
2389
|
+
if (!terminalResponseEvent) throw new Error("OpenAI Responses stream ended before a terminal response event");
|
|
2131
2390
|
}
|
|
2132
2391
|
//#endregion
|
|
2133
|
-
export {
|
|
2392
|
+
export { isOpenAIGpt54MiniModel as A, resolveUnsupportedToolSchemaKeywords as B, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as C, isResponsesTextContentPartType as D, isAzureResponsesTextDeltaEventType as E, resolveOpenAISupportedReasoningEfforts as F, uniqueStrings as G, stripUnsupportedSchemaKeywords as H, supportsOpenAIReasoningEffort as I, supportsOpenAITemperature as L, isOpenAIGpt56Model as M, normalizeOpenAIReasoningEffort as N, isResponsesTextDeltaEventType as O, resolveOpenAIReasoningEffortForModel as P, extractToolSchemaModelCompat as R, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as S, isAzureResponsesTextDeltaEvent as T, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as U, shouldOmitEmptyArrayItems as V, cleanSchemaForGemini as W, readResponsesToolCallItemIdentity as _, resolveResponsesReasoningEffort as a, resolveResponsesTerminalStopReason as b, clearOpenAIToolSchemaCacheForTest as c, normalizeOpenAIStrictToolParameters as d, normalizeStrictOpenAIJsonSchema as f, createResponsesToolCallTracker as g, normalizeOpenAIStrictCompatSchema as h, processResponsesStream as i, isOpenAIGpt55Model as j, resolveResponsesMessageSnapshotCollapse as k, findOpenAIStrictToolProjectionDiagnostics as l, findOpenAIStrictSchemaViolations as m, convertResponsesMessages as n, runResponsesStreamLifecycle as o, resolveOpenAIProjectedToolsStrictToolFlag as p, createResponsesAssistantOutput as r, convertResponsesToolPayload as s, applyCommonResponsesParams as t, isStrictOpenAIJsonSchemaCompatible as u, mapResponsesTerminalUsage as v, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as w, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as x, readResponsesReasoningTokens as y, normalizeToolParameterSchema as z };
|