Skip to content

Fix Runtime page breaker state rendering - #3533

Merged
diegosouzapw merged 3 commits into
diegosouzapw:release/v3.8.20from
rdself:coder/fix-runtime-internal-server-error
Jun 10, 2026
Merged

diegosouzapw merged 3 commits into
diegosouzapw:release/v3.8.20from
rdself:coder/fix-runtime-internal-server-error

Conversation

@rdself

@rdself rdself commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • handle DEGRADED provider breaker states on the Runtime dashboard
  • add a fallback tone for future unknown breaker states so the page does not crash
  • cover degraded and unknown states with a jsdom regression test

Root cause

The monitoring payload can return provider breaker states beyond CLOSED, OPEN, and HALF_OPEN. When a DEGRADED state was present, the Runtime page attempted to read styling from an undefined tone entry and crashed into the Next.js Internal Server Error screen.

Validation

  • npm exec vitest -- run --config vitest.config.ts tests/unit/ui/runtime-page-client.test.tsx --reporter verbose
  • npm exec eslint -- 'src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx' tests/unit/ui/runtime-page-client.test.tsx
  • npm run typecheck:core
  • npm run lint -- --quiet
  • git diff --check
  • verified /dashboard/runtime locally with a database copy that returns DEGRADED breaker state

@rdself
rdself requested a review from diegosouzapw as a code owner June 9, 2026 21:03
Copilot AI review requested due to automatic review settings June 9, 2026 21:03

