Skip to content

chore(release): v3.3.11 — analytics, backup control, CLI fixes, workflow unification - #860

Merged
diegosouzapw merged 2 commits into
mainfrom
release/v3.3.11
Mar 31, 2026
Merged

diegosouzapw merged 2 commits into
mainfrom
release/v3.3.11

Conversation

@diegosouzapw

@diegosouzapw diegosouzapw commented Mar 31, 2026 •

Copy link
Copy Markdown
Collaborator

🚀 Release v3.3.11

🚀 Features

🐛 Bug Fixes

🔧 Workflow Unification

  • Rewrote /review-prs, /resolve-issues, /implement-features workflows
  • All development now happens on a single release/vX.Y.Z branch
  • No more scattered fix/, feat/, topic branches — single branch per release cycle

🧹 Branch Cleanup

  • Deleted stale local branches: coder/provider-limits-last-refreshed, fix/issue-815, release/v3.3.9, feat/subscription-utilization

Tests

  • 1167/1167 tests pass (79 suites)

⚠️ After merging: run Phase 2 to tag, publish, and deploy.

Copilot AI review requested due to automatic review settings March 31, 2026 11:02
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@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 updates the project to version 3.3.11, introducing several bug fixes and features. Key changes include updating the Qwen provider's base URL and adding specific retry logic for its quota limits, expanding the CLI binary size detection limit to 350MB, and refining the Codex executor to prevent schema rejections. Additionally, the release workflow was automated, and OAuth popup blocking is now handled with a manual fallback. Feedback suggests improving test isolation by using temporary directories instead of the home directory, removing placeholder comments in documentation, and refactoring provider-specific logic out of the core chat handler to improve maintainability.

Comment on lines +18 to +22
const testRoot = path.join(os.homedir(), ".omniroute-test-tmp");
if (!fs.existsSync(testRoot)) {
fs.mkdirSync(testRoot, { recursive: true });
}
return fs.mkdtempSync(path.join(testRoot, "cli-test-"));

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.

high

Creating test directories in the user's home directory (os.homedir()) is intrusive and can leave clutter on the developer's machine. It may also fail in CI environments with restricted home directory access. It is better to use os.tmpdir() for temporary test files.

  const testRoot = path.join(os.tmpdir(), ".omniroute-test-tmp");
  if (!fs.existsSync(testRoot)) {
    fs.mkdirSync(testRoot, { recursive: true });
  }
  return fs.mkdtempSync(path.join(testRoot, "cli-test-"));

### 11. Pull main and create tag
### 11. Create Git Tag and GitHub Release (MANDATORY)

// turbo

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 string // turbo appears to be a leftover placeholder or an incorrectly formatted comment. In Markdown, comments should use the <!-- comment --> syntax, or if this is a note for the user, it should be formatted as plain text or a blockquote.

