Repository navigation
Release v3.6.9 - #1404
Release v3.6.9#1404
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1439d62b77
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| relayOptions: null as any, | ||
| allCombos: null, | ||
| relayOptions: null, |
There was a problem hiding this comment.
Remove duplicate
relayOptions key in test call objects
This object literal defines relayOptions twice, which triggers TS1117: An object literal cannot have multiple properties with the same name during TypeScript checks and can fail CI gates that lint/type-check tests. Because this duplicate pattern was added throughout the file, the release commit introduces widespread compile-time errors in the combo routing test suite until the duplicate key is removed (keeping only the typed form).
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Code Review
This pull request introduces TypeScript type annotations and casts to unit tests in chatcore-translation-paths.test.ts and combo-routing-engine.test.ts. A recurring issue was identified in combo-routing-engine.test.ts where the relayOptions property was added to object literals that already contained the key, resulting in duplicate property definitions across numerous test cases.
| relayOptions: null as any, | ||
| allCombos: null, | ||
| relayOptions: null, |
There was a problem hiding this comment.
The relayOptions key is duplicated in this object literal. The second occurrence at line 234 will overwrite the first one, making the as any cast at line 232 ineffective. This pattern appears to be repeated in multiple locations throughout this file (e.g., lines 308, 343, 379, 413, 458, 482, 511, 564, 603, 634, 694, 762, 785, 817, 843, 881, 917, 948, 981, 1028, 1072, 1114, 1157, 1187, 1222, 1256, 1300, 1323, 1358, 1390, 1418, 1444, 1466, 1512, 1547, 1582, 1631, 1663, 1693, 1717, 1744, 1782, 1812, 1848, 1886, 1927, 1961).
relayOptions: null as any,
allCombos: null,
CI Coverage Report
Coverage artifact was not available for this run. |
* fix(cloud-code): scope thinking stripping to executor boundaries (#1401) * fix(cloud-code): scope thinking stripping to executors * fix(cloud-code): guard antigravity normalized body * Update Claude Code obfuscation to version 2.1.114 - Update Claude Code version from 2.1.87 to 2.1.114 - Update X-Stainless-Package-Version from 0.80.0 to 0.81.0 - Add new beta flags: redact-thinking-2026-02-12, advisor-tool-2026-03-01, advanced-tool-use-2025-11-20 - Add missing headers: anthropic-version, anthropic-dangerous-direct-browser-access, x-app, X-Stainless-Timeout - Add all X-Stainless-* headers (Arch, Lang, OS, Runtime, Runtime-Version, Retry-Count) - Fix accept-encoding header: identity -> gzip, deflate, br, zstd - Add connection: keep-alive header - Update tool name mapping: add lsp, apply_patch, websearch These changes ensure that requests from OpenCode through Omniroute are indistinguishable from genuine Claude Code 2.1.114 requests, allowing proper authentication with Anthropic's API without triggering extra credits errors. * fix: resolve CodeQL password hash alert and TruffleHog CI failure --------- Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: Nikolay Popov <ekklesio.dev@gmail.com> Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0988a3ee00
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!tb.thinking) { | ||
| tb.thinking = { type: "adaptive" }; | ||
| } |
There was a problem hiding this comment.
Enforce Claude thinking constraints after auto-injecting thinking
This block now injects thinking: { type: "adaptive" } for every claude request that omits thinking, but it never applies the existing Claude Code constraints (enforceThinkingTemperature / disableThinkingIfToolChoiceForced). In requests that force a tool (tool_choice.type === "tool" or "any") or send a non-1 temperature, this can produce avoidable upstream 400s because the request is made invalid by the injected thinking field.
Useful? React with 👍 / 👎.
|
|
||
| const ccHeaders: Record<string, string> = { | ||
| "anthropic-version": "2023-06-01", | ||
| "anthropic-beta": "claude-code-20250219,oauth-2025-04-20,interleaved-thinking-2025-05-14,redact-thinking-2026-02-12,context-management-2025-06-27,prompt-caching-scope-2026-01-05,advisor-tool-2026-03-01,advanced-tool-use-2025-11-20,effort-2025-11-24", |
There was a problem hiding this comment.
Preserve context-1m beta when patching Claude headers
The code appends the context-1m-2025-08-07 beta earlier in execute() when extended context is requested, but this hardcoded anthropic-beta assignment overwrites that header value. As a result, [1m]/context-1m requests for claude lose the required beta flag and can fail or silently miss the 1M-context path.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 224abbd8fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const isClaudeCodeClient = | ||
| clientHeaders?.["x-app"] === "cli" || |
There was a problem hiding this comment.
Destructure clientHeaders before using it in execute
execute() now reads clientHeaders when computing isClaudeCodeClient, but clientHeaders is not destructured from ExecuteInput. In JavaScript this throws ReferenceError: clientHeaders is not defined before any upstream fetch runs, so requests through BaseExecutor.execute fail for all providers (not just Claude) as soon as this branch is evaluated.
Useful? React with 👍 / 👎.
#1406) Integrated into release/v3.6.9
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0370145160
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const compressionResult = compressContext(body, { | ||
| provider, | ||
| model: effectiveModel, | ||
| maxTokens: threshold, | ||
| reserveTokens: 0, |
There was a problem hiding this comment.
Restore post-translation compression for non-message payloads
This compression path now always calls compressContext(body, ...), but compressContext immediately returns without changes unless body.messages exists (contextManager.ts early-exit). For requests that arrive as input/contents (notably /v1/responses and other non-OpenAI source shapes), estimatedTokens can exceed the threshold yet no compression is applied, because the previous post-translation compression block was removed in this commit. That means large non-message requests can now bypass the proactive safeguard and hit upstream context-overflow failures.
Useful? React with 👍 / 👎.
| }); | ||
|
|
||
| if (compressionResult.compressed) { | ||
| body = compressionResult.body; |
There was a problem hiding this comment.
Avoid mutating request body after semantic cache read keying
When proactive compression triggers, this reassignment mutates body after the semantic cache lookup has already keyed on the original payload (earlier generateSignature call), while cache writes later key on the mutated body. For compressed requests, read and write signatures no longer match, so repeated identical prompts will miss the semantic cache even though a response was stored.
Useful? React with 👍 / 👎.
Integrated into release/v3.6.9
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e40753d68d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (isClaudeCodeCompatible(this.provider) || this.provider === "claude") { | ||
| bodyString = await signRequestBody(bodyString); |
There was a problem hiding this comment.
Gate CCH body signing behind Claude-Code patching
This change now signs every native Claude payload via if (isClaudeCodeCompatible(this.provider) || this.provider === "claude"), but signRequestBody() blindly rewrites the first cch=xxxxx; substring anywhere in the serialized JSON body. For non-Claude-Code requests, that means user/system/tool text containing a token like cch=00000; is silently mutated before upstream fetch, altering prompt content and cache keys unexpectedly. Signing should be limited to requests where the Claude-Code billing header placeholder was intentionally injected (or otherwise explicitly detected).
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eb0b1a8a9e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // regardless of combo strategy or cache_control settings. | ||
| translatedBody = { ...body }; | ||
| translatedBody._disableToolPrefix = true; | ||
| normalizeClaudeUpstreamMessages(translatedBody); |
There was a problem hiding this comment.
Preserve native Claude tool_result blocks in passthrough
Calling normalizeClaudeUpstreamMessages in the Claude passthrough branch rewrites native Messages payloads that should be forwarded as-is. In particular, tool_result content is converted into plain text (and unknown block types are dropped), which removes the structured tool_use_id linkage Anthropic expects for tool-turn continuation; this can cause repeated tool requests or incorrect follow-up behavior for Claude/Claude Code passthrough traffic.
Useful? React with 👍 / 👎.
| if (firstSystemCacheControl) { | ||
| billingBlock.cache_control = firstSystemCacheControl; | ||
| } | ||
| sysBlocks.unshift(billingBlock); |
There was a problem hiding this comment.
Stop mutating Claude request bodies across retries
This unshift mutates the request object in place, and BaseExecutor.execute can revisit the same path on 429 intra-retries. For claude, transformRequest commonly returns the original body object, so each retry prepends another billing block instead of reusing a stable payload. That makes retries non-idempotent and can leave multiple cch=00000; placeholders while signRequestBody only replaces the first, producing inconsistent retry requests.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cb95daf2ab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const parsed = parseModel(t.modelStr); | ||
| return getTokenLimit(parsed.provider, parsed.model); |
There was a problem hiding this comment.
Skip provider-less targets when computing combo token limits
This new combo compression branch calls getTokenLimit(parsed.provider, parsed.model) for every resolved target, but parseModel() returns provider: null for alias-style targets (for example plain model IDs or nested combo refs). getTokenLimit assumes a string provider and dereferences provider.toUpperCase(), so one provider-less target throws and the broad catch skips combo limit derivation entirely. In that case proactive compression falls back to a generic limit and can miss needed compression for small-context targets, leading to avoidable upstream context-overflow failures.
Useful? React with 👍 / 👎.
| if (isCombo && comboName) { | ||
| log?.info?.("CONTEXT", `Attempting to resolve combo limits for comboName=${comboName}`); | ||
| try { | ||
| const { getComboByName } = await import("../../src/lib/localDb"); |
There was a problem hiding this comment.
Replace localDb barrel import in combo hot path
This import violates the documented project rule in AGENTS.md (“No barrel imports from localDb.ts”) and does so inside request-time logic. Pulling getComboByName from the localDb compatibility barrel couples chatCore to all DB re-exports and adds avoidable module load overhead on combo requests that hit proactive compression. Importing directly from the owning DB module keeps the hot path smaller and avoids the prohibited dependency pattern.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 33119e7690
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return `name:${rawName.trim().toLowerCase()}`; | ||
| } | ||
|
|
||
| return "local"; |
There was a problem hiding this comment.
Keep unauthenticated requests out of shared memory owner
Falling back to "local" here makes memoryOwnerId truthy even when no API key is present, so the later memory/skills paths now run for anonymous traffic. In deployments with REQUIRE_API_KEY=false, different clients will read/write the same memory bucket and can influence each other’s injected memories/skills, which is a cross-user data isolation regression compared with the previous apiKeyInfo?.id gating.
Useful? React with 👍 / 👎.
| -- 027_skill_mode_and_metadata.sql | ||
| -- Adds per-skill mode metadata and indexing for provider/filter UX. | ||
|
|
||
| ALTER TABLE skills ADD COLUMN mode TEXT NOT NULL DEFAULT 'auto'; |
There was a problem hiding this comment.
Backfill skill mode from enabled state in migration 027
This migration assigns mode='auto' to every existing skill row, including previously enabled skills that were always injected before. After upgrade, those legacy skills are treated as auto-scored candidates, and injectSkills only keeps autos above the score threshold, so many previously working skills silently stop being injected until users manually re-toggle each skill mode.
Useful? React with 👍 / 👎.
| import { mergeOpenCodeConfig } from "@/shared/services/opencodeConfig"; | ||
| import { guideSettingsSaveSchema } from "@/shared/validation/schemas"; | ||
| import { isValidationFailure, validateBody } from "@/shared/validation/helpers"; | ||
| import { getApiKeyById } from "@/lib/localDb"; |
There was a problem hiding this comment.
Import API key lookup from db module instead of localDb barrel
This new barrel import violates the project rule in /workspace/OmniRoute/AGENTS.md (“No barrel imports from localDb.ts — import from the specific db/ module instead”). Using the compatibility barrel in a request path increases coupling and startup/load overhead by pulling unrelated DB exports into this route; import getApiKeyById from its owning DB module directly.
Useful? React with 👍 / 👎.
…arity feat: align CC Compatible requests with Claude CLI parity
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 744358525c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export const CLAUDE_CODE_COMPATIBLE_DEFAULT_CHAT_PATH = "/v1/messages?beta=true"; | ||
| export const CLAUDE_CODE_COMPATIBLE_DEFAULT_MODELS_PATH = "/models"; | ||
| export const CLAUDE_CODE_COMPATIBLE_DEFAULT_MAX_TOKENS = 8092; | ||
| export const CLAUDE_CODE_COMPATIBLE_DEFAULT_MAX_TOKENS = 64000; |
There was a problem hiding this comment.
Cap Claude Code default max_tokens to model limits
CLAUDE_CODE_COMPATIBLE_DEFAULT_MAX_TOKENS was raised to 64000, and resolveClaudeCodeCompatibleMaxTokens() falls back to this value whenever callers omit max_tokens (a common case). Several Claude models in this repo have lower output caps (for example claude-opus-4-5 is 32768 in src/shared/constants/modelSpecs.ts), so these requests can now be sent with an invalid token budget and fail upstream with 4xx validation errors before generation starts. Please clamp the fallback to the selected model’s max output limit (or keep a conservative default).
Useful? React with 👍 / 👎.
Prevent Gemini request translation from injecting default thoughtSignature values that the upstream API strictly validates and rejects. Only preserve real signatures resolved from prior upstream responses, and strip additionalProperties from Gemini function schemas to avoid 400 "Unknown name" errors. Also remove fallback-injected session_id and conversation_id fields before sending Codex requests, and restore compatibility with the legacy OUTBOUND_SSRF_GUARD_ENABLED flag when determining whether private provider URLs are allowed. Updates the Gemini translator and regression tests for issue #1410 and related 400 error cases.
…and testing - Update Codex token refresh detection logic - Mark provider connections invalid on unrecoverable refresh error - Fix Claude usage translation under-reporting cached tokens - Update test expectations - Update CHANGELOG.md for v3.6.9
Refresh checks now re-read the latest stored provider connection before attempting rotation so they do not use stale refresh tokens captured by an earlier sweep. Token updates also persist both expiresAt and tokenExpiresAt across the health check, usage-limit refresh path, and SSE refresh flow. This keeps known token expiry metadata in sync and avoids interval-based refreshes for connections whose tokens are still valid well into the future.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6947e71ba8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const system = buildClaudeCodeCompatibleSystemBlocks({ | ||
| messages: normalized.messages as MessageLike[], | ||
| systemBlocks: preparedClaudeBody?.system as Record<string, unknown>[] | undefined, | ||
| cwd, | ||
| now, | ||
| preserveCacheControl, | ||
| billingHeader, | ||
| injectDefaultSkeleton: !preparedClaudeBody, |
There was a problem hiding this comment.
Restore CCH placeholder in CC-compatible request system blocks
This request builder no longer injects the Claude Code billing header (x-anthropic-billing-header: ... cch=00000;) into the outgoing body, but BaseExecutor.execute() still calls signRequestBody() for anthropic-compatible-cc-* providers. Without the placeholder, signing is a no-op and relays that enforce Claude Code attestation will reject otherwise valid requests with auth/validation errors.
Useful? React with 👍 / 👎.
| "Content-Type": "application/json", | ||
| Accept: stream ? "text/event-stream" : "application/json", | ||
| "x-api-key": apiKey, | ||
| Accept: "application/json", |
There was a problem hiding this comment.
Respect stream flag when building CC-compatible Accept header
The header builder now hardcodes Accept: "application/json" even when stream=true, so streaming requests to CC-compatible relays can lose SSE negotiation and come back as buffered JSON (or be rejected), which breaks token streaming behavior for clients expecting event-stream responses.
Useful? React with 👍 / 👎.
Fix import aliases and strict TS typings for tests and ACP agents.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 40b7974398
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| getAccessToken, | ||
| updateProviderCredentials, | ||
| } from "@omniroute/open-sse/services/tokenRefresh"; |
There was a problem hiding this comment.
Import refresh persistence helper from the correct module
This route now imports updateProviderCredentials from @omniroute/open-sse/services/tokenRefresh, but that module does not export this symbol (it exports refresh helpers like getAccessToken only). In Next.js this causes module loading to fail for this endpoint with an export-resolution error, so manual provider refresh requests can fail before handler logic runs. Please import the persistence helper from the local wrapper/DB path that actually exports it.
Useful? React with 👍 / 👎.
| const spec = getModelSpec(normalizedModel); | ||
| if (typeof spec?.supportsThinking === "boolean") { | ||
| return !spec.supportsThinking; | ||
| } | ||
| return CLOUD_CODE_REASONING_UNSUPPORTED_PATTERNS.some((pattern) => pattern.test(normalizedModel)); |
There was a problem hiding this comment.
Keep provider-aware thinking stripping for unknown models
shouldStripCloudCodeThinking now decides only from getModelSpec(normalizedModel) plus generic model-name patterns, and no longer uses provider-aware capability resolution. For Antigravity, this means a newly added Gemini model that is not yet in modelSpecs will return false here, so reasoning/thinking fields are forwarded instead of stripped in AntigravityExecutor.transformRequest, reintroducing request-shape 4xxs for models whose upstream does not accept those fields.
Useful? React with 👍 / 👎.
Integrated into release/v3.6.9
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f0094f2ff5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| baseUrl: baseUrlWithV1, | ||
| apiKey: keyToUse, | ||
| apiKey: !cloudEnabled ? "sk_omniroute" : null, | ||
| keyId: selectedKeyId, |
There was a problem hiding this comment.
Send non-null API key payloads for cloud CLI config saves
When cloudEnabled is true this request now sends apiKey: null, but the receiving routes validate with Zod string schemas before keyId resolution (for example guideSettingsSaveSchema/cliModelConfigSchema), so the request is rejected with 400 before resolveApiKey can fetch the real key. In cloud deployments this breaks saving CLI tool configs even when a valid key is selected.
Useful? React with 👍 / 👎.
| if (savedKey && apiKeys?.length > 0) { | ||
| const prefix = savedKey.slice(0, 8); | ||
| const suffix = savedKey.slice(-4); | ||
| const matchedKey = apiKeys.find( | ||
| (k) => k.key && k.key.startsWith(prefix) && k.key.endsWith(suffix) |
There was a problem hiding this comment.
Restore saved API key selection by id
The component now persists the selected key as key.id, but restore logic still treats the stored value like a masked key string and only does prefix/suffix matching against k.key. After a reload, previously saved key ids will not match and the selection falls back to the default key, which can silently reconfigure tools with the wrong API key.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 420e7a2d5d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ apiKey: keyToUse, sudoPassword: password }), | ||
| body: JSON.stringify({ | ||
| apiKey: !cloudEnabled ? "sk_omniroute" : null, |
There was a problem hiding this comment.
Send a real apiKey value when starting Antigravity MITM
When cloudEnabled is true this request now posts apiKey: null, but /api/cli-tools/antigravity-mitm validates with cliMitmStartSchema where apiKey is a required non-empty string before keyId resolution runs. In cloud setups with valid saved keys, starting MITM will fail with a 400 validation error instead of resolving the selected key ID, so users cannot enable the proxy flow.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 437881b21d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| body: JSON.stringify({ | ||
| baseUrl: normalizedBaseUrl, | ||
| apiKey: selectedApiKey || "sk_omniroute", | ||
| apiKey: !cloudEnabled ? "sk_omniroute" : null, |
There was a problem hiding this comment.
Avoid posting null apiKey from cloud Cline config
In cloud mode this payload sends apiKey: null, but /api/cli-tools/cline-settings validates with cliModelConfigSchema where apiKey is z.string().optional(), so null is rejected and the request fails with 400 before keyId resolution can run. That means applying config fails even with a valid selected key id (the same request shape is also used by other CLI cards).
Useful? React with 👍 / 👎.
| /* fall through */ | ||
| } | ||
| } | ||
| return apiKey || "sk_omniroute"; |
There was a problem hiding this comment.
Fail fast when provided keyId cannot be resolved
If apiKeyId is present but lookup fails (for example, a key was deleted after the page loaded or there is a transient DB read failure), this helper silently falls back to "sk_omniroute" and callers proceed as if configuration succeeded. For cloud CLI tool setup this writes a placeholder credential to disk and causes delayed authentication failures at runtime; unresolved key ids should return an error instead of defaulting.
Useful? React with 👍 / 👎.
…on in Qwen CLI settings
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2d013fea4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| body: JSON.stringify({ | ||
| baseUrl: getEffectiveBaseUrl(), | ||
| apiKey: keyToUse, | ||
| apiKey: !cloudEnabled ? "sk_omniroute" : null, |
There was a problem hiding this comment.
Send a non-null apiKey in cloud Droid config requests
When cloudEnabled is true this payload sends apiKey: null, but /api/cli-tools/droid-settings validates with cliModelConfigSchema where apiKey is an optional string (not nullable), so the request is rejected with 400 before keyId resolution runs. In cloud deployments this breaks applying Droid settings even when a valid key is selected.
Useful? React with 👍 / 👎.
| } | ||
| } | ||
|
|
||
| const resolvedApiKey = apiKey || "sk_omniroute"; |
There was a problem hiding this comment.
Fail fast when Qwen keyId cannot be resolved
If keyId is present but lookup fails (deleted key, stale UI state, transient DB error), this path silently falls back to "sk_omniroute" and still returns success. That writes placeholder credentials into ~/.qwen/.env, causing delayed authentication failures that are hard to diagnose; unresolved key IDs should surface an error instead of being treated as non-critical.
Useful? React with 👍 / 👎.
| import { saveCliToolLastConfigured, deleteCliToolLastConfigured } from "@/lib/db/cliToolState"; | ||
| import { cliModelConfigSchema } from "@/shared/validation/schemas"; | ||
| import { isValidationFailure, validateBody } from "@/shared/validation/helpers"; | ||
| import { getApiKeyById } from "@/lib/localDb"; |
There was a problem hiding this comment.
Import API key lookup from db module instead of localDb
This new import violates the project rule in /workspace/OmniRoute/AGENTS.md ("No barrel imports from localDb.ts — import from the specific db/ module instead"). Pulling getApiKeyById through the localDb barrel increases coupling and unnecessary module load in a request path; import directly from the owning db module.
Useful? React with 👍 / 👎.
* test: resolve typescript strictness complaints in unit tests * Update Claude Code obfuscation to version 2.1.114 (cheaper-inference#1403) * fix(cloud-code): scope thinking stripping to executor boundaries (cheaper-inference#1401) * fix(cloud-code): scope thinking stripping to executors * fix(cloud-code): guard antigravity normalized body * Update Claude Code obfuscation to version 2.1.114 - Update Claude Code version from 2.1.87 to 2.1.114 - Update X-Stainless-Package-Version from 0.80.0 to 0.81.0 - Add new beta flags: redact-thinking-2026-02-12, advisor-tool-2026-03-01, advanced-tool-use-2025-11-20 - Add missing headers: anthropic-version, anthropic-dangerous-direct-browser-access, x-app, X-Stainless-Timeout - Add all X-Stainless-* headers (Arch, Lang, OS, Runtime, Runtime-Version, Retry-Count) - Fix accept-encoding header: identity -> gzip, deflate, br, zstd - Add connection: keep-alive header - Update tool name mapping: add lsp, apply_patch, websearch These changes ensure that requests from OpenCode through Omniroute are indistinguishable from genuine Claude Code 2.1.114 requests, allowing proper authentication with Anthropic's API without triggering extra credits errors. * fix: resolve CodeQL password hash alert and TruffleHog CI failure --------- Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: Nikolay Popov <ekklesio.dev@gmail.com> Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> * fix(claude-code): scope obfuscation to cli clients and fix tests * docs(workflows): enforce PR merge instead of manual close * docs(changelog): update 3.6.9 notes with missing PR 1403 and fixes * docs(workflows): update generate-release to use full changelog for PR body * fix(tsc): silence baseUrl deprecation warnings for TS 5.5+ * fix(chatcore): apply proactive compression before provider translation (cheaper-inference#1406) Integrated into release/v3.6.9 * docs(changelog): add PR 1406 * Makes text visible in dark-mode (cheaper-inference#1409) Integrated into release/v3.6.9 * docs(changelog): add PR 1409 * chore: save local work * chore(release): sync version references to 3.6.9 * fix(codex): prevent proactive token refresh consumption and strip background parameter * ci: shard long-running suites and relax timeouts * ci: allow manual CI dispatch for release branches * feat(skills): provider-aware marketplace UX, scored AUTO injection, and memory pipeline hardening (cheaper-inference#1411) * fix/400 for GeminiCLI(add "ref" in GEMINI_UNSUPPORTED_SCHEMA_KEYS) * feat(cc-compatible): align request shape with Claude CLI * fix(cc-compatible): add Claude CLI system skeleton for OpenAI input * preserve reasoning when translating chat to responses (cheaper-inference#1414) Integrated into release/v3.6.9 * fix(skills): optimize AUTO scoring and include Responses input context (cheaper-inference#1418) Integrated into release/v3.6.9 * chore: fix TS errors and update review-prs workflow * fix(api): stop sending unsupported Gemini and Codex parameters Prevent Gemini request translation from injecting default thoughtSignature values that the upstream API strictly validates and rejects. Only preserve real signatures resolved from prior upstream responses, and strip additionalProperties from Gemini function schemas to avoid 400 "Unknown name" errors. Also remove fallback-injected session_id and conversation_id fields before sending Codex requests, and restore compatibility with the legacy OUTBOUND_SSRF_GUARD_ENABLED flag when determining whether private provider URLs are allowed. Updates the Gemini translator and regression tests for issue cheaper-inference#1410 and related 400 error cases. * fix(core): stabilization fixes for token refresh, usage translation, and testing - Update Codex token refresh detection logic - Mark provider connections invalid on unrecoverable refresh error - Fix Claude usage translation under-reporting cached tokens - Update test expectations - Update CHANGELOG.md for v3.6.9 * fix(auth): reload fresh token state and unify expiry persistence Refresh checks now re-read the latest stored provider connection before attempting rotation so they do not use stale refresh tokens captured by an earlier sweep. Token updates also persist both expiresAt and tokenExpiresAt across the health check, usage-limit refresh path, and SSE refresh flow. This keeps known token expiry metadata in sync and avoids interval-based refreshes for connections whose tokens are still valid well into the future. * fix: resolve SSRF environment static evaluation bug (cheaper-inference#1427) Fix import aliases and strict TS typings for tests and ACP agents. * test: resolve remaining strict type errors in test files * test: fix provider service assertion for anthropic-compatible header * fix(codex): respect openaiStoreEnabled setting during native passthrough (cheaper-inference#1432) * fix(codex): fix token refresh unrecoverable detection for expired tokens * fix(ci): restore release v3.6.9 build and flaky tests * fix(cc-compatible): trim default OpenAI system skeleton (cheaper-inference#1433) Integrated into release/v3.6.9 * fix: prevent masked API keys from being written to CLI tool configs (cheaper-inference#1435) * feat: mark Qwen provider as deprecated and add deprecation warning to CLI tool (cheaper-inference#1437) * docs(changelog): comprehensive v3.6.9 update with all 59 commits since v3.6.8 * test(ci): align qwen guide settings assertions * fix(security): resolve CodeQL alert 163 for incomplete URL sanitization in Qwen CLI settings --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: Nikolay Popov <74762779+nikolay-popov-ideogram@users.noreply.github.com> Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Nikolay Popov <ekklesio.dev@gmail.com> Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com> Co-authored-by: Tim Massey <tim-massey@users.noreply.github.com> Co-authored-by: Paijo <oyi77@users.noreply.github.com> Co-authored-by: dail45 <dail45@yandex.ru> Co-authored-by: R.D. <rogerproself@gmail.com>
* test: resolve typescript strictness complaints in unit tests * Update Claude Code obfuscation to version 2.1.114 (cheaper-inference#1403) * fix(cloud-code): scope thinking stripping to executor boundaries (cheaper-inference#1401) * fix(cloud-code): scope thinking stripping to executors * fix(cloud-code): guard antigravity normalized body * Update Claude Code obfuscation to version 2.1.114 - Update Claude Code version from 2.1.87 to 2.1.114 - Update X-Stainless-Package-Version from 0.80.0 to 0.81.0 - Add new beta flags: redact-thinking-2026-02-12, advisor-tool-2026-03-01, advanced-tool-use-2025-11-20 - Add missing headers: anthropic-version, anthropic-dangerous-direct-browser-access, x-app, X-Stainless-Timeout - Add all X-Stainless-* headers (Arch, Lang, OS, Runtime, Runtime-Version, Retry-Count) - Fix accept-encoding header: identity -> gzip, deflate, br, zstd - Add connection: keep-alive header - Update tool name mapping: add lsp, apply_patch, websearch These changes ensure that requests from OpenCode through Omniroute are indistinguishable from genuine Claude Code 2.1.114 requests, allowing proper authentication with Anthropic's API without triggering extra credits errors. * fix: resolve CodeQL password hash alert and TruffleHog CI failure --------- Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Co-authored-by: Nikolay Popov <ekklesio.dev@gmail.com> Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> * fix(claude-code): scope obfuscation to cli clients and fix tests * docs(workflows): enforce PR merge instead of manual close * docs(changelog): update 3.6.9 notes with missing PR 1403 and fixes * docs(workflows): update generate-release to use full changelog for PR body * fix(tsc): silence baseUrl deprecation warnings for TS 5.5+ * fix(chatcore): apply proactive compression before provider translation (cheaper-inference#1406) Integrated into release/v3.6.9 * docs(changelog): add PR 1406 * Makes text visible in dark-mode (cheaper-inference#1409) Integrated into release/v3.6.9 * docs(changelog): add PR 1409 * chore: save local work * chore(release): sync version references to 3.6.9 * fix(codex): prevent proactive token refresh consumption and strip background parameter * ci: shard long-running suites and relax timeouts * ci: allow manual CI dispatch for release branches * feat(skills): provider-aware marketplace UX, scored AUTO injection, and memory pipeline hardening (cheaper-inference#1411) * fix/400 for GeminiCLI(add "ref" in GEMINI_UNSUPPORTED_SCHEMA_KEYS) * feat(cc-compatible): align request shape with Claude CLI * fix(cc-compatible): add Claude CLI system skeleton for OpenAI input * preserve reasoning when translating chat to responses (cheaper-inference#1414) Integrated into release/v3.6.9 * fix(skills): optimize AUTO scoring and include Responses input context (cheaper-inference#1418) Integrated into release/v3.6.9 * chore: fix TS errors and update review-prs workflow * fix(api): stop sending unsupported Gemini and Codex parameters Prevent Gemini request translation from injecting default thoughtSignature values that the upstream API strictly validates and rejects. Only preserve real signatures resolved from prior upstream responses, and strip additionalProperties from Gemini function schemas to avoid 400 "Unknown name" errors. Also remove fallback-injected session_id and conversation_id fields before sending Codex requests, and restore compatibility with the legacy OUTBOUND_SSRF_GUARD_ENABLED flag when determining whether private provider URLs are allowed. Updates the Gemini translator and regression tests for issue cheaper-inference#1410 and related 400 error cases. * fix(core): stabilization fixes for token refresh, usage translation, and testing - Update Codex token refresh detection logic - Mark provider connections invalid on unrecoverable refresh error - Fix Claude usage translation under-reporting cached tokens - Update test expectations - Update CHANGELOG.md for v3.6.9 * fix(auth): reload fresh token state and unify expiry persistence Refresh checks now re-read the latest stored provider connection before attempting rotation so they do not use stale refresh tokens captured by an earlier sweep. Token updates also persist both expiresAt and tokenExpiresAt across the health check, usage-limit refresh path, and SSE refresh flow. This keeps known token expiry metadata in sync and avoids interval-based refreshes for connections whose tokens are still valid well into the future. * fix: resolve SSRF environment static evaluation bug (cheaper-inference#1427) Fix import aliases and strict TS typings for tests and ACP agents. * test: resolve remaining strict type errors in test files * test: fix provider service assertion for anthropic-compatible header * fix(codex): respect openaiStoreEnabled setting during native passthrough (cheaper-inference#1432) * fix(codex): fix token refresh unrecoverable detection for expired tokens * fix(ci): restore release v3.6.9 build and flaky tests * fix(cc-compatible): trim default OpenAI system skeleton (cheaper-inference#1433) Integrated into release/v3.6.9 * fix: prevent masked API keys from being written to CLI tool configs (cheaper-inference#1435) * feat: mark Qwen provider as deprecated and add deprecation warning to CLI tool (cheaper-inference#1437) * docs(changelog): comprehensive v3.6.9 update with all 59 commits since v3.6.8 * test(ci): align qwen guide settings assertions * fix(security): resolve CodeQL alert 163 for incomplete URL sanitization in Qwen CLI settings --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: Nikolay Popov <74762779+nikolay-popov-ideogram@users.noreply.github.com> Co-authored-by: Randi <55005611+rdself@users.noreply.github.com> Co-authored-by: Nikolay Popov <ekklesio.dev@gmail.com> Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com> Co-authored-by: Tim Massey <tim-massey@users.noreply.github.com> Co-authored-by: Paijo <oyi77@users.noreply.github.com> Co-authored-by: dail45 <dail45@yandex.ru> Co-authored-by: R.D. <rogerproself@gmail.com>


[3.6.9] — 2026-04-19
✨ New Features
saveQwenConfigto inject OmniRoute as a multi-provider (openai, anthropic, gemini) via.qwen/settings.jsonand.qwen/.env(feat: add Qwen Code CLI tool with dedicated settings route and deprecate OAuth provider #1437)🐛 Bug Fixes
sk-31c4****8600) from being written to CLI tool config files. The dashboard UI now passeskey.idto the backend, which resolves the unmasked key from the database via a newresolveApiKey()helper. Fixes auth failures across all CLI tools (Claude, Codex, Cline, Kilo, Droid, OpenClaw, Antigravity) (fix: prevent masked API keys from being written to CLI tool configs #1435)reftoGEMINI_UNSUPPORTED_SCHEMA_KEYSto fix 400 errors from Gemini CLI when tool schemas contain JSON Schema$reffieldsbackgroundparameter from upstream requestsusage.prompt_tokensunder-reporting when translating Claude caching responses to OpenAI format ([BUG]usage.prompt_tokensexcludes cached tokens when Claude response is translated to OpenAI format #1426)token_expiredandinvalid_token) now correctly mark the connection as invalid to prompt user re-authentication, rather than silently failing ([BUG] Codex OpenAI Responses Store injects unsupported session_id on the Responses path #1415)additionalPropertiesschema field, resolving 400 errors during complex tool invocations ([BUG] additionalProperties in tool schemas causes Gemini API errors #1421)openaiStoreEnabledsetting during native passthrough for Responses API to prevent unsupported upstream arguments (Bug: native Codex/responsespassthrough defaults omittedstoretotrue#1432)systemtodeveloperroles instead of hoisting them into instructions, enabling prompt caching for system messages on GPT-5 models (fix(codex): cache system prompts for Chat Completions path via convertSystemToDeveloperRole #1400)baseUrldeprecation warnings for TypeScript 5.5+ configurations🧪 Tests
🛠️ Maintenance