flavor-code 1.4.0-beta.9 → 1.4.1

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.
@@ -214,9 +214,8 @@ var ProviderConfigSchema = z2.object({
214
214
  // parameter. Provider thinking deltas are forwarded whenever they arrive.
215
215
  thinkingBudget: z2.number().int().min(0).optional(),
216
216
  // Reasoning effort requested from the OpenAI Responses protocol (sent as
217
- // reasoning.effort). Omitted by default so strict compatible gateways never
218
- // see an unknown parameter and the endpoint uses its server-side default.
219
- thinkingEffort: z2.enum(["minimal", "low", "medium", "high", "xhigh"]).optional(),
217
+ // reasoning.effort). The adapter defaults an omitted value to high.
218
+ thinkingEffort: z2.enum(["minimal", "low", "medium", "high", "xhigh", "ultra"]).optional(),
220
219
  // Send the Claude Code client fingerprint (User-Agent/x-app) with Anthropic requests,
221
220
  // for gateways that restrict the Anthropic protocol to Claude clients.
222
221
  claudeClient: z2.boolean().optional(),
@@ -4271,6 +4270,8 @@ function normalizeProviderError(error) {
4271
4270
  code = "context_overflow";
4272
4271
  } else if (status === 404 || /model.*not.?found|not.?found.*model/.test(searchable)) {
4273
4272
  code = "model_not_found";
4273
+ } else if (status === 400 || status === 422 || /invalid schema|schema.*(?:invalid|not (?:a )?valid)/.test(searchable)) {
4274
+ code = "invalid_request";
4274
4275
  } else if (status !== void 0 && status >= 500 && status <= 599) {
4275
4276
  code = "network";
4276
4277
  } else if (status === void 0 && /econn|enet|socket|network|fetch failed|connection|timeout/.test(searchable)) {
@@ -6404,7 +6405,10 @@ function jsonSchemaFromZod(schema) {
6404
6405
  return z12.toJSONSchema(schema);
6405
6406
  }
6406
6407
  function strictJsonSchemaObject(schema) {
6407
- return ensureStrictSchema(schema);
6408
+ return normalizeOpenAIJsonSchemaObject(schema, true);
6409
+ }
6410
+ function openAIJsonSchemaObject(schema, strict) {
6411
+ return normalizeOpenAIJsonSchemaObject(schema, strict);
6408
6412
  }
6409
6413
  function extractJsonObject(text) {
6410
6414
  const trimmed = text.trim();
@@ -6542,41 +6546,194 @@ function jsonSchemaAllowsNull(schema) {
6542
6546
  function modelToolFromZod(name, description, schema) {
6543
6547
  return { name, description, inputSchema: strictJsonSchema(schema) };
6544
6548
  }
6545
- function ensureStrictSchema(schema) {
6549
+ var JSON_SCHEMA_TYPES = /* @__PURE__ */ new Set(["null", "boolean", "object", "array", "number", "string", "integer"]);
6550
+ var OPENAI_UNSUPPORTED_SCHEMA_KEYWORDS = [
6551
+ "$schema",
6552
+ "$id",
6553
+ "$anchor",
6554
+ "$dynamicAnchor",
6555
+ "$dynamicRef",
6556
+ "$comment",
6557
+ "default",
6558
+ "examples",
6559
+ "example",
6560
+ "deprecated",
6561
+ "readOnly",
6562
+ "writeOnly",
6563
+ "format",
6564
+ "propertyNames",
6565
+ "patternProperties",
6566
+ "unevaluatedProperties",
6567
+ "unevaluatedItems",
6568
+ "additionalItems",
6569
+ "contains",
6570
+ "minContains",
6571
+ "maxContains",
6572
+ "uniqueItems",
6573
+ "minProperties",
6574
+ "maxProperties",
6575
+ "contentEncoding",
6576
+ "contentMediaType",
6577
+ "not",
6578
+ "if",
6579
+ "then",
6580
+ "else",
6581
+ "dependentRequired",
6582
+ "dependentSchemas",
6583
+ "dependencies"
6584
+ ];
6585
+ function normalizeOpenAIJsonSchemaObject(schema, strict) {
6586
+ const normalized = normalizeOpenAIJsonSchemaNode(schema, strict);
6587
+ if (normalized.type === "object") return normalized;
6588
+ return strict ? { type: "object", properties: {}, required: [], additionalProperties: false } : { type: "object", properties: {}, additionalProperties: true };
6589
+ }
6590
+ function normalizeOpenAIJsonSchemaNode(rawSchema, strict) {
6591
+ const schema = mergeObjectAllOf(rawSchema);
6546
6592
  const output = { ...schema };
6547
- delete output.propertyNames;
6548
- delete output.patternProperties;
6549
- for (const keyword of ["anyOf", "oneOf", "allOf", "prefixItems"]) {
6550
- const branches = schema[keyword];
6551
- if (Array.isArray(branches)) {
6552
- output[keyword] = branches.map((branch) => typeof branch === "object" && branch !== null ? ensureStrictSchema(branch) : branch);
6553
- }
6554
- }
6555
- if (typeof schema.items === "object" && schema.items !== null) {
6556
- output.items = ensureStrictSchema(schema.items);
6557
- }
6558
- for (const keyword of ["$defs", "definitions"]) {
6559
- const definitions = schema[keyword];
6560
- if (typeof definitions === "object" && definitions !== null && !Array.isArray(definitions)) {
6561
- output[keyword] = Object.fromEntries(Object.entries(definitions).map(([key, definition]) => [
6562
- key,
6563
- typeof definition === "object" && definition !== null ? ensureStrictSchema(definition) : definition
6564
- ]));
6593
+ for (const keyword of OPENAI_UNSUPPORTED_SCHEMA_KEYWORDS) delete output[keyword];
6594
+ delete output.oneOf;
6595
+ delete output.allOf;
6596
+ delete output.prefixItems;
6597
+ delete output.nullable;
6598
+ delete output.definitions;
6599
+ if (typeof output.$ref === "string" && output.$ref.startsWith("#/definitions/")) {
6600
+ output.$ref = output.$ref.replace("#/definitions/", "#/$defs/");
6601
+ }
6602
+ const compositionBranches = [
6603
+ ...Array.isArray(schema.anyOf) ? schema.anyOf : [],
6604
+ ...Array.isArray(schema.oneOf) ? schema.oneOf : [],
6605
+ ...Array.isArray(schema.allOf) ? schema.allOf : []
6606
+ ];
6607
+ if (compositionBranches.length > 0) {
6608
+ output.anyOf = compositionBranches.map((branch) => normalizeOpenAISchemaValue(branch, strict));
6609
+ } else {
6610
+ delete output.anyOf;
6611
+ }
6612
+ const definitions = {
6613
+ ...isSchemaRecord(schema.definitions) ? schema.definitions : {},
6614
+ ...isSchemaRecord(schema.$defs) ? schema.$defs : {}
6615
+ };
6616
+ if (Object.keys(definitions).length > 0) {
6617
+ output.$defs = Object.fromEntries(Object.entries(definitions).map(([key, definition]) => [key, normalizeOpenAISchemaValue(definition, strict)]));
6618
+ }
6619
+ const prefixItems = Array.isArray(schema.prefixItems) ? schema.prefixItems : void 0;
6620
+ if (prefixItems !== void 0 && prefixItems.length > 0) {
6621
+ const tupleItems = prefixItems.map((item) => normalizeOpenAISchemaValue(item, strict));
6622
+ output.items = tupleItems.length === 1 ? tupleItems[0] : { anyOf: tupleItems };
6623
+ } else if (Array.isArray(schema.items)) {
6624
+ const tupleItems = schema.items.map((item) => normalizeOpenAISchemaValue(item, strict));
6625
+ output.items = tupleItems.length === 1 ? tupleItems[0] : { anyOf: tupleItems };
6626
+ } else if (isSchemaRecord(schema.items)) {
6627
+ output.items = normalizeOpenAIJsonSchemaNode(schema.items, strict);
6628
+ } else if (schema.items === true || schema.items === false) {
6629
+ output.items = universalJsonValueSchema(strict);
6630
+ }
6631
+ let type = schema.type;
6632
+ if (type === void 0 && isSchemaRecord(schema.properties)) type = "object";
6633
+ if (type === void 0 && output.items !== void 0) type = "array";
6634
+ if (type === void 0 && Array.isArray(schema.enum)) type = inferJsonTypes(schema.enum);
6635
+ if (type === void 0 && Object.hasOwn(schema, "const")) type = inferJsonTypes([schema.const]);
6636
+ if (typeof type === "string" && !JSON_SCHEMA_TYPES.has(type)) type = void 0;
6637
+ if (Array.isArray(type)) {
6638
+ const types = type.filter((candidate) => typeof candidate === "string" && JSON_SCHEMA_TYPES.has(candidate));
6639
+ type = types.length === 0 ? void 0 : types;
6640
+ }
6641
+ delete output.type;
6642
+ if (type !== void 0) output.type = type;
6643
+ if (schemaTypeIncludes(type, "array") && output.items === void 0) {
6644
+ output.items = universalJsonValueSchema(strict);
6645
+ }
6646
+ if (schemaTypeIncludes(type, "object")) {
6647
+ const sourceProperties = isSchemaRecord(schema.properties) ? schema.properties : {};
6648
+ const sourceRequired = new Set(Array.isArray(schema.required) ? schema.required.filter((key) => typeof key === "string") : []);
6649
+ const properties = {};
6650
+ for (const [key, value] of Object.entries(sourceProperties)) {
6651
+ const child = normalizeOpenAISchemaValue(value, strict);
6652
+ if (!strict || sourceRequired.has(key) || jsonSchemaAllowsNull(child)) properties[key] = child;
6653
+ else properties[key] = { anyOf: [child, { type: "null" }] };
6654
+ if (strict) sourceRequired.add(key);
6655
+ }
6656
+ output.properties = properties;
6657
+ const required2 = strict ? Object.keys(properties) : [...sourceRequired].filter((key) => Object.hasOwn(properties, key));
6658
+ if (strict || required2.length > 0 || Array.isArray(schema.required)) output.required = required2;
6659
+ else delete output.required;
6660
+ if (strict) {
6661
+ output.additionalProperties = false;
6662
+ } else if (schema.additionalProperties === true || schema.additionalProperties === false) {
6663
+ output.additionalProperties = schema.additionalProperties;
6664
+ } else if (isSchemaRecord(schema.additionalProperties)) {
6665
+ output.additionalProperties = Object.keys(schema.additionalProperties).length === 0 ? true : normalizeOpenAIJsonSchemaNode(schema.additionalProperties, false);
6666
+ } else {
6667
+ delete output.additionalProperties;
6565
6668
  }
6566
6669
  }
6567
- if (schema.type !== "object") {
6568
- return output;
6670
+ if (schema.nullable === true && !jsonSchemaAllowsNull(output)) {
6671
+ const description = typeof output.description === "string" ? output.description : void 0;
6672
+ const branch = { ...output };
6673
+ delete branch.description;
6674
+ return {
6675
+ ...description === void 0 ? {} : { description },
6676
+ anyOf: [branch, { type: "null" }]
6677
+ };
6569
6678
  }
6570
- const sourceProperties = typeof schema.properties === "object" && schema.properties !== null && !Array.isArray(schema.properties) ? schema.properties : {};
6571
- const requiredSet = new Set(Array.isArray(schema.required) ? schema.required : []);
6572
- const properties = {};
6573
- for (const [key, value] of Object.entries(sourceProperties)) {
6574
- const child = typeof value === "object" && value !== null ? ensureStrictSchema(value) : value;
6575
- if (requiredSet.has(key) || jsonSchemaAllowsNull(child)) properties[key] = child;
6576
- else properties[key] = { anyOf: [child, { type: "null" }] };
6577
- requiredSet.add(key);
6679
+ if (isTypedOrComposedSchema(output)) return output;
6680
+ return universalJsonValueSchema(strict);
6681
+ }
6682
+ function mergeObjectAllOf(schema) {
6683
+ const branches = Array.isArray(schema.allOf) ? schema.allOf.filter(isSchemaRecord) : [];
6684
+ if (branches.length === 0 || !branches.every(isObjectSchema)) return schema;
6685
+ const base = { ...schema };
6686
+ delete base.allOf;
6687
+ const properties = isSchemaRecord(base.properties) ? { ...base.properties } : {};
6688
+ const required2 = new Set(Array.isArray(base.required) ? base.required.filter((key) => typeof key === "string") : []);
6689
+ for (const branch of branches) {
6690
+ if (isSchemaRecord(branch.properties)) {
6691
+ for (const [key, value] of Object.entries(branch.properties)) {
6692
+ const existing = properties[key];
6693
+ properties[key] = existing === void 0 ? value : { anyOf: [existing, value] };
6694
+ }
6695
+ }
6696
+ if (Array.isArray(branch.required)) {
6697
+ for (const key of branch.required) if (typeof key === "string") required2.add(key);
6698
+ }
6578
6699
  }
6579
- return { ...output, additionalProperties: false, required: [...requiredSet], properties };
6700
+ return { ...base, type: "object", properties, required: [...required2] };
6701
+ }
6702
+ function normalizeOpenAISchemaValue(value, strict) {
6703
+ if (isSchemaRecord(value)) return normalizeOpenAIJsonSchemaNode(value, strict);
6704
+ return universalJsonValueSchema(strict);
6705
+ }
6706
+ function universalJsonValueSchema(strict) {
6707
+ const scalar = [{ type: "string" }, { type: "number" }, { type: "boolean" }, { type: "null" }];
6708
+ return {
6709
+ anyOf: [
6710
+ ...scalar,
6711
+ strict ? { type: "object", properties: {}, required: [], additionalProperties: false } : { type: "object", properties: {}, additionalProperties: true },
6712
+ { type: "array", items: { anyOf: scalar } }
6713
+ ]
6714
+ };
6715
+ }
6716
+ function inferJsonTypes(values) {
6717
+ const types = [...new Set(values.map((value) => {
6718
+ if (value === null) return "null";
6719
+ if (Array.isArray(value)) return "array";
6720
+ if (typeof value === "number") return Number.isInteger(value) ? "integer" : "number";
6721
+ if (typeof value === "object") return "object";
6722
+ return typeof value;
6723
+ }).filter((type) => ["null", "array", "object", "integer", "number", "string", "boolean"].includes(type)))];
6724
+ return types.length === 0 ? void 0 : types.length === 1 ? types[0] : types;
6725
+ }
6726
+ function isSchemaRecord(value) {
6727
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6728
+ }
6729
+ function isObjectSchema(schema) {
6730
+ return schema.type === "object" || isSchemaRecord(schema.properties);
6731
+ }
6732
+ function isTypedOrComposedSchema(schema) {
6733
+ return typeof schema.type === "string" || Array.isArray(schema.type) || typeof schema.$ref === "string" || Array.isArray(schema.anyOf);
6734
+ }
6735
+ function schemaTypeIncludes(type, expected) {
6736
+ return type === expected || Array.isArray(type) && type.includes(expected);
6580
6737
  }
6581
6738
  function repairMessages(messages, tool, original, candidate, error) {
6582
6739
  const details = [
@@ -7980,9 +8137,11 @@ var ToolRuntime = class {
7980
8137
  if (pre.decision === "deny") {
7981
8138
  return this.#fail(toolCallId, tool.name, input, context.agent, "hook_denied", pre.reason ?? "Tool use denied by hook");
7982
8139
  }
8140
+ const approvalInput = tool.permissionInput?.(input) ?? input;
7983
8141
  const request = {
7984
8142
  agent: context.agent,
7985
8143
  tool: tool.name,
8144
+ input: approvalInput,
7986
8145
  ...tool.permissions?.(input) ?? { paths: tool.paths(input) },
7987
8146
  ...tool.readOnly === true ? { readOnly: true } : {}
7988
8147
  };
@@ -8015,7 +8174,7 @@ var ToolRuntime = class {
8015
8174
  payload: {
8016
8175
  toolCallId,
8017
8176
  tool: tool.name,
8018
- input: tool.permissionInput?.(input) ?? input,
8177
+ input: approvalInput,
8019
8178
  agent: context.agent,
8020
8179
  reason,
8021
8180
  toolCategory: getToolCategory(tool.name),
@@ -11461,10 +11620,11 @@ async function createExampleFlavorConfig(cwd) {
11461
11620
  pkce: {
11462
11621
  type: "oauth-callback",
11463
11622
  apiType: "anthropic",
11464
- authorizationUrl: "http://192.168.1.100:8091/authorize",
11465
- tokenUrl: "http://192.168.1.100:8091/token",
11623
+ authorizationUrl: "http://127.0.0.1:8091/authorize",
11624
+ tokenUrl: "http://127.0.0.1:8091/token",
11466
11625
  clientId: "flavor-code-cli",
11467
- scope: "models:read models:use"
11626
+ scope: "models:read models:use",
11627
+ thinkingEffort: "high"
11468
11628
  }
11469
11629
  },
11470
11630
  agents: {
@@ -12034,7 +12194,7 @@ ${evidence.summary}`;
12034
12194
  }
12035
12195
  };
12036
12196
  function isResumableWorkerError(error) {
12037
- return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
12197
+ return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "invalid_request" && error.code !== "cancelled" && error.code !== "memory_pressure";
12038
12198
  }
12039
12199
  function countTrailingFailureSignature(cycles, signature) {
12040
12200
  let count = 0;
@@ -12748,10 +12908,10 @@ function resumeStartRound(state) {
12748
12908
  return state.verifyRounds >= state.workerRounds ? state.workerRounds + 1 : Math.max(state.workerRounds, 1);
12749
12909
  }
12750
12910
  function isResumableWorkerError2(error) {
12751
- return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
12911
+ return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "invalid_request" && error.code !== "cancelled" && error.code !== "memory_pressure";
12752
12912
  }
12753
12913
  function isResumableStageError(error) {
12754
- return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "cancelled" && error.code !== "memory_pressure";
12914
+ return error.code !== "authentication" && error.code !== "model_not_found" && error.code !== "invalid_request" && error.code !== "cancelled" && error.code !== "memory_pressure";
12755
12915
  }
12756
12916
  function stageRetryDelay(options, attempt) {
12757
12917
  const delayMs = options.stageRetryDelayMs?.(attempt) ?? Math.min(6e4, 1e3 * 2 ** Math.min(attempt - 1, 6));
@@ -14579,6 +14739,7 @@ function resolveCacheProfile(input) {
14579
14739
  // src/models/openai.ts
14580
14740
  import OpenAI from "openai";
14581
14741
  import { readFile as readFile16 } from "fs/promises";
14742
+ var DEFAULT_THINKING_EFFORT = "high";
14582
14743
  async function toInput(message2) {
14583
14744
  if (message2.role === "tool") {
14584
14745
  if (!message2.toolCallId) throw new Error("Tool messages require toolCallId");
@@ -14654,7 +14815,7 @@ var OpenAIModelAdapter = class {
14654
14815
  ...options.baseURL === void 0 ? {} : { baseURL: options.baseURL }
14655
14816
  });
14656
14817
  this.debugUsage = options.debugUsage ?? isEnvTruthy(process.env.FLAVOR_DEBUG_USAGE);
14657
- this.thinkingEffort = options.thinkingEffort;
14818
+ this.thinkingEffort = options.thinkingEffort ?? DEFAULT_THINKING_EFFORT;
14658
14819
  }
14659
14820
  #logUsage(model, breakdown) {
14660
14821
  if (breakdown === void 0) return;
@@ -14677,12 +14838,12 @@ var OpenAIModelAdapter = class {
14677
14838
  const body = {
14678
14839
  model: request.model,
14679
14840
  input: (await Promise.all(request.messages.map(toInput))).flat(),
14680
- ...this.thinkingEffort === void 0 ? {} : { reasoning: { effort: this.thinkingEffort } },
14841
+ reasoning: { effort: this.thinkingEffort },
14681
14842
  tools: [...request.tools].sort((a, b) => a.name.localeCompare(b.name)).map((tool) => ({
14682
14843
  type: "function",
14683
14844
  name: tool.name,
14684
14845
  description: tool.description,
14685
- parameters: tool.inputSchema,
14846
+ parameters: openAIJsonSchemaObject(tool.inputSchema, tool.strict ?? true),
14686
14847
  strict: tool.strict ?? true
14687
14848
  }))
14688
14849
  };
@@ -28805,7 +28966,7 @@ function terminalProgressState(status) {
28805
28966
  return "failed";
28806
28967
  }
28807
28968
  function isResumableLongTaskError(code) {
28808
- return code !== "authentication" && code !== "model_not_found" && code !== "cancelled" && code !== "memory_pressure";
28969
+ return code !== "authentication" && code !== "model_not_found" && code !== "invalid_request" && code !== "cancelled" && code !== "memory_pressure";
28809
28970
  }
28810
28971
  async function workspaceFingerprint(workspace) {
28811
28972
  const hash = createHash21("sha256");