@@ -959,7 +959,8 @@ export async function handleChatCore({
if (
targetFormat === FORMATS.OPENAI &&
!bodyToSend.prompt_cache_key &&
Array.isArray(bodyToSend.messages)
Array.isArray(bodyToSend.messages) &&
!["nvidia", "codex", "xai"].includes(provider)

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

Hardcoding provider-specific exclusions for prompt caching directly in the core handler reduces maintainability. As the number of providers grows, this list will become difficult to manage. Consider moving this configuration into the providerRegistry or adding a capability flag to the provider definition.

);
const rawResult = await withRateLimit(provider, connectionId, modelToCall, async () => {
let attempts = 0;
const maxAttempts = provider === "qwen" ? 3 : 1;

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

Provider-specific retry logic (like maxAttempts for "qwen") should ideally be encapsulated within the provider's executor or defined in the registry. Placing it here in handleChatCore couples the core logic to specific provider quirks.

@kilo-code-bot

kilo-code-bot Bot commented Mar 31, 2026 •

Copy link
Copy Markdown

Code Review Summary

Status: 1 Observation Found | Recommendation: Merge

Overview

Severity Count
WARNING 0
SUGGESTION 1
Observation Details (click to expand)

SUGGESTION

File Line Issue
src/shared/services/cliRuntime.ts 565 JSDoc documentation still says "30B - 100MB" but the actual code check was updated to 350MB. The code comments at line 594 were correctly updated, but the JSDoc at line 565 (the function-level documentation for checkKnownPath) still references the old 100MB limit. This creates a documentation inconsistency where the implementation no longer matches the description.
Files Reviewed (17 files)
  • .agents/workflows/generate-release.md - Workflow documentation update
  • .agents/workflows/implement-features.md - Workflow documentation update
  • .agents/workflows/resolve-issues.md - Workflow documentation update
  • .agents/workflows/review-prs.md - Workflow documentation update
  • CHANGELOG.md - Version 3.3.11 release notes
  • docs/openapi.yaml - Version bump
  • electron/package.json - Version bump
  • open-sse/config/providerRegistry.ts - Qwen endpoint fix & GPT-5.4-mini addition
  • open-sse/executors/codex.ts - Messages/prompt deletion for native passthrough
  • open-sse/handlers/chatCore.ts - Qwen 429 retry logic & prompt cache exclusion
  • open-sse/package.json - Version bump
  • package-lock.json - Version bump
  • package.json - Version bump
  • src/shared/components/OAuthModal.tsx - Popup blocked fallback
  • src/shared/services/cliRuntime.ts - Binary size threshold & env override
  • tests/unit/cli-runtime-detection.test.mjs - Test path fix
  • tests/unit/t28-model-catalog-updates.test.mjs - Qwen URL assertion update

Previous Issues Status

All 7 previously commented issues remain unchanged in this review:

Issue Status
Test directory in home directory (line 22) Not addressed - see previous comments
// turbo placeholder comment (line 183) Not addressed - see previous comments
Hardcoded provider exclusions (line 963) Not addressed - see previous comments
Provider-specific retry logic (line 974) Not addressed - see previous comments
Test cleanup (line 24) Not addressed - see previous comments
JSDoc vs code mismatch (line 599) Not addressed - see previous comments
PR scope mismatch (line 6) Not addressed - see previous comments

Code Quality Assessment

All changes in this PR appear sound:

  • Qwen retry logic correctly uses .clone() to peek at response body while preserving the original for return
  • Prompt cache exclusion appropriately handles providers that don't support this feature
  • CLI binary size increase from 100MB to 350MB accommodates modern tools like Claude Code
  • OAuth fallback properly handles browser popup blocking
  • Codex schema stripping correctly removes messages/prompt for native passthrough

The single observation (JSDoc inconsistency at line 565) is a minor documentation issue that doesn't affect functionality. The code implementation correctly reflects the 350MB limit.

Copilot AI 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.

Pull request overview

Release prep for v3.3.11, primarily addressing test regressions and CLI runtime detection behavior, along with additional provider/runtime fixes and version bumps across packages/docs.

Changes:

  • Fix CLI runtime detection to respect CLI_{TOOL}_BIN overrides and raise the known-path binary size ceiling.
  • Update Qwen registry URL expectation and add/adjust runtime/provider behaviors (Qwen retry handling, Codex request sanitization, OAuth popup-block fallback).
  • Bump versions and update release artifacts (OpenAPI version, changelog entry, release workflow steps).

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
tests/unit/t28-model-catalog-updates.test.mjs Updates Qwen registry base URL expectation in unit test.
tests/unit/cli-runtime-detection.test.mjs Adjusts temp dir strategy and padding in CLI detection tests.
src/shared/services/cliRuntime.ts Raises known-path size limit; ensures env override bypasses known-path discovery rules.
src/shared/components/OAuthModal.tsx Handles popup-blocked case by switching to manual input flow for Codex localhost flow.
open-sse/handlers/chatCore.ts Adds provider gating for prompt_cache_key injection; adds Qwen 429 quota backoff retries.
open-sse/executors/codex.ts Strips messages/prompt fields to satisfy strict Codex Responses schema.
open-sse/config/providerRegistry.ts Adds gpt-5.4-mini; updates Qwen base URL.
package.json Bumps app version to 3.3.11.
package-lock.json Updates lockfile versions to 3.3.11 (including @omniroute/open-sse).
open-sse/package.json Bumps @omniroute/open-sse version to 3.3.11.
electron/package.json Bumps desktop app version to 3.3.11.
docs/openapi.yaml Bumps OpenAPI info version to 3.3.11.
CHANGELOG.md Adds 3.3.11 release notes.
.agents/workflows/generate-release.md Consolidates tag + release creation steps in the release workflow doc.
Comments suppressed due to low confidence (1)

.agents/workflows/generate-release.md:193

  • Phase 2 step numbering now jumps from "11" to "14" (since old steps 12/13 were removed). Please renumber the headings (or reintroduce missing numbers) to keep the workflow instructions unambiguous.
### 11. Create Git Tag and GitHub Release (MANDATORY)

// turbo

```bash
git checkout main
git pull origin main
VERSION=$(node -p "require('./package.json').version")
git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin --tags
gh release create "v$VERSION" --title "v$VERSION" --notes "OmniRoute v$VERSION Release" --target main

14. 🐳 Trigger Docker Hub build (MANDATORY — keep npm and Docker in sync)

</details>



---

💡 <a href="/diegosouzapw/OmniRoute/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.

Comment on lines +18 to 24
const testRoot = path.join(os.homedir(), ".omniroute-test-tmp");
if (!fs.existsSync(testRoot)) {
fs.mkdirSync(testRoot, { recursive: true });
}
return fs.mkdtempSync(path.join(testRoot, "cli-test-"));
}

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

createTempDir now creates a persistent ~/.omniroute-test-tmp directory but the tests only rmSync the mkdtemp subdirectory, leaving the root directory behind after test runs. Consider reverting to os.tmpdir() (typical for unit tests) or explicitly removing the root directory when it becomes empty to avoid polluting developers’ home dirs and potential permission issues in restricted CI environments.

Suggested change
const testRoot = path.join(os.homedir(), ".omniroute-test-tmp");
if (!fs.existsSync(testRoot)) {
fs.mkdirSync(testRoot, { recursive: true });
}
return fs.mkdtempSync(path.join(testRoot, "cli-test-"));
}
// Use the OS temp directory for test isolation and to avoid polluting $HOME.
return fs.mkdtempSync(path.join(os.tmpdir(), "cli-test-"));
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +594 to 599
// CLI binaries should be > 30 bytes and < 350MB
// npm .cmd wrappers on Windows are ~300-500 bytes, JS wrappers on Linux can be ~44 bytes
// Minimum catches empty/suspicious files while allowing legitimate thin wrappers
if (stat.size < 30 || stat.size > 100 * 1024 * 1024) {
// Many modern CLIs (like Claude Code and OpenCode) build as single ~150-250MB binaries
if (stat.size < 30 || stat.size > 350 * 1024 * 1024) {
return { installed: false, commandPath: null, reason: "suspicious_size" };

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

The JSDoc above checkKnownPath still mentions a 100MB upper bound, but this change raises the limit to 350MB. Please update the JSDoc accordingly so documentation matches the implemented security checks.

Copilot uses AI. Check for mistakes.
Comment thread package.json
Comment on lines 1 to 6
{
"name": "omniroute",
"version": "3.3.10",
"version": "3.3.11",
"description": "Smart AI Router with auto fallback — route to FREE & cheap models, zero downtime. Works with Cursor, Cline, Claude Desktop, Codex, and any OpenAI-compatible tool.",
"type": "module",
"bin": {

Copilot AI Mar 31, 2026

Copy link

Choose a reason for hiding this comment

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

PR description/title say this is only "test regression fixes" (CLI override + DashScope/Qwen endpoint test correction), but this diff also includes additional functional changes (e.g., Qwen 429 retry logic in chatCore, Codex request body schema stripping, OAuth popup-block fallback behavior, Codex model registry update). Please update the PR description to reflect the full scope (or split unrelated changes) so reviewers/release notes match what’s actually shipping.

Copilot uses AI. Check for mistakes.
@diegosouzapw diegosouzapw changed the title chore(release): v3.3.11 — test regression fixes chore(release): v3.3.11 — analytics, backup control, CLI fixes, workflow unification Mar 31, 2026
@diegosouzapw
diegosouzapw merged commit dbe17b4 into main Mar 31, 2026
5 checks passed
@diegosouzapw
diegosouzapw deleted the release/v3.3.11 branch March 31, 2026 11:20
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
….3.11

chore(release): v3.3.11 — analytics, backup control, CLI fixes, workflow unification
diegosouzapw added a commit that referenced this pull request Aug 24, 2026
CodeQL js/incomplete-url-substring-sanitization, alerts #860 and #861:
volcengineConsoleAutoLogin accepted any cookie whose `domain` merely *contained*
"volcengine.com".

That check is an authorization decision, not a string test. The console
auto-login harvests `digest`, `AccountID`, `csrfToken` and `userInfo` out of the
Playwright context and persists them as the operator's Volcengine credentials,
so a cookie set by `volcengine.com.attacker.tld` — or `notvolcengine.com` — was
captured and stored as a provider connection.

Add `matchesCookieDomain()` (open-sse/utils/cookieDomain.ts): exact host or
dot-boundary suffix, leading dots and case normalized on both sides, failing
closed on an empty expected domain. Same shape as the existing
`isAdobeCookieDomain` in adobeFireflyBrowserLogin.ts, which already got this
right.

While sweeping the class, inAppLoginService's cookie capture had the identical
weakness — `c.domain.includes(domain.replace(/^\./, ""))` — with the identical
consequence: a look-alike host's cookie stored as the operator's credential.
CodeQL did not flag it because the expected domain comes from
TOKEN_EXTRACTION_CONFIGS rather than a literal. Both callsites now share the
helper.

tests/unit/volcengine-cookie-domain-suffix.test.ts — 5 tests, red before the
fix, covering the real domains, seven look-alikes, empty/missing input, and the
config-supplied path.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
diegosouzapw added a commit that referenced this pull request Aug 25, 2026
#11452)

Clears CodeQL js/incomplete-url-substring-sanitization alerts #860-#865:

- volcengineConsoleAutoLogin: cookie domain filter now uses an exact/
  dot-suffix helper (isVolcengineCookieDomain) instead of substring
  includes(), rejecting look-alike hosts like volcengine.com.evil.test
- security-s1-s2-s4 tests: agent-card/agent.json URL assertions compare
  parsed origin equality instead of startsWith prefix

Co-authored-by: Markus Hartung <mail@hartmark.se>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
….3.11

chore(release): v3.3.11 — analytics, backup control, CLI fixes, workflow unification
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
cheaper-inference#11452)

Clears CodeQL js/incomplete-url-substring-sanitization alerts cheaper-inference#860-cheaper-inference#865:

- volcengineConsoleAutoLogin: cookie domain filter now uses an exact/
  dot-suffix helper (isVolcengineCookieDomain) instead of substring
  includes(), rejecting look-alike hosts like volcengine.com.evil.test
- security-s1-s2-s4 tests: agent-card/agent.json URL assertions compare
  parsed origin equality instead of startsWith prefix

Co-authored-by: Markus Hartung <mail@hartmark.se>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…-inference#11429)

CodeQL js/incomplete-url-substring-sanitization, alerts cheaper-inference#860 and cheaper-inference#861:
volcengineConsoleAutoLogin accepted any cookie whose `domain` merely *contained*
"volcengine.com".

That check is an authorization decision, not a string test. The console
auto-login harvests `digest`, `AccountID`, `csrfToken` and `userInfo` out of the
Playwright context and persists them as the operator's Volcengine credentials,
so a cookie set by `volcengine.com.attacker.tld` — or `notvolcengine.com` — was
captured and stored as a provider connection.

Add `matchesCookieDomain()` (open-sse/utils/cookieDomain.ts): exact host or
dot-boundary suffix, leading dots and case normalized on both sides, failing
closed on an empty expected domain. Same shape as the existing
`isAdobeCookieDomain` in adobeFireflyBrowserLogin.ts, which already got this
right.

While sweeping the class, inAppLoginService's cookie capture had the identical
weakness — `c.domain.includes(domain.replace(/^\./, ""))` — with the identical
consequence: a look-alike host's cookie stored as the operator's credential.
CodeQL did not flag it because the expected domain comes from
TOKEN_EXTRACTION_CONFIGS rather than a literal. Both callsites now share the
helper.

tests/unit/volcengine-cookie-domain-suffix.test.ts — 5 tests, red before the
fix, covering the real domains, seven look-alikes, empty/missing input, and the
config-supplied path.

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
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.

2 participants