@openclaw/ai 0.0.0 → 2026.7.1-2

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.
Files changed (64) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -3
  3. package/dist/anthropic-B5gZQM5X.mjs +1383 -0
  4. package/dist/api-registry-BXYnCOIR.d.mts +33 -0
  5. package/dist/azure-openai-responses-DNoSk8Uy.mjs +141 -0
  6. package/dist/azure-openai-responses-client-compat-a_O_GVQV.mjs +41 -0
  7. package/dist/diagnostics-BaTA9eVl.d.mts +25 -0
  8. package/dist/diagnostics-COpOtRwq.mjs +36 -0
  9. package/dist/diagnostics.d.mts +2 -0
  10. package/dist/diagnostics.mjs +2 -0
  11. package/dist/env-api-keys-CtMlqaQ4.mjs +171 -0
  12. package/dist/event-stream-0nZeBKl2.d.mts +26 -0
  13. package/dist/event-stream-ReMmOTzX.mjs +65 -0
  14. package/dist/event-stream.d.mts +2 -0
  15. package/dist/event-stream.mjs +2 -0
  16. package/dist/github-copilot-headers-BsH5cqGj.mjs +48 -0
  17. package/dist/google-D6sIQ1bL.mjs +55 -0
  18. package/dist/google-shared-ZPSl2qTi.mjs +548 -0
  19. package/dist/google-vertex-rDGwkoZK.mjs +111 -0
  20. package/dist/hash-CHgqbJmD.mjs +16 -0
  21. package/dist/headers-B_e4-1J0.mjs +9 -0
  22. package/dist/host-4t713IeR.mjs +37 -0
  23. package/dist/index-BoTnz8cv.d.mts +74 -0
  24. package/dist/index.d.mts +69 -0
  25. package/dist/index.mjs +7 -0
  26. package/dist/internal/anthropic.d.mts +234 -0
  27. package/dist/internal/anthropic.mjs +4 -0
  28. package/dist/internal/openai.d.mts +244 -0
  29. package/dist/internal/openai.mjs +7 -0
  30. package/dist/internal/runtime.d.mts +245 -0
  31. package/dist/internal/runtime.mjs +176 -0
  32. package/dist/internal/shared.d.mts +48 -0
  33. package/dist/internal/shared.mjs +3 -0
  34. package/dist/json-parse-DzNSIQBq.mjs +134 -0
  35. package/dist/llm-request-activity-CehVkZP-.mjs +35 -0
  36. package/dist/mistral-CePVNdws.mjs +563 -0
  37. package/dist/model-utils-DgmOla96.mjs +69 -0
  38. package/dist/openai-chatgpt-jwt-DhAAzLkj.mjs +39 -0
  39. package/dist/openai-chatgpt-responses-DVC4Bk_A.mjs +1068 -0
  40. package/dist/openai-completions-B9QLIq2U.mjs +844 -0
  41. package/dist/openai-responses-B6LylGxM.mjs +136 -0
  42. package/dist/openai-responses-shared-sj2YUPYc.mjs +1944 -0
  43. package/dist/openai-tool-projection-BknoV11q.mjs +195 -0
  44. package/dist/providers.d.mts +11 -0
  45. package/dist/providers.mjs +109 -0
  46. package/dist/reasoning-tag-text-partitioner-axhAdUwg.mjs +394 -0
  47. package/dist/sanitize-unicode-BZiVbGwK.d.mts +24 -0
  48. package/dist/sanitize-unicode-DT5o51ur.mjs +26 -0
  49. package/dist/src-CZ503MYJ.mjs +99 -0
  50. package/dist/stream-CREqxHgU.mjs +74 -0
  51. package/dist/stream-first-event-timeout-RjWszj8c.mjs +106 -0
  52. package/dist/streaming-byte-guard-BrbkbwUu.mjs +46 -0
  53. package/dist/tool-schema-json-projection-BXtBc_mD.mjs +74 -0
  54. package/dist/transform-messages-BhGF_fF4.mjs +507 -0
  55. package/dist/types-BVVgDSdq.d.mts +1 -0
  56. package/dist/types-DRgdPqaZ.d.mts +587 -0
  57. package/dist/types.d.mts +6 -0
  58. package/dist/types.mjs +5 -0
  59. package/dist/validation-BDMWOr8d.d.mts +9 -0
  60. package/dist/validation-FrchoOlv.mjs +199 -0
  61. package/dist/validation.d.mts +2 -0
  62. package/dist/validation.mjs +2 -0
  63. package/npm-shrinkwrap.json +645 -0
  64. package/package.json +74 -2
