Skip to content

Release v3.6.9 - #1404

Merged
diegosouzapw merged 42 commits into
mainfrom
release/v3.6.9
Apr 19, 2026
Merged

diegosouzapw merged 42 commits into
mainfrom
release/v3.6.9

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Apr 18, 2026 •

Copy link
Copy Markdown
Collaborator

[3.6.9] — 2026-04-19

✨ New Features

🐛 Bug Fixes

🧪 Tests

  • test(core): Resolve typescript strictness complaints and fix combo-routing-engine test regression
  • test(core): Resolve remaining strict type errors across all unit test files
  • test(providers): Fix provider service assertion for anthropic-compatible header format
  • test(codex): Align codex passthrough assertions with explicit store retention policy
  • test(codex): Fix store assertion for codex responses
  • test(cli): Resolve strict null checks in Qoder unit tests

🛠️ Maintenance

  • chore: Sync infrastructure with docker postinstall components and secondary CodeQL analysis rules
  • chore: Enforce contributor credit rule in review-prs workflow
  • chore: Fix TS errors and update review-prs workflow for improved automation
  • ci: Allow manual CI dispatch for release branches
  • ci: Shard long-running test suites and relax timeouts for stability
  • ci: Restore release v3.6.9 build pipeline and fix flaky tests
  • docs: Update generate-release workflow to use full changelog for PR body
  • docs: Enforce PR merge instead of manual close in workflows

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +232 to 234
relayOptions: null as any,
allCombos: null,
relayOptions: null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +232 to 234
relayOptions: null as any,
allCombos: null,
relayOptions: null,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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,

@github-actions

github-actions Bot commented Apr 18, 2026 •

Copy link
Copy Markdown
Contributor

CI Coverage Report

  • Coverage job: success
  • PR test policy: success

Coverage artifact was not available for this run.

nikolay-popov-ideogram and others added 2 commits April 18, 2026 18:28
* 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>
Comment thread src/lib/usage/callLogArtifacts.ts Fixed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +470 to +472
if (!tb.thinking) {
tb.thinking = { type: "adaptive" };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment thread open-sse/executors/base.ts Outdated

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",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +440 to +441
const isClaudeCodeClient =
clientHeaders?.["x-app"] === "cli" ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +1150 to +1154
const compressionResult = compressContext(body, {
provider,
model: effectiveModel,
maxTokens: threshold,
reserveTokens: 0,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +555 to 556
if (isClaudeCodeCompatible(this.provider) || this.provider === "claude") {
bodyString = await signRequestBody(bodyString);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +1148 to +1149
const parsed = parseModel(t.modelStr);
return getTokenLimit(parsed.provider, parsed.model);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread open-sse/handlers/chatCore.ts Outdated
return `name:${rawName.trim().toLowerCase()}`;
}

return "local";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines 311 to +315
const system = buildClaudeCodeCompatibleSystemBlocks({
messages: normalized.messages as MessageLike[],
systemBlocks: preparedClaudeBody?.system as Record<string, unknown>[] | undefined,
cwd,
now,
preserveCacheControl,
billingHeader,
injectDefaultSkeleton: !preparedClaudeBody,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +4 to +6
getAccessToken,
updateProviderCredentials,
} from "@omniroute/open-sse/services/tokenRefresh";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +29 to +33
const spec = getModelSpec(normalizedModel);
if (typeof spec?.supportsThinking === "boolean") {
return !spec.supportsThinking;
}
return CLOUD_CODE_REASONING_UNSUPPORTED_PATTERNS.some((pattern) => pattern.test(normalizedModel));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines 141 to +143
baseUrl: baseUrlWithV1,
apiKey: keyToUse,
apiKey: !cloudEnabled ? "sk_omniroute" : null,
keyId: selectedKeyId,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +51 to +55
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)
10.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@diegosouzapw
diegosouzapw merged commit 3432dfd into main Apr 19, 2026
60 of 61 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
* 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>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
* 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants