@opencow-ai/opencow-agent-sdk 0.4.5 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -84304,7 +84304,8 @@ function sanitizeSchemaForOpenAICompat(schema) {
84304
84304
  }
84305
84305
  }
84306
84306
  if (Array.isArray(record2.required) && isSchemaRecord(record2.properties)) {
84307
- record2.required = record2.required.filter((value) => typeof value === "string" && (value in record2.properties));
84307
+ const properties = record2.properties;
84308
+ record2.required = record2.required.filter((value) => typeof value === "string" && (value in properties));
84308
84309
  }
84309
84310
  const schemaWithoutEnum = { ...record2 };
84310
84311
  delete schemaWithoutEnum.enum;
@@ -84323,6 +84324,77 @@ function sanitizeSchemaForOpenAICompat(schema) {
84323
84324
  }
84324
84325
  return record2;
84325
84326
  }
84327
+ function isEmptyStrictObject(schema) {
84328
+ if (schema.type !== "object" || schema.additionalProperties !== false) {
84329
+ return false;
84330
+ }
84331
+ const props = schema.properties;
84332
+ return !props || isSchemaRecord(props) && Object.keys(props).length === 0;
84333
+ }
84334
+ function strictifySchemaNode(schema, options, topLevel) {
84335
+ const {
84336
+ gemini = false,
84337
+ strict = true,
84338
+ stripUriFormat = false,
84339
+ dropEmptyObjectProperties = false,
84340
+ normalizeBareObjects = false
84341
+ } = options;
84342
+ let record2 = sanitizeSchemaForOpenAICompat(schema);
84343
+ if (gemini) {
84344
+ record2 = splitTypeArrayToAnyOf(record2);
84345
+ }
84346
+ if (stripUriFormat && record2.format === "uri") {
84347
+ delete record2.format;
84348
+ }
84349
+ if (record2.type === "object") {
84350
+ const props = isSchemaRecord(record2.properties) ? record2.properties : null;
84351
+ if (props) {
84352
+ const originalRequired = Array.isArray(record2.required) ? record2.required.filter((key) => typeof key === "string") : [];
84353
+ const enforcedProps = {};
84354
+ for (const [key, value] of Object.entries(props)) {
84355
+ const strictValue = strictifySchemaNode(value, options, false);
84356
+ if (dropEmptyObjectProperties && isEmptyStrictObject(strictValue)) {
84357
+ continue;
84358
+ }
84359
+ enforcedProps[key] = strictValue;
84360
+ }
84361
+ record2.properties = enforcedProps;
84362
+ if (strict) {
84363
+ record2.additionalProperties = false;
84364
+ record2.required = Object.keys(enforcedProps);
84365
+ if (topLevel) {
84366
+ const style = gemini ? "nullable" : "union";
84367
+ for (const key of Object.keys(enforcedProps)) {
84368
+ if (!originalRequired.includes(key)) {
84369
+ enforcedProps[key] = makeSchemaNullable(enforcedProps[key], style);
84370
+ }
84371
+ }
84372
+ }
84373
+ } else {
84374
+ record2.required = originalRequired.filter((key) => (key in enforcedProps));
84375
+ }
84376
+ } else if (normalizeBareObjects) {
84377
+ record2.additionalProperties = false;
84378
+ record2.required = [];
84379
+ }
84380
+ }
84381
+ if ("items" in record2) {
84382
+ if (Array.isArray(record2.items)) {
84383
+ record2.items = record2.items.map((item) => strictifySchemaNode(item, options, false));
84384
+ } else {
84385
+ record2.items = strictifySchemaNode(record2.items, options, false);
84386
+ }
84387
+ }
84388
+ for (const key of ["anyOf", "oneOf", "allOf"]) {
84389
+ if (key in record2 && Array.isArray(record2[key])) {
84390
+ record2[key] = record2[key].map((item) => strictifySchemaNode(item, options, false));
84391
+ }
84392
+ }
84393
+ return record2;
84394
+ }
84395
+ function strictifyJsonSchema(schema, options = {}) {
84396
+ return strictifySchemaNode(schema, options, true);
84397
+ }
84326
84398
  var OPENAI_INCOMPATIBLE_SCHEMA_KEYWORDS;