@@ -0,0 +1,1944 @@
1
+ import { n as getAiTransportHost } from "./host-4t713IeR.mjs";
2
+ import { n as calculateCost, r as clampThinkingLevel } from "./model-utils-DgmOla96.mjs";
3
+ import { t as headersToRecord } from "./headers-B_e4-1J0.mjs";
4
+ import { n as parseStreamingJson } from "./json-parse-DzNSIQBq.mjs";
5
+ import { t as sanitizeSurrogates } from "./sanitize-unicode-DT5o51ur.mjs";
6
+ import { C as normalizeLowercaseStringOrEmpty, b as stripSystemPromptCacheBoundary, c as isRecord, i as extractToolResultText, n as describeToolResultMediaPlaceholder, t as transformMessages, w as normalizeOptionalString } from "./transform-messages-BhGF_fF4.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-BknoV11q.mjs";
9
+ import { t as shortHash } from "./hash-CHgqbJmD.mjs";
10
+ import { createHash } from "node:crypto";
11
+ //#region packages/normalization-core/src/string-normalization.ts
12
+ /** Coerces entries to strings, trims them, and drops empty results. */
13
+ function normalizeStringEntries(list) {
14
+ return (list ?? []).map((entry) => normalizeOptionalString(String(entry)) ?? "").filter(Boolean);
15
+ }
16
+ /** Returns first-seen unique values while preserving insertion order. */
17
+ function uniqueValues(values) {
18
+ return [...new Set(values)];
19
+ }
20
+ /** Returns first-seen unique strings while preserving insertion order. */
21
+ function uniqueStrings(values) {
22
+ return uniqueValues(values);
23
+ }
24
+ //#endregion
25
+ //#region packages/ai/src/providers/clean-for-gemini.ts
26
+ const GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS = /* @__PURE__ */ new Set([
27
+ "patternProperties",
28
+ "additionalProperties",
29
+ "$schema",
30
+ "$id",
31
+ "$ref",
32
+ "$defs",
33
+ "definitions",
34
+ "examples",
35
+ "minLength",
36
+ "maxLength",
37
+ "minimum",
38
+ "maximum",
39
+ "multipleOf",
40
+ "pattern",
41
+ "format",
42
+ "minItems",
43
+ "maxItems",
44
+ "uniqueItems",
45
+ "minProperties",
46
+ "maxProperties",
47
+ "not"
48
+ ]);
49
+ const SCHEMA_META_KEYS = [
50
+ "description",
51
+ "title",
52
+ "default"
53
+ ];
54
+ function copySchemaMeta$1(from, to) {
55
+ for (const key of SCHEMA_META_KEYS) if (key in from && from[key] !== void 0) to[key] = from[key];
56
+ }
57
+ function tryFlattenLiteralAnyOf(variants) {
58
+ if (variants.length === 0) return null;
59
+ const allValues = [];
60
+ let commonType = null;
61
+ for (const variant of variants) {
62
+ if (!variant || typeof variant !== "object") return null;
63
+ const v = variant;
64
+ let literalValue;
65
+ if ("const" in v) literalValue = v.const;
66
+ else if (Array.isArray(v.enum) && v.enum.length === 1) literalValue = v.enum[0];
67
+ else return null;
68
+ const variantType = typeof v.type === "string" ? v.type : null;
69
+ if (!variantType) return null;
70
+ if (commonType === null) commonType = variantType;
71
+ else if (commonType !== variantType) return null;
72
+ allValues.push(literalValue);
73
+ }
74
+ if (commonType && allValues.length > 0) return {
75
+ type: commonType,
76
+ enum: allValues
77
+ };
78
+ return null;
79
+ }
80
+ function isNullSchema(variant) {
81
+ if (!variant || typeof variant !== "object" || Array.isArray(variant)) return false;
82
+ const record = variant;
83
+ if ("const" in record && record.const === null) return true;
84
+ if (Array.isArray(record.enum) && record.enum.length === 1) return record.enum[0] === null;
85
+ const typeValue = record.type;
86
+ if (typeValue === "null") return true;
87
+ if (Array.isArray(typeValue) && typeValue.length === 1 && typeValue[0] === "null") return true;
88
+ return false;
89
+ }
90
+ function stripNullVariants(variants) {
91
+ if (variants.length === 0) return {
92
+ variants,
93
+ stripped: false
94
+ };
95
+ const nonNull = variants.filter((variant) => !isNullSchema(variant));
96
+ return {
97
+ variants: nonNull,
98
+ stripped: nonNull.length !== variants.length
99
+ };
100
+ }
101
+ function extendSchemaDefs$1(defs, schema) {
102
+ const defsEntry = schema.$defs && typeof schema.$defs === "object" && !Array.isArray(schema.$defs) ? schema.$defs : void 0;
103
+ const legacyDefsEntry = schema.definitions && typeof schema.definitions === "object" && !Array.isArray(schema.definitions) ? schema.definitions : void 0;
104
+ if (!defsEntry && !legacyDefsEntry) return defs;
105
+ const next = defs ? new Map(defs) : /* @__PURE__ */ new Map();
106
+ if (defsEntry) for (const [key, value] of Object.entries(defsEntry)) next.set(key, value);
107
+ if (legacyDefsEntry) for (const [key, value] of Object.entries(legacyDefsEntry)) next.set(key, value);
108
+ return next;
109
+ }
110
+ function decodeJsonPointerSegment$1(segment) {
111
+ return segment.replaceAll("~1", "/").replaceAll("~0", "~");
112
+ }
113
+ function tryResolveLocalRef$1(ref, defs) {
114
+ if (!defs) return;
115
+ const match = ref.match(/^#\/(?:\$defs|definitions)\/(.+)$/);
116
+ if (!match) return;
117
+ const name = decodeJsonPointerSegment$1(match[1] ?? "");
118
+ if (!name) return;
119
+ return defs.get(name);
120
+ }
121
+ function simplifyUnionVariants(params) {
122
+ const { obj, variants } = params;
123
+ const { variants: nonNullVariants, stripped } = stripNullVariants(variants);
124
+ const flattened = tryFlattenLiteralAnyOf(nonNullVariants);
125
+ if (flattened) {
126
+ const result = {
127
+ type: flattened.type,
128
+ enum: flattened.enum
129
+ };
130
+ copySchemaMeta$1(obj, result);
131
+ return {
132
+ variants: nonNullVariants,
133
+ simplified: result
134
+ };
135
+ }
136
+ if (stripped && nonNullVariants.length === 1) {
137
+ const lone = nonNullVariants[0];
138
+ if (lone && typeof lone === "object" && !Array.isArray(lone)) {
139
+ const result = { ...lone };
140
+ copySchemaMeta$1(obj, result);
141
+ return {
142
+ variants: nonNullVariants,
143
+ simplified: result
144
+ };
145
+ }
146
+ return {
147
+ variants: nonNullVariants,
148
+ simplified: lone
149
+ };
150
+ }
151
+ return { variants: stripped ? nonNullVariants : variants };
152
+ }
153
+ function sanitizeRequiredFields(schema) {
154
+ if (!Array.isArray(schema.required)) return schema;
155
+ if (!schema.properties || typeof schema.properties !== "object" || Array.isArray(schema.properties)) {
156
+ if (schema.type === "object") delete schema.required;
157
+ return schema;
158
+ }
159
+ const properties = schema.properties;
160
+ const required = schema.required.filter((key) => typeof key === "string" && Object.hasOwn(properties, key));
161
+ if (required.length > 0) schema.required = required;
162
+ else delete schema.required;
163
+ return schema;
164
+ }
165
+ function cleanSchemaForGeminiWithDefs(schema, defs, refStack) {
166
+ if (!schema || typeof schema !== "object") return schema;
167
+ if (Array.isArray(schema)) return schema.map((item) => cleanSchemaForGeminiWithDefs(item, defs, refStack));
168
+ const obj = schema;
169
+ const nextDefs = extendSchemaDefs$1(defs, obj);
170
+ const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
171
+ if (refValue) {
172
+ if (refStack?.has(refValue)) return {};
173
+ const resolved = tryResolveLocalRef$1(refValue, nextDefs);
174
+ if (resolved) {
175
+ const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
176
+ nextRefStack.add(refValue);
177
+ const cleaned = cleanSchemaForGeminiWithDefs(resolved, nextDefs, nextRefStack);
178
+ if (!cleaned || typeof cleaned !== "object" || Array.isArray(cleaned)) return cleaned;
179
+ const result = { ...cleaned };
180
+ copySchemaMeta$1(obj, result);
181
+ return result;
182
+ }
183
+ const result = {};
184
+ copySchemaMeta$1(obj, result);
185
+ return result;
186
+ }
187
+ const hasAnyOf = "anyOf" in obj && Array.isArray(obj.anyOf);
188
+ const hasOneOf = "oneOf" in obj && Array.isArray(obj.oneOf);
189
+ let cleanedAnyOf = hasAnyOf ? obj.anyOf.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack)) : void 0;
190
+ let cleanedOneOf = hasOneOf ? obj.oneOf.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack)) : void 0;
191
+ if (hasAnyOf) {
192
+ const simplified = simplifyUnionVariants({
193
+ obj,
194
+ variants: cleanedAnyOf ?? []
195
+ });
196
+ cleanedAnyOf = simplified.variants;
197
+ if ("simplified" in simplified) return simplified.simplified;
198
+ }
199
+ if (hasOneOf) {
200
+ const simplified = simplifyUnionVariants({
201
+ obj,
202
+ variants: cleanedOneOf ?? []
203
+ });
204
+ cleanedOneOf = simplified.variants;
205
+ if ("simplified" in simplified) return simplified.simplified;
206
+ }
207
+ const cleaned = {};
208
+ for (const [key, value] of Object.entries(obj)) {
209
+ if (GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS.has(key)) continue;
210
+ if (key === "const") {
211
+ cleaned.enum = [value];
212
+ continue;
213
+ }
214
+ if (key === "required" && Array.isArray(value) && value.length === 0) continue;
215
+ if (key === "type" && (hasAnyOf || hasOneOf)) continue;
216
+ if (key === "type" && Array.isArray(value) && value.every((entry) => typeof entry === "string")) {
217
+ const types = value.filter((entry) => entry !== "null");
218
+ cleaned.type = types.length === 1 ? types[0] : types;
219
+ continue;
220
+ }
221
+ if (key === "properties") if (value && typeof value === "object" && !Array.isArray(value)) cleaned[key] = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, cleanSchemaForGeminiWithDefs(v, nextDefs, refStack)]));
222
+ else cleaned[key] = {};
223
+ else if (key === "items" && value) if (Array.isArray(value)) cleaned[key] = value.map((entry) => cleanSchemaForGeminiWithDefs(entry, nextDefs, refStack));
224
+ else if (typeof value === "object") cleaned[key] = cleanSchemaForGeminiWithDefs(value, nextDefs, refStack);
225
+ else cleaned[key] = value;
226
+ else if (key === "anyOf" && Array.isArray(value)) cleaned[key] = cleanedAnyOf ?? value.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack));
227
+ else if (key === "oneOf" && Array.isArray(value)) cleaned[key] = cleanedOneOf ?? value.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack));
228
+ else if (key === "allOf" && Array.isArray(value)) cleaned[key] = value.map((variant) => cleanSchemaForGeminiWithDefs(variant, nextDefs, refStack));
229
+ else cleaned[key] = value;
230
+ }
231
+ if (cleaned.anyOf && Array.isArray(cleaned.anyOf)) {
232
+ const flattened = flattenUnionFallback(cleaned, cleaned.anyOf);
233
+ if (flattened) return sanitizeRequiredFields(flattened);
234
+ }
235
+ if (cleaned.oneOf && Array.isArray(cleaned.oneOf)) {
236
+ const flattened = flattenUnionFallback(cleaned, cleaned.oneOf);
237
+ if (flattened) return sanitizeRequiredFields(flattened);
238
+ }
239
+ return sanitizeRequiredFields(cleaned);
240
+ }
241
+ /**
242
+ * Last-resort flattening for anyOf/oneOf arrays that could not be simplified
243
+ * by `simplifyUnionVariants`. Picks a representative type so the schema is
244
+ * accepted by Google's restricted JSON Schema validation.
245
+ */
246
+ function flattenUnionFallback(obj, variants) {
247
+ const objects = variants.filter((v) => Boolean(v) && typeof v === "object");
248
+ if (objects.length === 0) return;
249
+ const types = new Set(objects.map((v) => v.type).filter(Boolean));
250
+ if (objects.length === 1) {
251
+ const merged = { ...objects[0] };
252
+ copySchemaMeta$1(obj, merged);
253
+ return merged;
254
+ }
255
+ if (types.size === 1) {
256
+ const merged = { type: Array.from(types)[0] };
257
+ copySchemaMeta$1(obj, merged);
258
+ return merged;
259
+ }
260
+ const first = objects[0];
261
+ if (first?.type) {
262
+ const merged = { type: first.type };
263
+ copySchemaMeta$1(obj, merged);
264
+ return merged;
265
+ }
266
+ const merged = {};
267
+ copySchemaMeta$1(obj, merged);
268
+ return merged;
269
+ }
270
+ function cleanSchemaForGemini(schema) {
271
+ if (!schema || typeof schema !== "object") return schema;
272
+ if (Array.isArray(schema)) return schema.map(cleanSchemaForGemini);
273
+ return cleanSchemaForGeminiWithDefs(schema, extendSchemaDefs$1(void 0, schema), void 0);
274
+ }
275
+ //#endregion
276
+ //#region packages/ai/src/providers/schema-keyword-strip.ts
277
+ /** Recursively remove schema keywords unsupported by a target provider/tool surface. */
278
+ function stripUnsupportedSchemaKeywords(schema, unsupportedKeywords) {
279
+ if (!schema || typeof schema !== "object") return schema;
280
+ if (Array.isArray(schema)) return schema.map((entry) => stripUnsupportedSchemaKeywords(entry, unsupportedKeywords));
281
+ const obj = schema;
282
+ const cleaned = {};
283
+ for (const [key, value] of Object.entries(obj)) {
284
+ if (unsupportedKeywords.has(key)) continue;
285
+ if (key === "properties" && value && typeof value === "object" && !Array.isArray(value)) {
286
+ cleaned[key] = Object.fromEntries(Object.entries(value).map(([childKey, childValue]) => [childKey, stripUnsupportedSchemaKeywords(childValue, unsupportedKeywords)]));
287
+ continue;
288
+ }
289
+ if (key === "items" && value && typeof value === "object") {
290
+ cleaned[key] = Array.isArray(value) ? value.map((entry) => stripUnsupportedSchemaKeywords(entry, unsupportedKeywords)) : stripUnsupportedSchemaKeywords(value, unsupportedKeywords);
291
+ continue;
292
+ }
293
+ if ((key === "anyOf" || key === "oneOf" || key === "allOf") && Array.isArray(value)) {
294
+ cleaned[key] = value.map((entry) => stripUnsupportedSchemaKeywords(entry, unsupportedKeywords));
295
+ continue;
296
+ }
297
+ cleaned[key] = value;
298
+ }
299
+ return cleaned;
300
+ }
301
+ //#endregion
302
+ //#region packages/ai/src/providers/agent-tools-parameter-schema.ts
303
+ /**
304
+ * Normalizes model-facing tool parameter schemas across provider quirks.
305
+ * Handles local JSON Schema refs, OpenAPI nullable syntax, top-level unions,
306
+ * and provider-specific unsupported keyword stripping.
307
+ */
308
+ /** Extracts the compat record whether callers pass a model (`{ compat }`) or the compat itself. */
309
+ function extractToolSchemaModelCompat(modelOrCompat) {
310
+ if (!modelOrCompat || typeof modelOrCompat !== "object") return;
311
+ if ("compat" in modelOrCompat) {
312
+ const compat = modelOrCompat.compat;
313
+ return compat && typeof compat === "object" ? compat : void 0;
314
+ }
315
+ return modelOrCompat;
316
+ }
317
+ /** JSON Schema keywords this model/provider rejects in tool schemas. */
318
+ function resolveUnsupportedToolSchemaKeywords(modelOrCompat) {
319
+ const keywords = extractToolSchemaModelCompat(modelOrCompat)?.unsupportedToolSchemaKeywords ?? [];
320
+ return new Set(normalizeStringEntries(keywords.filter((keyword) => typeof keyword === "string")));
321
+ }
322
+ /** Whether empty `items: {}` on array schemas must be omitted for this model/provider. */
323
+ function shouldOmitEmptyArrayItems(modelOrCompat) {
324
+ return extractToolSchemaModelCompat(modelOrCompat)?.omitEmptyArrayItems === true;
325
+ }
326
+ const MAX_TOOL_PARAMETER_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
327
+ const toolParameterSchemaCache = /* @__PURE__ */ new WeakMap();
328
+ function resolveToolParameterSchemaCacheKey(options) {
329
+ const normalizedProvider = normalizeLowercaseStringOrEmpty(options?.modelProvider);
330
+ const normalizedModelId = normalizeLowercaseStringOrEmpty(options?.modelId);
331
+ const toolSchemaProfile = normalizeLowercaseStringOrEmpty(options?.modelCompat?.toolSchemaProfile);
332
+ const unsupportedKeywords = Array.from(resolveUnsupportedToolSchemaKeywords(options?.modelCompat)).toSorted();
333
+ const omitEmptyArrayItems = shouldOmitEmptyArrayItems(options?.modelCompat);
334
+ return JSON.stringify([
335
+ normalizedProvider,
336
+ normalizedModelId,
337
+ toolSchemaProfile,
338
+ unsupportedKeywords,
339
+ omitEmptyArrayItems
340
+ ]);
341
+ }
342
+ function getCachedToolParameterSchema(schema, key) {
343
+ return toolParameterSchemaCache.get(schema)?.find((entry) => entry.key === key)?.value;
344
+ }
345
+ function rememberCachedToolParameterSchema(schema, key, value) {
346
+ const entries = toolParameterSchemaCache.get(schema) ?? [];
347
+ toolParameterSchemaCache.set(schema, [{
348
+ key,
349
+ value
350
+ }, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_TOOL_PARAMETER_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
351
+ return value;
352
+ }
353
+ function isGeminiModelId(modelId) {
354
+ return /(?:^|[/:])gemini(?:$|[-/:.])/.test(modelId);
355
+ }
356
+ function extractEnumValues(schema) {
357
+ if (!schema || typeof schema !== "object") return;
358
+ const record = schema;
359
+ if (Array.isArray(record.enum)) return record.enum;
360
+ if ("const" in record) return [record.const];
361
+ const variants = Array.isArray(record.anyOf) ? record.anyOf : Array.isArray(record.oneOf) ? record.oneOf : null;
362
+ if (variants) {
363
+ const values = variants.flatMap((variant) => {
364
+ return extractEnumValues(variant) ?? [];
365
+ });
366
+ return values.length > 0 ? values : void 0;
367
+ }
368
+ }
369
+ function mergePropertySchemas(existing, incoming) {
370
+ if (!existing) return incoming;
371
+ if (!incoming) return existing;
372
+ const existingEnum = extractEnumValues(existing);
373
+ const incomingEnum = extractEnumValues(incoming);
374
+ if (existingEnum || incomingEnum) {
375
+ const values = uniqueValues([...existingEnum ?? [], ...incomingEnum ?? []]);
376
+ const merged = {};
377
+ for (const source of [existing, incoming]) {
378
+ if (!source || typeof source !== "object") continue;
379
+ const record = source;
380
+ for (const key of [
381
+ "title",
382
+ "description",
383
+ "default"
384
+ ]) if (!(key in merged) && key in record) merged[key] = record[key];
385
+ }
386
+ const types = new Set(values.map((value) => typeof value));
387
+ if (types.size === 1) merged.type = Array.from(types)[0];
388
+ merged.enum = values;
389
+ return merged;
390
+ }
391
+ return existing;
392
+ }
393
+ function setOwnSchemaProperty(target, key, value) {
394
+ Object.defineProperty(target, key, {
395
+ value,
396
+ enumerable: true,
397
+ configurable: true,
398
+ writable: true
399
+ });
400
+ }
401
+ function hasTopLevelArrayKeyword(schemaRecord, key) {
402
+ return Array.isArray(schemaRecord[key]);
403
+ }
404
+ function getFlattenableVariantKey(schemaRecord) {
405
+ if (hasTopLevelArrayKeyword(schemaRecord, "anyOf")) return "anyOf";
406
+ if (hasTopLevelArrayKeyword(schemaRecord, "oneOf")) return "oneOf";
407
+ return null;
408
+ }
409
+ function getTopLevelConditionalKey(schemaRecord) {
410
+ return getFlattenableVariantKey(schemaRecord) ?? (hasTopLevelArrayKeyword(schemaRecord, "allOf") ? "allOf" : null);
411
+ }
412
+ function hasTopLevelObjectSchema(schemaRecord, conditionalKey) {
413
+ return schemaRecord.type === "object" && isRecord(schemaRecord.properties) && conditionalKey === null;
414
+ }
415
+ function isObjectLikeSchemaMissingType(schemaRecord, conditionalKey) {
416
+ return !("type" in schemaRecord) && (isRecord(schemaRecord.properties) || Array.isArray(schemaRecord.required)) && conditionalKey === null;
417
+ }
418
+ function isTypedObjectSchemaMissingValidProperties(schemaRecord, conditionalKey) {
419
+ return schemaRecord.type === "object" && !isRecord(schemaRecord.properties) && conditionalKey === null;
420
+ }
421
+ function isTrulyEmptySchema(schemaRecord) {
422
+ return Object.keys(schemaRecord).length === 0;
423
+ }
424
+ function normalizeArraySchemasMissingItems(schema) {
425
+ if (!isRecord(schema)) return schema;
426
+ let changed = false;
427
+ const nextSchema = { ...schema };
428
+ if (nextSchema.type === "array" && nextSchema.items === void 0) {
429
+ nextSchema.items = {};
430
+ changed = true;
431
+ }
432
+ const normalizeSchemaValue = (key) => {
433
+ if (!(key in nextSchema)) return;
434
+ const value = nextSchema[key];
435
+ if (Array.isArray(value)) {
436
+ const normalized = value.map(normalizeArraySchemasMissingItems);
437
+ if (normalized.some((entry, index) => entry !== value[index])) {
438
+ nextSchema[key] = normalized;
439
+ changed = true;
440
+ }
441
+ return;
442
+ }
443
+ const normalized = normalizeArraySchemasMissingItems(value);
444
+ if (normalized !== value) {
445
+ nextSchema[key] = normalized;
446
+ changed = true;
447
+ }
448
+ };
449
+ for (const key of [
450
+ "items",
451
+ "contains",
452
+ "additionalProperties",
453
+ "propertyNames",
454
+ "not",
455
+ "if",
456
+ "then",
457
+ "else"
458
+ ]) normalizeSchemaValue(key);
459
+ for (const key of [
460
+ "anyOf",
461
+ "oneOf",
462
+ "allOf",
463
+ "prefixItems"
464
+ ]) normalizeSchemaValue(key);
465
+ for (const key of [
466
+ "properties",
467
+ "patternProperties",
468
+ "dependentSchemas",
469
+ "$defs",
470
+ "definitions"
471
+ ]) {
472
+ const value = nextSchema[key];
473
+ if (!isRecord(value)) continue;
474
+ let entriesChanged = false;
475
+ const normalizedEntries = Object.entries(value).map(([entryKey, entryValue]) => {
476
+ const normalizedEntryValue = normalizeArraySchemasMissingItems(entryValue);
477
+ if (normalizedEntryValue !== entryValue) entriesChanged = true;
478
+ return [entryKey, normalizedEntryValue];
479
+ });
480
+ if (entriesChanged) {
481
+ nextSchema[key] = Object.fromEntries(normalizedEntries);
482
+ changed = true;
483
+ }
484
+ }
485
+ return changed ? nextSchema : schema;
486
+ }
487
+ function schemaAllowsArrayType(schema) {
488
+ const type = schema.type;
489
+ return type === "array" || Array.isArray(type) && type.includes("array");
490
+ }
491
+ const ARRAY_ITEMS_SCHEMA_OBJECT_KEYS = /* @__PURE__ */ new Set([
492
+ "additionalProperties",
493
+ "contains",
494
+ "else",
495
+ "if",
496
+ "items",
497
+ "not",
498
+ "propertyNames",
499
+ "then"
500
+ ]);
501
+ const ARRAY_ITEMS_SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set([
502
+ "allOf",
503
+ "anyOf",
504
+ "oneOf",
505
+ "prefixItems"
506
+ ]);
507
+ const ARRAY_ITEMS_SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
508
+ "$defs",
509
+ "definitions",
510
+ "dependentSchemas",
511
+ "patternProperties",
512
+ "properties"
513
+ ]);
514
+ function stripEmptyArrayItemsFromArraySchemas(schema) {
515
+ if (Array.isArray(schema)) {
516
+ let changed = false;
517
+ const entries = schema.map((entry) => {
518
+ const next = stripEmptyArrayItemsFromArraySchemas(entry);
519
+ changed ||= next !== entry;
520
+ return next;
521
+ });
522
+ return changed ? entries : schema;
523
+ }
524
+ if (!isRecord(schema)) return schema;
525
+ let changed = false;
526
+ const entries = Object.entries(schema).flatMap(([key, value]) => {
527
+ if (key === "items" && schemaAllowsArrayType(schema) && isRecord(value) && isTrulyEmptySchema(value)) {
528
+ changed = true;
529
+ return [];
530
+ }
531
+ if (ARRAY_ITEMS_SCHEMA_OBJECT_KEYS.has(key)) {
532
+ const next = stripEmptyArrayItemsFromArraySchemas(value);
533
+ changed ||= next !== value;
534
+ return [[key, next]];
535
+ }
536
+ if (ARRAY_ITEMS_SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
537
+ const next = stripEmptyArrayItemsFromArraySchemas(value);
538
+ changed ||= next !== value;
539
+ return [[key, next]];
540
+ }
541
+ if (ARRAY_ITEMS_SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
542
+ let mapChanged = false;
543
+ const next = Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => {
544
+ const entryNext = stripEmptyArrayItemsFromArraySchemas(entryValue);
545
+ mapChanged ||= entryNext !== entryValue;
546
+ return [entryKey, entryNext];
547
+ }));
548
+ changed ||= mapChanged;
549
+ return [[key, mapChanged ? next : value]];
550
+ }
551
+ return [[key, value]];
552
+ });
553
+ return changed ? Object.fromEntries(entries) : schema;
554
+ }
555
+ function copySchemaMeta(from, to) {
556
+ for (const key of [
557
+ "title",
558
+ "description",
559
+ "default"
560
+ ]) if (key in from && from[key] !== void 0) to[key] = from[key];
561
+ }
562
+ function extendSchemaDefs(defs, schema) {
563
+ const defsEntry = schema.$defs && typeof schema.$defs === "object" && !Array.isArray(schema.$defs) ? schema.$defs : void 0;
564
+ const legacyDefsEntry = schema.definitions && typeof schema.definitions === "object" && !Array.isArray(schema.definitions) ? schema.definitions : void 0;
565
+ if (!defsEntry && !legacyDefsEntry) return defs;
566
+ const next = defs ? {
567
+ $defs: new Map(defs.$defs),
568
+ definitions: new Map(defs.definitions)
569
+ } : {
570
+ $defs: /* @__PURE__ */ new Map(),
571
+ definitions: /* @__PURE__ */ new Map()
572
+ };
573
+ if (defsEntry) for (const [key, value] of Object.entries(defsEntry)) next.$defs.set(key, value);
574
+ if (legacyDefsEntry) for (const [key, value] of Object.entries(legacyDefsEntry)) next.definitions.set(key, value);
575
+ return next;
576
+ }
577
+ function decodeJsonPointerSegment(segment) {
578
+ return segment.replaceAll("~1", "/").replaceAll("~0", "~");
579
+ }
580
+ function resolveJsonPointerPath(value, segments) {
581
+ let current = value;
582
+ for (const segment of segments) {
583
+ if (!current || typeof current !== "object") return;
584
+ const key = decodeJsonPointerSegment(segment);
585
+ if (Array.isArray(current)) {
586
+ const index = Number(key);
587
+ if (!Number.isInteger(index) || index < 0 || index >= current.length) return;
588
+ current = current[index];
589
+ continue;
590
+ }
591
+ const record = current;
592
+ if (!Object.hasOwn(record, key)) return;
593
+ current = record[key];
594
+ }
595
+ return current;
596
+ }
597
+ function resolveLocalJsonPointer(rootDocument, ref) {
598
+ if (!ref.startsWith("#/")) return;
599
+ return resolveJsonPointerPath(rootDocument, ref.slice(2).split("/"));
600
+ }
601
+ const SCHEMA_MAP_KEYS = /* @__PURE__ */ new Set([
602
+ "$defs",
603
+ "definitions",
604
+ "dependentSchemas",
605
+ "patternProperties",
606
+ "properties"
607
+ ]);
608
+ const SCHEMA_OBJECT_KEYS = /* @__PURE__ */ new Set([
609
+ "additionalProperties",
610
+ "contains",
611
+ "else",
612
+ "if",
613
+ "items",
614
+ "not",
615
+ "propertyNames",
616
+ "then"
617
+ ]);
618
+ const SCHEMA_ARRAY_KEYS = /* @__PURE__ */ new Set([
619
+ "allOf",
620
+ "anyOf",
621
+ "items",
622
+ "oneOf",
623
+ "prefixItems"
624
+ ]);
625
+ const SCHEMA_LITERAL_KEYS = /* @__PURE__ */ new Set([
626
+ "const",
627
+ "default",
628
+ "enum",
629
+ "examples"
630
+ ]);
631
+ function tryResolveLocalRef(ref, defs, rootDocument) {
632
+ const match = ref.match(/^#\/(\$defs|definitions)\/([^/]+)(?:\/(.*))?$/);
633
+ if (match && defs) {
634
+ const namespace = match[1] === "$defs" ? defs.$defs : defs.definitions;
635
+ const name = decodeJsonPointerSegment(match[2] ?? "");
636
+ const resolved = name ? namespace.get(name) : void 0;
637
+ if (resolved !== void 0) return resolveJsonPointerPath(resolved, match[3] ? match[3].split("/") : []);
638
+ }
639
+ return resolveLocalJsonPointer(rootDocument, ref);
640
+ }
641
+ function inlineLocalSchemaRefsWithDefs(schema, defs, refStack, state, rootDocument) {
642
+ if (!schema || typeof schema !== "object") return schema;
643
+ if (Array.isArray(schema)) return schema.map((entry) => inlineLocalSchemaRefsWithDefs(entry, defs, refStack, state, rootDocument));
644
+ const obj = schema;
645
+ const nextDefs = extendSchemaDefs(defs, obj);
646
+ const refValue = typeof obj.$ref === "string" ? obj.$ref : void 0;
647
+ if (refValue) {
648
+ if (refStack?.has(refValue)) return {};
649
+ const resolved = tryResolveLocalRef(refValue, nextDefs, rootDocument);
650
+ if (resolved === void 0) {
651
+ if (refValue.startsWith("#/")) state.unresolvedLocalRefs = true;
652
+ return { ...obj };
653
+ }
654
+ const nextRefStack = refStack ? new Set(refStack) : /* @__PURE__ */ new Set();
655
+ nextRefStack.add(refValue);
656
+ const inlined = inlineLocalSchemaRefsWithDefs(resolved, nextDefs, nextRefStack, state, rootDocument);
657
+ if (!inlined || typeof inlined !== "object" || Array.isArray(inlined)) return inlined;
658
+ const result = { ...inlined };
659
+ copySchemaMeta(obj, result);
660
+ if (obj.nullable === true) result.nullable = true;
661
+ return result;
662
+ }
663
+ const result = {};
664
+ for (const [key, value] of Object.entries(obj)) {
665
+ if (key === "$defs" || key === "definitions" || key === "components") continue;
666
+ if (SCHEMA_LITERAL_KEYS.has(key)) {
667
+ setOwnSchemaProperty(result, key, value);
668
+ continue;
669
+ }
670
+ if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
671
+ setOwnSchemaProperty(result, key, Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => [entryKey, inlineLocalSchemaRefsWithDefs(entryValue, nextDefs, refStack, state, rootDocument)])));
672
+ continue;
673
+ }
674
+ if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) {
675
+ setOwnSchemaProperty(result, key, inlineLocalSchemaRefsWithDefs(value, nextDefs, refStack, state, rootDocument));
676
+ continue;
677
+ }
678
+ if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
679
+ setOwnSchemaProperty(result, key, value.map((entry) => inlineLocalSchemaRefsWithDefs(entry, nextDefs, refStack, state, rootDocument)));
680
+ continue;
681
+ }
682
+ setOwnSchemaProperty(result, key, value);
683
+ }
684
+ if (state.unresolvedLocalRefs) {
685
+ if ("$defs" in obj) result.$defs = obj.$defs;
686
+ if ("definitions" in obj) result.definitions = obj.definitions;
687
+ if ("components" in obj) result.components = obj.components;
688
+ }
689
+ return result;
690
+ }
691
+ /** Inline local $ref pointers so providers receive self-contained tool schemas. */
692
+ function inlineLocalToolSchemaRefs(schema) {
693
+ if (!schema || typeof schema !== "object") return schema;
694
+ return inlineLocalSchemaRefsWithDefs(schema, extendSchemaDefs(void 0, schema), void 0, { unresolvedLocalRefs: false }, schema);
695
+ }
696
+ const OPENAPI_SCHEMA_ANNOTATION_KEYS = /* @__PURE__ */ new Set([
697
+ "discriminator",
698
+ "externalDocs",
699
+ "readOnly",
700
+ "writeOnly",
701
+ "xml",
702
+ "example"
703
+ ]);
704
+ function appendNullSchemaType(type) {
705
+ if (type === "null") return type;
706
+ if (typeof type === "string") return [type, "null"];
707
+ if (Array.isArray(type)) return type.includes("null") ? type : [...type, "null"];
708
+ return type;
709
+ }
710
+ function isNullSchemaLike(schema) {
711
+ if (!isRecord(schema)) return false;
712
+ if (schema.type === "null") return true;
713
+ if (Array.isArray(schema.type) && schema.type.includes("null")) return true;
714
+ if ("const" in schema && schema.const === null) return true;
715
+ return Array.isArray(schema.enum) && schema.enum.includes(null);
716
+ }
717
+ function hasOpenApiComposition(schema) {
718
+ return [
719
+ "allOf",
720
+ "anyOf",
721
+ "oneOf"
722
+ ].some((key) => Array.isArray(schema[key]));
723
+ }
724
+ function schemaCompositionAlreadyAllowsNull(schema) {
725
+ return Array.isArray(schema.anyOf) && schema.anyOf.some(isNullSchemaLike) || Array.isArray(schema.oneOf) && schema.oneOf.some(isNullSchemaLike);
726
+ }
727
+ function wrapNullableComposedSchema(schema) {
728
+ if (schemaCompositionAlreadyAllowsNull(schema)) return schema;
729
+ const wrapped = { anyOf: [schema, { type: "null" }] };
730
+ copySchemaMeta(schema, wrapped);
731
+ return wrapped;
732
+ }
733
+ function normalizeOpenApiSchemaKeywords(schema) {
734
+ if (Array.isArray(schema)) {
735
+ let changed = false;
736
+ const normalized = schema.map((entry) => {
737
+ const next = normalizeOpenApiSchemaKeywords(entry);
738
+ changed ||= next !== entry;
739
+ return next;
740
+ });
741
+ return changed ? normalized : schema;
742
+ }
743
+ if (!isRecord(schema)) return schema;
744
+ let changed = false;
745
+ const nullable = schema.nullable === true;
746
+ const normalized = {};
747
+ for (const [key, value] of Object.entries(schema)) {
748
+ if (key === "nullable" || OPENAPI_SCHEMA_ANNOTATION_KEYS.has(key)) {
749
+ changed = true;
750
+ continue;
751
+ }
752
+ if (SCHEMA_LITERAL_KEYS.has(key)) {
753
+ normalized[key] = value;
754
+ continue;
755
+ }
756
+ if (SCHEMA_MAP_KEYS.has(key) && isRecord(value)) {
757
+ let mapChanged = false;
758
+ const next = Object.fromEntries(Object.entries(value).map(([entryKey, entryValue]) => {
759
+ const nextEntry = normalizeOpenApiSchemaKeywords(entryValue);
760
+ mapChanged ||= nextEntry !== entryValue;
761
+ return [entryKey, nextEntry];
762
+ }));
763
+ normalized[key] = mapChanged ? next : value;
764
+ changed ||= mapChanged;
765
+ continue;
766
+ }
767
+ if (key === "components") {
768
+ normalized[key] = value;
769
+ continue;
770
+ }
771
+ if (SCHEMA_OBJECT_KEYS.has(key) && isRecord(value)) {
772
+ const next = normalizeOpenApiSchemaKeywords(value);
773
+ normalized[key] = next;
774
+ changed ||= next !== value;
775
+ continue;
776
+ }
777
+ if (SCHEMA_ARRAY_KEYS.has(key) && Array.isArray(value)) {
778
+ const next = value.map(normalizeOpenApiSchemaKeywords);
779
+ normalized[key] = next;
780
+ changed ||= next.some((entry, index) => entry !== value[index]);
781
+ continue;
782
+ }
783
+ normalized[key] = value;
784
+ }
785
+ if (nullable) {
786
+ if (hasOpenApiComposition(normalized)) return wrapNullableComposedSchema(normalized);
787
+ if ("type" in normalized) {
788
+ const nextType = appendNullSchemaType(normalized.type);
789
+ if (nextType !== normalized.type) normalized.type = nextType;
790
+ }
791
+ if (Array.isArray(normalized.enum) && !normalized.enum.includes(null)) normalized.enum = [...normalized.enum, null];
792
+ }
793
+ return changed || nullable ? normalized : schema;
794
+ }
795
+ function normalizeToolParameterSchemaUncached(schema, options) {
796
+ const inlinedSchema = normalizeOpenApiSchemaKeywords(inlineLocalToolSchemaRefs(schema));
797
+ const schemaRecord = inlinedSchema && typeof inlinedSchema === "object" ? inlinedSchema : void 0;
798
+ if (!schemaRecord) return inlinedSchema;
799
+ const normalizedProvider = normalizeLowercaseStringOrEmpty(options?.modelProvider);
800
+ const normalizedModelId = normalizeLowercaseStringOrEmpty(options?.modelId);
801
+ const normalizedToolSchemaProfile = normalizeLowercaseStringOrEmpty(options?.modelCompat?.toolSchemaProfile);
802
+ const isGeminiProvider = normalizedProvider.includes("google") || normalizedProvider.includes("gemini") || isGeminiModelId(normalizedModelId) || normalizedToolSchemaProfile === "gemini";
803
+ const isAnthropicProvider = normalizedProvider.includes("anthropic");
804
+ const unsupportedToolSchemaKeywords = resolveUnsupportedToolSchemaKeywords(options?.modelCompat);
805
+ const omitEmptyArrayItems = shouldOmitEmptyArrayItems(options?.modelCompat);
806
+ function applyProviderCleaning(s) {
807
+ const normalizedSchema = normalizeArraySchemasMissingItems(s);
808
+ const arrayItemsCompatibleSchema = omitEmptyArrayItems ? stripEmptyArrayItemsFromArraySchemas(normalizedSchema) : normalizedSchema;
809
+ if (isGeminiProvider && !isAnthropicProvider) {
810
+ const geminiCompatibleSchema = cleanSchemaForGemini(arrayItemsCompatibleSchema);
811
+ return unsupportedToolSchemaKeywords.size > 0 ? stripUnsupportedSchemaKeywords(geminiCompatibleSchema, unsupportedToolSchemaKeywords) : geminiCompatibleSchema;
812
+ }
813
+ if (unsupportedToolSchemaKeywords.size > 0) return stripUnsupportedSchemaKeywords(arrayItemsCompatibleSchema, unsupportedToolSchemaKeywords);
814
+ return arrayItemsCompatibleSchema;
815
+ }
816
+ const conditionalKey = getTopLevelConditionalKey(schemaRecord);
817
+ const flattenableVariantKey = getFlattenableVariantKey(schemaRecord);
818
+ if (hasTopLevelObjectSchema(schemaRecord, conditionalKey)) return applyProviderCleaning(schemaRecord);
819
+ if (isObjectLikeSchemaMissingType(schemaRecord, conditionalKey)) return applyProviderCleaning({
820
+ ...schemaRecord,
821
+ type: "object",
822
+ properties: isRecord(schemaRecord.properties) ? schemaRecord.properties : {}
823
+ });
824
+ if (isTypedObjectSchemaMissingValidProperties(schemaRecord, conditionalKey)) return applyProviderCleaning({
825
+ ...schemaRecord,
826
+ properties: {}
827
+ });
828
+ if (!flattenableVariantKey) {
829
+ if (isTrulyEmptySchema(schemaRecord)) return applyProviderCleaning({
830
+ type: "object",
831
+ properties: {}
832
+ });
833
+ if (conditionalKey === "allOf") return applyProviderCleaning(inlinedSchema);
834
+ return applyProviderCleaning(inlinedSchema);
835
+ }
836
+ const variants = schemaRecord[flattenableVariantKey];
837
+ const mergedProperties = {};
838
+ const requiredCounts = /* @__PURE__ */ new Map();
839
+ let objectVariants = 0;
840
+ for (const entry of variants) {
841
+ if (!entry || typeof entry !== "object") continue;
842
+ const props = entry.properties;
843
+ if (!props || typeof props !== "object") continue;
844
+ objectVariants += 1;
845
+ for (const [key, value] of Object.entries(props)) {
846
+ if (!(key in mergedProperties)) {
847
+ mergedProperties[key] = value;
848
+ continue;
849
+ }
850
+ mergedProperties[key] = mergePropertySchemas(mergedProperties[key], value);
851
+ }
852
+ const required = Array.isArray(entry.required) ? entry.required : [];
853
+ for (const key of required) {
854
+ if (typeof key !== "string") continue;
855
+ requiredCounts.set(key, (requiredCounts.get(key) ?? 0) + 1);
856
+ }
857
+ }
858
+ const baseRequired = Array.isArray(schemaRecord.required) ? schemaRecord.required.filter((key) => typeof key === "string") : void 0;
859
+ const mergedRequired = baseRequired && baseRequired.length > 0 ? baseRequired : objectVariants > 0 ? Array.from(requiredCounts.entries()).filter(([, count]) => count === objectVariants).map(([key]) => key) : void 0;
860
+ const nextSchema = { ...schemaRecord };
861
+ return applyProviderCleaning({
862
+ type: "object",
863
+ ...typeof nextSchema.title === "string" ? { title: nextSchema.title } : {},
864
+ ...typeof nextSchema.description === "string" ? { description: nextSchema.description } : {},
865
+ properties: Object.keys(mergedProperties).length > 0 ? mergedProperties : schemaRecord.properties ?? {},
866
+ ...mergedRequired && mergedRequired.length > 0 ? { required: mergedRequired } : {},
867
+ additionalProperties: "additionalProperties" in schemaRecord ? schemaRecord.additionalProperties : true
868
+ });
869
+ }
870
+ /** Return a provider-compatible JSON schema for a model-facing tool. */
871
+ function normalizeToolParameterSchema(schema, options) {
872
+ if (!schema || typeof schema !== "object") return normalizeToolParameterSchemaUncached(schema, options);
873
+ const cacheKey = resolveToolParameterSchemaCacheKey(options);
874
+ const cached = getCachedToolParameterSchema(schema, cacheKey);
875
+ if (cached) return cached;
876
+ return rememberCachedToolParameterSchema(schema, cacheKey, normalizeToolParameterSchemaUncached(schema, options));
877
+ }
878
+ //#endregion
879
+ //#region packages/ai/src/providers/openai-reasoning-effort.ts
880
+ /**
881
+ * OpenAI-compatible reasoning-effort normalization. Different GPT families
882
+ * expose different accepted effort enums, so callers map requested values here
883
+ * before constructing provider payloads.
884
+ */
885
+ const GPT_5_REASONING_EFFORTS = [
886
+ "minimal",
887
+ "low",
888
+ "medium",
889
+ "high"
890
+ ];
891
+ const GPT_51_REASONING_EFFORTS = [
892
+ "none",
893
+ "low",
894
+ "medium",
895
+ "high"
896
+ ];
897
+ const GPT_52_REASONING_EFFORTS = [
898
+ "none",
899
+ "low",
900
+ "medium",
901
+ "high",
902
+ "xhigh"
903
+ ];
904
+ const GPT_56_REASONING_EFFORTS = [
905
+ "none",
906
+ "low",
907
+ "medium",
908
+ "high",
909
+ "xhigh",
910
+ "max"
911
+ ];
912
+ const GPT_CODEX_REASONING_EFFORTS = [
913
+ "low",
914
+ "medium",
915
+ "high",
916
+ "xhigh"
917
+ ];
918
+ const GPT_PRO_REASONING_EFFORTS = [
919
+ "medium",
920
+ "high",
921
+ "xhigh"
922
+ ];
923
+ const GPT_5_PRO_REASONING_EFFORTS = ["high"];
924
+ const GPT_51_CODEX_MAX_REASONING_EFFORTS = [
925
+ "none",
926
+ "medium",
927
+ "high",
928
+ "xhigh"
929
+ ];
930
+ const GPT_51_CODEX_MINI_REASONING_EFFORTS = ["medium"];
931
+ const GENERIC_REASONING_EFFORTS = [
932
+ "low",
933
+ "medium",
934
+ "high"
935
+ ];
936
+ function normalizeModelId(id) {
937
+ return normalizeLowercaseStringOrEmpty(id ?? "").replace(/-\d{4}-\d{2}-\d{2}$/u, "");
938
+ }
939
+ /** Return whether a model is the GPT-5.4 mini family. */
940
+ function isOpenAIGpt54MiniModel(model) {
941
+ const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
942
+ return /^gpt-5\.4-mini(?:-|$)/u.test(id);
943
+ }
944
+ /** Return whether a model is the GPT-5.5 family. */
945
+ function isOpenAIGpt55Model(model) {
946
+ const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
947
+ const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
948
+ return /^gpt-5\.5(?:-|$)/u.test(id) || /^gpt-5\.5(?:\s|\(|-|$)/u.test(name);
949
+ }
950
+ /** Return whether a model is the GPT-5.6 family. */
951
+ function isOpenAIGpt56Model(model) {
952
+ const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
953
+ const name = normalizeModelId(typeof model.name === "string" ? model.name : void 0);
954
+ return /^gpt-5\.6(?:-|$)/u.test(id) || /^gpt-5\.6(?:\s|\(|-|$)/u.test(name);
955
+ }
956
+ /** Normalize user-facing reasoning effort names to API effort names. */
957
+ function normalizeOpenAIReasoningEffort(effort) {
958
+ return effort === "minimal" ? "minimal" : effort;
959
+ }
960
+ function readCompatReasoningEfforts(compat) {
961
+ if (!compat || typeof compat !== "object") return;
962
+ if (compat.supportsReasoningEffort === false) return [];
963
+ const raw = compat.supportedReasoningEfforts;
964
+ if (!Array.isArray(raw)) return;
965
+ const supported = uniqueStrings(normalizeStringEntries(raw.filter((value) => typeof value === "string")));
966
+ return supported.length > 0 ? supported : void 0;
967
+ }
968
+ function isDisabledReasoningEffort(effort) {
969
+ return effort === "none" || effort === "off";
970
+ }
971
+ /** Resolve the reasoning efforts accepted by a specific OpenAI-compatible model. */
972
+ function resolveOpenAISupportedReasoningEfforts(model) {
973
+ const compatEfforts = readCompatReasoningEfforts(model.compat);
974
+ if (compatEfforts) return compatEfforts;
975
+ const id = normalizeModelId(typeof model.id === "string" ? model.id : void 0);
976
+ if (/^gpt-5\.6(?:-|$)/u.test(id)) return GPT_56_REASONING_EFFORTS;
977
+ if (id === "gpt-5.1-codex-mini") return GPT_51_CODEX_MINI_REASONING_EFFORTS;
978
+ if (id === "gpt-5.1-codex-max") return GPT_51_CODEX_MAX_REASONING_EFFORTS;
979
+ if (/^gpt-5(?:\.\d+)?-codex(?:-|$)/u.test(id)) return GPT_CODEX_REASONING_EFFORTS;
980
+ if (id === "gpt-5-pro") return GPT_5_PRO_REASONING_EFFORTS;
981
+ if (/^gpt-5\.[2-9](?:\.\d+)?-pro(?:-|$)/u.test(id)) return GPT_PRO_REASONING_EFFORTS;
982
+ if (/^gpt-5\.[2-9](?:\.\d+)?(?:-|$)/u.test(id)) return GPT_52_REASONING_EFFORTS;
983
+ if (/^gpt-5\.1(?:-|$)/u.test(id)) return GPT_51_REASONING_EFFORTS;
984
+ if (/^gpt-5(?:-|$)/u.test(id)) return GPT_5_REASONING_EFFORTS;
985
+ return GENERIC_REASONING_EFFORTS;
986
+ }
987
+ /** Return whether a model accepts a requested reasoning effort. */
988
+ function supportsOpenAIReasoningEffort(model, effort) {
989
+ return resolveOpenAISupportedReasoningEfforts(model).includes(normalizeOpenAIReasoningEffort(effort));
990
+ }
991
+ /** Resolve a requested reasoning effort to the closest value supported by the model. */
992
+ function resolveOpenAIReasoningEffortForModel(params) {
993
+ const requested = normalizeOpenAIReasoningEffort(params.effort);
994
+ const normalized = normalizeOpenAIReasoningEffort(params.fallbackMap?.[requested] ?? requested);
995
+ const supported = resolveOpenAISupportedReasoningEfforts(params.model);
996
+ if (supported.includes(normalized)) return normalized;
997
+ if (requested === "off" && supported.includes("none")) return "none";
998
+ if (isDisabledReasoningEffort(requested) || isDisabledReasoningEffort(normalized)) return;
999
+ if (requested === "minimal" && supported.includes("low")) return "low";
1000
+ if ((requested === "minimal" || requested === "low") && supported.includes("medium")) return "medium";
1001
+ if (requested === "xhigh" && supported.includes("high")) return "high";
1002
+ if (requested === "max" && supported.includes("xhigh")) return "xhigh";
1003
+ return supported.find((effort) => effort !== "none");
1004
+ }
1005
+ //#endregion
1006
+ //#region packages/ai/src/providers/openai-responses-stream-compat.ts
1007
+ const OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE = "output_text";
1008
+ const AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE = "text";
1009
+ const OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE = "response.output_text.delta";
1010
+ const AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE = "response.text.delta";
1011
+ function isResponsesTextContentPartType(type) {
1012
+ return type === "output_text" || type === "text";
1013
+ }
1014
+ function isResponsesTextDeltaEventType(type) {
1015
+ return type === "response.output_text.delta" || type === "response.text.delta";
1016
+ }
1017
+ function isAzureResponsesTextDeltaEventType(type) {
1018
+ return type === AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE;
1019
+ }
1020
+ function isAzureResponsesTextDeltaEvent(event) {
1021
+ return isAzureResponsesTextDeltaEventType(event.type) && typeof event.delta === "string";
1022
+ }
1023
+ function resolveResponsesMessageSnapshotCollapse(params) {
1024
+ const { prior, nextText } = params;
1025
+ if (!prior?.text || !nextText || prior.phase !== params.nextPhase) return { kind: "keep" };
1026
+ if (nextText.length > prior.text.length && nextText.startsWith(prior.text)) return {
1027
+ kind: "extend",
1028
+ text: nextText
1029
+ };
1030
+ return { kind: "keep" };
1031
+ }
1032
+ //#endregion
1033
+ //#region packages/ai/src/providers/openai-tool-schema.ts
1034
+ /**
1035
+ * OpenAI strict JSON-schema normalization for tool inventories and request payloads.
1036
+ *
1037
+ * Caches normalized object inputs by provider compatibility so repeated inventory builds preserve identity.
1038
+ */
1039
+ const MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA = 8;
1040
+ let strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1041
+ function resolveToolSchemaModelCompat(compat) {
1042
+ if (!compat) return;
1043
+ const unsupportedToolSchemaKeywords = Array.isArray(compat.unsupportedToolSchemaKeywords) ? compat.unsupportedToolSchemaKeywords.filter((keyword) => typeof keyword === "string") : [];
1044
+ if (unsupportedToolSchemaKeywords.length === 0 && compat.omitEmptyArrayItems !== true) return;
1045
+ return {
1046
+ ...unsupportedToolSchemaKeywords.length > 0 ? { unsupportedToolSchemaKeywords } : {},
1047
+ ...compat.omitEmptyArrayItems === true ? { omitEmptyArrayItems: true } : {}
1048
+ };
1049
+ }
1050
+ function resolveStrictOpenAISchemaCacheKey(modelCompat) {
1051
+ const compat = resolveToolSchemaModelCompat(modelCompat);
1052
+ return JSON.stringify([[...compat?.unsupportedToolSchemaKeywords ?? []].toSorted(), shouldOmitEmptyArrayItems(compat)]);
1053
+ }
1054
+ function readCachedStrictOpenAISchema(schema, key) {
1055
+ return strictOpenAISchemaCache.get(schema)?.find((entry) => entry.key === key)?.value;
1056
+ }
1057
+ function rememberStrictOpenAISchema(schema, key, value) {
1058
+ const entries = strictOpenAISchemaCache.get(schema) ?? [];
1059
+ strictOpenAISchemaCache.set(schema, [{
1060
+ key,
1061
+ value
1062
+ }, ...entries.filter((entry) => entry.key !== key)].slice(0, MAX_STRICT_SCHEMA_CACHE_ENTRIES_PER_SCHEMA));
1063
+ return value;
1064
+ }
1065
+ function clearOpenAIToolSchemaCacheForTest() {
1066
+ strictOpenAISchemaCache = /* @__PURE__ */ new WeakMap();
1067
+ }
1068
+ /** Normalizes a tool parameter schema into the OpenAI strict JSON-schema subset. */
1069
+ function normalizeStrictOpenAIJsonSchema(schema, modelCompat) {
1070
+ const schemaInput = schema ?? {};
1071
+ if (!schemaInput || typeof schemaInput !== "object") return normalizeStrictOpenAIJsonSchemaRecursive(normalizeToolParameterSchema(schemaInput, { modelCompat: resolveToolSchemaModelCompat(modelCompat) }), 0);
1072
+ const cacheKey = resolveStrictOpenAISchemaCacheKey(modelCompat);
1073
+ const cached = readCachedStrictOpenAISchema(schemaInput, cacheKey);
1074
+ if (cached !== void 0) return cached;
1075
+ return rememberStrictOpenAISchema(schemaInput, cacheKey, normalizeStrictOpenAIJsonSchemaRecursive(normalizeToolParameterSchema(schemaInput, { modelCompat: resolveToolSchemaModelCompat(modelCompat) }), 0));
1076
+ }
1077
+ function normalizeStrictOpenAIJsonSchemaRecursive(schema, depth) {
1078
+ if (Array.isArray(schema)) {
1079
+ let changed = false;
1080
+ const normalized = schema.map((entry) => {
1081
+ const next = normalizeStrictOpenAIJsonSchemaRecursive(entry, depth);
1082
+ changed ||= next !== entry;
1083
+ return next;
1084
+ });
1085
+ return changed ? normalized : schema;
1086
+ }
1087
+ if (!schema || typeof schema !== "object") return schema;
1088
+ const record = schema;
1089
+ let changed = false;
1090
+ const normalized = {};
1091
+ for (const [key, value] of Object.entries(record)) {
1092
+ const next = normalizeStrictOpenAIJsonSchemaRecursive(value, key === "properties" ? depth : depth + 1);
1093
+ normalized[key] = next;
1094
+ changed ||= next !== value;
1095
+ }
1096
+ if (normalized.type === "object") {
1097
+ const properties = normalized.properties && typeof normalized.properties === "object" && !Array.isArray(normalized.properties) ? normalized.properties : void 0;
1098
+ if (properties && Object.keys(properties).length === 0 && !Array.isArray(normalized.required)) {
1099
+ normalized.required = [];
1100
+ changed = true;
1101
+ }
1102
+ if (depth === 0 && !("additionalProperties" in normalized)) {
1103
+ normalized.additionalProperties = false;
1104
+ changed = true;
1105
+ }
1106
+ }
1107
+ return changed ? normalized : schema;
1108
+ }
1109
+ /** Normalizes tool parameters using strict OpenAI rules only when strict mode is active. */
1110
+ function normalizeOpenAIStrictToolParameters(schema, strict, modelCompat) {
1111
+ const toolSchemaCompat = resolveToolSchemaModelCompat(modelCompat);
1112
+ if (!strict) return normalizeToolParameterSchema(schema ?? {}, { modelCompat: toolSchemaCompat });
1113
+ return normalizeStrictOpenAIJsonSchema(schema, toolSchemaCompat);
1114
+ }
1115
+ /** Returns whether a schema already satisfies OpenAI strict tool-schema constraints. */
1116
+ function isStrictOpenAIJsonSchemaCompatible(schema) {
1117
+ return isStrictOpenAIJsonSchemaCompatibleRecursive(normalizeStrictOpenAIJsonSchema(schema));
1118
+ }
1119
+ /** Returns strict-schema diagnostics for an already materialized OpenAI tool projection. */
1120
+ function findOpenAIStrictToolProjectionDiagnostics(projection) {
1121
+ return [...projection.diagnostics.map((diagnostic) => ({
1122
+ toolIndex: diagnostic.toolIndex,
1123
+ ...diagnostic.toolName ? { toolName: diagnostic.toolName } : {},
1124
+ violations: [...diagnostic.violations]
1125
+ })), ...projection.tools.flatMap((tool) => {
1126
+ const violations = findStrictOpenAIJsonSchemaViolations(normalizeStrictOpenAIJsonSchema(tool.parameters), `${tool.name}.parameters`);
1127
+ return violations.length > 0 ? [{
1128
+ toolIndex: tool.toolIndex,
1129
+ toolName: tool.name,
1130
+ violations
1131
+ }] : [];
1132
+ })];
1133
+ }
1134
+ function isStrictOpenAIJsonSchemaCompatibleRecursive(schema) {
1135
+ if (Array.isArray(schema)) return schema.every((entry) => isStrictOpenAIJsonSchemaCompatibleRecursive(entry));
1136
+ if (!schema || typeof schema !== "object") return true;
1137
+ const record = schema;
1138
+ if ("anyOf" in record || "oneOf" in record || "allOf" in record) return false;
1139
+ if (Array.isArray(record.type)) return false;
1140
+ if (record.type === "object" && record.additionalProperties !== false) return false;
1141
+ if (record.type === "object") {
1142
+ const properties = record.properties && typeof record.properties === "object" && !Array.isArray(record.properties) ? record.properties : {};
1143
+ const required = Array.isArray(record.required) ? record.required.filter((entry) => typeof entry === "string") : void 0;
1144
+ if (!required) return false;
1145
+ const requiredSet = new Set(required);
1146
+ if (Object.keys(properties).some((key) => !requiredSet.has(key))) return false;
1147
+ }
1148
+ return Object.entries(record).every(([key, entry]) => {
1149
+ if (key === "properties" && entry && typeof entry === "object" && !Array.isArray(entry)) return Object.values(entry).every((value) => isStrictOpenAIJsonSchemaCompatibleRecursive(value));
1150
+ return isStrictOpenAIJsonSchemaCompatibleRecursive(entry);
1151
+ });
1152
+ }
1153
+ function findStrictOpenAIJsonSchemaViolations(schema, path) {
1154
+ if (Array.isArray(schema)) return schema.flatMap((entry, index) => findStrictOpenAIJsonSchemaViolations(entry, `${path}[${index}]`));
1155
+ if (!schema || typeof schema !== "object") return [];
1156
+ const record = schema;
1157
+ const violations = [];
1158
+ for (const key of [
1159
+ "anyOf",
1160
+ "oneOf",
1161
+ "allOf"
1162
+ ]) if (key in record) violations.push(`${path}.${key}`);
1163
+ if (Array.isArray(record.type)) violations.push(`${path}.type`);
1164
+ if (record.type === "object") {
1165
+ if (record.additionalProperties !== false) violations.push(`${path}.additionalProperties`);
1166
+ const properties = record.properties && typeof record.properties === "object" && !Array.isArray(record.properties) ? record.properties : {};
1167
+ const required = Array.isArray(record.required) ? record.required.filter((entry) => typeof entry === "string") : void 0;
1168
+ if (!required) violations.push(`${path}.required`);
1169
+ else {
1170
+ const requiredSet = new Set(required);
1171
+ for (const key of Object.keys(properties)) if (!requiredSet.has(key)) violations.push(`${path}.required.${key}`);
1172
+ }
1173
+ }
1174
+ 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}`));
1175
+ for (const [key, value] of Object.entries(record)) {
1176
+ if (key === "properties") continue;
1177
+ if (value && typeof value === "object") violations.push(...findStrictOpenAIJsonSchemaViolations(value, `${path}.${key}`));
1178
+ }
1179
+ return violations;
1180
+ }
1181
+ /** Resolves strict mode for the projected tools that will be emitted in the request payload. */
1182
+ function resolveOpenAIProjectedToolsStrictToolFlag(projection, strict) {
1183
+ if (strict !== true) return strict === false ? false : void 0;
1184
+ return projection.tools.every((tool) => isStrictOpenAIJsonSchemaCompatible(tool.parameters));
1185
+ }
1186
+ //#endregion
1187
+ //#region packages/ai/src/providers/openai-responses-tools.ts
1188
+ const LOG_SUBSYSTEM = "llm/openai-responses";
1189
+ const MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS = 64;
1190
+ const loggedStrictToolDowngradeDiagnosticKeys = /* @__PURE__ */ new Set();
1191
+ /** Converts and returns the projection used to reconcile tool choices. */
1192
+ function convertResponsesToolPayload(tools, options) {
1193
+ const projection = projectOpenAITools(tools);
1194
+ const strict = resolveResponsesStrictToolFlag(projection, resolveResponsesStrictToolSetting(options), options?.model);
1195
+ return {
1196
+ projection,
1197
+ tools: sortResponsesToolsByName(projection.tools).map((tool) => {
1198
+ const result = {
1199
+ type: "function",
1200
+ name: tool.name,
1201
+ description: tool.description,
1202
+ parameters: normalizeOpenAIStrictToolParameters(tool.parameters, strict === true, options?.model?.compat)
1203
+ };
1204
+ if (strict !== void 0) result.strict = strict;
1205
+ return result;
1206
+ })
1207
+ };
1208
+ }
1209
+ function resolveResponsesStrictToolSetting(options) {
1210
+ if (options?.strict !== void 0) return options.strict;
1211
+ if (options?.model) return getAiTransportHost().resolveOpenAIStrictToolSetting(options.model, {
1212
+ transport: "stream",
1213
+ supportsStrictMode: options.supportsStrictMode
1214
+ });
1215
+ return false;
1216
+ }
1217
+ function resolveResponsesStrictToolFlag(projection, strictSetting, model) {
1218
+ const strict = resolveOpenAIProjectedToolsStrictToolFlag(projection, strictSetting);
1219
+ if (strictSetting === true && strict === false && model) getAiTransportHost().logDebug(LOG_SUBSYSTEM, () => {
1220
+ const diagnostics = findOpenAIStrictToolProjectionDiagnostics(projection);
1221
+ if (!shouldLogStrictToolDowngradeDiagnostic(diagnostics, model)) return null;
1222
+ const sample = diagnostics.slice(0, 5).map((entry) => ({
1223
+ tool: entry.toolName ?? `tool[${entry.toolIndex}]`,
1224
+ violations: entry.violations.slice(0, 8)
1225
+ }));
1226
+ return {
1227
+ message: `OpenAI responses tool schema strict mode downgraded to strict=false for ${model.provider ?? "unknown"}/${model.id ?? "unknown"} because ${diagnostics.length} tool schema(s) are not strict-compatible`,
1228
+ data: {
1229
+ provider: model.provider,
1230
+ model: model.id,
1231
+ incompatibleToolCount: diagnostics.length,
1232
+ sample
1233
+ }
1234
+ };
1235
+ });
1236
+ return strict;
1237
+ }
1238
+ function shouldLogStrictToolDowngradeDiagnostic(diagnostics, model) {
1239
+ const key = createHash("sha256").update(JSON.stringify({
1240
+ provider: model.provider,
1241
+ model: model.id,
1242
+ diagnostics: diagnostics.map((entry) => ({
1243
+ toolIndex: entry.toolIndex,
1244
+ toolName: entry.toolName ?? null,
1245
+ violations: entry.violations
1246
+ }))
1247
+ })).digest("hex");
1248
+ if (loggedStrictToolDowngradeDiagnosticKeys.has(key)) return false;
1249
+ if (loggedStrictToolDowngradeDiagnosticKeys.size >= MAX_STRICT_TOOL_DOWNGRADE_DIAGNOSTIC_KEYS) loggedStrictToolDowngradeDiagnosticKeys.clear();
1250
+ loggedStrictToolDowngradeDiagnosticKeys.add(key);
1251
+ return true;
1252
+ }
1253
+ function compareToolText(left, right) {
1254
+ const leftText = left ?? "";
1255
+ const rightText = right ?? "";
1256
+ if (leftText < rightText) return -1;
1257
+ if (leftText > rightText) return 1;
1258
+ return 0;
1259
+ }
1260
+ function sortResponsesToolsByName(tools) {
1261
+ return tools.toSorted((left, right) => compareToolText(left.name, right.name) || compareToolText(left.description, right.description));
1262
+ }
1263
+ //#endregion
1264
+ //#region packages/ai/src/providers/openai-responses-shared.ts
1265
+ const EMPTY_TOOL_RESULT_TEXT = "(no output)";
1266
+ function sanitizeToolResultText(text, fallback) {
1267
+ const sanitized = sanitizeSurrogates(text);
1268
+ return sanitized.trim().length > 0 ? sanitized : fallback;
1269
+ }
1270
+ function normalizeResponsesReasoningReplayItem(params) {
1271
+ const next = { ...params.item };
1272
+ if (!Array.isArray(next.summary)) next.summary = [];
1273
+ if (!params.replayResponsesItemIds) delete next.id;
1274
+ return next;
1275
+ }
1276
+ function encodeTextSignatureV1(id, phase) {
1277
+ const payload = {
1278
+ v: 1,
1279
+ id
1280
+ };
1281
+ if (phase) payload.phase = phase;
1282
+ return JSON.stringify(payload);
1283
+ }
1284
+ function parseTextSignature(signature) {
1285
+ if (!signature) return;
1286
+ if (signature.startsWith("{")) try {
1287
+ const parsed = JSON.parse(signature);
1288
+ if (parsed.v === 1) {
1289
+ const id = typeof parsed.id === "string" ? parsed.id : void 0;
1290
+ const phase = parsed.phase === "commentary" || parsed.phase === "final_answer" ? parsed.phase : void 0;
1291
+ if (id !== void 0 || phase !== void 0) return {
1292
+ id,
1293
+ phase
1294
+ };
1295
+ return;
1296
+ }
1297
+ } catch {}
1298
+ return { id: signature };
1299
+ }
1300
+ function resolveReplayableResponsesMessageId(params) {
1301
+ if (!params.textSignatureId) return params.fallbackOrdinal === 0 ? params.fallbackId : `${params.fallbackId}_${params.fallbackOrdinal}`;
1302
+ return params.previousReplayItemWasReasoning ? params.textSignatureId : void 0;
1303
+ }
1304
+ function isResponsesReasoningEffort(effort) {
1305
+ return effort === "minimal" || effort === "low" || effort === "medium" || effort === "high" || effort === "xhigh" || effort === "max";
1306
+ }
1307
+ function convertResponsesMessages(model, context, allowedToolCallProviders, options) {
1308
+ const messages = [];
1309
+ const shouldReplayResponsesItemIds = options?.replayResponsesItemIds ?? true;
1310
+ const normalizeIdPart = (part) => {
1311
+ const sanitized = part.replace(/[^a-zA-Z0-9_-]/g, "_");
1312
+ return (sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized).replace(/_+$/, "");
1313
+ };
1314
+ const buildForeignResponsesItemId = (itemId) => {
1315
+ const normalized = `fc_${shortHash(itemId)}`;
1316
+ return normalized.length > 64 ? normalized.slice(0, 64) : normalized;
1317
+ };
1318
+ const normalizeToolCallId = (id, targetModel, source) => {
1319
+ if (!allowedToolCallProviders.has(model.provider)) return normalizeIdPart(id);
1320
+ if (!id.includes("|")) return normalizeIdPart(id);
1321
+ const [callId, itemId] = id.split("|");
1322
+ const normalizedCallId = normalizeIdPart(callId);
1323
+ let normalizedItemId = source.provider !== model.provider || source.api !== model.api ? buildForeignResponsesItemId(itemId) : normalizeIdPart(itemId);
1324
+ if (!normalizedItemId.startsWith("fc_")) normalizedItemId = normalizeIdPart(`fc_${normalizedItemId}`);
1325
+ return `${normalizedCallId}|${normalizedItemId}`;
1326
+ };
1327
+ const transformedMessages = transformMessages(context.messages, model, normalizeToolCallId);
1328
+ if ((options?.includeSystemPrompt ?? true) && context.systemPrompt) {
1329
+ const role = model.reasoning ? "developer" : "system";
1330
+ messages.push({
1331
+ type: "message",
1332
+ role,
1333
+ content: [{
1334
+ type: "input_text",
1335
+ text: sanitizeSurrogates(stripSystemPromptCacheBoundary(context.systemPrompt))
1336
+ }]
1337
+ });
1338
+ }
1339
+ let msgIndex = 0;
1340
+ for (const msg of transformedMessages) {
1341
+ if (msg.role === "user") if (typeof msg.content === "string") messages.push({
1342
+ type: "message",
1343
+ role: "user",
1344
+ content: [{
1345
+ type: "input_text",
1346
+ text: sanitizeSurrogates(msg.content)
1347
+ }]
1348
+ });
1349
+ else {
1350
+ const content = msg.content.map((item) => {
1351
+ if (item.type === "text") return {
1352
+ type: "input_text",
1353
+ text: sanitizeSurrogates(item.text)
1354
+ };
1355
+ return {
1356
+ type: "input_image",
1357
+ detail: "auto",
1358
+ image_url: `data:${item.mimeType};base64,${item.data}`
1359
+ };
1360
+ });
1361
+ if (content.length === 0) continue;
1362
+ messages.push({
1363
+ type: "message",
1364
+ role: "user",
1365
+ content
1366
+ });
1367
+ }
1368
+ else if (msg.role === "assistant") {
1369
+ const output = [];
1370
+ let textFallbackOrdinal = 0;
1371
+ const assistantMsg = msg;
1372
+ let previousReplayItemWasReasoning = false;
1373
+ const isDifferentModel = assistantMsg.model !== model.id && assistantMsg.provider === model.provider && assistantMsg.api === model.api;
1374
+ for (const block of msg.content) if (block.type === "thinking") {
1375
+ if (block.thinkingSignature) {
1376
+ const reasoningItem = normalizeResponsesReasoningReplayItem({
1377
+ item: JSON.parse(block.thinkingSignature),
1378
+ replayResponsesItemIds: shouldReplayResponsesItemIds
1379
+ });
1380
+ output.push(reasoningItem);
1381
+ previousReplayItemWasReasoning = true;
1382
+ }
1383
+ } else if (block.type === "text") {
1384
+ const textBlock = block;
1385
+ const parsedSignature = parseTextSignature(textBlock.textSignature);
1386
+ let msgId = shouldReplayResponsesItemIds ? resolveReplayableResponsesMessageId({
1387
+ textSignatureId: parsedSignature?.id,
1388
+ fallbackId: `msg_${msgIndex}`,
1389
+ fallbackOrdinal: textFallbackOrdinal,
1390
+ previousReplayItemWasReasoning
1391
+ }) : void 0;
1392
+ if (!parsedSignature?.id) textFallbackOrdinal += 1;
1393
+ if (msgId && msgId.length > 64) msgId = `msg_${shortHash(msgId)}`;
1394
+ const messageItem = {
1395
+ type: "message",
1396
+ role: "assistant",
1397
+ content: [{
1398
+ type: "output_text",
1399
+ text: sanitizeSurrogates(textBlock.text),
1400
+ annotations: []
1401
+ }],
1402
+ status: "completed",
1403
+ ...msgId ? { id: msgId } : {},
1404
+ phase: parsedSignature?.phase
1405
+ };
1406
+ output.push(messageItem);
1407
+ previousReplayItemWasReasoning = false;
1408
+ } else if (block.type === "toolCall") {
1409
+ const toolCall = block;
1410
+ const [callId, itemIdRaw] = toolCall.id.split("|");
1411
+ let itemId = shouldReplayResponsesItemIds ? itemIdRaw : void 0;
1412
+ if (shouldReplayResponsesItemIds && isDifferentModel && itemId?.startsWith("fc_")) itemId = void 0;
1413
+ output.push({
1414
+ type: "function_call",
1415
+ ...itemId ? { id: itemId } : {},
1416
+ call_id: callId,
1417
+ name: toolCall.name,
1418
+ arguments: JSON.stringify(toolCall.arguments)
1419
+ });
1420
+ previousReplayItemWasReasoning = false;
1421
+ }
1422
+ if (output.length === 0) continue;
1423
+ messages.push(...output);
1424
+ } else if (msg.role === "toolResult") {
1425
+ const textResult = extractToolResultText(msg.content);
1426
+ const sanitizedTextResult = sanitizeSurrogates(textResult);
1427
+ const hasImages = msg.content.some((c) => c.type === "image");
1428
+ const mediaPlaceholder = describeToolResultMediaPlaceholder(msg.content);
1429
+ const hasText = sanitizedTextResult.trim().length > 0;
1430
+ const [callId] = msg.toolCallId.split("|");
1431
+ let output;
1432
+ if (hasImages && model.input.includes("image")) {
1433
+ const contentParts = [];
1434
+ if (hasText) contentParts.push({
1435
+ type: "input_text",
1436
+ text: sanitizedTextResult
1437
+ });
1438
+ else if (mediaPlaceholder === "(see attached media)") contentParts.push({
1439
+ type: "input_text",
1440
+ text: mediaPlaceholder
1441
+ });
1442
+ for (const block of msg.content) if (block.type === "image") contentParts.push({
1443
+ type: "input_image",
1444
+ detail: "auto",
1445
+ image_url: `data:${block.mimeType};base64,${block.data}`
1446
+ });
1447
+ output = contentParts;
1448
+ } else output = sanitizeToolResultText(textResult, mediaPlaceholder ?? EMPTY_TOOL_RESULT_TEXT);
1449
+ messages.push({
1450
+ type: "function_call_output",
1451
+ call_id: callId,
1452
+ output
1453
+ });
1454
+ }
1455
+ msgIndex++;
1456
+ }
1457
+ return messages;
1458
+ }
1459
+ function createResponsesAssistantOutput(model, api = model.api) {
1460
+ return {
1461
+ role: "assistant",
1462
+ content: [],
1463
+ api,
1464
+ provider: model.provider,
1465
+ model: model.id,
1466
+ usage: {
1467
+ input: 0,
1468
+ output: 0,
1469
+ cacheRead: 0,
1470
+ cacheWrite: 0,
1471
+ totalTokens: 0,
1472
+ cost: {
1473
+ input: 0,
1474
+ output: 0,
1475
+ cacheRead: 0,
1476
+ cacheWrite: 0,
1477
+ total: 0
1478
+ }
1479
+ },
1480
+ stopReason: "stop",
1481
+ timestamp: Date.now()
1482
+ };
1483
+ }
1484
+ function resolveResponsesReasoningEffort(model, reasoning) {
1485
+ const clampedReasoning = reasoning ? clampThinkingLevel(model, reasoning) : void 0;
1486
+ if (!clampedReasoning || clampedReasoning === "off") return;
1487
+ if (clampedReasoning === "max") return supportsOpenAIReasoningEffort(model, "max") ? "max" : "xhigh";
1488
+ if (clampedReasoning === "minimal" && model.provider === "openai" && supportsOpenAIReasoningEffort(model, "max")) {
1489
+ const effort = resolveOpenAIReasoningEffortForModel({
1490
+ model,
1491
+ effort: "minimal"
1492
+ });
1493
+ return isResponsesReasoningEffort(effort) ? effort : void 0;
1494
+ }
1495
+ return clampedReasoning;
1496
+ }
1497
+ function applyCommonResponsesParams(params, model, context, options, config) {
1498
+ if (options?.maxTokens) params.max_output_tokens = options.maxTokens;
1499
+ if (options?.temperature !== void 0) params.temperature = options.temperature;
1500
+ if (context.tools) {
1501
+ const converted = convertResponsesToolPayload(context.tools, { model });
1502
+ if (converted.tools.length > 0) params.tools = converted.tools;
1503
+ }
1504
+ if (!model.reasoning) return;
1505
+ if (options?.reasoningEffort || options?.reasoningSummary) {
1506
+ params.reasoning = {
1507
+ effort: options?.reasoningEffort ? model.thinkingLevelMap?.[options.reasoningEffort] ?? options.reasoningEffort : "medium",
1508
+ summary: options?.reasoningSummary || "auto"
1509
+ };
1510
+ params.include = ["reasoning.encrypted_content"];
1511
+ } else if ((config?.setDefaultReasoningOff ?? true) && model.thinkingLevelMap?.off !== null) params.reasoning = { effort: model.thinkingLevelMap?.off ?? "none" };
1512
+ }
1513
+ function buildResponsesRequestOptions(options) {
1514
+ return {
1515
+ ...options?.signal ? { signal: options.signal } : {},
1516
+ ...options?.timeoutMs !== void 0 ? { timeout: options.timeoutMs } : {},
1517
+ ...options?.maxRetries !== void 0 ? { maxRetries: options.maxRetries } : {}
1518
+ };
1519
+ }
1520
+ function cleanStreamingScratchBuffers(output) {
1521
+ for (const block of output.content) {
1522
+ delete block.index;
1523
+ delete block.partialJson;
1524
+ }
1525
+ }
1526
+ async function runResponsesStreamLifecycle(params) {
1527
+ const { stream, model, output, options } = params;
1528
+ let firstEventAbort;
1529
+ try {
1530
+ const client = params.createClient();
1531
+ let requestParams = params.buildParams();
1532
+ const nextParams = await options?.onPayload?.(requestParams, model);
1533
+ if (nextParams !== void 0) requestParams = nextParams;
1534
+ firstEventAbort = createFirstStreamEventAbortController(options?.signal);
1535
+ const { data: openaiStream, response } = await client.responses.create(requestParams, {
1536
+ ...buildResponsesRequestOptions(options),
1537
+ signal: firstEventAbort.signal
1538
+ }).withResponse();
1539
+ await options?.onResponse?.({
1540
+ status: response.status,
1541
+ headers: headersToRecord(response.headers)
1542
+ }, model);
1543
+ stream.push({
1544
+ type: "start",
1545
+ partial: output
1546
+ });
1547
+ const firstEventTimeoutMs = getFirstStreamEventTimeoutMs(options);
1548
+ const onFirstEventTimeout = getFirstStreamEventTimeoutHandler(options);
1549
+ await processResponsesStream(openaiStream, output, stream, model, params.processStreamOptions || firstEventTimeoutMs !== void 0 || onFirstEventTimeout !== void 0 ? {
1550
+ ...params.processStreamOptions,
1551
+ firstEventTimeoutMs: params.processStreamOptions?.firstEventTimeoutMs ?? firstEventTimeoutMs,
1552
+ abortFirstEventStream: params.processStreamOptions?.abortFirstEventStream ?? firstEventAbort.abort,
1553
+ onFirstEventTimeout: params.processStreamOptions?.onFirstEventTimeout ?? onFirstEventTimeout
1554
+ } : void 0);
1555
+ if (options?.signal?.aborted) throw new Error("Request was aborted");
1556
+ if (output.stopReason === "aborted" || output.stopReason === "error") throw new Error("An unknown error occurred");
1557
+ stream.push({
1558
+ type: "done",
1559
+ reason: output.stopReason,
1560
+ message: output
1561
+ });
1562
+ stream.end();
1563
+ } catch (error) {
1564
+ cleanStreamingScratchBuffers(output);
1565
+ output.stopReason = options?.signal?.aborted ? "aborted" : "error";
1566
+ output.errorMessage = params.formatError(error);
1567
+ stream.push({
1568
+ type: "error",
1569
+ reason: output.stopReason,
1570
+ error: output
1571
+ });
1572
+ stream.end();
1573
+ } finally {
1574
+ firstEventAbort?.dispose();
1575
+ }
1576
+ }
1577
+ async function processResponsesStream(openaiStream, output, stream, model, options) {
1578
+ let currentItem = null;
1579
+ let currentBlock = null;
1580
+ let lastTextBlock = null;
1581
+ let pendingMessageText = null;
1582
+ const blocks = output.content;
1583
+ const blockIndex = () => blocks.length - 1;
1584
+ const appendPendingMessageDelta = (delta) => {
1585
+ pendingMessageText = `${pendingMessageText ?? ""}${delta}`;
1586
+ const priorText = lastTextBlock?.block.text ?? "";
1587
+ if (priorText.startsWith(pendingMessageText) || pendingMessageText.startsWith(priorText)) return;
1588
+ currentBlock = {
1589
+ type: "text",
1590
+ text: pendingMessageText
1591
+ };
1592
+ blocks.push(currentBlock);
1593
+ stream.push({
1594
+ type: "text_start",
1595
+ contentIndex: blockIndex(),
1596
+ partial: output
1597
+ });
1598
+ stream.push({
1599
+ type: "text_delta",
1600
+ contentIndex: blockIndex(),
1601
+ delta: pendingMessageText,
1602
+ partial: output
1603
+ });
1604
+ pendingMessageText = null;
1605
+ };
1606
+ const guardedStream = withFirstStreamEventTimeout(openaiStream, {
1607
+ provider: model.provider,
1608
+ api: model.api,
1609
+ model: model.id,
1610
+ timeoutMs: options?.firstEventTimeoutMs ?? 0,
1611
+ stage: "responses",
1612
+ abort: options?.abortFirstEventStream,
1613
+ onTimeout: options?.onFirstEventTimeout,
1614
+ hint: "The provider may be stalled while parsing the tool payload; retry with a smaller tool surface or enable OPENCLAW_DEBUG_MODEL_PAYLOAD=tools to inspect exposed tools."
1615
+ });
1616
+ for await (const event of guardedStream) if (event.type === "response.created") output.responseId = event.response.id;
1617
+ else if (event.type === "response.output_item.added") {
1618
+ const item = event.item;
1619
+ if (item.type !== "message") {
1620
+ lastTextBlock = null;
1621
+ pendingMessageText = null;
1622
+ }
1623
+ if (item.type === "reasoning") {
1624
+ currentItem = item;
1625
+ currentBlock = {
1626
+ type: "thinking",
1627
+ thinking: ""
1628
+ };
1629
+ output.content.push(currentBlock);
1630
+ stream.push({
1631
+ type: "thinking_start",
1632
+ contentIndex: blockIndex(),
1633
+ partial: output
1634
+ });
1635
+ } else if (item.type === "message") {
1636
+ currentItem = item;
1637
+ if (lastTextBlock) {
1638
+ currentBlock = null;
1639
+ pendingMessageText = "";
1640
+ } else {
1641
+ currentBlock = {
1642
+ type: "text",
1643
+ text: ""
1644
+ };
1645
+ output.content.push(currentBlock);
1646
+ stream.push({
1647
+ type: "text_start",
1648
+ contentIndex: blockIndex(),
1649
+ partial: output
1650
+ });
1651
+ }
1652
+ } else if (item.type === "function_call") {
1653
+ currentItem = item;
1654
+ currentBlock = {
1655
+ type: "toolCall",
1656
+ id: `${item.call_id}|${item.id}`,
1657
+ name: item.name,
1658
+ arguments: {},
1659
+ partialJson: item.arguments || ""
1660
+ };
1661
+ output.content.push(currentBlock);
1662
+ stream.push({
1663
+ type: "toolcall_start",
1664
+ contentIndex: blockIndex(),
1665
+ partial: output
1666
+ });
1667
+ }
1668
+ } else if (event.type === "response.reasoning_summary_part.added") {
1669
+ if (currentItem && currentItem.type === "reasoning") {
1670
+ currentItem.summary = currentItem.summary || [];
1671
+ currentItem.summary.push(event.part);
1672
+ }
1673
+ } else if (event.type === "response.reasoning_summary_text.delta") {
1674
+ if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
1675
+ currentItem.summary = currentItem.summary || [];
1676
+ const lastPart = currentItem.summary[currentItem.summary.length - 1];
1677
+ if (lastPart) {
1678
+ currentBlock.thinking += event.delta;
1679
+ lastPart.text += event.delta;
1680
+ stream.push({
1681
+ type: "thinking_delta",
1682
+ contentIndex: blockIndex(),
1683
+ delta: event.delta,
1684
+ partial: output
1685
+ });
1686
+ }
1687
+ }
1688
+ } else if (event.type === "response.reasoning_summary_part.done") {
1689
+ if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
1690
+ currentItem.summary = currentItem.summary || [];
1691
+ const lastPart = currentItem.summary[currentItem.summary.length - 1];
1692
+ if (lastPart) {
1693
+ currentBlock.thinking += "\n\n";
1694
+ lastPart.text += "\n\n";
1695
+ stream.push({
1696
+ type: "thinking_delta",
1697
+ contentIndex: blockIndex(),
1698
+ delta: "\n\n",
1699
+ partial: output
1700
+ });
1701
+ }
1702
+ }
1703
+ } else if (event.type === "response.reasoning_text.delta") {
1704
+ if (currentItem?.type === "reasoning" && currentBlock?.type === "thinking") {
1705
+ currentBlock.thinking += event.delta;
1706
+ stream.push({
1707
+ type: "thinking_delta",
1708
+ contentIndex: blockIndex(),
1709
+ delta: event.delta,
1710
+ partial: output
1711
+ });
1712
+ }
1713
+ } else if (event.type === "response.content_part.added") {
1714
+ if (currentItem?.type === "message") {
1715
+ currentItem.content = currentItem.content || [];
1716
+ if (event.part.type === "output_text" || event.part.type === "text" || event.part.type === "refusal") currentItem.content.push(event.part);
1717
+ }
1718
+ } else if (event.type === "response.output_text.delta") {
1719
+ if (currentItem?.type === "message") {
1720
+ if (!currentItem.content || currentItem.content.length === 0) continue;
1721
+ const lastPart = currentItem.content[currentItem.content.length - 1];
1722
+ if (isResponsesTextContentPartType(lastPart?.type)) {
1723
+ lastPart.text += event.delta;
1724
+ if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
1725
+ else if (currentBlock?.type === "text") {
1726
+ currentBlock.text += event.delta;
1727
+ stream.push({
1728
+ type: "text_delta",
1729
+ contentIndex: blockIndex(),
1730
+ delta: event.delta,
1731
+ partial: output
1732
+ });
1733
+ }
1734
+ }
1735
+ }
1736
+ } else if (isAzureResponsesTextDeltaEvent(event)) {
1737
+ if (currentItem?.type === "message") {
1738
+ currentItem.content = currentItem.content || [];
1739
+ let lastPart = currentItem.content[currentItem.content.length - 1];
1740
+ if (lastPart?.type !== "text") {
1741
+ lastPart = {
1742
+ type: "text",
1743
+ text: ""
1744
+ };
1745
+ currentItem.content.push(lastPart);
1746
+ }
1747
+ lastPart.text += event.delta;
1748
+ if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
1749
+ else if (currentBlock?.type === "text") {
1750
+ currentBlock.text += event.delta;
1751
+ stream.push({
1752
+ type: "text_delta",
1753
+ contentIndex: blockIndex(),
1754
+ delta: event.delta,
1755
+ partial: output
1756
+ });
1757
+ }
1758
+ }
1759
+ } else if (event.type === "response.refusal.delta") {
1760
+ if (currentItem?.type === "message") {
1761
+ if (!currentItem.content || currentItem.content.length === 0) continue;
1762
+ const lastPart = currentItem.content[currentItem.content.length - 1];
1763
+ if (lastPart?.type === "refusal") {
1764
+ lastPart.refusal += event.delta;
1765
+ if (pendingMessageText !== null) appendPendingMessageDelta(event.delta);
1766
+ else if (currentBlock?.type === "text") {
1767
+ currentBlock.text += event.delta;
1768
+ stream.push({
1769
+ type: "text_delta",
1770
+ contentIndex: blockIndex(),
1771
+ delta: event.delta,
1772
+ partial: output
1773
+ });
1774
+ }
1775
+ }
1776
+ }
1777
+ } else if (event.type === "response.function_call_arguments.delta") {
1778
+ if (currentItem?.type === "function_call" && currentBlock?.type === "toolCall") {
1779
+ currentBlock.partialJson += event.delta;
1780
+ currentBlock.arguments = parseStreamingJson(currentBlock.partialJson);
1781
+ stream.push({
1782
+ type: "toolcall_delta",
1783
+ contentIndex: blockIndex(),
1784
+ delta: event.delta,
1785
+ partial: output
1786
+ });
1787
+ }
1788
+ } else if (event.type === "response.function_call_arguments.done") {
1789
+ if (currentItem?.type === "function_call" && currentBlock?.type === "toolCall") {
1790
+ const previousPartialJson = currentBlock.partialJson;
1791
+ const doneArguments = typeof event.arguments === "string" ? event.arguments : void 0;
1792
+ if (doneArguments !== void 0 && (doneArguments.length > 0 || previousPartialJson === "")) {
1793
+ currentBlock.partialJson = doneArguments;
1794
+ currentBlock.arguments = parseStreamingJson(currentBlock.partialJson);
1795
+ }
1796
+ if (doneArguments?.startsWith(previousPartialJson)) {
1797
+ const delta = doneArguments.slice(previousPartialJson.length);
1798
+ if (delta.length > 0) stream.push({
1799
+ type: "toolcall_delta",
1800
+ contentIndex: blockIndex(),
1801
+ delta,
1802
+ partial: output
1803
+ });
1804
+ }
1805
+ }
1806
+ } else if (event.type === "response.output_item.done") {
1807
+ const item = event.item;
1808
+ if (item.type !== "message") {
1809
+ lastTextBlock = null;
1810
+ pendingMessageText = null;
1811
+ }
1812
+ if (item.type === "reasoning" && currentBlock?.type === "thinking") {
1813
+ const summaryText = item.summary?.map((s) => s.text).join("\n\n") || "";
1814
+ const contentText = item.content?.map((c) => c.text).join("\n\n") || "";
1815
+ currentBlock.thinking = summaryText || contentText || currentBlock.thinking;
1816
+ currentBlock.thinkingSignature = JSON.stringify(item);
1817
+ stream.push({
1818
+ type: "thinking_end",
1819
+ contentIndex: blockIndex(),
1820
+ content: currentBlock.thinking,
1821
+ partial: output
1822
+ });
1823
+ currentBlock = null;
1824
+ } else if (item.type === "message" && (currentBlock?.type === "text" || pendingMessageText !== null)) {
1825
+ const finalText = item.content.map((c) => c.type === "output_text" || c.type === "text" ? c.text : c.refusal).join("");
1826
+ const phase = item.phase ?? void 0;
1827
+ const collapse = pendingMessageText !== null ? resolveResponsesMessageSnapshotCollapse({
1828
+ prior: lastTextBlock && {
1829
+ text: lastTextBlock.block.text,
1830
+ phase: lastTextBlock.phase
1831
+ },
1832
+ nextText: finalText,
1833
+ nextPhase: phase
1834
+ }) : { kind: "keep" };
1835
+ pendingMessageText = null;
1836
+ if (collapse.kind === "extend" && lastTextBlock) {
1837
+ lastTextBlock.block.text = collapse.text;
1838
+ lastTextBlock.block.textSignature = encodeTextSignatureV1(item.id, phase);
1839
+ stream.push({
1840
+ type: "text_end",
1841
+ contentIndex: lastTextBlock.index,
1842
+ content: collapse.text,
1843
+ partial: output
1844
+ });
1845
+ } else {
1846
+ if (currentBlock?.type !== "text") {
1847
+ currentBlock = {
1848
+ type: "text",
1849
+ text: ""
1850
+ };
1851
+ blocks.push(currentBlock);
1852
+ stream.push({
1853
+ type: "text_start",
1854
+ contentIndex: blockIndex(),
1855
+ partial: output
1856
+ });
1857
+ }
1858
+ currentBlock.text = finalText;
1859
+ currentBlock.textSignature = encodeTextSignatureV1(item.id, phase);
1860
+ lastTextBlock = {
1861
+ block: currentBlock,
1862
+ index: blockIndex(),
1863
+ phase
1864
+ };
1865
+ stream.push({
1866
+ type: "text_end",
1867
+ contentIndex: blockIndex(),
1868
+ content: currentBlock.text,
1869
+ partial: output
1870
+ });
1871
+ }
1872
+ currentBlock = null;
1873
+ } else if (item.type === "function_call") {
1874
+ const args = currentBlock?.type === "toolCall" && currentBlock.partialJson ? parseStreamingJson(currentBlock.partialJson) : parseStreamingJson(item.arguments || "{}");
1875
+ let toolCall;
1876
+ if (currentBlock?.type === "toolCall") {
1877
+ currentBlock.arguments = args;
1878
+ delete currentBlock.partialJson;
1879
+ toolCall = currentBlock;
1880
+ } else toolCall = {
1881
+ type: "toolCall",
1882
+ id: `${item.call_id}|${item.id}`,
1883
+ name: item.name,
1884
+ arguments: args
1885
+ };
1886
+ currentBlock = null;
1887
+ stream.push({
1888
+ type: "toolcall_end",
1889
+ contentIndex: blockIndex(),
1890
+ toolCall,
1891
+ partial: output
1892
+ });
1893
+ }
1894
+ } else if (event.type === "response.completed") {
1895
+ const response = event.response;
1896
+ if (response?.id) output.responseId = response.id;
1897
+ if (response?.usage) {
1898
+ const inputTokenDetails = response.usage.input_tokens_details;
1899
+ const cachedTokens = inputTokenDetails?.cached_tokens || 0;
1900
+ const cacheWriteTokens = inputTokenDetails?.cache_write_tokens || 0;
1901
+ output.usage = {
1902
+ input: Math.max(0, (response.usage.input_tokens || 0) - cachedTokens - cacheWriteTokens),
1903
+ output: response.usage.output_tokens || 0,
1904
+ cacheRead: cachedTokens,
1905
+ cacheWrite: cacheWriteTokens,
1906
+ totalTokens: response.usage.total_tokens || 0,
1907
+ cost: {
1908
+ input: 0,
1909
+ output: 0,
1910
+ cacheRead: 0,
1911
+ cacheWrite: 0,
1912
+ total: 0
1913
+ }
1914
+ };
1915
+ }
1916
+ calculateCost(model, output.usage);
1917
+ if (options?.applyServiceTierPricing) {
1918
+ const serviceTier = options.resolveServiceTier ? options.resolveServiceTier(response?.service_tier, options.serviceTier) : response?.service_tier ?? options.serviceTier;
1919
+ options.applyServiceTierPricing(output.usage, serviceTier);
1920
+ }
1921
+ output.stopReason = mapStopReason(response?.status);
1922
+ if (output.content.some((b) => b.type === "toolCall") && output.stopReason === "stop") output.stopReason = "toolUse";
1923
+ } else if (event.type === "error") throw new Error(event.message ? `Error Code ${event.code}: ${event.message}` : "Unknown error");
1924
+ else if (event.type === "response.failed") {
1925
+ const error = event.response?.error;
1926
+ const details = event.response?.incomplete_details;
1927
+ const msg = error ? `${error.code || "unknown"}: ${error.message || "no message"}` : details?.reason ? `incomplete: ${details.reason}` : "Unknown error (no error details in response)";
1928
+ throw new Error(msg);
1929
+ }
1930
+ }
1931
+ function mapStopReason(status) {
1932
+ if (!status) return "stop";
1933
+ switch (status) {
1934
+ case "completed": return "stop";
1935
+ case "incomplete": return "length";
1936
+ case "failed":
1937
+ case "cancelled": return "error";
1938
+ case "in_progress":
1939
+ case "queued": return "stop";
1940
+ default: throw new Error(`Unhandled stop reason: ${String(status)}`);
1941
+ }
1942
+ }
1943
+ //#endregion
1944
+ export { extractToolSchemaModelCompat as A, isOpenAIGpt54MiniModel as C, resolveOpenAIReasoningEffortForModel as D, normalizeOpenAIReasoningEffort as E, GEMINI_UNSUPPORTED_SCHEMA_KEYWORDS as F, cleanSchemaForGemini as I, resolveUnsupportedToolSchemaKeywords as M, shouldOmitEmptyArrayItems as N, resolveOpenAISupportedReasoningEfforts as O, stripUnsupportedSchemaKeywords as P, resolveResponsesMessageSnapshotCollapse as S, isOpenAIGpt56Model as T, OPENAI_RESPONSES_OUTPUT_TEXT_DELTA_EVENT_TYPE as _, resolveResponsesReasoningEffort as a, isResponsesTextContentPartType as b, clearOpenAIToolSchemaCacheForTest as c, normalizeOpenAIStrictToolParameters as d, normalizeStrictOpenAIJsonSchema as f, OPENAI_RESPONSES_OUTPUT_TEXT_CONTENT_PART_TYPE as g, AZURE_RESPONSES_TEXT_DELTA_EVENT_TYPE as h, processResponsesStream as i, normalizeToolParameterSchema as j, supportsOpenAIReasoningEffort as k, findOpenAIStrictToolProjectionDiagnostics as l, AZURE_RESPONSES_TEXT_CONTENT_PART_TYPE as m, convertResponsesMessages as n, runResponsesStreamLifecycle as o, resolveOpenAIProjectedToolsStrictToolFlag as p, createResponsesAssistantOutput as r, convertResponsesToolPayload as s, applyCommonResponsesParams as t, isStrictOpenAIJsonSchemaCompatible as u, isAzureResponsesTextDeltaEvent as v, isOpenAIGpt55Model as w, isResponsesTextDeltaEventType as x, isAzureResponsesTextDeltaEventType as y };