mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-07-26 09:52:11 +03:00
* fix(codex): strip regex lookaround from tool schema patterns (port from 9router#1556) Codex/OpenAI's Responses API rejects JSON Schema pattern fields using regex lookaround (e.g. ^(?=.*@).+$) with a 400 'regex lookaround is not supported' error. The existing numeric-field sanitizer (coerceSchemaNumericFields) was only wired into the translated-request path (openai-to-claude.ts), not the native codex/openai passthrough path (normalizeCodexTools in open-sse/executors/codex/tools.ts), so lookahead/lookbehind patterns reached upstream unmodified and broke tool calls for clients that emit them (e.g. IDE agent harnesses validating an email field). Reported-by: evin (@evinjohnn) (https://github.com/decolua/9router/issues/1556) * chore(changelog): move #1556 entry to changelog.d fragment Consistency with the repo's canonical changelog.d/fixes/ workflow (avoids merge-storm re-conflicts from editing CHANGELOG.md directly). * refactor(codex): table-drive the regex-strip recursion to keep the complexity ratchet at baseline The #1556 lookaround strip walked every sub-schema field with its own copy-pasted if-block (properties / patternProperties / definitions / $defs, then prefixItems / anyOf / oneOf / allOf), pushing stripUnsupportedRegexPatterns past the cyclomatic threshold and check:complexity to 2057 > baseline 2056. Collapse the eight near-identical blocks into two loops over the field-name constants, with the object-map recursion factored into a helper. Same fields, same traversal order, same behavior — complexity is back at baseline 2056 and the #1556 regression tests still pass.
75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { test } from "node:test";
|
|
import assert from "node:assert/strict";
|
|
|
|
import { normalizeCodexTools } from "../../open-sse/executors/codex/tools.ts";
|
|
|
|
// Port of 9router#1556: OpenAI/Codex Responses API rejects JSON Schema `pattern`
|
|
// fields containing regex lookaround (lookahead/lookbehind) with:
|
|
// "Invalid JSON schema: regex lookaround is not supported. Found at $.properties.email.pattern."
|
|
// Clients (e.g. IDE agent harnesses) commonly emit lookahead patterns such as
|
|
// `^(?=.*@).+$` for "must contain an @". These must be stripped before the
|
|
// tool schema reaches the Codex/OpenAI Responses API.
|
|
test("normalizeCodexTools strips regex lookaround from function tool parameter patterns", () => {
|
|
const body: Record<string, unknown> = {
|
|
tools: [
|
|
{
|
|
type: "function",
|
|
function: {
|
|
name: "send_email",
|
|
description: "Send an email",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
email: {
|
|
type: "string",
|
|
pattern: "^(?=.*@).+$",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
normalizeCodexTools(body);
|
|
|
|
const tools = body.tools as Array<Record<string, unknown>>;
|
|
const parameters = tools[0].parameters as Record<string, unknown>;
|
|
const properties = parameters.properties as Record<string, unknown>;
|
|
const emailSchema = properties.email as Record<string, unknown>;
|
|
|
|
assert.equal(
|
|
emailSchema.pattern,
|
|
undefined,
|
|
"lookaround pattern must be stripped, not forwarded upstream"
|
|
);
|
|
});
|
|
|
|
test("normalizeCodexTools preserves plain (non-lookaround) regex patterns", () => {
|
|
const body: Record<string, unknown> = {
|
|
tools: [
|
|
{
|
|
type: "function",
|
|
function: {
|
|
name: "send_email",
|
|
parameters: {
|
|
type: "object",
|
|
properties: {
|
|
zip: { type: "string", pattern: "^[0-9]{5}$" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
normalizeCodexTools(body);
|
|
|
|
const tools = body.tools as Array<Record<string, unknown>>;
|
|
const parameters = tools[0].parameters as Record<string, unknown>;
|
|
const properties = parameters.properties as Record<string, unknown>;
|
|
const zipSchema = properties.zip as Record<string, unknown>;
|
|
|
|
assert.equal(zipSchema.pattern, "^[0-9]{5}$");
|
|
});
|