@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 support for a new "DEGRADED" circuit breaker state and gracefully handles unknown states in the dashboard runtime page. It adds helper functions for state normalization and tone retrieval, updates the UI to display degraded and unknown circuits in metrics and badges, and includes a new unit test suite under the tests/ directory. The review feedback identifies two valuable optimization opportunities: refactoring the multiple .filter() calls inside the useMemo hook into a single-pass loop to avoid redundant array allocations, and passing the raw state directly to getBreakerTone to prevent duplicate string normalization.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 468 to +481
const counts = useMemo(() => {
const openCircuits = breakers.filter((b) => b.state === "OPEN").length;
const halfCircuits = breakers.filter((b) => b.state === "HALF_OPEN").length;
const knownBreakerStates = new Set(["CLOSED", "OPEN", "HALF_OPEN", "DEGRADED"]);
const openCircuits = breakers.filter((b) => normalizeBreakerState(b.state) === "OPEN").length;
const halfCircuits = breakers.filter(
(b) => normalizeBreakerState(b.state) === "HALF_OPEN"
).length;
const degradedCircuits = breakers.filter(
(b) => normalizeBreakerState(b.state) === "DEGRADED"
).length;
const unknownCircuits = breakers.filter(
(b) => !knownBreakerStates.has(normalizeBreakerState(b.state))
).length;
const totalBreakers = breakers.length;
const affectedCircuits = openCircuits + halfCircuits + degradedCircuits + unknownCircuits;

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 current implementation performs four separate .filter() operations on the breakers array, calling normalizeBreakerState repeatedly for each element. Since this runs inside a useMemo hook that executes on every health update (every 5 seconds), we can optimize this to a single-pass loop. This avoids multiple array allocations and redundant string normalization operations, improving both performance and readability.

  const counts = useMemo(() => {
    let openCircuits = 0;
    let halfCircuits = 0;
    let degradedCircuits = 0;
    let unknownCircuits = 0;

    const knownBreakerStates = new Set(["CLOSED", "OPEN", "HALF_OPEN", "DEGRADED"]);

    for (const b of breakers) {
      const state = normalizeBreakerState(b.state);
      if (state === "OPEN") {
        openCircuits++;
      } else if (state === "HALF_OPEN") {
        halfCircuits++;
      } else if (state === "DEGRADED") {
        degradedCircuits++;
      } else if (!knownBreakerStates.has(state)) {
        unknownCircuits++;
      }
    }

    const totalBreakers = breakers.length;
    const affectedCircuits = openCircuits + halfCircuits + degradedCircuits + unknownCircuits;

{breakers.map((b) => {
const tone = BREAKER_TONE[b.state];
const state = normalizeBreakerState(b.state);
const tone = getBreakerTone(state);

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

Passing state (which is already normalized via normalizeBreakerState(b.state)) to getBreakerTone causes redundant normalization because getBreakerTone calls normalizeBreakerState internally. Passing b.state directly to getBreakerTone avoids this double normalization.

Suggested change
const tone = getBreakerTone(state);
const tone = getBreakerTone(b.state);

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

Note

Copilot was unable to run its full agentic suite in this review.

Adds support for additional/unknown circuit breaker states in the Runtime dashboard UI to avoid crashes and improve display, along with a unit test to validate rendering of new states.

Changes:

  • Expanded breaker state handling to include DEGRADED plus a safe fallback for unknown states.
  • Normalized breaker state comparisons and updated KPI/health aggregation to account for degraded/unknown states.
  • Added a jsdom unit test to ensure degraded/unknown provider breaker states render without crashing.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
tests/unit/ui/runtime-page-client.test.tsx Adds a UI unit test that mocks data with DEGRADED and an unknown breaker state and asserts the page renders expected labels.
src/app/(dashboard)/dashboard/runtime/RuntimePageClient.tsx Normalizes breaker states, adds DEGRADED tone + unknown fallback tone, and updates derived counts/UI to include degraded/unknown states.

Comment on lines +258 to +266
} else if (nextState === "DEGRADED") {
out.push({
id: `cb-deg-${provider}-${nowTs}`,
ts: nowTs,
kind: "circuit-recovered",
title: `${provider} DEGRADED`,
detail: `${nextB.failureCount} failures · degraded but serving`,
});
} else if (nextState === "CLOSED" && prevState !== "CLOSED") {
Comment on lines 468 to +481
const counts = useMemo(() => {
const openCircuits = breakers.filter((b) => b.state === "OPEN").length;
const halfCircuits = breakers.filter((b) => b.state === "HALF_OPEN").length;
const knownBreakerStates = new Set(["CLOSED", "OPEN", "HALF_OPEN", "DEGRADED"]);
const openCircuits = breakers.filter((b) => normalizeBreakerState(b.state) === "OPEN").length;
const halfCircuits = breakers.filter(
(b) => normalizeBreakerState(b.state) === "HALF_OPEN"
).length;
const degradedCircuits = breakers.filter(
(b) => normalizeBreakerState(b.state) === "DEGRADED"
).length;
const unknownCircuits = breakers.filter(
(b) => !knownBreakerStates.has(normalizeBreakerState(b.state))
).length;
const totalBreakers = breakers.length;
const affectedCircuits = openCircuits + halfCircuits + degradedCircuits + unknownCircuits;
Comment on lines +207 to +215
function normalizeBreakerState(state: string | null | undefined): string {
return String(state || "")
.trim()
.toUpperCase();
}

function getBreakerTone(state: string | null | undefined): BreakerTone {
return BREAKER_TONE[normalizeBreakerState(state)] || FALLBACK_BREAKER_TONE;
}
Comment on lines +21 to +29
async function waitForText(text: string) {
const startedAt = Date.now();
while (!document.body.textContent?.includes(text)) {
if (Date.now() - startedAt > 1000) {
throw new Error(`Timed out waiting for text: ${text}`);
}
await new Promise((resolve) => setTimeout(resolve, 10));
}
}
@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.20 June 10, 2026 06:15
@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks @rdself! Solid fix — the Runtime page crashed when a provider breaker reported a state not in BREAKER_TONE (tone undefined → tone.ring throw). Normalizing the state + a FALLBACK_BREAKER_TONE (UNKNOWN) makes it resilient, and adding the DEGRADED tone/feed-event pairs cleanly with #3535 (which exposes the degradation threshold backend). The jsdom test renders the real component with DEGRADED+unknown states and asserts no crash. Shipping in the next release. 🙌

@diegosouzapw
diegosouzapw merged commit 08908a3 into diegosouzapw:release/v3.8.20 Jun 10, 2026
1 check passed
diegosouzapw added a commit that referenced this pull request Jun 10, 2026
* chore(release): open v3.8.20 development cycle

* fix(images): prefer bare combos over image aliases (#3527)

Integrated into release/v3.8.20

* fix(translator): map Codex local_shell tool (#3534)

Integrated into release/v3.8.20

* fix(usage): make opencode-go quota fetcher fail-open instead of throwing 500 (#3522)

Integrated into release/v3.8.20

* Fix Runtime page breaker state rendering (#3533)

Integrated into release/v3.8.20

* Expose provider breaker degradation threshold setting (#3535)

Integrated into release/v3.8.20

* fix(executor): strip provider prefix from versioned built-in tool model field (#3532)

Integrated into release/v3.8.20

* feat(providers): add Claude Fable 5 support (#3524)

Integrated into release/v3.8.20

* feat(resilience): add global provider cooldown tracking to prevent combo re-walking (#3556)

Integrated into release/v3.8.20 (default OFF, opt-in)

* fix(translator): scope thoughtSignature bypass to Antigravity/CLI only (#3560)

Integrated into release/v3.8.20. Co-authored-by: Six7Day <six7day@gmail.com>

* fix(routing): normalize thinking:disabled for combo-substituted models that reject it (#3554) (#3563)

Integrated into release/v3.8.20

* fix(usage): accept 0/empty budget limits so the dashboard can save and clear (#3537) (#3564)

Integrated into release/v3.8.20

* docs(changelog): credit @Six7Day for #3560 thoughtSignature fix (#3414)

The #3560 squash co-author trailer landed inline (unparsed by GitHub), so add
an explicit CHANGELOG credit ensuring @Six7Day (original #3414) and @oyi77 are
on the public record for the Gemini thoughtSignature fix.

* fix(gamification): dedup badge unlock via user_badges so events don't re-fire every request (#3472) (#3565)

Integrated into release/v3.8.20

* fix(routing): pass through 'auto' keyword on codex /v1/responses instead of rewriting to codex/auto (#3509) (#3566)

Integrated into release/v3.8.20

* fix(cli-tools): normalize apiKey null in guide-settings schema so cloud-mode config saves (#3552) (#3567)

Integrated into release/v3.8.20

* fix(catalog): reclassify PublicAI from keyless to one-time-initial (requires API key) (#3558) (#3568)

Integrated into release/v3.8.20

* fix(gemini-web): surface missing Playwright browser as actionable 503 + cooldown hint, not a retryable 500 loop (#3516) (#3570)

Integrated into release/v3.8.20

* fix(security): sanitize raw err.message in web executors + embeddings/search response bodies (Rule #12) (#3494, #3495) (#3573)

Integrated into release/v3.8.20

* fix(dashboard): point CustomHostsManager + FeatureFlagsGrid at real routes (#3486, #3487) (#3574)

Integrated into release/v3.8.20

* chore(providers): remove dead krutrim entry (#3483) + docs(api): fix agent-bridge per-agent state route (#3489) (#3575)

Integrated into release/v3.8.20

* docs(api): correct API_REFERENCE.md paths for skills/plugins/admin/cache/acp/system-info (#3497) (#3577)

Integrated into release/v3.8.20

* fix(proxy): drive SOCKS5 UI option from runtime ENABLE_SOCKS5_PROXY, not build-time NEXT_PUBLIC (#3508) (#3579)

Integrated into release/v3.8.20

* fix(playground): filter playground models by node prefix so custom-endpoint models appear (#3505) (#3581)

Integrated into release/v3.8.20

* fix(usage): show an informative message instead of a blank Kiro quota card when no usage breakdown (#3506) (#3582)

Integrated into release/v3.8.20

* docs(changelog): add the #3506 Kiro quota entry (missed in #3582 due to a stale-base CHANGELOG anchor) (#3583)

Integrated into release/v3.8.20

* fix(auto-update): use stable PROJECT_ROOT walker, not frozen process.cwd() (#3561)

Integrated into release/v3.8.20. Auto-update PROJECT_ROOT now uses a stable __dirname-anchored upward walker instead of the no-op process.cwd() resolver.

* fix: address PR #3518 review comments (lifecycle hooks, regex, indentation, route params) (#3562)

Integrated into release/v3.8.20. Addresses #3518 review: regex literals, logs/[id] route params (Next 16), indentation, and wires plugin lifecycle hooks (onInstall/onActivate/onDeactivate/onUninstall) in the loader so manager.ts can register them. Adds Rule #18 regression test.

* docs(changelog): credit @ViFigueiredo (#3423) for PROJECT_ROOT + log #3561/#3562 (v3.8.20)

* fix: openai to gemini incorrectly translates historical tool calls into text (#3569)

Integrated into release/v3.8.20. Standard Gemini direct path now maps historical tool calls to native functionCall/functionResponse parts (signaturelessToolCallMode: native) instead of inert text — validated against the real Gemini API (gemini-2.5-flash returns 200 for signatureless native functionCall, even with tools+thinking; Hard Rule #18). Eliminates the text-serialization leak. Antigravity/CLI sentinel path (#3560) untouched.

* docs(changelog)+test: reconcile standard-Gemini native mode (#3569) — update round-2 rationale comment + log VPS validation

* docs(changelog): reconcile v3.8.20 — add 9 missing bullets + move [Unreleased] to versioned section

* docs(changelog): complete v3.8.20 reconciliation — 27 bullets, 11 contributors

---------

Co-authored-by: Alexander Averyanov <alex@averyan.ru>
Co-authored-by: Hakan Kurşun <bykamaka@gmail.com>
Co-authored-by: Wilson <pedbookmed@gmail.com>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Giorgos Giakoumettis <giorgos@yiakoumettis.gr>
Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Markus Hartung <mail@hartmark.se>
rafacpti23 pushed a commit to rafacpti23/OmniRoute that referenced this pull request Jun 10, 2026
* chore(release): open v3.8.20 development cycle

* fix(images): prefer bare combos over image aliases (diegosouzapw#3527)

Integrated into release/v3.8.20

* fix(translator): map Codex local_shell tool (diegosouzapw#3534)

Integrated into release/v3.8.20

* fix(usage): make opencode-go quota fetcher fail-open instead of throwing 500 (diegosouzapw#3522)

Integrated into release/v3.8.20

* Fix Runtime page breaker state rendering (diegosouzapw#3533)

Integrated into release/v3.8.20

* Expose provider breaker degradation threshold setting (diegosouzapw#3535)

Integrated into release/v3.8.20

* fix(executor): strip provider prefix from versioned built-in tool model field (diegosouzapw#3532)

Integrated into release/v3.8.20

* feat(providers): add Claude Fable 5 support (diegosouzapw#3524)

Integrated into release/v3.8.20

* feat(resilience): add global provider cooldown tracking to prevent combo re-walking (diegosouzapw#3556)

Integrated into release/v3.8.20 (default OFF, opt-in)

* fix(translator): scope thoughtSignature bypass to Antigravity/CLI only (diegosouzapw#3560)

Integrated into release/v3.8.20. Co-authored-by: Six7Day <six7day@gmail.com>

* fix(routing): normalize thinking:disabled for combo-substituted models that reject it (diegosouzapw#3554) (diegosouzapw#3563)

Integrated into release/v3.8.20

* fix(usage): accept 0/empty budget limits so the dashboard can save and clear (diegosouzapw#3537) (diegosouzapw#3564)

Integrated into release/v3.8.20

* docs(changelog): credit @Six7Day for diegosouzapw#3560 thoughtSignature fix (diegosouzapw#3414)

The diegosouzapw#3560 squash co-author trailer landed inline (unparsed by GitHub), so add
an explicit CHANGELOG credit ensuring @Six7Day (original diegosouzapw#3414) and @oyi77 are
on the public record for the Gemini thoughtSignature fix.

* fix(gamification): dedup badge unlock via user_badges so events don't re-fire every request (diegosouzapw#3472) (diegosouzapw#3565)

Integrated into release/v3.8.20

* fix(routing): pass through 'auto' keyword on codex /v1/responses instead of rewriting to codex/auto (diegosouzapw#3509) (diegosouzapw#3566)

Integrated into release/v3.8.20

* fix(cli-tools): normalize apiKey null in guide-settings schema so cloud-mode config saves (diegosouzapw#3552) (diegosouzapw#3567)

Integrated into release/v3.8.20

* fix(catalog): reclassify PublicAI from keyless to one-time-initial (requires API key) (diegosouzapw#3558) (diegosouzapw#3568)

Integrated into release/v3.8.20

* fix(gemini-web): surface missing Playwright browser as actionable 503 + cooldown hint, not a retryable 500 loop (diegosouzapw#3516) (diegosouzapw#3570)

Integrated into release/v3.8.20

* fix(security): sanitize raw err.message in web executors + embeddings/search response bodies (Rule diegosouzapw#12) (diegosouzapw#3494, diegosouzapw#3495) (diegosouzapw#3573)

Integrated into release/v3.8.20

* fix(dashboard): point CustomHostsManager + FeatureFlagsGrid at real routes (diegosouzapw#3486, diegosouzapw#3487) (diegosouzapw#3574)

Integrated into release/v3.8.20

* chore(providers): remove dead krutrim entry (diegosouzapw#3483) + docs(api): fix agent-bridge per-agent state route (diegosouzapw#3489) (diegosouzapw#3575)

Integrated into release/v3.8.20

* docs(api): correct API_REFERENCE.md paths for skills/plugins/admin/cache/acp/system-info (diegosouzapw#3497) (diegosouzapw#3577)

Integrated into release/v3.8.20

* fix(proxy): drive SOCKS5 UI option from runtime ENABLE_SOCKS5_PROXY, not build-time NEXT_PUBLIC (diegosouzapw#3508) (diegosouzapw#3579)

Integrated into release/v3.8.20

* fix(playground): filter playground models by node prefix so custom-endpoint models appear (diegosouzapw#3505) (diegosouzapw#3581)

Integrated into release/v3.8.20

* fix(usage): show an informative message instead of a blank Kiro quota card when no usage breakdown (diegosouzapw#3506) (diegosouzapw#3582)

Integrated into release/v3.8.20

* docs(changelog): add the diegosouzapw#3506 Kiro quota entry (missed in diegosouzapw#3582 due to a stale-base CHANGELOG anchor) (diegosouzapw#3583)

Integrated into release/v3.8.20

* fix(auto-update): use stable PROJECT_ROOT walker, not frozen process.cwd() (diegosouzapw#3561)

Integrated into release/v3.8.20. Auto-update PROJECT_ROOT now uses a stable __dirname-anchored upward walker instead of the no-op process.cwd() resolver.

* fix: address PR diegosouzapw#3518 review comments (lifecycle hooks, regex, indentation, route params) (diegosouzapw#3562)

Integrated into release/v3.8.20. Addresses diegosouzapw#3518 review: regex literals, logs/[id] route params (Next 16), indentation, and wires plugin lifecycle hooks (onInstall/onActivate/onDeactivate/onUninstall) in the loader so manager.ts can register them. Adds Rule diegosouzapw#18 regression test.

* docs(changelog): credit @ViFigueiredo (diegosouzapw#3423) for PROJECT_ROOT + log diegosouzapw#3561/diegosouzapw#3562 (v3.8.20)

* fix: openai to gemini incorrectly translates historical tool calls into text (diegosouzapw#3569)

Integrated into release/v3.8.20. Standard Gemini direct path now maps historical tool calls to native functionCall/functionResponse parts (signaturelessToolCallMode: native) instead of inert text — validated against the real Gemini API (gemini-2.5-flash returns 200 for signatureless native functionCall, even with tools+thinking; Hard Rule diegosouzapw#18). Eliminates the text-serialization leak. Antigravity/CLI sentinel path (diegosouzapw#3560) untouched.

* docs(changelog)+test: reconcile standard-Gemini native mode (diegosouzapw#3569) — update round-2 rationale comment + log VPS validation

* docs(changelog): reconcile v3.8.20 — add 9 missing bullets + move [Unreleased] to versioned section

* docs(changelog): complete v3.8.20 reconciliation — 27 bullets, 11 contributors

---------

Co-authored-by: Alexander Averyanov <alex@averyan.ru>
Co-authored-by: Hakan Kurşun <bykamaka@gmail.com>
Co-authored-by: Wilson <pedbookmed@gmail.com>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Giorgos Giakoumettis <giorgos@yiakoumettis.gr>
Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Markus Hartung <mail@hartmark.se>
@rdself
rdself deleted the coder/fix-runtime-internal-server-error branch June 24, 2026 03:25
HouMinXi pushed a commit to HouMinXi/OmniRoute that referenced this pull request Aug 2, 2026
* chore(release): open v3.8.20 development cycle

* fix(images): prefer bare combos over image aliases (diegosouzapw#3527)

Integrated into release/v3.8.20

* fix(translator): map Codex local_shell tool (diegosouzapw#3534)

Integrated into release/v3.8.20

* fix(usage): make opencode-go quota fetcher fail-open instead of throwing 500 (diegosouzapw#3522)

Integrated into release/v3.8.20

* Fix Runtime page breaker state rendering (diegosouzapw#3533)

Integrated into release/v3.8.20

* Expose provider breaker degradation threshold setting (diegosouzapw#3535)

Integrated into release/v3.8.20

* fix(executor): strip provider prefix from versioned built-in tool model field (diegosouzapw#3532)

Integrated into release/v3.8.20

* feat(providers): add Claude Fable 5 support (diegosouzapw#3524)

Integrated into release/v3.8.20

* feat(resilience): add global provider cooldown tracking to prevent combo re-walking (diegosouzapw#3556)

Integrated into release/v3.8.20 (default OFF, opt-in)

* fix(translator): scope thoughtSignature bypass to Antigravity/CLI only (diegosouzapw#3560)

Integrated into release/v3.8.20. Co-authored-by: Six7Day <six7day@gmail.com>

* fix(routing): normalize thinking:disabled for combo-substituted models that reject it (diegosouzapw#3554) (diegosouzapw#3563)

Integrated into release/v3.8.20

* fix(usage): accept 0/empty budget limits so the dashboard can save and clear (diegosouzapw#3537) (diegosouzapw#3564)

Integrated into release/v3.8.20

* docs(changelog): credit @Six7Day for diegosouzapw#3560 thoughtSignature fix (diegosouzapw#3414)

The diegosouzapw#3560 squash co-author trailer landed inline (unparsed by GitHub), so add
an explicit CHANGELOG credit ensuring @Six7Day (original diegosouzapw#3414) and @oyi77 are
on the public record for the Gemini thoughtSignature fix.

* fix(gamification): dedup badge unlock via user_badges so events don't re-fire every request (diegosouzapw#3472) (diegosouzapw#3565)

Integrated into release/v3.8.20

* fix(routing): pass through 'auto' keyword on codex /v1/responses instead of rewriting to codex/auto (diegosouzapw#3509) (diegosouzapw#3566)

Integrated into release/v3.8.20

* fix(cli-tools): normalize apiKey null in guide-settings schema so cloud-mode config saves (diegosouzapw#3552) (diegosouzapw#3567)

Integrated into release/v3.8.20

* fix(catalog): reclassify PublicAI from keyless to one-time-initial (requires API key) (diegosouzapw#3558) (diegosouzapw#3568)

Integrated into release/v3.8.20

* fix(gemini-web): surface missing Playwright browser as actionable 503 + cooldown hint, not a retryable 500 loop (diegosouzapw#3516) (diegosouzapw#3570)

Integrated into release/v3.8.20

* fix(security): sanitize raw err.message in web executors + embeddings/search response bodies (Rule diegosouzapw#12) (diegosouzapw#3494, diegosouzapw#3495) (diegosouzapw#3573)

Integrated into release/v3.8.20

* fix(dashboard): point CustomHostsManager + FeatureFlagsGrid at real routes (diegosouzapw#3486, diegosouzapw#3487) (diegosouzapw#3574)

Integrated into release/v3.8.20

* chore(providers): remove dead krutrim entry (diegosouzapw#3483) + docs(api): fix agent-bridge per-agent state route (diegosouzapw#3489) (diegosouzapw#3575)

Integrated into release/v3.8.20

* docs(api): correct API_REFERENCE.md paths for skills/plugins/admin/cache/acp/system-info (diegosouzapw#3497) (diegosouzapw#3577)

Integrated into release/v3.8.20

* fix(proxy): drive SOCKS5 UI option from runtime ENABLE_SOCKS5_PROXY, not build-time NEXT_PUBLIC (diegosouzapw#3508) (diegosouzapw#3579)

Integrated into release/v3.8.20

* fix(playground): filter playground models by node prefix so custom-endpoint models appear (diegosouzapw#3505) (diegosouzapw#3581)

Integrated into release/v3.8.20

* fix(usage): show an informative message instead of a blank Kiro quota card when no usage breakdown (diegosouzapw#3506) (diegosouzapw#3582)

Integrated into release/v3.8.20

* docs(changelog): add the diegosouzapw#3506 Kiro quota entry (missed in diegosouzapw#3582 due to a stale-base CHANGELOG anchor) (diegosouzapw#3583)

Integrated into release/v3.8.20

* fix(auto-update): use stable PROJECT_ROOT walker, not frozen process.cwd() (diegosouzapw#3561)

Integrated into release/v3.8.20. Auto-update PROJECT_ROOT now uses a stable __dirname-anchored upward walker instead of the no-op process.cwd() resolver.

* fix: address PR diegosouzapw#3518 review comments (lifecycle hooks, regex, indentation, route params) (diegosouzapw#3562)

Integrated into release/v3.8.20. Addresses diegosouzapw#3518 review: regex literals, logs/[id] route params (Next 16), indentation, and wires plugin lifecycle hooks (onInstall/onActivate/onDeactivate/onUninstall) in the loader so manager.ts can register them. Adds Rule diegosouzapw#18 regression test.

* docs(changelog): credit @ViFigueiredo (diegosouzapw#3423) for PROJECT_ROOT + log diegosouzapw#3561/diegosouzapw#3562 (v3.8.20)

* fix: openai to gemini incorrectly translates historical tool calls into text (diegosouzapw#3569)

Integrated into release/v3.8.20. Standard Gemini direct path now maps historical tool calls to native functionCall/functionResponse parts (signaturelessToolCallMode: native) instead of inert text — validated against the real Gemini API (gemini-2.5-flash returns 200 for signatureless native functionCall, even with tools+thinking; Hard Rule diegosouzapw#18). Eliminates the text-serialization leak. Antigravity/CLI sentinel path (diegosouzapw#3560) untouched.

* docs(changelog)+test: reconcile standard-Gemini native mode (diegosouzapw#3569) — update round-2 rationale comment + log VPS validation

* docs(changelog): reconcile v3.8.20 — add 9 missing bullets + move [Unreleased] to versioned section

* docs(changelog): complete v3.8.20 reconciliation — 27 bullets, 11 contributors

---------

Co-authored-by: Alexander Averyanov <alex@averyan.ru>
Co-authored-by: Hakan Kurşun <bykamaka@gmail.com>
Co-authored-by: Wilson <pedbookmed@gmail.com>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Giorgos Giakoumettis <giorgos@yiakoumettis.gr>
Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Markus Hartung <mail@hartmark.se>
Poid-ZA pushed a commit to Poid-ZA/OmniRoute that referenced this pull request Aug 5, 2026
* chore(release): open v3.8.20 development cycle

* fix(images): prefer bare combos over image aliases (diegosouzapw#3527)

Integrated into release/v3.8.20

* fix(translator): map Codex local_shell tool (diegosouzapw#3534)

Integrated into release/v3.8.20

* fix(usage): make opencode-go quota fetcher fail-open instead of throwing 500 (diegosouzapw#3522)

Integrated into release/v3.8.20

* Fix Runtime page breaker state rendering (diegosouzapw#3533)

Integrated into release/v3.8.20

* Expose provider breaker degradation threshold setting (diegosouzapw#3535)

Integrated into release/v3.8.20

* fix(executor): strip provider prefix from versioned built-in tool model field (diegosouzapw#3532)

Integrated into release/v3.8.20

* feat(providers): add Claude Fable 5 support (diegosouzapw#3524)

Integrated into release/v3.8.20

* feat(resilience): add global provider cooldown tracking to prevent combo re-walking (diegosouzapw#3556)

Integrated into release/v3.8.20 (default OFF, opt-in)

* fix(translator): scope thoughtSignature bypass to Antigravity/CLI only (diegosouzapw#3560)

Integrated into release/v3.8.20. Co-authored-by: Six7Day <six7day@gmail.com>

* fix(routing): normalize thinking:disabled for combo-substituted models that reject it (diegosouzapw#3554) (diegosouzapw#3563)

Integrated into release/v3.8.20

* fix(usage): accept 0/empty budget limits so the dashboard can save and clear (diegosouzapw#3537) (diegosouzapw#3564)

Integrated into release/v3.8.20

* docs(changelog): credit @Six7Day for diegosouzapw#3560 thoughtSignature fix (diegosouzapw#3414)

The diegosouzapw#3560 squash co-author trailer landed inline (unparsed by GitHub), so add
an explicit CHANGELOG credit ensuring @Six7Day (original diegosouzapw#3414) and @oyi77 are
on the public record for the Gemini thoughtSignature fix.

* fix(gamification): dedup badge unlock via user_badges so events don't re-fire every request (diegosouzapw#3472) (diegosouzapw#3565)

Integrated into release/v3.8.20

* fix(routing): pass through 'auto' keyword on codex /v1/responses instead of rewriting to codex/auto (diegosouzapw#3509) (diegosouzapw#3566)

Integrated into release/v3.8.20

* fix(cli-tools): normalize apiKey null in guide-settings schema so cloud-mode config saves (diegosouzapw#3552) (diegosouzapw#3567)

Integrated into release/v3.8.20

* fix(catalog): reclassify PublicAI from keyless to one-time-initial (requires API key) (diegosouzapw#3558) (diegosouzapw#3568)

Integrated into release/v3.8.20

* fix(gemini-web): surface missing Playwright browser as actionable 503 + cooldown hint, not a retryable 500 loop (diegosouzapw#3516) (diegosouzapw#3570)

Integrated into release/v3.8.20

* fix(security): sanitize raw err.message in web executors + embeddings/search response bodies (Rule diegosouzapw#12) (diegosouzapw#3494, diegosouzapw#3495) (diegosouzapw#3573)

Integrated into release/v3.8.20

* fix(dashboard): point CustomHostsManager + FeatureFlagsGrid at real routes (diegosouzapw#3486, diegosouzapw#3487) (diegosouzapw#3574)

Integrated into release/v3.8.20

* chore(providers): remove dead krutrim entry (diegosouzapw#3483) + docs(api): fix agent-bridge per-agent state route (diegosouzapw#3489) (diegosouzapw#3575)

Integrated into release/v3.8.20

* docs(api): correct API_REFERENCE.md paths for skills/plugins/admin/cache/acp/system-info (diegosouzapw#3497) (diegosouzapw#3577)

Integrated into release/v3.8.20

* fix(proxy): drive SOCKS5 UI option from runtime ENABLE_SOCKS5_PROXY, not build-time NEXT_PUBLIC (diegosouzapw#3508) (diegosouzapw#3579)

Integrated into release/v3.8.20

* fix(playground): filter playground models by node prefix so custom-endpoint models appear (diegosouzapw#3505) (diegosouzapw#3581)

Integrated into release/v3.8.20

* fix(usage): show an informative message instead of a blank Kiro quota card when no usage breakdown (diegosouzapw#3506) (diegosouzapw#3582)

Integrated into release/v3.8.20

* docs(changelog): add the diegosouzapw#3506 Kiro quota entry (missed in diegosouzapw#3582 due to a stale-base CHANGELOG anchor) (diegosouzapw#3583)

Integrated into release/v3.8.20

* fix(auto-update): use stable PROJECT_ROOT walker, not frozen process.cwd() (diegosouzapw#3561)

Integrated into release/v3.8.20. Auto-update PROJECT_ROOT now uses a stable __dirname-anchored upward walker instead of the no-op process.cwd() resolver.

* fix: address PR diegosouzapw#3518 review comments (lifecycle hooks, regex, indentation, route params) (diegosouzapw#3562)

Integrated into release/v3.8.20. Addresses diegosouzapw#3518 review: regex literals, logs/[id] route params (Next 16), indentation, and wires plugin lifecycle hooks (onInstall/onActivate/onDeactivate/onUninstall) in the loader so manager.ts can register them. Adds Rule diegosouzapw#18 regression test.

* docs(changelog): credit @ViFigueiredo (diegosouzapw#3423) for PROJECT_ROOT + log diegosouzapw#3561/diegosouzapw#3562 (v3.8.20)

* fix: openai to gemini incorrectly translates historical tool calls into text (diegosouzapw#3569)

Integrated into release/v3.8.20. Standard Gemini direct path now maps historical tool calls to native functionCall/functionResponse parts (signaturelessToolCallMode: native) instead of inert text — validated against the real Gemini API (gemini-2.5-flash returns 200 for signatureless native functionCall, even with tools+thinking; Hard Rule diegosouzapw#18). Eliminates the text-serialization leak. Antigravity/CLI sentinel path (diegosouzapw#3560) untouched.

* docs(changelog)+test: reconcile standard-Gemini native mode (diegosouzapw#3569) — update round-2 rationale comment + log VPS validation

* docs(changelog): reconcile v3.8.20 — add 9 missing bullets + move [Unreleased] to versioned section

* docs(changelog): complete v3.8.20 reconciliation — 27 bullets, 11 contributors

---------

Co-authored-by: Alexander Averyanov <alex@averyan.ru>
Co-authored-by: Hakan Kurşun <bykamaka@gmail.com>
Co-authored-by: Wilson <pedbookmed@gmail.com>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Giorgos Giakoumettis <giorgos@yiakoumettis.gr>
Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Markus Hartung <mail@hartmark.se>
tkgo11 pushed a commit to tkgo11/OmniRoute that referenced this pull request Sep 23, 2026
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
* chore(release): open v3.8.20 development cycle

* fix(images): prefer bare combos over image aliases (diegosouzapw#3527)

Integrated into release/v3.8.20

* fix(translator): map Codex local_shell tool (diegosouzapw#3534)

Integrated into release/v3.8.20

* fix(usage): make opencode-go quota fetcher fail-open instead of throwing 500 (diegosouzapw#3522)

Integrated into release/v3.8.20

* Fix Runtime page breaker state rendering (diegosouzapw#3533)

Integrated into release/v3.8.20

* Expose provider breaker degradation threshold setting (diegosouzapw#3535)

Integrated into release/v3.8.20

* fix(executor): strip provider prefix from versioned built-in tool model field (diegosouzapw#3532)

Integrated into release/v3.8.20

* feat(providers): add Claude Fable 5 support (diegosouzapw#3524)

Integrated into release/v3.8.20

* feat(resilience): add global provider cooldown tracking to prevent combo re-walking (diegosouzapw#3556)

Integrated into release/v3.8.20 (default OFF, opt-in)

* fix(translator): scope thoughtSignature bypass to Antigravity/CLI only (diegosouzapw#3560)

Integrated into release/v3.8.20. Co-authored-by: Six7Day <six7day@gmail.com>

* fix(routing): normalize thinking:disabled for combo-substituted models that reject it (diegosouzapw#3554) (diegosouzapw#3563)

Integrated into release/v3.8.20

* fix(usage): accept 0/empty budget limits so the dashboard can save and clear (diegosouzapw#3537) (diegosouzapw#3564)

Integrated into release/v3.8.20

* docs(changelog): credit @Six7Day for diegosouzapw#3560 thoughtSignature fix (diegosouzapw#3414)

The diegosouzapw#3560 squash co-author trailer landed inline (unparsed by GitHub), so add
an explicit CHANGELOG credit ensuring @Six7Day (original diegosouzapw#3414) and @oyi77 are
on the public record for the Gemini thoughtSignature fix.

* fix(gamification): dedup badge unlock via user_badges so events don't re-fire every request (diegosouzapw#3472) (diegosouzapw#3565)

Integrated into release/v3.8.20

* fix(routing): pass through 'auto' keyword on codex /v1/responses instead of rewriting to codex/auto (diegosouzapw#3509) (diegosouzapw#3566)

Integrated into release/v3.8.20

* fix(cli-tools): normalize apiKey null in guide-settings schema so cloud-mode config saves (diegosouzapw#3552) (diegosouzapw#3567)

Integrated into release/v3.8.20

* fix(catalog): reclassify PublicAI from keyless to one-time-initial (requires API key) (diegosouzapw#3558) (diegosouzapw#3568)

Integrated into release/v3.8.20

* fix(gemini-web): surface missing Playwright browser as actionable 503 + cooldown hint, not a retryable 500 loop (diegosouzapw#3516) (diegosouzapw#3570)

Integrated into release/v3.8.20

* fix(security): sanitize raw err.message in web executors + embeddings/search response bodies (Rule diegosouzapw#12) (diegosouzapw#3494, diegosouzapw#3495) (diegosouzapw#3573)

Integrated into release/v3.8.20

* fix(dashboard): point CustomHostsManager + FeatureFlagsGrid at real routes (diegosouzapw#3486, diegosouzapw#3487) (diegosouzapw#3574)

Integrated into release/v3.8.20

* chore(providers): remove dead krutrim entry (diegosouzapw#3483) + docs(api): fix agent-bridge per-agent state route (diegosouzapw#3489) (diegosouzapw#3575)

Integrated into release/v3.8.20

* docs(api): correct API_REFERENCE.md paths for skills/plugins/admin/cache/acp/system-info (diegosouzapw#3497) (diegosouzapw#3577)

Integrated into release/v3.8.20

* fix(proxy): drive SOCKS5 UI option from runtime ENABLE_SOCKS5_PROXY, not build-time NEXT_PUBLIC (diegosouzapw#3508) (diegosouzapw#3579)

Integrated into release/v3.8.20

* fix(playground): filter playground models by node prefix so custom-endpoint models appear (diegosouzapw#3505) (diegosouzapw#3581)

Integrated into release/v3.8.20

* fix(usage): show an informative message instead of a blank Kiro quota card when no usage breakdown (diegosouzapw#3506) (diegosouzapw#3582)

Integrated into release/v3.8.20

* docs(changelog): add the diegosouzapw#3506 Kiro quota entry (missed in diegosouzapw#3582 due to a stale-base CHANGELOG anchor) (diegosouzapw#3583)

Integrated into release/v3.8.20

* fix(auto-update): use stable PROJECT_ROOT walker, not frozen process.cwd() (diegosouzapw#3561)

Integrated into release/v3.8.20. Auto-update PROJECT_ROOT now uses a stable __dirname-anchored upward walker instead of the no-op process.cwd() resolver.

* fix: address PR diegosouzapw#3518 review comments (lifecycle hooks, regex, indentation, route params) (diegosouzapw#3562)

Integrated into release/v3.8.20. Addresses diegosouzapw#3518 review: regex literals, logs/[id] route params (Next 16), indentation, and wires plugin lifecycle hooks (onInstall/onActivate/onDeactivate/onUninstall) in the loader so manager.ts can register them. Adds Rule diegosouzapw#18 regression test.

* docs(changelog): credit @ViFigueiredo (diegosouzapw#3423) for PROJECT_ROOT + log diegosouzapw#3561/diegosouzapw#3562 (v3.8.20)

* fix: openai to gemini incorrectly translates historical tool calls into text (diegosouzapw#3569)

Integrated into release/v3.8.20. Standard Gemini direct path now maps historical tool calls to native functionCall/functionResponse parts (signaturelessToolCallMode: native) instead of inert text — validated against the real Gemini API (gemini-2.5-flash returns 200 for signatureless native functionCall, even with tools+thinking; Hard Rule diegosouzapw#18). Eliminates the text-serialization leak. Antigravity/CLI sentinel path (diegosouzapw#3560) untouched.

* docs(changelog)+test: reconcile standard-Gemini native mode (diegosouzapw#3569) — update round-2 rationale comment + log VPS validation

* docs(changelog): reconcile v3.8.20 — add 9 missing bullets + move [Unreleased] to versioned section

* docs(changelog): complete v3.8.20 reconciliation — 27 bullets, 11 contributors

---------

Co-authored-by: Alexander Averyanov <alex@averyan.ru>
Co-authored-by: Hakan Kurşun <bykamaka@gmail.com>
Co-authored-by: Wilson <pedbookmed@gmail.com>
Co-authored-by: Randi <55005611+rdself@users.noreply.github.com>
Co-authored-by: Giorgos Giakoumettis <giorgos@yiakoumettis.gr>
Co-authored-by: PizzaV <103120356+pizzav-xyz@users.noreply.github.com>
Co-authored-by: Paijo <14921983+oyi77@users.noreply.github.com>
Co-authored-by: Markus Hartung <mail@hartmark.se>
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.

3 participants