84327
84399
  var init_schemaSanitizer = __esm(() => {
84328
84400
  OPENAI_INCOMPATIBLE_SCHEMA_KEYWORDS = new Set([
@@ -84351,6 +84423,51 @@ var init_schema = __esm(() => {
84351
84423
  init_schemaSanitizer();
84352
84424
  });
84353
84425
 
84426
+ // src/providers/openai/capabilities.ts
84427
+ function supportsReasoningEffort(model) {
84428
+ return /^(o\d|gpt-5|gpt-4\.5)/i.test(model);
84429
+ }
84430
+ function isGeminiLikeModel(model) {
84431
+ const normalized = (model ?? "").trim().toLowerCase();
84432
+ return normalized.startsWith("gemini-") || normalized.includes("/gemini-");
84433
+ }
84434
+ function isGeminiTarget(model) {
84435
+ if (isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI")))
84436
+ return true;
84437
+ return isGeminiLikeModel(model);
84438
+ }
84439
+ function supportsParallelToolCalls(model) {
84440
+ return !isGeminiTarget(model);
84441
+ }
84442
+ function getOpenAICompatMaxOutputTokens(model) {
84443
+ const max = getOpenAIMaxOutputTokens(model);
84444
+ if (max === undefined)
84445
+ return null;
84446
+ return { default: max, upperLimit: max };
84447
+ }
84448
+ function getOpenAICompatContextWindow(model) {
84449
+ return getOpenAIContextWindow(model) ?? null;
84450
+ }
84451
+ function openAICompatSupports(feature, model) {
84452
+ if (feature === "reasoning-effort")
84453
+ return supportsReasoningEffort(model);
84454
+ if (feature === "parallel-tool-calls")
84455
+ return supportsParallelToolCalls(model);
84456
+ return FEATURES_OPENAI_COMPAT.includes(feature);
84457
+ }
84458
+ var FEATURES_OPENAI_COMPAT;
84459
+ var init_capabilities2 = __esm(() => {
84460
+ init_openaiContextWindows();
84461
+ init_envUtils();
84462
+ init_state2();
84463
+ FEATURES_OPENAI_COMPAT = Object.freeze([
84464
+ "streaming",
84465
+ "tool-use",
84466
+ "image-input",
84467
+ "system-message-top-level"
84468
+ ]);
84469
+ });
84470
+
84354
84471
  // src/providers/codex/shim.ts
84355
84472
  function parseSseChunk(chunk) {
84356
84473
  const lines = chunk.split(`
@@ -84593,58 +84710,23 @@ function convertAnthropicMessagesToResponsesInput(messages) {
84593
84710
  }
84594
84711
  return items.filter((item) => item.type !== "message" || item.content.length > 0);
84595
84712
  }
84596
- function enforceStrictSchema(schema, topLevel = true) {
84597
- const record2 = sanitizeSchemaForOpenAICompat(schema);
84598
- if (record2.format === "uri") {
84599
- delete record2.format;
84600
- }
84601
- if (record2.type === "object") {
84602
- record2.additionalProperties = false;
84603
- if (record2.properties && typeof record2.properties === "object" && !Array.isArray(record2.properties)) {
84604
- const props = record2.properties;
84605
- const originalRequired = Array.isArray(record2.required) ? record2.required.filter((key) => typeof key === "string") : [];
84606
- const enforcedProps = {};
84607
- for (const [key, value] of Object.entries(props)) {
84608
- const strictValue = enforceStrictSchema(value, false);
84609
- if (strictValue && typeof strictValue === "object" && strictValue.type === "object" && strictValue.additionalProperties === false && (!strictValue.properties || Object.keys(strictValue.properties).length === 0)) {
84610
- continue;
84611
- }
84612
- enforcedProps[key] = strictValue;
84613
- }
84614
- record2.properties = enforcedProps;
84615
- record2.required = Object.keys(enforcedProps);
84616
- if (topLevel) {
84617
- for (const key of Object.keys(enforcedProps)) {
84618
- if (!originalRequired.includes(key)) {
84619
- enforcedProps[key] = makeSchemaNullable(enforcedProps[key]);
84620
- }
84621
- }
84622
- }
84623
- } else {
84624
- record2.required = [];
84625
- }
84626
- }
84627
- if ("items" in record2) {
84628
- if (Array.isArray(record2.items)) {
84629
- record2.items = record2.items.map((item) => enforceStrictSchema(item, false));
84630
- } else {
84631
- record2.items = enforceStrictSchema(record2.items, false);
84632
- }
84633
- }
84634
- for (const key of ["anyOf", "oneOf", "allOf"]) {
84635
- if (key in record2 && Array.isArray(record2[key])) {
84636
- record2[key] = record2[key].map((item) => enforceStrictSchema(item, false));
84637
- }
84638
- }
84639
- return record2;
84713
+ function toResponsesParameters(schema, geminiTarget) {
84714
+ return strictifyJsonSchema(schema, {
84715
+ strict: true,
84716
+ gemini: geminiTarget,
84717
+ stripUriFormat: true,
84718
+ dropEmptyObjectProperties: true,
84719
+ normalizeBareObjects: true
84720
+ });
84640
84721
  }
84641
- function convertToolsToResponsesTools(tools) {
84722
+ function convertToolsToResponsesTools(tools, model = "") {
84723
+ const geminiTarget = isGeminiTarget(model);
84642
84724
  return tools.flatMap((tool) => {
84643
84725
  if (tool.input_schema && (!tool.type || tool.type === "function")) {
84644
84726
  if (!tool.name || tool.name === "ToolSearchTool")
84645
84727
  return [];
84646
84728
  const rawParameters = tool.input_schema ?? { type: "object", properties: {} };
84647
- const parameters = enforceStrictSchema(rawParameters);
84729
+ const parameters = toResponsesParameters(rawParameters, geminiTarget);
84648
84730
  return [
84649
84731
  {
84650
84732
  type: "function",
@@ -84659,7 +84741,7 @@ function convertToolsToResponsesTools(tools) {
84659
84741
  return [tool];
84660
84742
  }
84661
84743
  if (tool.name && tool.name !== "ToolSearchTool" && (!tool.type || tool.type === "function")) {
84662
- const parameters = enforceStrictSchema({ type: "object", properties: {} });
84744
+ const parameters = toResponsesParameters({ type: "object", properties: {} }, geminiTarget);
84663
84745
  return [
84664
84746
  {
84665
84747
  type: "function",
@@ -84726,10 +84808,10 @@ async function performCodexRequest(options) {
84726
84808
  body.tool_choice = toolChoice;
84727
84809
  }
84728
84810
  if (options.params.tools && options.params.tools.length > 0) {
84729
- const convertedTools = convertToolsToResponsesTools(options.params.tools);
84811
+ const convertedTools = convertToolsToResponsesTools(options.params.tools, options.request.resolvedModel);
84730
84812
  if (convertedTools.length > 0) {
84731
84813
  body.tools = convertedTools;
84732
- body.parallel_tool_calls = true;
84814
+ body.parallel_tool_calls = !isGeminiTarget(options.request.resolvedModel);
84733
84815
  body.tool_choice ??= "auto";
84734
84816
  }
84735
84817
  }
@@ -85099,51 +85181,7 @@ function convertCodexResponseToAnthropicMessage(data, model) {
85099
85181
  var init_shim = __esm(() => {
85100
85182
  init_sdk();
85101
85183
  init_schema();
85102
- });
85103
-
85104
- // src/providers/openai/capabilities.ts
85105
- function supportsReasoningEffort(model) {
85106
- return /^(o\d|gpt-5|gpt-4\.5)/i.test(model);
85107
- }
85108
- function isGeminiLikeModel(model) {
85109
- const normalized = (model ?? "").trim().toLowerCase();
85110
- return normalized.startsWith("gemini-") || normalized.includes("/gemini-");
85111
- }
85112
- function isGeminiTarget(model) {
85113
- if (isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI")))
85114
- return true;
85115
- return isGeminiLikeModel(model);
85116
- }
85117
- function supportsParallelToolCalls(model) {
85118
- return !isGeminiTarget(model);
85119
- }
85120
- function getOpenAICompatMaxOutputTokens(model) {
85121
- const max = getOpenAIMaxOutputTokens(model);
85122
- if (max === undefined)
85123
- return null;
85124
- return { default: max, upperLimit: max };
85125
- }
85126
- function getOpenAICompatContextWindow(model) {
85127
- return getOpenAIContextWindow(model) ?? null;
85128
- }
85129
- function openAICompatSupports(feature, model) {
85130
- if (feature === "reasoning-effort")
85131
- return supportsReasoningEffort(model);
85132
- if (feature === "parallel-tool-calls")
85133
- return supportsParallelToolCalls(model);
85134
- return FEATURES_OPENAI_COMPAT.includes(feature);
85135
- }
85136
- var FEATURES_OPENAI_COMPAT;
85137
- var init_capabilities2 = __esm(() => {
85138
- init_openaiContextWindows();
85139
- init_envUtils();
85140
- init_state2();
85141
- FEATURES_OPENAI_COMPAT = Object.freeze([
85142
- "streaming",
85143
- "tool-use",
85144
- "image-input",
85145
- "system-message-top-level"
85146
- ]);
85184
+ init_capabilities2();
85147
85185
  });
85148
85186
 
85149
85187
  // src/providers/openai/shim.ts
@@ -85373,49 +85411,6 @@ function convertMessages(messages, system) {
85373
85411
  }
85374
85412
  return result;
85375
85413
  }
85376
- function normalizeSchemaForOpenAI(schema, strict = true, topLevel = true, geminiTarget = false) {
85377
- let record2 = sanitizeSchemaForOpenAICompat(schema);
85378
- if (geminiTarget) {
85379
- record2 = splitTypeArrayToAnyOf(record2);
85380
- }
85381
- if (record2.type === "object" && record2.properties) {
85382
- const properties = record2.properties;
85383
- const existingRequired = Array.isArray(record2.required) ? record2.required : [];
85384
- const normalizedProps = {};
85385
- for (const [key, value] of Object.entries(properties)) {
85386
- normalizedProps[key] = normalizeSchemaForOpenAI(value, strict, false, geminiTarget);
85387
- }
85388
- record2.properties = normalizedProps;
85389
- if (strict) {
85390
- const allKeys = Object.keys(normalizedProps);
85391
- record2.required = Array.from(new Set([...existingRequired, ...allKeys]));
85392
- record2.additionalProperties = false;
85393
- if (topLevel) {
85394
- const style = geminiTarget ? "nullable" : "union";
85395
- for (const key of allKeys) {
85396
- if (!existingRequired.includes(key)) {
85397
- normalizedProps[key] = makeSchemaNullable(normalizedProps[key], style);
85398
- }
85399
- }
85400
- }
85401
- } else {
85402
- record2.required = existingRequired.filter((k) => (k in normalizedProps));
85403
- }
85404
- }
85405
- if ("items" in record2) {
85406
- if (Array.isArray(record2.items)) {
85407
- record2.items = record2.items.map((item) => normalizeSchemaForOpenAI(item, strict, false, geminiTarget));
85408
- } else {
85409
- record2.items = normalizeSchemaForOpenAI(record2.items, strict, false, geminiTarget);
85410
- }
85411
- }
85412
- for (const key of ["anyOf", "oneOf", "allOf"]) {
85413
- if (key in record2 && Array.isArray(record2[key])) {
85414
- record2[key] = record2[key].map((item) => normalizeSchemaForOpenAI(item, strict, false, geminiTarget));
85415
- }
85416
- }
85417
- return record2;
85418
- }
85419
85414
  function convertTools(tools, model = "") {
85420
85415
  const isGemini = isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI"));
85421
85416
  const geminiTarget = isGeminiTarget(model);
@@ -85436,7 +85431,7 @@ function convertTools(tools, model = "") {
85436
85431
  function: {
85437
85432
  name: t.name,
85438
85433
  description: t.description ?? "",
85439
- parameters: normalizeSchemaForOpenAI(schema, !isGemini, true, geminiTarget)
85434
+ parameters: strictifyJsonSchema(schema, { strict: !isGemini, gemini: geminiTarget })
85440
85435
  }
85441
85436
  };
85442
85437
  });
@@ -94366,7 +94361,7 @@ function printStartupScreen() {
94366
94361
  const sLen = ` ● ${sL} Ready — type /help to begin`.length;
94367
94362
  out.push(boxRow(sRow, W2, sLen));
94368
94363
  out.push(`${rgb(...BORDER)}╚${"═".repeat(W2 - 2)}╝${RESET}`);
94369
- out.push(` ${DIM}${rgb(...DIMCOL)}opencow ${RESET}${rgb(...ACCENT)}v${"0.4.5"}${RESET}`);
94364
+ out.push(` ${DIM}${rgb(...DIMCOL)}opencow ${RESET}${rgb(...ACCENT)}v${"0.4.6"}${RESET}`);
94370
94365
  out.push("");
94371
94366
  process.stdout.write(out.join(`
94372
94367
  `) + `
@@ -244175,7 +244170,7 @@ function getAnthropicEnvMetadata() {
244175
244170
  function getBuildAgeMinutes() {
244176
244171
  if (false)
244177
244172
  ;
244178
- const buildTime = new Date("2026-06-03T12:46:47.435Z").getTime();
244173
+ const buildTime = new Date("2026-06-03T14:42:10.545Z").getTime();
244179
244174
  if (isNaN(buildTime))
244180
244175
  return;
244181
244176
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -479315,7 +479310,7 @@ function buildPrimarySection() {
479315
479310
  }, undefined, false, undefined, this);
479316
479311
  return [{
479317
479312
  label: "Version",
479318
- value: "0.4.5"
479313
+ value: "0.4.6"
479319
479314
  }, {
479320
479315
  label: "Session name",
479321
479316
  value: nameValue
@@ -535633,7 +535628,7 @@ var init_bridge_kick = __esm(() => {
535633
535628
  var call58 = async () => {
535634
535629
  return {
535635
535630
  type: "text",
535636
- value: `${"99.0.0"} (built ${"2026-06-03T12:46:47.435Z"})`
535631
+ value: `${"99.0.0"} (built ${"2026-06-03T14:42:10.545Z"})`
535637
535632
  };
535638
535633
  }, version2, version_default;
535639
535634
  var init_version = __esm(() => {
@@ -557743,7 +557738,7 @@ function WelcomeV2() {
557743
557738
  dimColor: true,
557744
557739
  children: [
557745
557740
  "v",
557746
- "0.4.5",
557741
+ "0.4.6",
557747
557742
  " "
557748
557743
  ]
557749
557744
  }, undefined, true, undefined, this)
@@ -557943,7 +557938,7 @@ function WelcomeV2() {
557943
557938
  dimColor: true,
557944
557939
  children: [
557945
557940
  "v",
557946
- "0.4.5",
557941
+ "0.4.6",
557947
557942
  " "
557948
557943
  ]
557949
557944
  }, undefined, true, undefined, this)
@@ -558169,7 +558164,7 @@ function AppleTerminalWelcomeV2(t0) {
558169
558164
  dimColor: true,
558170
558165
  children: [
558171
558166
  "v",
558172
- "0.4.5",
558167
+ "0.4.6",
558173
558168
  " "
558174
558169
  ]
558175
558170
  }, undefined, true, undefined, this);
@@ -558423,7 +558418,7 @@ function AppleTerminalWelcomeV2(t0) {
558423
558418
  dimColor: true,
558424
558419
  children: [
558425
558420
  "v",
558426
- "0.4.5",
558421
+ "0.4.6",
558427
558422
  " "
558428
558423
  ]
558429
558424
  }, undefined, true, undefined, this);
@@ -579269,7 +579264,7 @@ Usage: claude --remote "your task description"`, () => gracefulShutdown(1));
579269
579264
  pendingHookMessages
579270
579265
  }, renderAndRun);
579271
579266
  }
579272
- }).version("0.4.5 (OpenCow)", "-v, --version", "Output the version number");
579267
+ }).version("0.4.6 (OpenCow)", "-v, --version", "Output the version number");
579273
579268
  program2.option("-w, --worktree [name]", "Create a new git worktree for this session (optionally specify a name)");
579274
579269
  program2.option("--tmux", "Create a tmux session for the worktree (requires --worktree). Uses iTerm2 native panes when available; use --tmux=classic for traditional tmux.");
579275
579270
  if (canUserConfigureAdvisor()) {
@@ -579915,7 +579910,7 @@ if (false) {}
579915
579910
  async function main2() {
579916
579911
  const args = process.argv.slice(2);
579917
579912
  if (args.length === 1 && (args[0] === "--version" || args[0] === "-v" || args[0] === "-V")) {
579918
- console.log(`${"0.4.5"} (OpenCow)`);
579913
+ console.log(`${"0.4.6"} (OpenCow)`);
579919
579914
  return;
579920
579915
  }
579921
579916
  if (args.includes("--provider")) {
@@ -580033,4 +580028,4 @@ async function main2() {
580033
580028
  }
580034
580029
  main2();
580035
580030
 
580036
- //# debugId=A32EDDBB8A04BA5B64756E2164756E21
580031
+ //# debugId=6B8704627517D02B64756E2164756E21
package/dist/client.js CHANGED
@@ -95053,7 +95053,8 @@ function sanitizeSchemaForOpenAICompat(schema) {
95053
95053
  }
95054
95054
  }
95055
95055
  if (Array.isArray(record3.required) && isSchemaRecord(record3.properties)) {
95056
- record3.required = record3.required.filter((value) => typeof value === "string" && (value in record3.properties));
95056
+ const properties = record3.properties;
95057
+ record3.required = record3.required.filter((value) => typeof value === "string" && (value in properties));
95057
95058
  }
95058
95059
  const schemaWithoutEnum = { ...record3 };
95059
95060
  delete schemaWithoutEnum.enum;
@@ -95072,6 +95073,77 @@ function sanitizeSchemaForOpenAICompat(schema) {
95072
95073
  }
95073
95074
  return record3;
95074
95075
  }
95076
+ function isEmptyStrictObject(schema) {
95077
+ if (schema.type !== "object" || schema.additionalProperties !== false) {
95078
+ return false;
95079
+ }
95080
+ const props = schema.properties;
95081
+ return !props || isSchemaRecord(props) && Object.keys(props).length === 0;
95082
+ }
95083
+ function strictifySchemaNode(schema, options, topLevel) {
95084
+ const {
95085
+ gemini = false,
95086
+ strict = true,
95087
+ stripUriFormat = false,
95088
+ dropEmptyObjectProperties = false,
95089
+ normalizeBareObjects = false
95090
+ } = options;
95091
+ let record3 = sanitizeSchemaForOpenAICompat(schema);
95092
+ if (gemini) {
95093
+ record3 = splitTypeArrayToAnyOf(record3);
95094
+ }
95095
+ if (stripUriFormat && record3.format === "uri") {
95096
+ delete record3.format;
95097
+ }
95098
+ if (record3.type === "object") {
95099
+ const props = isSchemaRecord(record3.properties) ? record3.properties : null;
95100
+ if (props) {
95101
+ const originalRequired = Array.isArray(record3.required) ? record3.required.filter((key) => typeof key === "string") : [];
95102
+ const enforcedProps = {};
95103
+ for (const [key, value] of Object.entries(props)) {
95104
+ const strictValue = strictifySchemaNode(value, options, false);
95105
+ if (dropEmptyObjectProperties && isEmptyStrictObject(strictValue)) {
95106
+ continue;
95107
+ }
95108
+ enforcedProps[key] = strictValue;
95109
+ }
95110
+ record3.properties = enforcedProps;
95111
+ if (strict) {
95112
+ record3.additionalProperties = false;
95113
+ record3.required = Object.keys(enforcedProps);
95114
+ if (topLevel) {
95115
+ const style = gemini ? "nullable" : "union";
95116
+ for (const key of Object.keys(enforcedProps)) {
95117
+ if (!originalRequired.includes(key)) {
95118
+ enforcedProps[key] = makeSchemaNullable(enforcedProps[key], style);
95119
+ }
95120
+ }
95121
+ }
95122
+ } else {
95123
+ record3.required = originalRequired.filter((key) => (key in enforcedProps));
95124
+ }
95125
+ } else if (normalizeBareObjects) {
95126
+ record3.additionalProperties = false;
95127
+ record3.required = [];
95128
+ }
95129
+ }
95130
+ if ("items" in record3) {
95131
+ if (Array.isArray(record3.items)) {
95132
+ record3.items = record3.items.map((item) => strictifySchemaNode(item, options, false));
95133
+ } else {
95134
+ record3.items = strictifySchemaNode(record3.items, options, false);
95135
+ }
95136
+ }
95137
+ for (const key of ["anyOf", "oneOf", "allOf"]) {
95138
+ if (key in record3 && Array.isArray(record3[key])) {
95139
+ record3[key] = record3[key].map((item) => strictifySchemaNode(item, options, false));
95140
+ }
95141
+ }
95142
+ return record3;
95143
+ }
95144
+ function strictifyJsonSchema(schema, options = {}) {
95145
+ return strictifySchemaNode(schema, options, true);
95146
+ }
95075
95147
  var OPENAI_INCOMPATIBLE_SCHEMA_KEYWORDS;
95076
95148
  var init_schemaSanitizer = __esm(() => {
95077
95149
  OPENAI_INCOMPATIBLE_SCHEMA_KEYWORDS = new Set([
@@ -95100,6 +95172,51 @@ var init_schema = __esm(() => {
95100
95172
  init_schemaSanitizer();
95101
95173
  });
95102
95174
 
95175
+ // src/providers/openai/capabilities.ts
95176
+ function supportsReasoningEffort(model) {
95177
+ return /^(o\d|gpt-5|gpt-4\.5)/i.test(model);
95178
+ }
95179
+ function isGeminiLikeModel(model) {
95180
+ const normalized = (model ?? "").trim().toLowerCase();
95181
+ return normalized.startsWith("gemini-") || normalized.includes("/gemini-");
95182
+ }
95183
+ function isGeminiTarget(model) {
95184
+ if (isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI")))
95185
+ return true;
95186
+ return isGeminiLikeModel(model);
95187
+ }
95188
+ function supportsParallelToolCalls(model) {
95189
+ return !isGeminiTarget(model);
95190
+ }
95191
+ function getOpenAICompatMaxOutputTokens(model) {
95192
+ const max = getOpenAIMaxOutputTokens(model);
95193
+ if (max === undefined)
95194
+ return null;
95195
+ return { default: max, upperLimit: max };
95196
+ }
95197
+ function getOpenAICompatContextWindow(model) {
95198
+ return getOpenAIContextWindow(model) ?? null;
95199
+ }
95200
+ function openAICompatSupports(feature, model) {
95201
+ if (feature === "reasoning-effort")
95202
+ return supportsReasoningEffort(model);
95203
+ if (feature === "parallel-tool-calls")
95204
+ return supportsParallelToolCalls(model);
95205
+ return FEATURES_OPENAI_COMPAT.includes(feature);
95206
+ }
95207
+ var FEATURES_OPENAI_COMPAT;
95208
+ var init_capabilities2 = __esm(() => {
95209
+ init_openaiContextWindows();
95210
+ init_envUtils();
95211
+ init_state2();
95212
+ FEATURES_OPENAI_COMPAT = Object.freeze([
95213
+ "streaming",
95214
+ "tool-use",
95215
+ "image-input",
95216
+ "system-message-top-level"
95217
+ ]);
95218
+ });
95219
+
95103
95220
  // src/providers/codex/shim.ts
95104
95221
  function parseSseChunk(chunk) {
95105
95222
  const lines = chunk.split(`
@@ -95342,58 +95459,23 @@ function convertAnthropicMessagesToResponsesInput(messages) {
95342
95459
  }
95343
95460
  return items.filter((item) => item.type !== "message" || item.content.length > 0);
95344
95461
  }
95345
- function enforceStrictSchema(schema, topLevel = true) {
95346
- const record3 = sanitizeSchemaForOpenAICompat(schema);
95347
- if (record3.format === "uri") {
95348
- delete record3.format;
95349
- }
95350
- if (record3.type === "object") {
95351
- record3.additionalProperties = false;
95352
- if (record3.properties && typeof record3.properties === "object" && !Array.isArray(record3.properties)) {
95353
- const props = record3.properties;
95354
- const originalRequired = Array.isArray(record3.required) ? record3.required.filter((key) => typeof key === "string") : [];
95355
- const enforcedProps = {};
95356
- for (const [key, value] of Object.entries(props)) {
95357
- const strictValue = enforceStrictSchema(value, false);
95358
- if (strictValue && typeof strictValue === "object" && strictValue.type === "object" && strictValue.additionalProperties === false && (!strictValue.properties || Object.keys(strictValue.properties).length === 0)) {
95359
- continue;
95360
- }
95361
- enforcedProps[key] = strictValue;
95362
- }
95363
- record3.properties = enforcedProps;
95364
- record3.required = Object.keys(enforcedProps);
95365
- if (topLevel) {
95366
- for (const key of Object.keys(enforcedProps)) {
95367
- if (!originalRequired.includes(key)) {
95368
- enforcedProps[key] = makeSchemaNullable(enforcedProps[key]);
95369
- }
95370
- }
95371
- }
95372
- } else {
95373
- record3.required = [];
95374
- }
95375
- }
95376
- if ("items" in record3) {
95377
- if (Array.isArray(record3.items)) {
95378
- record3.items = record3.items.map((item) => enforceStrictSchema(item, false));
95379
- } else {
95380
- record3.items = enforceStrictSchema(record3.items, false);
95381
- }
95382
- }
95383
- for (const key of ["anyOf", "oneOf", "allOf"]) {
95384
- if (key in record3 && Array.isArray(record3[key])) {
95385
- record3[key] = record3[key].map((item) => enforceStrictSchema(item, false));
95386
- }
95387
- }
95388
- return record3;
95462
+ function toResponsesParameters(schema, geminiTarget) {
95463
+ return strictifyJsonSchema(schema, {
95464
+ strict: true,
95465
+ gemini: geminiTarget,
95466
+ stripUriFormat: true,
95467
+ dropEmptyObjectProperties: true,
95468
+ normalizeBareObjects: true
95469
+ });
95389
95470
  }
95390
- function convertToolsToResponsesTools(tools) {
95471
+ function convertToolsToResponsesTools(tools, model = "") {
95472
+ const geminiTarget = isGeminiTarget(model);
95391
95473
  return tools.flatMap((tool) => {
95392
95474
  if (tool.input_schema && (!tool.type || tool.type === "function")) {
95393
95475
  if (!tool.name || tool.name === "ToolSearchTool")
95394
95476
  return [];
95395
95477
  const rawParameters = tool.input_schema ?? { type: "object", properties: {} };
95396
- const parameters = enforceStrictSchema(rawParameters);
95478
+ const parameters = toResponsesParameters(rawParameters, geminiTarget);
95397
95479
  return [
95398
95480
  {
95399
95481
  type: "function",
@@ -95408,7 +95490,7 @@ function convertToolsToResponsesTools(tools) {
95408
95490
  return [tool];
95409
95491
  }
95410
95492
  if (tool.name && tool.name !== "ToolSearchTool" && (!tool.type || tool.type === "function")) {
95411
- const parameters = enforceStrictSchema({ type: "object", properties: {} });
95493
+ const parameters = toResponsesParameters({ type: "object", properties: {} }, geminiTarget);
95412
95494
  return [
95413
95495
  {
95414
95496
  type: "function",
@@ -95475,10 +95557,10 @@ async function performCodexRequest(options) {
95475
95557
  body.tool_choice = toolChoice;
95476
95558
  }
95477
95559
  if (options.params.tools && options.params.tools.length > 0) {
95478
- const convertedTools = convertToolsToResponsesTools(options.params.tools);
95560
+ const convertedTools = convertToolsToResponsesTools(options.params.tools, options.request.resolvedModel);
95479
95561
  if (convertedTools.length > 0) {
95480
95562
  body.tools = convertedTools;
95481
- body.parallel_tool_calls = true;
95563
+ body.parallel_tool_calls = !isGeminiTarget(options.request.resolvedModel);
95482
95564
  body.tool_choice ??= "auto";
95483
95565
  }
95484
95566
  }
@@ -95848,6 +95930,7 @@ function convertCodexResponseToAnthropicMessage(data, model) {
95848
95930
  var init_shim = __esm(() => {
95849
95931
  init_sdk();
95850
95932
  init_schema();
95933
+ init_capabilities2();
95851
95934
  });
95852
95935
 
95853
95936
  // src/providers/shared/providerRecommendation.ts
@@ -95925,51 +96008,6 @@ var init_providerProfile = __esm(() => {
95925
96008
  ];
95926
96009
  });
95927
96010
 
95928
- // src/providers/openai/capabilities.ts
95929
- function supportsReasoningEffort(model) {
95930
- return /^(o\d|gpt-5|gpt-4\.5)/i.test(model);
95931
- }
95932
- function isGeminiLikeModel(model) {
95933
- const normalized = (model ?? "").trim().toLowerCase();
95934
- return normalized.startsWith("gemini-") || normalized.includes("/gemini-");
95935
- }
95936
- function isGeminiTarget(model) {
95937
- if (isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI")))
95938
- return true;
95939
- return isGeminiLikeModel(model);
95940
- }
95941
- function supportsParallelToolCalls(model) {
95942
- return !isGeminiTarget(model);
95943
- }
95944
- function getOpenAICompatMaxOutputTokens(model) {
95945
- const max = getOpenAIMaxOutputTokens(model);
95946
- if (max === undefined)
95947
- return null;
95948
- return { default: max, upperLimit: max };
95949
- }
95950
- function getOpenAICompatContextWindow(model) {
95951
- return getOpenAIContextWindow(model) ?? null;
95952
- }
95953
- function openAICompatSupports(feature, model) {
95954
- if (feature === "reasoning-effort")
95955
- return supportsReasoningEffort(model);
95956
- if (feature === "parallel-tool-calls")
95957
- return supportsParallelToolCalls(model);
95958
- return FEATURES_OPENAI_COMPAT.includes(feature);
95959
- }
95960
- var FEATURES_OPENAI_COMPAT;
95961
- var init_capabilities2 = __esm(() => {
95962
- init_openaiContextWindows();
95963
- init_envUtils();
95964
- init_state2();
95965
- FEATURES_OPENAI_COMPAT = Object.freeze([
95966
- "streaming",
95967
- "tool-use",
95968
- "image-input",
95969
- "system-message-top-level"
95970
- ]);
95971
- });
95972
-
95973
96011
  // src/providers/openai/shim.ts
95974
96012
  var exports_shim = {};
95975
96013
  __export(exports_shim, {
@@ -96197,49 +96235,6 @@ function convertMessages(messages, system) {
96197
96235
  }
96198
96236
  return result;
96199
96237
  }
96200
- function normalizeSchemaForOpenAI(schema, strict = true, topLevel = true, geminiTarget = false) {
96201
- let record3 = sanitizeSchemaForOpenAICompat(schema);
96202
- if (geminiTarget) {
96203
- record3 = splitTypeArrayToAnyOf(record3);
96204
- }
96205
- if (record3.type === "object" && record3.properties) {
96206
- const properties = record3.properties;
96207
- const existingRequired = Array.isArray(record3.required) ? record3.required : [];
96208
- const normalizedProps = {};
96209
- for (const [key, value] of Object.entries(properties)) {
96210
- normalizedProps[key] = normalizeSchemaForOpenAI(value, strict, false, geminiTarget);
96211
- }
96212
- record3.properties = normalizedProps;
96213
- if (strict) {
96214
- const allKeys = Object.keys(normalizedProps);
96215
- record3.required = Array.from(new Set([...existingRequired, ...allKeys]));
96216
- record3.additionalProperties = false;
96217
- if (topLevel) {
96218
- const style = geminiTarget ? "nullable" : "union";
96219
- for (const key of allKeys) {
96220
- if (!existingRequired.includes(key)) {
96221
- normalizedProps[key] = makeSchemaNullable(normalizedProps[key], style);
96222
- }
96223
- }
96224
- }
96225
- } else {
96226
- record3.required = existingRequired.filter((k) => (k in normalizedProps));
96227
- }
96228
- }
96229
- if ("items" in record3) {
96230
- if (Array.isArray(record3.items)) {
96231
- record3.items = record3.items.map((item) => normalizeSchemaForOpenAI(item, strict, false, geminiTarget));
96232
- } else {
96233
- record3.items = normalizeSchemaForOpenAI(record3.items, strict, false, geminiTarget);
96234
- }
96235
- }
96236
- for (const key of ["anyOf", "oneOf", "allOf"]) {
96237
- if (key in record3 && Array.isArray(record3[key])) {
96238
- record3[key] = record3[key].map((item) => normalizeSchemaForOpenAI(item, strict, false, geminiTarget));
96239
- }
96240
- }
96241
- return record3;
96242
- }
96243
96238
  function convertTools(tools, model = "") {
96244
96239
  const isGemini = isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI"));
96245
96240
  const geminiTarget = isGeminiTarget(model);
@@ -96260,7 +96255,7 @@ function convertTools(tools, model = "") {
96260
96255
  function: {
96261
96256
  name: t.name,
96262
96257
  description: t.description ?? "",
96263
- parameters: normalizeSchemaForOpenAI(schema, !isGemini, true, geminiTarget)
96258
+ parameters: strictifyJsonSchema(schema, { strict: !isGemini, gemini: geminiTarget })
96264
96259
  }
96265
96260
  };
96266
96261
  });
@@ -282271,7 +282266,7 @@ function getAnthropicEnvMetadata() {
282271
282266
  function getBuildAgeMinutes() {
282272
282267
  if (false)
282273
282268
  ;
282274
- const buildTime = new Date("2026-06-03T12:46:47.435Z").getTime();
282269
+ const buildTime = new Date("2026-06-03T14:42:10.545Z").getTime();
282275
282270
  if (isNaN(buildTime))
282276
282271
  return;
282277
282272
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -335452,4 +335447,4 @@ export {
335452
335447
  AbortError2 as AbortError
335453
335448
  };
335454
335449
 
335455
- //# debugId=EF5892485DBD67B164756E2164756E21
335450
+ //# debugId=43217E45406B3AFE64756E2164756E21
@@ -40,3 +40,46 @@ export declare function splitTypeArrayToAnyOf(schema: Record<string, unknown>):
40
40
  * keywords while keeping enum/const cleanup defensive for imperfect MCP schemas.
41
41
  */
42
42
  export declare function sanitizeSchemaForOpenAICompat(schema: unknown): Record<string, unknown>;
43
+ /**
44
+ * 「Anthropic 工具 schema → 严格 / Gemini 安全 schema」的统一规整入口。
45
+ *
46
+ * 历史上 chat_completions 路径(openai shim 的 normalizeSchemaForOpenAI)与 Responses
47
+ * 路径(codex shim 的 enforceStrictSchema)各自维护了一份几乎相同的递归实现,Gemini
48
+ * 适配(issue #79/#77、Vertex 400)需要在两处手工同步——典型的「两份会逐渐发散的拷贝」。
49
+ * 这里收敛为单一数据源:递归骨架只此一份,两条路径的差异通过 options 显式表达。
50
+ *
51
+ * 组合的原子能力:
52
+ * - {@link sanitizeSchemaForOpenAICompat}:剥离 provider 不接受的关键字、清洗 enum/const
53
+ * - {@link splitTypeArrayToAnyOf}(仅 gemini):type 数组 → {type, nullable:true}
54
+ * - {@link makeSchemaNullable}:strict 下被强制 required 的「原本可选」字段标可空
55
+ */
56
+ export interface StrictifyJsonSchemaOptions {
57
+ /**
58
+ * 目标为 Gemini/Vertex。拆 type 数组、可空字段用 nullable:true 而非 type:[T,"null"]
59
+ * (Gemini strict 唯一接受的可空写法)。默认 false(OpenAI/Codex/DeepSeek/Kimi…)。
60
+ */
61
+ gemini?: boolean;
62
+ /**
63
+ * strict 结构化输出(默认 true):每个属性强制并入 required、对象补
64
+ * additionalProperties:false、顶层「原本可选」字段标可空。设 false(如
65
+ * CLAUDE_CODE_USE_GEMINI 原生路径)则保留原始 required、不强制 additionalProperties、
66
+ * 不加可空。
67
+ */
68
+ strict?: boolean;
69
+ /**
70
+ * 删除 `format:"uri"`(Codex Responses 拒绝该 format,URL 校验留在工具层)。默认 false。
71
+ */
72
+ stripUriFormat?: boolean;
73
+ /**
74
+ * 丢弃「规整后退化为空对象」的属性(strict 下 OpenAI/Codex 会静默剥离其 schema、再因
75
+ * 残留 required 报 mismatch;典型如 z.record() / AskUserQuestion.answers)。默认 false。
76
+ */
77
+ dropEmptyObjectProperties?: boolean;
78
+ /**
79
+ * 对「`type:"object"` 但无 properties 键」的对象也补 additionalProperties:false +
80
+ * required:[](Codex Responses 要求每个对象都严格闭合)。chat 路径保持原样,避免改变
81
+ * 自由对象(freeform object)字段的既有行为。默认 false。
82
+ */
83
+ normalizeBareObjects?: boolean;
84
+ }
85
+ export declare function strictifyJsonSchema(schema: unknown, options?: StrictifyJsonSchemaOptions): Record<string, unknown>;
@@ -115,7 +115,7 @@ export declare function convertToolsToResponsesTools(tools: Array<{
115
115
  input_schema?: Record<string, unknown>;
116
116
  type?: string;
117
117
  [k: string]: unknown;
118
- }>): ResponsesTool[];
118
+ }>, model?: string): ResponsesTool[];
119
119
  export declare function performCodexRequest(options: {
120
120
  request: ResolvedProviderRequest;
121
121
  credentials: ResolvedCodexCredentials;
@@ -1 +1 @@
1
- export { sanitizeSchemaForOpenAICompat, makeSchemaNullable, } from '../../lib/schemaSanitizer.js';
1
+ export { sanitizeSchemaForOpenAICompat, makeSchemaNullable, splitTypeArrayToAnyOf, strictifyJsonSchema, } from '../../lib/schemaSanitizer.js';
@@ -1,4 +1,4 @@
1
- import { type AnthropicStreamEvent } from '../../providers/openai/shim.js';
1
+ import type { AnthropicStreamEvent } from '../../providers/codex/shim.js';
2
2
  import type { NormalizedRequest, NormalizedResponse, StreamEvent } from '../types.js';
3
3
  export interface OpenAIWireContext {
4
4
  /**
package/dist/sdk.js CHANGED
@@ -95053,7 +95053,8 @@ function sanitizeSchemaForOpenAICompat(schema) {
95053
95053
  }
95054
95054
  }
95055
95055
  if (Array.isArray(record3.required) && isSchemaRecord(record3.properties)) {
95056
- record3.required = record3.required.filter((value) => typeof value === "string" && (value in record3.properties));
95056
+ const properties = record3.properties;
95057
+ record3.required = record3.required.filter((value) => typeof value === "string" && (value in properties));
95057
95058
  }
95058
95059
  const schemaWithoutEnum = { ...record3 };
95059
95060
  delete schemaWithoutEnum.enum;
@@ -95072,6 +95073,77 @@ function sanitizeSchemaForOpenAICompat(schema) {
95072
95073
  }
95073
95074
  return record3;
95074
95075
  }
95076
+ function isEmptyStrictObject(schema) {
95077
+ if (schema.type !== "object" || schema.additionalProperties !== false) {
95078
+ return false;
95079
+ }
95080
+ const props = schema.properties;
95081
+ return !props || isSchemaRecord(props) && Object.keys(props).length === 0;
95082
+ }
95083
+ function strictifySchemaNode(schema, options, topLevel) {
95084
+ const {
95085
+ gemini = false,
95086
+ strict = true,
95087
+ stripUriFormat = false,
95088
+ dropEmptyObjectProperties = false,
95089
+ normalizeBareObjects = false
95090
+ } = options;
95091
+ let record3 = sanitizeSchemaForOpenAICompat(schema);
95092
+ if (gemini) {
95093
+ record3 = splitTypeArrayToAnyOf(record3);
95094
+ }
95095
+ if (stripUriFormat && record3.format === "uri") {
95096
+ delete record3.format;
95097
+ }
95098
+ if (record3.type === "object") {
95099
+ const props = isSchemaRecord(record3.properties) ? record3.properties : null;
95100
+ if (props) {
95101
+ const originalRequired = Array.isArray(record3.required) ? record3.required.filter((key) => typeof key === "string") : [];
95102
+ const enforcedProps = {};
95103
+ for (const [key, value] of Object.entries(props)) {
95104
+ const strictValue = strictifySchemaNode(value, options, false);
95105
+ if (dropEmptyObjectProperties && isEmptyStrictObject(strictValue)) {
95106
+ continue;
95107
+ }
95108
+ enforcedProps[key] = strictValue;
95109
+ }
95110
+ record3.properties = enforcedProps;
95111
+ if (strict) {
95112
+ record3.additionalProperties = false;
95113
+ record3.required = Object.keys(enforcedProps);
95114
+ if (topLevel) {
95115
+ const style = gemini ? "nullable" : "union";
95116
+ for (const key of Object.keys(enforcedProps)) {
95117
+ if (!originalRequired.includes(key)) {
95118
+ enforcedProps[key] = makeSchemaNullable(enforcedProps[key], style);
95119
+ }
95120
+ }
95121
+ }
95122
+ } else {
95123
+ record3.required = originalRequired.filter((key) => (key in enforcedProps));
95124
+ }
95125
+ } else if (normalizeBareObjects) {
95126
+ record3.additionalProperties = false;
95127
+ record3.required = [];
95128
+ }
95129
+ }
95130
+ if ("items" in record3) {
95131
+ if (Array.isArray(record3.items)) {
95132
+ record3.items = record3.items.map((item) => strictifySchemaNode(item, options, false));
95133
+ } else {
95134
+ record3.items = strictifySchemaNode(record3.items, options, false);
95135
+ }
95136
+ }
95137
+ for (const key of ["anyOf", "oneOf", "allOf"]) {
95138
+ if (key in record3 && Array.isArray(record3[key])) {
95139
+ record3[key] = record3[key].map((item) => strictifySchemaNode(item, options, false));
95140
+ }
95141
+ }
95142
+ return record3;
95143
+ }
95144
+ function strictifyJsonSchema(schema, options = {}) {
95145
+ return strictifySchemaNode(schema, options, true);
95146
+ }
95075
95147
  var OPENAI_INCOMPATIBLE_SCHEMA_KEYWORDS;
95076
95148
  var init_schemaSanitizer = __esm(() => {
95077
95149
  OPENAI_INCOMPATIBLE_SCHEMA_KEYWORDS = new Set([
@@ -95100,6 +95172,51 @@ var init_schema = __esm(() => {
95100
95172
  init_schemaSanitizer();
95101
95173
  });
95102
95174
 
95175
+ // src/providers/openai/capabilities.ts
95176
+ function supportsReasoningEffort(model) {
95177
+ return /^(o\d|gpt-5|gpt-4\.5)/i.test(model);
95178
+ }
95179
+ function isGeminiLikeModel(model) {
95180
+ const normalized = (model ?? "").trim().toLowerCase();
95181
+ return normalized.startsWith("gemini-") || normalized.includes("/gemini-");
95182
+ }
95183
+ function isGeminiTarget(model) {
95184
+ if (isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI")))
95185
+ return true;
95186
+ return isGeminiLikeModel(model);
95187
+ }
95188
+ function supportsParallelToolCalls(model) {
95189
+ return !isGeminiTarget(model);
95190
+ }
95191
+ function getOpenAICompatMaxOutputTokens(model) {
95192
+ const max = getOpenAIMaxOutputTokens(model);
95193
+ if (max === undefined)
95194
+ return null;
95195
+ return { default: max, upperLimit: max };
95196
+ }
95197
+ function getOpenAICompatContextWindow(model) {
95198
+ return getOpenAIContextWindow(model) ?? null;
95199
+ }
95200
+ function openAICompatSupports(feature, model) {
95201
+ if (feature === "reasoning-effort")
95202
+ return supportsReasoningEffort(model);
95203
+ if (feature === "parallel-tool-calls")
95204
+ return supportsParallelToolCalls(model);
95205
+ return FEATURES_OPENAI_COMPAT.includes(feature);
95206
+ }
95207
+ var FEATURES_OPENAI_COMPAT;
95208
+ var init_capabilities2 = __esm(() => {
95209
+ init_openaiContextWindows();
95210
+ init_envUtils();
95211
+ init_state2();
95212
+ FEATURES_OPENAI_COMPAT = Object.freeze([
95213
+ "streaming",
95214
+ "tool-use",
95215
+ "image-input",
95216
+ "system-message-top-level"
95217
+ ]);
95218
+ });
95219
+
95103
95220
  // src/providers/codex/shim.ts
95104
95221
  function parseSseChunk(chunk) {
95105
95222
  const lines = chunk.split(`
@@ -95342,58 +95459,23 @@ function convertAnthropicMessagesToResponsesInput(messages) {
95342
95459
  }
95343
95460
  return items.filter((item) => item.type !== "message" || item.content.length > 0);
95344
95461
  }
95345
- function enforceStrictSchema(schema, topLevel = true) {
95346
- const record3 = sanitizeSchemaForOpenAICompat(schema);
95347
- if (record3.format === "uri") {
95348
- delete record3.format;
95349
- }
95350
- if (record3.type === "object") {
95351
- record3.additionalProperties = false;
95352
- if (record3.properties && typeof record3.properties === "object" && !Array.isArray(record3.properties)) {
95353
- const props = record3.properties;
95354
- const originalRequired = Array.isArray(record3.required) ? record3.required.filter((key) => typeof key === "string") : [];
95355
- const enforcedProps = {};
95356
- for (const [key, value] of Object.entries(props)) {
95357
- const strictValue = enforceStrictSchema(value, false);
95358
- if (strictValue && typeof strictValue === "object" && strictValue.type === "object" && strictValue.additionalProperties === false && (!strictValue.properties || Object.keys(strictValue.properties).length === 0)) {
95359
- continue;
95360
- }
95361
- enforcedProps[key] = strictValue;
95362
- }
95363
- record3.properties = enforcedProps;
95364
- record3.required = Object.keys(enforcedProps);
95365
- if (topLevel) {
95366
- for (const key of Object.keys(enforcedProps)) {
95367
- if (!originalRequired.includes(key)) {
95368
- enforcedProps[key] = makeSchemaNullable(enforcedProps[key]);
95369
- }
95370
- }
95371
- }
95372
- } else {
95373
- record3.required = [];
95374
- }
95375
- }
95376
- if ("items" in record3) {
95377
- if (Array.isArray(record3.items)) {
95378
- record3.items = record3.items.map((item) => enforceStrictSchema(item, false));
95379
- } else {
95380
- record3.items = enforceStrictSchema(record3.items, false);
95381
- }
95382
- }
95383
- for (const key of ["anyOf", "oneOf", "allOf"]) {
95384
- if (key in record3 && Array.isArray(record3[key])) {
95385
- record3[key] = record3[key].map((item) => enforceStrictSchema(item, false));
95386
- }
95387
- }
95388
- return record3;
95462
+ function toResponsesParameters(schema, geminiTarget) {
95463
+ return strictifyJsonSchema(schema, {
95464
+ strict: true,
95465
+ gemini: geminiTarget,
95466
+ stripUriFormat: true,
95467
+ dropEmptyObjectProperties: true,
95468
+ normalizeBareObjects: true
95469
+ });
95389
95470
  }
95390
- function convertToolsToResponsesTools(tools) {
95471
+ function convertToolsToResponsesTools(tools, model = "") {
95472
+ const geminiTarget = isGeminiTarget(model);
95391
95473
  return tools.flatMap((tool) => {
95392
95474
  if (tool.input_schema && (!tool.type || tool.type === "function")) {
95393
95475
  if (!tool.name || tool.name === "ToolSearchTool")
95394
95476
  return [];
95395
95477
  const rawParameters = tool.input_schema ?? { type: "object", properties: {} };
95396
- const parameters = enforceStrictSchema(rawParameters);
95478
+ const parameters = toResponsesParameters(rawParameters, geminiTarget);
95397
95479
  return [
95398
95480
  {
95399
95481
  type: "function",
@@ -95408,7 +95490,7 @@ function convertToolsToResponsesTools(tools) {
95408
95490
  return [tool];
95409
95491
  }
95410
95492
  if (tool.name && tool.name !== "ToolSearchTool" && (!tool.type || tool.type === "function")) {
95411
- const parameters = enforceStrictSchema({ type: "object", properties: {} });
95493
+ const parameters = toResponsesParameters({ type: "object", properties: {} }, geminiTarget);
95412
95494
  return [
95413
95495
  {
95414
95496
  type: "function",
@@ -95475,10 +95557,10 @@ async function performCodexRequest(options) {
95475
95557
  body.tool_choice = toolChoice;
95476
95558
  }
95477
95559
  if (options.params.tools && options.params.tools.length > 0) {
95478
- const convertedTools = convertToolsToResponsesTools(options.params.tools);
95560
+ const convertedTools = convertToolsToResponsesTools(options.params.tools, options.request.resolvedModel);
95479
95561
  if (convertedTools.length > 0) {
95480
95562
  body.tools = convertedTools;
95481
- body.parallel_tool_calls = true;
95563
+ body.parallel_tool_calls = !isGeminiTarget(options.request.resolvedModel);
95482
95564
  body.tool_choice ??= "auto";
95483
95565
  }
95484
95566
  }
@@ -95848,6 +95930,7 @@ function convertCodexResponseToAnthropicMessage(data, model) {
95848
95930
  var init_shim = __esm(() => {
95849
95931
  init_sdk();
95850
95932
  init_schema();
95933
+ init_capabilities2();
95851
95934
  });
95852
95935
 
95853
95936
  // src/providers/shared/providerRecommendation.ts
@@ -95925,51 +96008,6 @@ var init_providerProfile = __esm(() => {
95925
96008
  ];
95926
96009
  });
95927
96010
 
95928
- // src/providers/openai/capabilities.ts
95929
- function supportsReasoningEffort(model) {
95930
- return /^(o\d|gpt-5|gpt-4\.5)/i.test(model);
95931
- }
95932
- function isGeminiLikeModel(model) {
95933
- const normalized = (model ?? "").trim().toLowerCase();
95934
- return normalized.startsWith("gemini-") || normalized.includes("/gemini-");
95935
- }
95936
- function isGeminiTarget(model) {
95937
- if (isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI")))
95938
- return true;
95939
- return isGeminiLikeModel(model);
95940
- }
95941
- function supportsParallelToolCalls(model) {
95942
- return !isGeminiTarget(model);
95943
- }
95944
- function getOpenAICompatMaxOutputTokens(model) {
95945
- const max = getOpenAIMaxOutputTokens(model);
95946
- if (max === undefined)
95947
- return null;
95948
- return { default: max, upperLimit: max };
95949
- }
95950
- function getOpenAICompatContextWindow(model) {
95951
- return getOpenAIContextWindow(model) ?? null;
95952
- }
95953
- function openAICompatSupports(feature, model) {
95954
- if (feature === "reasoning-effort")
95955
- return supportsReasoningEffort(model);
95956
- if (feature === "parallel-tool-calls")
95957
- return supportsParallelToolCalls(model);
95958
- return FEATURES_OPENAI_COMPAT.includes(feature);
95959
- }
95960
- var FEATURES_OPENAI_COMPAT;
95961
- var init_capabilities2 = __esm(() => {
95962
- init_openaiContextWindows();
95963
- init_envUtils();
95964
- init_state2();
95965
- FEATURES_OPENAI_COMPAT = Object.freeze([
95966
- "streaming",
95967
- "tool-use",
95968
- "image-input",
95969
- "system-message-top-level"
95970
- ]);
95971
- });
95972
-
95973
96011
  // src/providers/openai/shim.ts
95974
96012
  var exports_shim = {};
95975
96013
  __export(exports_shim, {
@@ -96197,49 +96235,6 @@ function convertMessages(messages, system) {
96197
96235
  }
96198
96236
  return result;
96199
96237
  }
96200
- function normalizeSchemaForOpenAI(schema, strict = true, topLevel = true, geminiTarget = false) {
96201
- let record3 = sanitizeSchemaForOpenAICompat(schema);
96202
- if (geminiTarget) {
96203
- record3 = splitTypeArrayToAnyOf(record3);
96204
- }
96205
- if (record3.type === "object" && record3.properties) {
96206
- const properties = record3.properties;
96207
- const existingRequired = Array.isArray(record3.required) ? record3.required : [];
96208
- const normalizedProps = {};
96209
- for (const [key, value] of Object.entries(properties)) {
96210
- normalizedProps[key] = normalizeSchemaForOpenAI(value, strict, false, geminiTarget);
96211
- }
96212
- record3.properties = normalizedProps;
96213
- if (strict) {
96214
- const allKeys = Object.keys(normalizedProps);
96215
- record3.required = Array.from(new Set([...existingRequired, ...allKeys]));
96216
- record3.additionalProperties = false;
96217
- if (topLevel) {
96218
- const style = geminiTarget ? "nullable" : "union";
96219
- for (const key of allKeys) {
96220
- if (!existingRequired.includes(key)) {
96221
- normalizedProps[key] = makeSchemaNullable(normalizedProps[key], style);
96222
- }
96223
- }
96224
- }
96225
- } else {
96226
- record3.required = existingRequired.filter((k) => (k in normalizedProps));
96227
- }
96228
- }
96229
- if ("items" in record3) {
96230
- if (Array.isArray(record3.items)) {
96231
- record3.items = record3.items.map((item) => normalizeSchemaForOpenAI(item, strict, false, geminiTarget));
96232
- } else {
96233
- record3.items = normalizeSchemaForOpenAI(record3.items, strict, false, geminiTarget);
96234
- }
96235
- }
96236
- for (const key of ["anyOf", "oneOf", "allOf"]) {
96237
- if (key in record3 && Array.isArray(record3[key])) {
96238
- record3[key] = record3[key].map((item) => normalizeSchemaForOpenAI(item, strict, false, geminiTarget));
96239
- }
96240
- }
96241
- return record3;
96242
- }
96243
96238
  function convertTools(tools, model = "") {
96244
96239
  const isGemini = isEnvTruthy(getQueryEnvVar("CLAUDE_CODE_USE_GEMINI"));
96245
96240
  const geminiTarget = isGeminiTarget(model);
@@ -96260,7 +96255,7 @@ function convertTools(tools, model = "") {
96260
96255
  function: {
96261
96256
  name: t.name,
96262
96257
  description: t.description ?? "",
96263
- parameters: normalizeSchemaForOpenAI(schema, !isGemini, true, geminiTarget)
96258
+ parameters: strictifyJsonSchema(schema, { strict: !isGemini, gemini: geminiTarget })
96264
96259
  }
96265
96260
  };
96266
96261
  });
@@ -282271,7 +282266,7 @@ function getAnthropicEnvMetadata() {
282271
282266
  function getBuildAgeMinutes() {
282272
282267
  if (false)
282273
282268
  ;
282274
- const buildTime = new Date("2026-06-03T12:46:47.435Z").getTime();
282269
+ const buildTime = new Date("2026-06-03T14:42:10.545Z").getTime();
282275
282270
  if (isNaN(buildTime))
282276
282271
  return;
282277
282272
  return Math.floor((Date.now() - buildTime) / 60000);
@@ -335452,4 +335447,4 @@ export {
335452
335447
  AbortError2 as AbortError
335453
335448
  };
335454
335449
 
335455
- //# debugId=0D97A1D470E3660864756E2164756E21
335450
+ //# debugId=FBE6B15D8EFBA32B64756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opencow-ai/opencow-agent-sdk",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "description": "Claude Code opened to any LLM — OpenAI, Gemini, DeepSeek, Ollama, and 200+ models",
5
5
  "type": "module",
6
6
  "main": "./dist/sdk.js",