mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-14 03:02:14 +03:00
48124fca5a811b9fa54fdd54858e2dca694dd476
6747 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
48124fca5a |
fix(zed-hosted): send the provider wire values cloud.zed.dev accepts (#10051)
Every zed-hosted completion failed with
500 {"error":{"message":"[500]: An internal server error occurred."}}
for every model id, including deliberately invalid ones.
Root cause: ZED_PROVIDER held display-cased names ("Anthropic", "OpenAi",
"Google", "XAi"), and normalizeZedProvider's return value is serialized
straight into the `provider` field of the POST /completions envelope. Zed
matches that field exactly and fails the request before looking at the model,
which is why the model id never mattered.
Verified live against cloud.zed.dev with an otherwise identical request:
{"provider":"anthropic",...} -> 200
{"provider":"Anthropic",...} -> 500 {"message":"An internal server error occurred."}
{"provider":"open_ai",...} -> reaches the OpenAI request parser
{"provider":"openai",...} -> 500 (same internal error)
The spellings now follow Zed's own GET /models catalog, which reports
`anthropic`, `open_ai` and `google`. That also makes normalizeZedProvider
identity on catalog values instead of corrupting a value Zed just supplied —
previously it accepted the correct lowercase input and re-cased it into the
form that 500s.
`x_ai` follows the same underscore convention; this account's catalog exposes
no xAI models, so that one spelling is by convention rather than observation.
The constant is module-local and every branch compares against it, so internal
dispatch (initProviderState / convertProviderEvent / buildProviderRequest) is
unaffected. Two existing tests asserted the display-cased values and one passed
"Anthropic" to wrapZedCompletionStream directly; all are updated to the wire
values the executor now produces.
Co-authored-by: root <root@srv1710948.hstgr.cloud>
|
||
|
|
397ec88751 |
fix(ci): repair and wire the two live-server E2E suites (#10050)
tests/e2e/ecosystem.test.ts and tests/e2e/protocol-clients.test.ts appear in the AGENTS.md test matrix but ran in no workflow, and could not run at all: both are listed in vitest.config.ts include AND exclude, and their runners invoked Vitest without --config, so the default config's exclusion discarded the very file each passed as a positional filter. No test files found, exiting with code 1 filter: tests/e2e/ecosystem.test.ts Add vitest.e2e-live.config.ts covering only these two suites, point both runners at it, and drop the contradictory include entries. The exclusions stay: these drive a real server and must never run in the jsdom UI job. Wire both into CI. test-ecosystem is blocking (20/20 green). test-protocols-e2e is advisory pending #10049 — restoring it surfaced a pre-existing discrepancy where GET /api/mcp/audit answers 403 over loopback against an expected 200|401. |
||
|
|
7f2d75d6d5 |
feat(open-sse): expose provider-level circuit breaker thresholds via env vars (#10040) (#10046)
The provider-level breaker fields in PROVIDER_PROFILES (providerFailureThreshold, providerFailureWindowMs, providerCooldownMs, degradationThreshold, maxBackoffMultiplier, backoffEscalationCount) are now env-overridable via OMNIROUTE_PROVIDER_BREAKER_<CATEGORY>_<FIELD> variables, with the historical hardcoded defaults preserved when unset. This makes the provider-level fuse (the entire-provider cooldown applied after repeated upstream failures) tunable from the deployment surface, matching the existing per-key circuit breaker knobs. Operators can now raise thresholds to tolerate transient upstream sheds without blacklisting the provider, or lower them to fail over faster on premium routes — without rebuilding from source. Closes #10040 Category-by-category field map (defaults preserved): - oauth: FAILURE_THRESHOLD=10, FAILURE_WINDOW_MS=900000, COOLDOWN_MS=300000, DEGRADATION_THRESHOLD=5, MAX_BACKOFF_MULTIPLIER=8, BACKOFF_ESCALATION_COUNT=2 - apikey: [REDACTED:auth_header], FAILURE_WINDOW_MS=1800000, COOLDOWN_MS=600000, DEGRADATION_THRESHOLD=7, MAX_BACKOFF_MULTIPLIER=4, BACKOFF_ESCALATION_COUNT=3 - local: FAILURE_THRESHOLD=2, FAILURE_WINDOW_MS=300000, COOLDOWN_MS=60000 (local category omits the adaptive v2 fields) Docs: - .env.example — 15 new commented entries grouped under a "Provider-level circuit breaker thresholds and cooldowns" section. - docs/reference/ENVIRONMENT.md — 15 new rows documenting the provider-level breaker surface. Tests: - tests/unit/provider-breaker-env-overrides.test.ts — 4 cases: 1. Every new env var is wired in constants.ts via envInt(). 2. Every new env var is documented in ENVIRONMENT.md. 3. Every new env var is listed in .env.example. 4. The historical defaults are preserved as the envInt fallback. Behavior tests (loading the actual module with controlled env vars) are left to upstream CI; the static source-shape test is sufficient here because the envInt() helper is a plain function whose only dependency is process.env at module load time. Co-authored-by: Tiangao (hermes) <montigaud@aikumi.pro> |
||
|
|
1a8d38655d | fix(reasoning): preserve and replay assistant turns (#10045) | ||
|
|
7366bb6c3a | fix(types): tighten chatCore helper contracts (#10175) | ||
|
|
c481ee3312 |
deps: bump the development group across 1 directory with 22 updates (#10043)
Bumps the development group with 22 updates in the / directory: | Package | From | To | | --- | --- | --- | | [@playwright/test](https://github.com/microsoft/playwright) | `1.61.1` | `1.62.1` | | [@size-limit/file](https://github.com/ai/size-limit) | `12.1.0` | `13.0.3` | | [@testing-library/jest-dom](https://github.com/testing-library/jest-dom) | `6.9.1` | `7.0.0` | | [@types/better-sqlite3](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/better-sqlite3) | `7.6.13` | `9.6.0` | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `26.1.1` | `26.2.0` | | [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) | `19.2.17` | `19.2.18` | | [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom) | `19.2.3` | `19.2.4` | | [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/tree/HEAD/packages/plugin-react) | `6.0.3` | `6.0.5` | | [concurrently](https://github.com/open-cli-tools/concurrently) | `10.0.3` | `10.0.4` | | [dpdm](https://github.com/acrazing/dpdm) | `4.2.0` | `4.3.0` | | [eslint-config-next](https://github.com/vercel/next.js/tree/HEAD/packages/eslint-config-next) | `16.2.10` | `16.3.0` | | [fumadocs-mdx](https://github.com/fuma-nama/fumadocs) | `15.2.0` | `15.2.2` | | [jsdom](https://github.com/jsdom/jsdom) | `29.1.1` | `30.0.1` | | [knip](https://github.com/webpro-nl/knip/tree/HEAD/packages/knip) | `6.27.0` | `6.32.0` | | [lint-staged](https://github.com/lint-staged/lint-staged) | `17.1.0` | `17.3.0` | | [opencode-ai](https://github.com/anomalyco/opencode) | `1.18.8` | `1.18.15` | | [prettier](https://github.com/prettier/prettier) | `3.9.5` | `3.9.6` | | [promptfoo](https://github.com/promptfoo/promptfoo) | `0.121.19` | `0.122.0` | | [size-limit](https://github.com/ai/size-limit) | `12.1.0` | `13.0.3` | | [type-coverage](https://github.com/plantain-00/type-coverage) | `2.29.7` | `2.30.1` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.65.0` | `8.66.0` | | [wait-on](https://github.com/jeffbski/wait-on) | `9.0.10` | `9.1.0` | Updates `@playwright/test` from 1.61.1 to 1.62.1 - [Release notes](https://github.com/microsoft/playwright/releases) - [Commits](https://github.com/microsoft/playwright/compare/v1.61.1...v1.62.1) Updates `@size-limit/file` from 12.1.0 to 13.0.3 - [Release notes](https://github.com/ai/size-limit/releases) - [Changelog](https://github.com/ai/size-limit/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/size-limit/compare/12.1.0...13.0.3) Updates `@testing-library/jest-dom` from 6.9.1 to 7.0.0 - [Release notes](https://github.com/testing-library/jest-dom/releases) - [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md) - [Commits](https://github.com/testing-library/jest-dom/compare/v6.9.1...v7.0.0) Updates `@types/better-sqlite3` from 7.6.13 to 9.6.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/better-sqlite3) Updates `@types/node` from 26.1.1 to 26.2.0 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node) Updates `@types/react` from 19.2.17 to 19.2.18 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Updates `@types/react-dom` from 19.2.3 to 19.2.4 - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom) Updates `@vitejs/plugin-react` from 6.0.3 to 6.0.5 - [Release notes](https://github.com/vitejs/vite-plugin-react/releases) - [Changelog](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite-plugin-react/commits/plugin-react@6.0.5/packages/plugin-react) Updates `concurrently` from 10.0.3 to 10.0.4 - [Release notes](https://github.com/open-cli-tools/concurrently/releases) - [Commits](https://github.com/open-cli-tools/concurrently/compare/v10.0.3...v10.0.4) Updates `dpdm` from 4.2.0 to 4.3.0 - [Release notes](https://github.com/acrazing/dpdm/releases) - [Commits](https://github.com/acrazing/dpdm/compare/v4.2.0...v4.3.0) Updates `eslint-config-next` from 16.2.10 to 16.3.0 - [Release notes](https://github.com/vercel/next.js/releases) - [Commits](https://github.com/vercel/next.js/commits/v16.3.0/packages/eslint-config-next) Updates `fumadocs-mdx` from 15.2.0 to 15.2.2 - [Release notes](https://github.com/fuma-nama/fumadocs/releases) - [Commits](https://github.com/fuma-nama/fumadocs/compare/fumadocs-mdx@15.2.0...fumadocs-mdx@15.2.2) Updates `jsdom` from 29.1.1 to 30.0.1 - [Release notes](https://github.com/jsdom/jsdom/releases) - [Commits](https://github.com/jsdom/jsdom/compare/v29.1.1...v30.0.1) Updates `knip` from 6.27.0 to 6.32.0 - [Release notes](https://github.com/webpro-nl/knip/releases) - [Commits](https://github.com/webpro-nl/knip/commits/knip@6.32.0/packages/knip) Updates `lint-staged` from 17.1.0 to 17.3.0 - [Release notes](https://github.com/lint-staged/lint-staged/releases) - [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md) - [Commits](https://github.com/lint-staged/lint-staged/compare/v17.1.0...v17.3.0) Updates `opencode-ai` from 1.18.8 to 1.18.15 - [Release notes](https://github.com/anomalyco/opencode/releases) - [Commits](https://github.com/anomalyco/opencode/compare/v1.18.8...v1.18.15) Updates `prettier` from 3.9.5 to 3.9.6 - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/3.9.5...3.9.6) Updates `promptfoo` from 0.121.19 to 0.122.0 - [Release notes](https://github.com/promptfoo/promptfoo/releases) - [Changelog](https://github.com/promptfoo/promptfoo/blob/main/CHANGELOG.md) - [Commits](https://github.com/promptfoo/promptfoo/compare/0.121.19...0.122.0) Updates `size-limit` from 12.1.0 to 13.0.3 - [Release notes](https://github.com/ai/size-limit/releases) - [Changelog](https://github.com/ai/size-limit/blob/main/CHANGELOG.md) - [Commits](https://github.com/ai/size-limit/compare/12.1.0...13.0.3) Updates `type-coverage` from 2.29.7 to 2.30.1 - [Changelog](https://github.com/plantain-00/type-coverage/blob/master/CHANGELOG.md) - [Commits](https://github.com/plantain-00/type-coverage/compare/v2.29.7...v2.30.1) Updates `typescript-eslint` from 8.65.0 to 8.66.0 - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.66.0/packages/typescript-eslint) Updates `wait-on` from 9.0.10 to 9.1.0 - [Release notes](https://github.com/jeffbski/wait-on/releases) - [Commits](https://github.com/jeffbski/wait-on/compare/v9.0.10...v9.1.0) --- updated-dependencies: - dependency-name: "@playwright/test" dependency-version: 1.62.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: "@size-limit/file" dependency-version: 13.0.3 dependency-type: direct:development update-type: version-update:semver-major dependency-group: development - dependency-name: "@testing-library/jest-dom" dependency-version: 7.0.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: development - dependency-name: "@types/better-sqlite3" dependency-version: 9.6.0 dependency-type: direct:development update-type: version-update:semver-major dependency-group: development - dependency-name: "@types/node" dependency-version: 26.2.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: "@types/react" dependency-version: 19.2.18 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: "@types/react-dom" dependency-version: 19.2.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: "@vitejs/plugin-react" dependency-version: 6.0.5 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: concurrently dependency-version: 10.0.4 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: dpdm dependency-version: 4.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: eslint-config-next dependency-version: 16.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: fumadocs-mdx dependency-version: 15.2.2 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: jsdom dependency-version: 30.0.1 dependency-type: direct:development update-type: version-update:semver-major dependency-group: development - dependency-name: knip dependency-version: 6.32.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: lint-staged dependency-version: 17.3.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: opencode-ai dependency-version: 1.18.15 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: prettier dependency-version: 3.9.6 dependency-type: direct:development update-type: version-update:semver-patch dependency-group: development - dependency-name: promptfoo dependency-version: 0.122.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: size-limit dependency-version: 13.0.3 dependency-type: direct:development update-type: version-update:semver-major dependency-group: development - dependency-name: type-coverage dependency-version: 2.30.1 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: typescript-eslint dependency-version: 8.66.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development - dependency-name: wait-on dependency-version: 9.1.0 dependency-type: direct:development update-type: version-update:semver-minor dependency-group: development ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
242cc5e797 |
deps: bump electron from 43.2.0 to 43.3.0 in /electron (#10042)
Bumps [electron](https://github.com/electron/electron) from 43.2.0 to 43.3.0. - [Release notes](https://github.com/electron/electron/releases) - [Commits](https://github.com/electron/electron/compare/v43.2.0...v43.3.0) --- updated-dependencies: - dependency-name: electron dependency-version: 43.3.0 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> |
||
|
|
d2dd39ea78 |
feat(dashboard): Kimi 15% first-top-up campaign — dedicated tracked link + discount-first banner copy (#10240)
Moonshot approved a 15% extra-credits offer for new users' first top-up, attached to a dedicated tracked link issued for OmniRoute (valid through 2026-09-30). The dashboard banner and the three README API platform placements now use that link, and the banner description leads with the discount in all 43 locales, keeping the commitment made when the offer was requested. The README CTA gains the 15% mention. A code comment marks the strings to revisit after 2026-09-30 if the offer is not renewed. Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
558412c9bb |
fix(cli): read the full provider catalog instead of the 6-entry fallback (#10097)
loadAvailableProviders() always returned COMMON_PROVIDERS, so 'omniroute keys
add <provider>' rejected ~290 of the ~296 catalog providers with 'Unknown
provider' and 'providers available' under-reported the catalog by ~98%. Two
independent causes, either sufficient on its own:
1. extractProviderBlocks() required 'typescript' at runtime, but it is only a
devDependency — absent from every published/global install. The require
failure was swallowed and the parse returned [].
2. The parser read src/shared/constants/providers.ts, which after the god-file
decomposition contains only re-exports plus an empty 'FREE_PROVIDERS = {}'.
Even with typescript present it yielded zero entries.
Replace the AST parse with a dependency-free, string/comment-aware brace walk
(these files are pure data literals) and walk src/shared/constants/providers/**
instead of the barrel. An explicit catalogPath / OMNIROUTE_PROVIDER_CATALOG_PATH
still wins, and the COMMON_PROVIDERS fallback still applies when no catalog is
present.
The walk is also hardened against an unbalanced literal (#10093): it recovers
the entries before the damage and terminates, instead of looping forever on a
reset regex lastIndex.
Closes #10080
|
||
|
|
3ee5c1b4ae |
fix(cli): stop swallowing non-2xx responses into benign-looking results (#10092)
Three commands turned a transport failure into something that reads as real state: - `keys add` aborted on any 4xx. `/api/v1/providers/keys` is not mounted on the shipped server, so a 404 stranded the user with "HTTP 404" while the SQLite fallback directly below it — which works — was unreachable whenever the server was up. New isRouteUnavailableStatus() (404/405/501) lets the caller fall through; genuine client errors (400/401/403/409/422/429) stay fatal. - `providers test-all` reported every OAuth connection as FAILED because getProviderApiKey() throws for non-apikey connections by design — and persisted that verdict to provider_connections.test_status, marking healthy OAuth providers broken. Those connections are now skipped. An "unsupported" probe result (no recipe in PROVIDER_TEST_CONFIGS) is likewise a CLI gap, not a provider failure, so it no longer overwrites a good test_status. - `combo list` printed "No combos configured" when /api/combos returned non-2xx, which is indistinguishable from genuine emptiness. It now reports the status and exits non-zero. Refs #10081 |
||
|
|
4a7e8ddc16 |
fix(cli): openapi endpoints/paths/validate accept the served catalog shape (#10091)
GET /api/openapi/spec answers with a compact catalog
({ info, servers, tags, endpoints[], schemas }) rather than an OpenAPI document,
while dist/docs/openapi.yaml is a real spec. The CLI only read spec.paths, so
against a live server 'openapi endpoints' and 'openapi paths' printed nothing
and 'openapi validate' reported 'missing openapi/swagger version field' — with
318 endpoints sitting in spec.endpoints.
Normalize both shapes through extractEndpoints()/extractPaths() and let
validateBasic() accept a catalog that carries endpoints[] instead of a version
field. Path Item members that are not operations (parameters, summary,
description, servers, $ref) are no longer emitted as fake operations.
Closes #10082
|
||
|
|
2c720f1fa7 |
fix(cli): doctor detects prebuilt better-sqlite3 binaries (#10090)
checkNativeBinary only probed the node-gyp layout (build/Release/better_sqlite3.node), which exists only when better-sqlite3 is compiled locally. Installs that resolve a prebuilt binary — the normal case for `npm i -g omniroute` — ship prebuilds/<platform>-<arch>.node instead, so the check never found a binary and warned "better-sqlite3 native binary was not found" on every such install, next to real warnings. Probe both layouts and report both in the failure details. prebuiltBinaryName() mirrors the prebuild-install lookup, including the linuxmusl- prefix for musl-based Linux. Closes #10083 |
||
|
|
8718d2b62f |
fix(providers): kilo-gateway authType should be optional, not apikey (#10086)
Probed live: /chat/completions answers HTTP 200 with no Authorization header (kilo-auto/free routed to stepfun/step-3.7-flash). A real key still raises limits, so this matches the ovhcloud/pollinations pattern of authType: "optional" rather than "apikey". Fixes #10068 |
||
|
|
92a27f268a |
fix(cli): strip inline comments when parsing .env values (#10101)
loadEnvFile() took everything after the first '=', so 'KEY=value # note' stored the comment text as part of the value. The shipped .env/.env.example do exactly that for QUOTA_STORE_DRIVER, so every install ran with QUOTA_STORE_DRIVER='sqlite # sqlite | redis'. Consumers compare with '===' (storeFactory.ts), so a user following the annotation in .env.example and writing 'QUOTA_STORE_DRIVER=redis # ...' got driver !== 'redis', fell through to SQLite, and saw no warning — the existing 'no Redis URL configured' warning is inside the redis branch and never fires. parseEnvValue() adopts dotenv semantics: quoted values verbatim (a '#' inside quotes is data), unquoted values cut at the first whitespace-preceded '#', so 'pass#word' survives. .env.example moves the annotation to its own line. Closes #10100 |
||
|
|
d925f6bf73 |
fix(logging): document CHAT_LOG_MAX_BODY_KB, capture messageCount for Responses API bodies (#10038)
* fix(logging): document CHAT_LOG_MAX_BODY_KB, capture messageCount for Responses API bodies Extracted from PR #9439 (agentic conversation tracking). Most of the original scope this commit was cherry-picked from (CHAT_LOG_MAX_BODY_KB env var support, the estimateSizeFast() earlyExitAt parameterization) turned out to already be present on the current upstream/release/v3.8.50 tip -- confirmed via diff and by running check-env-doc-sync.test.ts / tests/unit/chatcore-log-truncation.test.ts against pristine upstream before making any changes here. Only two genuine gaps remained: 1. CHAT_LOG_MAX_BODY_KB was read by getChatLogMaxBodyBytes() but undocumented in .env.example and docs/reference/ENVIRONMENT.md -- tests/unit/check-env-doc-sync.test.ts flags any env var read in code but missing from both doc files. Documented it (both required -- the same test enforces the pairing). 2. truncateForLog()'s summary only computed messageCount from obj.messages (OpenAI-chat/Gemini field name) -- a large /v1/responses request (which uses input[], not messages[]) got summarized with no count at all, leaving the dashboard's "Full Conversation" panel nothing to base its "N messages not shown" placeholder on for any Responses-API conversation, even though the same summarization logic applies to it. Test plan: - TDD: tests/unit/chatcore-log-truncation.test.ts's new regression test ("captures a message count for Responses API bodies too") confirmed failing against the pre-fix code, passing after. - tests/unit/check-env-doc-sync.test.ts confirms CHAT_LOG_MAX_BODY_KB no longer appears in codeMissingEnv (remaining drift in that test is pre-existing/unrelated -- ANTIGRAVITY_ALLOW_SIGNATURE_BYPASS, COMMANDCODE_API_URL, OMNIROUTE_STRICT_SYSTEM_PROVIDERS, TLS_FINGERPRINT_PROVIDERS -- confirmed identical on a pristine upstream/release/v3.8.50 checkout, base-red inherited: #9985). - tests/unit/chatcore-log-truncation.test.ts -- 19/19 passing. - npx tsc --noEmit / npm run lint -- clean. ⚠️ base-red inherited: #9985 * docs(logging): consolidate CHAT_LOG_MAX_BODY_KB into a single entry per file The variable was already documented (with a stale src/lib/chatLogTruncation.ts reference in .env.example); keep the new richer entries next to the CHAT_LOG_* family and drop the old duplicates. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> |
||
|
|
2f264d96dc |
fix(dashboard): expose OpenAI Responses store toggle for non-Codex connections (#10121)
* fix(dashboard): expose OpenAI Responses store toggle for non-Codex connections
`EditConnectionModal` only rendered and saved the "OpenAI Responses store"
toggle (providerSpecificData.openaiStoreEnabled) inside the Codex-only
settings block, even though the backend policy that reads this flag
(open-sse/utils/responsesStatePolicy.ts::isOpenAIResponsesStoreEnabled,
applyResponsesPreviousResponseIdPolicy) is already fully provider-agnostic,
and the component already computes a generic `isResponsesConnection` flag
(provider === "openai" or any openai-compatible-responses-* connection, in
addition to codex) that the sibling `preserveEncryptedReasoning` toggle
already correctly uses.
Net effect: an operator with a plain OpenAI API-key connection, or any
generic OpenAI-Responses-compatible proxy connection, had no way anywhere in
the dashboard to opt that connection into `store`/`previous_response_id`
continuation — the policy layer was ready, the control just never rendered
for anything but Codex.
Move the toggle (and its save-time write) out of the isCodex-only block and
gate it on isResponsesConnection instead, matching preserveEncryptedReasoning.
Renamed the local formData field from codexOpenaiStoreEnabled to
openaiResponsesStoreEnabled since it is no longer Codex-specific.
Regression test added (TDD): renders the modal for a plain provider:"openai"
connection and asserts the toggle is present and reflects a persisted flag —
fails on the pre-fix code, passes after.
* fix(responses): stop store-marker leak into Chat Completions requests
The OpenAI Responses store toggle exposed in the previous commit was only
half the fix: the actual store functionality was broken for any model
routed to /v1/chat/completions instead of /v1/responses (e.g. gpt-5-nano,
which lacks the responses-only targetFormat capability). translateRequest
stashes the client's Responses-shaped store intent under an internal
_omnirouteResponsesStore marker so a later re-conversion back to Responses
shape can restore it as store -- but when the destination stays in Chat
Completions shape, that re-conversion never runs, nothing else consumed
the marker, and it leaked verbatim into the real upstream request body.
OpenAI's own API rejects it with 'Unknown parameter: _omnirouteResponsesStore'.
Confirmed live against the real OpenAI API.
Fix: drop the marker unconditionally at the end of translateRequest once
translation is complete, regardless of destination format. Chat Completions'
own store field means something different (dashboard eval storage, not
Responses-style previous_response_id continuation), so the client's intent
must not be silently remapped onto it either -- it's simply dropped.
Also fixes a real crash discovered while live-testing store-enabled
requests: src/sse/handlers/chat.ts referenced isProviderBreakerFailureStatus
without importing it (only the unused PROVIDER_BREAKER_FAILURE_STATUSES
constant was imported), turning a clean 429/'no credits' response into an
uncaught ReferenceError whenever all provider accounts were rate-limited.
Confirmed live (container logs showed the exact ReferenceError before the
fix, and clean error responses after).
Plus two small unrelated base-red fixes needed to get the test suite
running at all on this branch: a broken relative import in
conol-web/index.ts (one path segment short, pointed at a nonexistent
directory), and a real syntax error in gateways.ts (missing closing brace)
that broke esbuild's TypeScript transform for every test file that
transitively imports it, including the pre-existing combo-breaker-429
suite used to verify the isProviderBreakerFailureStatus fix doesn't
regress breaker classification.
Regression test: tests/unit/responses-store-marker-leak.test.ts (confirmed
failing before the translator/index.ts fix, passing after).
⚠️ base-red inherited: migration 143_job_registry.sql duplicated an
already-existing 146_job_registry.sql (byte-identical migration body,
confirmed via diff); the 143 file is deleted since 146 is canonical per
SCHEMA_VERSION_RENAMES. Needed for translateRequest's DB-backed model
capability lookup to run at all in tests.
|
||
|
|
c9daf99e37 |
fix(combo): clear LKGP pin when its target fails, not only set it on success (#10034)
setLKGP() was only ever called on success — nothing invalidated a "last
known good provider" pin once that provider started failing, so a
*separate* subsequent request kept re-selecting the same just-failed
target via applyStrategyOrdering.ts's LKGP reordering.
Live incident: an OpenClaw request to combo "default" (routerStrategy:
lkgp) got a real reasoning + apply_patch tool call from
opencode-zen/big-pickle, then 3 separate follow-up requests over the
next ~2 minutes each independently re-selected the same big-pickle
target and each timed out with "504 Stream produced no non-ping SSE
event within 95000ms" before the client gave up — instead of failing
over to any of the combo's other 12 models.
Root cause confirmed via code read: circuit breaker and model lockout
deliberately don't react to this failure class (isStreamReadinessFailureErrorBody
exempts STREAM_READINESS_TIMEOUT/combo_target_timeout 504s from tripping
the provider breaker, and REQUEST_SCOPED_UPSTREAM_ERROR_CODES suppresses
model-lockout recording for the same class — both intentional, to avoid
poisoning a healthy provider on request-specific timing). Nothing else
in the system was clearing the stale LKGP pin, so it kept winning
target-selection ordering for every new top-level request.
Fix: add clearLKGP(comboName, modelId) to src/lib/db/settings/lkgp.ts,
export it through settings.ts/localDb.ts, and call it (mirroring the
existing setLKGP-on-success call pattern exactly, same two keys) in both
combo.ts's per-target failure paths -- handleComboChat's "Done retrying
this model" block and handleRoundRobinCombo's structurally identical
twin -- right where a target is finally given up on and the loop moves
to the next one.
TDD: new regression test in tests/unit/combo-routing-engine.test.ts
("clears LKGP after the last-known-good target fails") reproduces the
exact live scenario -- confirmed failing against the pre-fix code,
passing after. Added direct unit coverage for clearLKGP itself in
tests/unit/db-settings-crud.test.ts (deletes only the targeted key,
sibling keys survive; no-op on an unset key doesn't throw) and
registered the new export in db-settings-split.test.ts's public API
surface characterization test.
Test plan:
- Full combo/LKGP-related suite (combo-routing-engine, db-settings-crud,
db-settings-split, combo-strategy-fallbacks,
combo-selected-connection-success,
delete-provider-connection-invalidates-lkgp-8887, db-read-cache) --
183/183 passing.
- npx tsc --noEmit -- clean for all changed files (pre-existing unrelated
errors elsewhere in the same test files confirmed identical against a
pristine upstream/release/v3.8.50 checkout, zero diff at those lines).
- npm run lint -- clean (new test's any usage properly typed, not left
to inflate the file's frozen any-budget suppression).
⚠️ base-red inherited: #9985
|
||
|
|
4bda22583e |
fix(sse): provider-response summary format bugs (dashboard Provider Response panel) (#10037)
* fix(sse): provider-response summary reconstructed from truncated events The dashboard's "Provider Response" panel showed a stale, incomplete snapshot for long streamed responses. Root cause: open-sse/utils/stream.ts reconstructed the summary from buildStreamSummaryFromEvents(providerPayloadCollector.getEvents(), ...) -- but getEvents() only returns whatever survived the collector's maxEvents/maxBytes cap, so once a stream exceeded it (easy with a reasoning + tool-calling model), everything after the cutoff (final finish_reason, tool_calls, rest of reasoning_content, usage) was silently dropped from the reconstruction, even though the client actually received the correct, complete response. Fix: streamPayloadCollector.ts's per-format summary builders (buildOpenAISummary/buildResponsesSummary/buildClaudeSummary/ buildGeminiSummary) are now also available as incremental reducers (createXReducer: ingest one chunk at a time, finalize at the end). createStructuredSSECollector accepts a format + fallbackModel and feeds the reducer on every push() -- including chunks that get dropped from the retained event array once the cap is hit -- via a new getSummary() method. stream.ts's error-path call site now uses collector.getSummary() instead of reconstructing from the (possibly truncated) getEvents(). Extracted from a squashed commit (originally authored alongside a conversation-tracking continuation fix in the same commit) -- only the files relevant to this SSE-summary bug are included here (stream.ts/streamPayloadCollector.ts + their test); the unrelated conversationTracker.ts continuation fix stays with the conversation- tracking PR it belongs to. Test plan: - New TDD regression tests in tests/unit/stream-payload-collector.test.ts, confirmed failing before the fix and passing after. * fix(sse): provider-response summary used the client's format, not the provider's providerPayloadCollector (dashboard "Provider Response" panel) was keyed on sourceFormat (the CLIENT's wire format) instead of targetFormat (the PROVIDER's — see createSSEStream's own @param doc: "targetFormat - Provider format", "sourceFormat - Client format"). Whenever a request translates between two different formats — e.g. a Responses-API client routed to a plain-OpenAI-chat-completions upstream, the common OpenClaw/opencode-zen shape — the reducer picked for sourceFormat could never recognize the provider's actual raw event shape, so it stayed stuck at its empty initial state. The dashboard's "Provider Response" panel showed a permanently empty `output: []` while "Client Response" (built from separately-accumulated state, unaffected by this bug) correctly showed full content — reading as if the two panels simply disagreed about the same request. Confirmed live via a wire-level pcap capture (scripts/sre/tcp-close- analyzer.py) cross-referenced against the dashboard log (1786032832181-1c6275): the actual response was complete and correct: this was purely a logging/summary bug, never a wire-format bug. Fix is mode-aware: TRANSLATE mode uses targetFormat (the provider's true format); PASSTHROUGH mode keeps sourceFormat, since passthrough has no separate provider/client format split — nothing gets translated there, and real passthrough callers (createPassthroughStreamWithLogger) don't even pass targetFormat. New regression test reproduces the exact live scenario (Responses-API source, OpenAI target, real chat.completion.chunk deltas) and asserts the provider summary reflects them — confirmed it fails with the old `sourceFormat`-keyed code (reproducing the live `output: []`-style symptom) and passes with the fix. Co-authored-by: Markus Hartung <markus.hartung@gmail.com> * fix(sse): stamp object: chat.completion on the provider-summary fallback createSSEStream's providerPayloadCollector.build() falls back to the synthesized responseBody as the "Provider Response" dashboard summary whenever sourceFormat/targetFormat isn't OPENAI_RESPONSES (in both the passthrough and translate branches) -- but responseBody is built purely for the client and never carries an `object` field at all, so the summary ended up with `object: undefined` instead of the expected "chat.completion", even though everything else (choices, usage) was correct. Caught by this PR's own new regression test ("createSSEStream translate mode: providerPayload summary reflects the PROVIDER's format, not the client's") -- the code itself was unchanged by the rebase (applied cleanly from the original commit), so this was a latent gap in the original fix, not a rebase regression. Fix: stamp `object: "chat.completion"` on a shallow copy used only for the provider summary in both branches; responseBody itself (sent to the client elsewhere) stays untouched. Verified: tests/unit/stream-utils.test.ts 51/52 passing (the one remaining failure is an unrelated, pre-existing v3.6.6-era test, confirmed present and failing identically on a pristine upstream/release/v3.8.50 checkout -- base-red inherited: #9985). typecheck/lint clean (pre-existing unrelated errors elsewhere in the file, confirmed identical to upstream). --------- Co-authored-by: Markus Hartung <markus.hartung@gmail.com> |
||
|
|
ae54c6221c |
fix(responses-api): tool call after reasoning collided on the same output_index (#10025)
emitToolCallAdded/closeToolCall used the provider's raw Chat Completions tool_calls[].index directly as the Responses API output_index. That index is scoped only to the tool_calls array and legitimately restarts at 0 for the first tool call, but a reasoning item (and/or a text message) emitted earlier in the same turn may already have claimed output_index 0 (and 1). A client that tracks response items by output_index (as the Responses API spec expects) then sees the tool call's added/delta/done events land on an index it already marked complete, and silently drops the tool call -- producing an "incomplete turn" that never dispatches it. Reported live: OpenClaw on combo default -> opencode-zen/big-pickle sent a reasoning block immediately followed by a function call in the same turn (no text message in between); the function call's output_index collided with the reasoning item's. A similar collision (tool call after a *text message*) was already fixed in open-sse/translator/response/openai-responses.ts (#9822/#9843), but that file is only used by the zed-hosted executor -- the general /v1/responses path (wired via responsesHandler.ts) goes through this file, which never received the equivalent fix. Fix: compute the tool call's output_index once (offset past any reasoning/ message item already emitted this turn) and cache it in state.funcOutputIndex, so every added/delta/done event for that call -- including ones emitted later from the finish_reason handler or flush() -- shares exactly the same output_index. TDD: new regression tests in tests/unit/responses-transformer-tool-call-reasoning-collision.test.ts reproduce the exact live scenario (reasoning immediately followed by a tool call, and multiple tool calls after reasoning) -- confirmed failing against the pre-fix code, passing after. Full transformer test suite (responses-transformer*.test.ts, responses-replay-fixes.test.ts, responses-api-truncation.test.ts, responses-request-translation.test.ts) -- 24/24 passing, no regressions. ⚠️ base-red inherited: #9985 |
||
|
|
0a72988bde |
fix(responses-api): explicit function-tool declaration must win over apply_patch-is-custom fallback (#10041)
open-sse/translator/response/openai-responses.ts's isCustomTool check
unconditionally treats any tool named "apply_patch" as a Codex-style
custom tool: `toolName === "apply_patch" || state.customToolNames?.has?.(toolName)`.
This overrides a client's own explicit declaration whenever it registers
apply_patch as a plain `type:"function"` tool (with its own JSON-schema
parameters) instead of `type:"custom"`.
Live incident: OpenClaw (combo "default" -> opencode-zen/big-pickle)
declared apply_patch as `type:"function"` with `{input:string}`
parameters. The model correctly produced valid JSON matching that
schema (`{"input":"*** Begin Patch..."}`), but OmniRoute unwrapped it
into a custom_tool_call with raw-text `input` instead of the
function_call/`arguments` shape the client actually registered.
OpenClaw's own dispatcher only implements function_call handling for a
name it declared as type:"function", so it silently never recognized
the tool call at all -- no error, no execution, no follow-up request
ever carrying a result back to the model.
Traced the exact live code path (chatCore.ts -> createSSEStream
translate mode -> translator/index.ts's hub-and-spoke openai ->
openai-responses conversion) to confirm this file -- not
transformer/responsesTransformer.ts -- is what handles combo-routed
streaming for this client/provider format pair.
PR #7905 ("Restore Responses API custom tool calls") already states
this exact precedence should hold ("...while preserving explicit
function-tool precedence") but its unconditional `toolName ===
"apply_patch"` OR never actually implemented that carve-out for
apply_patch specifically -- this fixes the gap between that PR's
stated intent and its actual behavior.
Fix: state.toolSchemas (populated from body.tools by
extractToolSchemaMap(), already threaded through stream.ts's translate
state for a different purpose -- #6951's stripEmptyOptionalToolArgs)
only contains an entry for a tool name when the client's request
declared it with a `parameters` JSON schema, i.e. as type:"function".
Gate the apply_patch fallback on NOT finding it there: apply_patch
still defaults to custom (native Codex CLI convention -- the model
emits it without the client ever declaring it as a tool) unless the
client explicitly registered it as a function tool, in which case that
explicit declaration wins.
Test plan:
- TDD: two new regression tests in
tests/unit/translator-openai-responses-custom-tool-1007.test.ts --
"...with tool defined" (function_call, arguments stay raw JSON) and
"...without tool defined" (unchanged custom_tool_call fallback,
mirroring the existing #1007 coverage). The "with" test is confirmed
failing against the pre-fix code, passing after; the "without" test
passed before and after (regression guard for the existing fallback
behavior).
- Full related suite (translator-openai-responses-custom-tool-1007,
responses-handler, responses-active-stream-custom-tool,
translator-resp-openai-responses,
translator-resp-openai-responses-namespace-identity,
translator-openai-responses-image-output-8459,
responses-transformer) -- 64/64 passing, no regressions to PR #7905's
own custom-tool coverage.
- npx tsc --noEmit -- clean (pre-existing loose-typing errors in this
test file confirmed identical on a pristine upstream checkout).
- npm run lint -- clean.
⚠️ base-red inherited: #9985
|
||
|
|
32da2a1afe |
fix: repair Audio Bridge runtime multipart self-loop (#10229)
* fix(guardrails): serialize audio bridge multipart safely * docs(changelog): record Audio Bridge multipart fix --------- Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
7acddd91a9 |
test(ci): align release expectations with provider behavior (#10236)
* test(xai): align executor expectations with Responses * test(ci): align release expectations with provider behavior --------- Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
cc41503c4a |
fix(chatgpt-web): preserve native max thinking effort (#10077)
* fix(chatgpt-web): preserve max thinking effort * fix(chatgpt-web): allow native max effort * test(chatgpt-web): cover native max effort * docs(changelog): record ChatGPT Web max effort fix |
||
|
|
fffeb14e40 | fix(kimi): recupera limite temporario sem bloquear conta (#10058) | ||
|
|
3b41e795fc |
fix(translator): preserve Responses custom tools for OpenAI-compatible providers (#10114)
* fix(translator): preserve Responses custom tools * fix(translator): preserve Responses namespace tools * fix(translator): restore dotted namespace tool aliases --------- Co-authored-by: mtb-ninja <mtb-ninja@users.noreply.github.com> |
||
|
|
b9319d05aa |
fix(providers): correct conol-web fallback-models import depth (#10140)
* fix(providers): correct conol-web fallback-models import depth The registry entry resolved `../../../services/conolModels.ts`, which points at `open-sse/config/services/` -- a directory that does not exist. Every sibling registry (hyperagent, notion-web, promptql) uses four levels. The wrong depth makes any suite that loads the provider registry fail to resolve, including the translator tests this PR needs. * docs(changelog): add fragment for #10140 |
||
|
|
d085a0e693 |
fix(providers): xai-oauth chat→responses body + missing breaker import (#10165) (#10170)
- Import isProviderBreakerFailureStatus in chat.ts (ReferenceError on cooldown path) - Tag xai-oauth/grok-4.5 with targetFormat openai-responses - XaiExecutor converts messages/max_tokens/response_format before /v1/responses - normalizeOpenAIResponsesRequest safety net for chat-shaped bodies Fixes #10165 Co-authored-by: nordz0r <nordz0r@users.noreply.github.com> |
||
|
|
f2d94957c8 | fix(ollama-cloud): map xhigh reasoning effort to max (#10160) | ||
|
|
e21f6acaab |
fix(translator): strip Codex encrypted tool-schema key for Gemini/Antigravity (#10053)
Co-authored-by: gsc-technofip <gsc@ecofip.com> |
||
|
|
c2a8505bd9 | fix(combo): preserve OpenCode Free oc/ prefix for connections (#10180) | ||
|
|
7b2cc8c0f2 |
fix(sse): apply free-tier filter to auto/best-free on chat path (#10199)
classifyAutoModel in autoRouting.ts returned only {variant:"cheap"} for
auto/best-free, without the spec.tier="free" that builtinCatalog.ts
hardcodes. chat.ts routes via resolveAutoRoutingState (autoRouting.ts),
not createBuiltinAutoCombo (chatHelpers.ts), so the tier filter was
skipped entirely and auto/best-free behaved as plain auto/cheap — paid
backends (e.g. antigravity/gemini-3.6-flash-high) could be selected from
the full pool.
Mirrors the hardcoded spec from builtinCatalog.ts:120 in classifyAutoModel
so both paths apply the free-tier candidate filter consistently.
TDD: tests/unit/auto-best-free-tier-filter.test.ts (RED → GREEN).
|
||
|
|
10c622afa6 |
fix(providers): default missing cache_control.ttl to 1h on the native Claude OAuth path (#10221)
Real Claude Code (and CC-protocol-compatible clients) commonly send
`cache_control: { type: "ephemeral" }` with no `ttl`. On the native
Claude OAuth path (provider `claude`/`cc`) the outbound anthropic-beta
set always includes extended-cache-ttl-2025-04-11, so requesting the 1h
TTL is always valid here — but Anthropic only honors it when `ttl` is
explicit; an absent `ttl` silently falls back to the platform default of
5 minutes even though the 1h beta was negotiated.
Practical effect: any pause longer than 5 minutes between turns forces a
full prefix rewrite (tens of thousands of tokens for a typical Claude
Code system+tools prefix) instead of a cache hit, burning through the
subscription's rate limit far faster than native (direct-to-Anthropic)
usage for the same workload.
Adds `normalizeCacheControlTtl()` to claudeCodeConstraints.ts (same
module as the sibling cache_control helpers enforceCacheControlLimit /
ensureCacheControlOnLastUserMessage) and calls it right after the
billing-header system-block manipulation in base.ts, immediately before
the request is signed and sent. Never touches a cache_control that
already specifies a ttl.
Measured before/after with a real Claude Code CLI session through this
path (system + tools prefix ~46k tokens):
before: cache writes always land in ephemeral_5m_input_tokens; a >5min
gap between turns forces a full rewrite (cache_read resets to 0)
after: cache writes land in ephemeral_1h_input_tokens; a >6min gap
survives (cache_read stays intact)
--no-verify note: local pre-commit's check:docs-sync fails on this branch
tip ("CHANGELOG.md first section must be Unreleased") for reasons
unrelated to this diff (pre-existing state of release/v3.8.50 mid-cycle,
CHANGELOG.md untouched by this change). Added the required changelog.d
fragment per CONTRIBUTING.md regardless.
Co-authored-by: Jefferson Alves <jefferson@rastrosystem.com.br>
|
||
|
|
9a0b007e05 |
fix(api): custom-model delete no longer tombstones a same-id synced model (#10228)
* fix(api): custom-model delete no longer tombstones a same-id synced model DELETE /api/provider-models is addressed by `provider` + `model` alone, so it cannot tell a manually-added custom row from a provider-synced row that shares the same id. It removed both unconditionally and, because the synced removal reported success, wrote `isDeleted:true`. That tombstone is permanent: replaceSyncedAvailableModelsForConnection filters deleted ids out of every re-import via getModelIsDeleted, so the provider can never resync. Model sync keeps reporting `added: N` while the catalog stays empty and /v1/models never lists the model again — even though routing to it still works, which makes the provider look broken only in discovery. Reachable via: eye-hide the synced models (#3782 keeps them in the synced store), manually add custom models with the same ids, then delete those custom models. The originals disappear from the catalog while the UI still lists them. Remove the custom row first and treat its presence as the operator's intent, so only a synced-only delete tombstones. #3199 (deleted models stay dropped) and #3782 (eye-hidden models survive re-sync) are unaffected. Covered by tests/unit/synced-model-delete-custom-sibling-tombstone.test.ts, which drives the real route handler: A fails without this change, B guards the #3199 path. * chore(changelog): rename fragment to the assigned PR number #10228 |
||
|
|
f0dc77892a |
fix(api): reach DeepSeek V4's native max reasoning tier (#10230)
* fix(api): reach DeepSeek V4's native max reasoning tier DeepSeek V4 accepts reasoning_effort low | high | max, defaults to high, and maps medium and xhigh down to high (https://api-docs.deepseek.com/api/create-chat-completion; the upstream 400 on an invalid value enumerates none, minimal, low, medium, high, xhigh, max). OmniRoute's canonical vocabulary is none|low|medium|high|xhigh, where `max` is an alias collapsing onto `xhigh`. DeepSeek then maps `xhigh` back down to `high`, so a client sending {"effort":"max"} silently got high — the model's top reasoning tier was unreachable through the canonical field, and the catalog never advertised `max` as an available tier. Mirror the existing extendCodexGpt56EffortValues precedent: expose the provider-native tier for these models only, without widening the global request vocabulary. CANONICAL_EFFORT_VALUES and normalizeEffort() are unchanged, so every other provider keeps collapsing max -> xhigh. Scoped to the native `deepseek`/`ds` provider. Routed namespaces that merely carry "deepseek" in the id (openrouter/deepseek/..., tllm/deepseek_v4, oc/deepseek-v4-flash-free) terminate at a different upstream whose effort vocabulary we do not control, so they keep the canonical behavior. The provider is not resolved yet where the canonical params are folded in (chat.ts), so the check also accepts a `<prefix>/<model>` id. An explicit client reasoning_effort / reasoning.effort still wins, as before. Covered by tests/unit/deepseek-native-max-effort.test.ts: 4 of its 6 cases fail without this change. * chore(changelog): add fragment for #10230 |
||
|
|
d259d9fcba |
fix(ci): clear base-reds on release/v3.8.50 (round 3) (#10213)
* fix(ci): clear base-reds on release/v3.8.50 (round 3) - CHANGELOG.md: restore the top [Unreleased] section dropped by the #10189 reconcile (docs-sync gate: first section must be Unreleased) - env-doc-sync: document CONDUCTOR_ORCHESTRATOR_TOKEN + CONDUCTOR_SPOKESPERSON_URL in .env.example/ENVIRONMENT.md; allowlist the CI-only GITHUB_STEP_SUMMARY and TS7_BASE_REF (ts7 ratchet signals); drop a stray merge artifact line - providers: restore the audited chatanywhere metadata entry that base-reds round 2 dropped together with its duplicate — the provider was half-wired (registry+endpoint without APIKEY metadata), which is what the wave3 test catches; re-pin providers-constants-split at the measured 228 - docs counts: 338 -> 339 (today's +2 void-ai/helixmind, -1 Puter) via gen:provider-reference + README/AGENTS/llm.txt/package.json/diagrams/i18n mirrors - file-size ratchet: annotated rebaseline for the two pre-existing drifts (ModelSelectModal 1138, gateways 1250) following the 2026-08-11 precedent Refs #9985 * fix(ci): base-reds round 3b — stale sibling tests + mode-pack weight contract - check-docs-counts-sync.test.ts: drop the imports/subtests of the four helpers #10196 removed from the gate script (readMcpFactsFromSource, listLocalizedDocs, makeRequiredCountsValidator, checkFreeTierInventory) — the new-API tests that #10196 added stay; the file now loads again under the node runner - quota-connection-recovery.test.ts: convert from vitest APIs to node:test — the file lives in tests/unit/*.test.ts (node-runner glob) and the vitest runtime crashes when imported outside vitest, killing the whole shard entry - modePacks.ts: re-normalize all six mode packs to sum 1.0 — #8940 added sessionAvailability: 0.05 to every pack without rebalancing (1.05 total); ratios preserved exactly (÷1.05), so post-normalizeScoringWeights behavior is unchanged; restores the declared sum-to-1.0 contract the 4235 test pins Refs #9985 * fix(ci): base-reds round 3c — vitest siblings, weights default, secrets FP, mutation tap - DistributeProxiesButton.test.tsx: wrap renders in NextIntlClientProvider — #9245 localized the component (useTranslations) and left the test without the intl context, failing all 14 cases - scoring.ts: re-normalize DEFAULT_WEIGHTS to sum 1.0 (same #8940 class as the mode packs — sessionAvailability added without rebalancing; ratios preserved) - .gitleaks.toml: generalize the kimi sponsor-banner localStorage-key allowlist to -v\d+ — #10200 bumped v1→v2 and the stale regex regressed the secrets ratchet with a false positive - stryker.conf.json: register 6 covering unit tests in tap.testFiles (4 modules) so their mutant kills count — unblocks check:mutation-test-coverage --strict Refs #9985 * fix(ci): base-reds round 3d — inspector factor gap, stale registry/gap tests, i18n key sync - comboScoringInspector: add cacheAffinity/sessionAvailability/connectionDensity to FACTOR_KEYS + the factor-key type — calculateScore() weighs them but the breakdown omitted them, so the explained contributions never summed to the reported score (inspector bug, red on the pure tip) - combo-scoring-inspector.test: make the explicit-weights override sum-neutral (±0.05 shift) so it stays valid for any DEFAULT_WEIGHTS values — the hardcoded override only summed to 1.0 against the pre-#8940 defaults, which is also why explicit weights silently fell back to 'default' on the tip - unorouter-registry.test: align to the canonical .com host (api.unorouter.ai 301-redirects there, verified live) and to wave4's live model discovery (passthrough, no static seed) — the .ai/auto-model expectations were stale - check-migration-numbering.test: 147 left KNOWN_GAPS when 147_api_keys_model_access_mode.sql landed — assert absent (same as 143) - i18n: sync-ui pass — 35,914 missing UI keys stamped as __MISSING__ placeholders across 42 locales (mechanical; greens the pt-BR key-presence integrity test; coverage pct unchanged by design — translation is a separate workstream) Refs #9985 * fix(ci): base-reds round 3e — 2 real defects + 14 stale sibling tests (waves A-E) Real defects fixed: - src/lib/db/apiKeys.ts: #9313's empty-allowlist early return bypassed the group permission check, silently disabling group deny rules (#8817) for every key without a per-key allowlist; fall-through restored, restricted+[] deny-all kept - open-sse/utils/proxyFetch.ts: #10032 re-appended the raw transport error to the propagated message, reintroducing the proxy user:password leak #9837 closed; new redactProxyDetailsInMessage() keeps the reason, redacts URL/credentials - .github/workflows/quality.yml: #10134 added the TS7 ratchet as a separate blocking step AFTER the aggregated gates — the exact #8542 masking mechanism; folded into the non-fail-fast loop (still blocking, still PR-only) ⚠️ CI edit, gate-strengthening — explicit owner sign-off requested on the PR - src/i18n/messages/ko.json: 3 machine-mistranslation regressions caught by the #8244 glossary checker (장애인→비활성화됨, 양말5://→socks5://, 비클로드→Claude가 아닌) Stale sibling tests aligned to deliberately-moved contracts (each cites its mover): request-log-detail-layout + -stream (#9245 intl provider), repro-8542 pin update, quality-rail-gate-membership (#10134 shape), agentSkills-routes 45→46 (#9058), cloudflare-ai-catalog-8717 (#8804 supersedes #8808), executor-xai (#9994), vision-bridge-claude-wire (#9463 minimax→openai), sse-auth forced-pin (#8893), tls-proxy-context (strengthened leak guards), rate-limit-local-error-classification (#9164/#9342), minimax-thinking-signature (#9463), codebuddy-cn (#9723 +1 test), github-copilot-custom-model (#9050), providers-g4f-batch3 (#9584), synced-capability-warmup (#9199, stricter), sidebar-tools-group (#8221), oauth-modal-grok-cli-paste (#9245); agentSkills/catalog.ts comment 45→46; file-size rebaseline for proxyFetch (+19, annotated) Refs #9985 * fix(ci): base-reds round 3f — waves F-J: 9 more real defects + stale sibling sweep Real production defects fixed (all red on the pure tip, each with its origin): - routeGuard.ts: #8949 accidentally DELETED the /api/providers/[id]/login local-only pattern — the route spawns a browser, so the loopback gate for a process-spawning route was gone (Hard Rules #15/#17); restored (314 guard tests green) - agentSkills generator: #9058's category dispatch gave the config category an empty body, wiping skills/config-codex-cli/SKILL.md at the #10131 sync; fixed + SKILL.md regenerated via the official generator - imageRegistry: #9982 broke same-provider bare aliasing (antigravity preview id sent upstream unresolved); new resolveSameProviderBareAlias() keeps the fal cross-provider fix intact - imageRegistry: #9982's prefix strip handed the bare nano-banana ids to fal-ai, violating the pinned 2026-07-31 operator decision (adobe-firefly owns them); fal entries made prefix-only (dispatch already re-prefixes) - mediaGeneration/fal.ts: the missing-credential 401 guard was lost when #10198 deleted the superseded falHandler — tests were hitting the live network - bottleneckPatch/rateLimitManager: #9041's merge clobbered #9604, resurrecting the Bottleneck v2.19.5 heartbeat bug (reservoir never refills); patched the library defect at the root and re-aligned chat-rate-limit-body-lock to the working reservoir contract - processSupervisor.mjs: #9761 regressed the Node spawn to bare "node" (the #9156 launchd bug) and dropped #9209's ipv4first args; both restored - openai-responses/pureHelpers: #9423's Agent null-sentinel was unreachable on the schemaless JSON-string path; gate extended - i18n en.json: #8222's regen reverted the #9976 unclosed-tag fix and #8559's combo-cooldown copy; #9038 shipped 40 t() calls with no messages (runtime MISSING_MESSAGE); all restored/added + official sync-ui stamps, and vi's zero-marker policy re-established via the sanctioned translation backend Stale sibling tests aligned (movers cited inline): chat-helpers (#9447), executor-antigravity (#9351), video-fal-grok (#9982), visionBridge (#9759), web-session-credentials (#8974), production-build-module-integrity (positive anchor added), agentSkills-generator/skillManifestsLint/skills-injection/ agentSkillTools-mcp/listCapabilities-a2a (#9058), memory-settings (#10010), model-catalog-policy-invalidation (#8906), model-alias-seed (#9485), reactive-context-compaction (#8949), combo-provider-wildcard (broken upsert helper), oauth-google-loopback (43-locale resurrected-key removal) Validation: 501/501 across the 47 touched test files; typecheck:core, lint, file-size, docs-sync all green. Refs #9985 * fix(ci): base-reds round 3g — wave K/L: 4 more real defects + stale alignments Real defects: - base/reasoningEffort.ts: the stale duplicate cherry-pick #9612 re-added the codex minimal→low rewrite that #9883 had deliberately removed (OMP minimal passthrough); block removed again - cursorImages.ts: #9840 wired prepareCursorImageForWire (sharp re-encode, fail-closed) into the SHARED resolveCursorImages, breaking zai-web and conol-web image uploads (HTTP 400 'undecodable'); new prepareForWire opt-out, Cursor default path unchanged (8 cursor suites green) - modelCapabilities/snapshot: catalog prepare still issued 323 per-model reads of model_context_overrides + max_input_tokens overrides, violating #9199's bulk-load contract; both now resolve from the snapshot single pass - v1-models-discovery-conformance: re-pinned to the bounded 30s SWR window (#9199/#10198) — the old 'stale-first regardless of age' contract is gone Stale tests aligned (movers cited inline): codex-tools-strict-default (#9828 redundant-oneOf strip), devin-providers (#9245 i18n), db-migrationrunner- constants-split (147→151 renumber #8228), gitlab-duo-oauth-setup (#9245), chatcore-extracted-modules (#9161 outbound-protocol keying) compression-api CI failures were cascade artifacts of codex-tools-strict-default failing in the same force-exit shard process — no own defect (171/171 local). Refs #9985 * fix(test): compression-api — register both describes before the runner starts The DATA_DIR setup + route/db top-level awaits sat BETWEEN the two describes; under --test-force-exit (the CI unit-runner flag) the process exits once the already-registered tests finish, so on slow CI machines the whole second describe died as 'Promise resolution is still pending' — the recurring CI-only shard-2 failure that never reproduced locally without the flag. Moved to the top of the file; 10/10 under --test-force-exit locally. Refs #9985 * fix(quality): freeze modelCapabilities.ts at 1006 (annotated) — snapshot routing growth Refs #9985 * fix(quality): move the modelCapabilities freeze into the frozen map (nested schema) Refs #9985 * fix(i18n): translate all 39,718 pending UI keys across 42 locales (owner-approved) Mass-translated every __MISSING__ placeholder via the official i18n:sync-ui --translate-markers pipeline (operator backend), restoring i18nUiCoverage to the 100 baseline (was 89.9 after the merge-storm UI landings + the 42 keys #9038 never shipped). Post-pass repairs, all caught by the existing gates: - glossary: retired renderings the machine reintroduced normalized again (提供商→提供者 zh-CN/zh-TW, 鏈接→連結, 文檔→文件, 調用→呼叫, 供應商→提供者, 響應→回應, 不活躍→未啟用 zh-TW; 클로드→Claude, 옴니루트→OmniRoute ko); DATA_DIR forbidden rendering avoided via 数据文件夹 rephrase - ICU integrity: 120 values with renamed/dropped {params} repaired (39 positional renames, 81 reset to the en source — functional over fluent) Validation: glossary/pt-BR/vi/deno-relay/settings-keys/value-drift/google- loopback suites 76/76; placeholder diff en×42 locales = 0; worst-locale coverage = 100.0%. Refs #9985 --------- Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
f1eb0b8357 |
refactor(providers): remove the Puter provider at its owner's request (#10210)
Remove the Puter provider (id `puter`, alias `pu`) entirely, at the request of Puter's owner, Nariman Jelveh: - registry entry (open-sse/config/providers/registry/puter/) and PuterExecutor (open-sse/executors/puter.ts), with their registrations - API-key preset card (gateways.ts), provider icon and public SVG asset - 33 free-model catalog entries (pool `puter`) - authHint i18n key across all 43 UI locales - credential-requirement frozen-list entry and related comments - docs: ARCHITECTURE, CODEBASE_DOCUMENTATION, FREE_TIERS (removal note), PROVIDER_REFERENCE regenerated (337 providers), translated doc mirrors, llm.txt + its 42 i18n mirrors, README/AGENTS/package.json counts (338→337 providers, 144→145 migrations) and the 5 canonical SVGs - migration 152 cleans up stored puter connections/keys/custom models; historical usage records are preserved (same principle as migration 151) - regression guard: tests/unit/puter-provider-removed.test.ts; puter fixtures in shared tests swapped for neutral providers; translate-path golden snapshot regenerated Historical CHANGELOG mentions are intentionally preserved; the removal carries its own CHANGELOG entry. Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
ecc89eef14 |
feat(providers): integrate audited free-tier gateways (#9210)
* feat(providers): add Zylo UnoRouter and Poolside registries * feat(providers): integrate audited free-tier gateways * feat: add wave2 free-tier provider registries * feat(providers): add Mixlayer Speka and TokenReply registries * feat: add wave 2 free-tier provider registries * fix: align meganova provider slug * feat(providers): integrate wave2 free-tier gateways * feat(providers): add Wave 3-A free-tier registries * feat(providers): add HelyxAI Auriko and Poixe registries * feat(providers): add Naga AI and Chat Oripe registries * feat(providers): integrate wave3 free-tier gateways * feat(providers): add FreeInference registry * feat(providers): add Free.ai registry * feat(providers): integrate wave4 free-tier gateways * docs: synchronize provider and free-tier inventories * refactor(providers): split audited gateway catalog * feat(providers): add audited Void AI and HelixMind gateways * feat(providers): finalize audited free-tier integration * test(providers): update APIKEY split count to 229 after rebase onto release/v3.8.50 The rebase merged the release catalog (201 APIKEY providers) with the PR's 28 free-tier additions, yielding 229 total. Correct the characterization count so the partition assertion reflects the true merged state. --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
f6ccd3cf9f |
fix(quality): green release/v3.8.50 base-reds round 2 (#9985) (#10131)
* fix(quality): green release/v3.8.50 base-reds round 2 — gateways/conol/deepai corruption, migrations, docs, ratchets, dashboard-typecheck Base-red fix for issue #9985 after the 2026-08-11 merge storm (99 PRs). Real defects fixed: - gateways.ts: close regolo entry (was swallowing naga-ac + chatanywhere from #9421), drop stale duplicate chatanywhere entry (#9594) - conol-web + deepai registry: correct ../shared import depth + deepai executor:default - modelSelectModalHelpers: close isProviderModelHidden (#9011) - driverFactory.test.ts: restore eaten test-closing brace (#9173) - usageTracking: remove duplicate cache_* props - modelCapability{Overrides,ResolutionSnapshot,Capabilities}: max_token -> max_output_tokens (#9199 vs #8908) + test align - videoGeneration: drop duplicate handleFalVideoGeneration import (mediaGeneration/fal canonical, #9982) - responseSanitizer: cast input_tokens_details before .cached_tokens access - EditConnectionModal: missing alibaba code fields, hoist validationPsd, providerPageHelpers Badge variant union - FreeBudgetCard: t() -> labels.noApiKey - peerRouting + cliRuntime: ProcessEnv typing - image-combo.test.ts: type any -> unknown - fal.test.ts: moved to tests/unit/services (collected path) 14 tests green - remove duplicate 143_job_registry.sql (146 canonical), KNOWN_GAPS fix Docs/ratchets (owner-authorized rebaselines, annotated): - CHANGELOG 3.8.50 living section restored + 42 i18n mirrors - MCP-SERVER.md 104->105 tools + i18n - ENVIRONMENT.md/.env.example: ADOBE_FIREFLY_CHROME_HEADED + DEBUG_CLAUDE_NONSTREAM - fabricated-docs allowlist: TELEGRAM proposal env vars - file-size: 5 grown files + proxyFetch 1207->1220 - dead-code 230->248, codeql 2->9 (drift from merged PRs, not this PR) - untrack _tasks symlink; agent-skills-sync --apply (config-codex-cli) * fix(changelog): reformat two feature fragments to the bullet convention (#9239, #9490) * fix(quality): prune stale ESLint suppressions (base-red) * fix(quality): resolve open-sse type errors + catalog/build regressions (base-red round 3) Storm-merge splices repaired in the base-fix PR #10131: - doctor.ts: AppConfig missing brokerSocketPath - conol-web.ts: Buffer not assignable to BodyInit (Uint8Array) - tinycms.ts: TinyCmsExecutor.execute return matches BaseExecutor (response/url/transformedBody) - tinycmsSigner.ts: encodeInto never-narrowing guard + dead wasm URL fallback (Turbopack) - virtualFactory.ts: options slot for resolutionSnapshot - bottleneckPatch.ts: insufficient-overlap casts (as unknown as) - imageCombo.ts: narrow handleImageGeneration union result - browser-worker.ts: AppConfig + turn.capabilities splice - conolDiscovery.ts: getProviderOutboundGuard from Policy module - catalog.ts: drop removed SWR hooks (getCatalogStaleWhileRevalidateMs + accessors), CatalogCachePolicy -> inline settings, resolve 4-arg call - catalogCache.ts: remove dead inFlight/promise refs - chat.ts: add isProviderBreakerFailureStatus import - model-catalog-cache-swr-8728.test.ts: align to #9199 new API (policy injection removed) * fix(quality): align UI test fixtures to current component contracts (base-red vitest) - setup-wizard: provide required serverState prop (component gained it in a merged PR) - grok-device-oauth-modal: next-intl stub resolves grok flow keys to EN labels - provider-quota-widget: label now inline (PR #8916 removed AutoRefreshButtonLabel extraction) — test the widget - use-provider-connections-cursor-refresh + phase1f: match /api/providers?provider=<id> query form; hoist heavy dynamic imports to module scope (timeout flake) - home-topology: mock next/navigation useRouter (component added node-click navigation) - cooling/lobe/AutoComboCatalog: raise cold-import describe timeouts to 30-60s - request-logger-*: align to current detail-view contract * fix(search): guard params.token undefined in serper headers (typecheck base-red) * fix(search): guard token headers + non-null providerConfig (typecheck base-red) * fix(changelog): restore base CHANGELOGs eaten by merge auto-resolve (43 files) --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
85c4292ce3 |
fix(security): correct XML double-unescape and non-CSPRNG nonce from CodeQL sweep (#10154)
* fix(security): correct XML double-unescape and non-CSPRNG nonce from CodeQL sweep Two real defects surfaced by the 2026-08-12 code-scanning triage. decodeXmlText decoded `&` before `"`/`'`, so `&quot;` — the encoding of the literal text `"` — collapsed to `"` in a second pass. The decoded values feed the workspace-root trust comparison in parseTrustedCodexEnvironment, so an encoded path could decode into a different path than the client declared. Decoding `&` last fixes it. The tinycms nonce fell back to `Date.now()` plus a non-cryptographic PRNG when `crypto.randomUUID` was absent. That nonce is signed into the provider's anti-replay payload, so the fallback produced a predictable value silently. It is now always `randomUUID()` from node:crypto, which is present on every supported runtime. Both guards are mutation-validated: reverting either fix makes the new test fail. Refs #9985 * fix(security): reword tinycms nonce comment so the CSPRNG regression test holds --------- Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
3852ae533a |
fix(docker): eliminate npm-bundled CVEs from the published image (#10182)
* chore(repo): re-untrack the _tasks self-referential symlink
`caf768e3c4` untracked it; the DeepAI merge (
|
||
|
|
c19da4db46 |
fix(security): resolve open CodeQL alerts (#10188)
Alert 806 (js/insecure-randomness, open-sse/executors/tinycms.ts): the TinyCMS nonce is signed into x-secure-signature and reused as x-secure-nonce / x-session-id, so the Math.random() fallback made a signed request predictable and replayable. Use randomUUID() from node:crypto unconditionally. Alert 811 (js/double-escaping, chatgpt-web adapters/environment.ts): decodeXmlText() decoded & before " / ', so the bare & it produced was re-consumed and the text was unescaped twice (&quot; collapsed to "). These values become the trusted Codex sandbox cwd / workspace_roots, so the double-unescape silently rewrote the workspace boundary. Decode & last. Alerts 813/814 (js/incomplete-url-substring-sanitization, test files): replace the includes() URL checks with exact comparisons (new URL(url).hostname === ... and an explicit === over the recorded URL array). Both assertions get strictly tighter. Regression guards: tests/unit/tinycms-secure-nonce-randomness.test.ts and tests/unit/chatgpt-web-environment-double-unescape.test.ts, both failing before the fix and passing after. Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
423b616503 |
fix(dashboard): retarget Kimi promo CTA to the API platform aff link (#10200)
Moonshot cannot sell coding plan subscriptions to most new users, so the Get Kimi Code traffic could not convert. At their request the dashboard banner and the README promotional spots now point at platform.kimi.ai?aff=omniroute with partner-approved copy, in all 43 locales. The dismissal key bumps to -v2 so the retargeted banner shows once to users who dismissed the old one, and the in-app title finally adopts the founding Open Source Friend framing agreed in July (title key renamed to foundingFriendTitle per the value-drift gate rename rule). Kimi Code provider pages keep kimi.com/code on purpose: they serve existing coding plan subscribers. Also un-excludes the now-fixed kimiSponsorBanner.test.tsx from vitest.config.ts (#8618 is closed). Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
00a3edc3ce |
docs(readme): add olud.ai directory badge (#10205)
olud.ai featured OmniRoute in its open-source directory (health score 96/100). The badge is dynamic, it reads the live star count and rank, so it never goes stale. Placed with the other ranking badges (Trendshift, Star History). Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
37d70785c7 |
fix(build): repair broken production build, red lint gate and SWR crash (#10198)
The Build CI job is advisory, so eight module-level defects from eight different PRs accumulated on release/v3.8.50 until `npm run build` failed with 7 Turbopack errors and `npm run lint` with 14. Build (link-time): - modelSelectModalHelpers.ts: a lost `}` swallowed PROVIDER_TEST_CHUNK_SIZE into isProviderModelHidden's body (#9011). - videoGeneration.ts: handleFalVideoGeneration imported twice; the standalone falHandler.ts is superseded by the provider-neutral mediaGeneration/fal.ts and is removed here (#9982 over #9969). - catalog.ts: re-exported and called the injectable SWR policy that #9199 deliberately replaced with a fixed 30s bound. Fixed on the consumer side — restoring the accessor would resurrect the unbounded window #9199 removed after measuring a 41s catalog build in production. - tinycmsSigner.ts: generated wasm-bindgen glue kept a sidecar `new URL('wasm_signer_bg.wasm', import.meta.url)` that no file backs; Turbopack resolves it statically. The module ships inlined as WASM_BASE64 and the only caller always passes it explicitly (#8736/#10087). - conolDiscovery.ts: imported getProviderOutboundGuard from outboundUrlGuard, which does not export it. Fixed on the consumer side: outboundUrlGuard.ts is loaded by the packaged CLI without a tsconfig, so it must stay free of `@/`-aliased imports (#7682). Runtime (the build never caught this one): - catalogCache.ts::scheduleBackgroundRefresh had two dangling statements referencing undeclared `inFlight`/`promise`, so EVERY stale-while-revalidate read threw a ReferenceError. Surfaced by realigning the #8728 suite, which #9199 left asserting a removed contract. Lint: - driverFactory.test.ts: a case inserted between the preceding test's `finally` and its `});` left the file unparseable, so the SQLite driver-cascade suite (26 tests) had not run since 2026-08-11 (#9173). - providerModelsConfig.ts: imported an executor directly, crossing the G14 boundary; routed through a new open-sse/services/zaiWebCredentials.ts (#8451). - image-combo.test.ts: 11 `any` violations, now typed (#9499). Validation: npm run build exit 0, npm run lint clean, typecheck:core clean, 41/41 tests green across the affected suites. Refs #9011 #9982 #9199 #8728 #8736 #10087 #8974 #9173 #8451 #9499 Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
bfad01ecb3 |
docs(readme): fold the evolution section into one compact table with New markers (#10207)
Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
cffaeebb27 |
docs(readme): expand the v3.8.51 teaser into an in-flight feature grid with provider numbers (#10204)
Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
db8d2b2013 |
docs(readme): add cycle-evolution section — 291→338 providers and the v3.8.51+ teaser (#10203)
Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
8bd17be8aa |
docs: refresh every stale count to measured values + harden docs-counts gate (#10196)
* docs(reference): regenerate PROVIDER_REFERENCE from live provider modules The catalog was hand-stale at 291 since 2026-08-05 while the live provider modules define 338 unique IDs. The generator also omitted the NOAUTH_PROVIDERS module entirely (10 providers) and hardcoded the executor count in its footer; both are now sourced from the live modules. Refs #9985 * docs: refresh stale counts across README/AGENTS/llm.txt and architecture docs Every count updated to values measured from the live code on 2026-08-12: providers 291/271/248/236/226/212->338, migrations 110/117/130->144, MCP tools 94/99/104->105 (base 42->43), scopes 13/32->31, strategies 17/18->19, Auto-Combo factors 12/13->14 (sessionAvailability row added to the table), executors 67/78/84/89->101, quality gates ~48->~80, locales 29/30/39/40+->43 (41 non-source), A2A skills 5->6 (list-capabilities), free tier 43 pools/516 models/~1.53B/~2.15B->42/495/~1.51B/~2.13B, contributors 500+->320+ (324 unique emails), llm.txt version 3.8.47->3.8.50. llm.txt i18n mirrors resynced (headers preserved, body mirrored). Refs #9985 * docs(diagrams): sync SVG hero/pillars/comparison/cli/tier numbers Text nodes and aria-labels only; layout, coordinates and animation values untouched. providers 278/290->338 (cli list footer 264->334 more), MCP tools 104->105, strategies 18->19, free tier 43 pools/460+/516 models->42/495, headline ~1.53B/~2.15B->~1.51B/~2.13B. All six SVGs re-validated as XML. Refs #9985 * feat(check): harden docs-counts gate - live provider source, llm.txt, migrations, SVGs The gate trusted PROVIDER_REFERENCE.md as the provider total, so a hand-stale doc (291 vs 338 live) kept it falsely green. New STRICT checks: doc total vs the live provider modules (same collections the generator unions), provider count in llm.txt and package.json description, migration count vs README/AGENTS/llm.txt, and a canonical-number sweep (providers/MCP tools/strategies/pools) over the six README SVG diagrams with coordinate/attribute-safe patterns. TDD: 9 new unit tests (red first on the missing exports, green after) in tests/unit/check-docs-counts-sync.test.ts. Refs #9985 * docs(readme): refresh What's New range and add v3.8.50 cycle highlights --------- Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
be62ca04f7 |
chore(repo): hygiene sweep — approved deletions, ignore repairs, tracked-artifacts guard, Hard Rule 23 (#10193)
* chore(repo): remove one-shot reports and stale docs approved by owner * chore(repo): untrack _references and superpowers planning artifacts * fix(repo): repair .gitignore anchors and un-ignore published CLI entrypoint * feat(ci): extend check:tracked-artifacts never-allowed classes * docs(agents): add Hard Rule 23 (_tasks append-only) and sync scripts/ layout * feat(ci): generic never-track rule for every root underscore path (_*) --------- Co-authored-by: backryun <bakryun0718@proton.me> |
||
|
|
a543992b96 |
docs: restructure — planning artifacts to _tasks, duplicate merges, nav gaps closed (#10190)
* docs: migrate planning artifacts out of docs/ (superpowers, sessions, proposals) * docs(ops): relocate redis/production and contribution guides, move ROADMAP to repo root * docs: merge duplicate guides (troubleshooting, chatgpt-web codex, docker channels, memory backend) * docs: close fumadocs nav gaps (meta.json manifests + index) * chore(check): drop dead allowlist entries after docs restructure * docs: prettier formatting follow-up on merged guides * docs: point README at merged guide targets and allow ROADMAP.md at repo root --------- Co-authored-by: backryun <bakryun0718@proton.me> |