feat(providers): add Agnes AI (China) as agnes-cn on api.agnes-ai.cn - #13399
Merged
diegosouzapw merged 161 commits intoSep 16, 2026
Merged
diegosouzapw merged 161 commits into
diegosouzapw merged 161 commits into
Conversation
…leaf CN and intl Agnes keys are separate. Tests lock the split before the provider id exists so a later pairing cannot sneak in green. Signed-off-by: Minxi Hou <houminxi@gmail.com>
Agnes CN keys 401 on apihub.agnes-ai.com. A second registry id keeps the default host and the credential pool off the intl card. Signed-off-by: Minxi Hou <houminxi@gmail.com>
… rows The CN host is a different keyspace. Dashboard, onboarding, and live /v1/models discovery have to name that id, not reuse agnes. Signed-off-by: Minxi Hou <houminxi@gmail.com>
A search-pair or sibling-catalog entry would merge the two key spaces. The scan and the credential lookup both have to stay red if that pairing appears. Signed-off-by: Minxi Hou <houminxi@gmail.com>
The golden map must record api.agnes-ai.cn so a later default-host drift fails the suite instead of shipping CN keys to apihub. Signed-off-by: Minxi Hou <houminxi@gmail.com>
hasFree without freeNote is the only regional card that leaves the dashboard with no explanation of the free tier. Signed-off-by: Minxi Hou <houminxi@gmail.com>
Tip added arcee-ai after the Agnes CN snapshot was cut. Refresh so the golden map matches the current registry. Signed-off-by: Minxi Hou <houminxi@gmail.com>
GET /v1/models on api.agnes-ai.cn lists agnes-3.0-flash and does not list retired 1.5. The CN seed and free-catalog rows had the opposite set. Signed-off-by: Minxi Hou <houminxi@gmail.com>
HouMinXi
force-pushed
the
feat/agnes-cn-provider
branch
from
September 14, 2026 16:53
5a58708 to
2c94cf9
Compare
Contributor
Author
|
Backport: live Probed
So the registry now declares two tier constants ( Amended into the seeding commit as |
…ouzapw#12849) (diegosouzapw#13248) Merged after renumbering. `176_provider_connection_synced_models_at.sql` collided with `176_xp_action_counts.sql` (diegosouzapw#12651), which made the migration runner abort on every DB open. Renamed to **177**; the doc count moves 173 → 174 across README.md, AGENTS.md, llm.txt and the i18n mirrors (operator-approved, 206 numeric substitutions and nothing else). - `check:migration-numbering`: OK, 174 migrations, no duplicates - `check:docs-counts` migrations: ✓ - 84/84 across the NVIDIA suite plus the seven DB-touching suites the collision had taken down - ESLint and `typecheck:core`: exit 0 Heads-up for whoever lands next: **177 is claimed by eight other open PRs** (diegosouzapw#13610, diegosouzapw#13602, diegosouzapw#13580, diegosouzapw#13554, diegosouzapw#13405, diegosouzapw#13331, diegosouzapw#13177, diegosouzapw#13116) and 176 by diegosouzapw#13373 and diegosouzapw#13102. With this merged, all of them need to renumber at merge time — `check:migration-numbering` forbids new gaps, so the next free number is always the only valid one.⚠️ base-red inherited: diegosouzapw#12732
…k, docs provider count, agent-skills sync (diegosouzapw#13216) Merged after reconciling against the tip. The one conflict was `docs/reference/PROVIDER_REFERENCE.md`, a generated file — regenerated with `npm run gen:provider-reference` (358 unique IDs) rather than hand-merged. The three base-reds this PR targets, re-checked on the reconciled tree: - `check:docs-counts`: **exit 0** — provider count 356 → 358 in AGENTS.md, llm.txt, the i18n mirrors and the SVG diagrams was its last red - `check:open-sse-typecheck`: OK, 0 errors - `check:agent-skills-sync`: exit 0 (`skills/cli-tunnel/SKILL.md` → `tunnel create [type]`) - `autoCombo.test.ts` under the mcp vitest config: 63/63 - ESLint over the changed files: exit 0 AGENTS.md, llm.txt and SKILL.md are agent-instruction surfaces; the operator approved them for this PR explicitly.
…, Sinhala, Burmese, Khmer (59 locales) (diegosouzapw#13660) Batch 2 of the locale expansion across the dashboard catalog, docs mirrors, CLI catalog, README, locale index and the site. 51 → 59 locales. Also: the translator restores the ICU literal escape around angle placeholders, and the docs chunker splits oversized sections before translating.⚠️ base-red inherited: diegosouzapw#12732 — the eight red checks fail identically on unrelated PRs cut from the same base (e.g. diegosouzapw#13197); every gate is green locally after merging the base.
…xt mirrors (diegosouzapw#13674) Unblocks the pre-commit docs-sync gate on the release tip.
…zapw#12867 pipeline extraction, a legacy-DB boot abort and the catalog readers (diegosouzapw#13349) Merged after a real reconciliation — this PR and diegosouzapw#13069 fixed the same diegosouzapw#12867 regression (the non-streaming leg losing failure classification and credential refresh) with different strategies, and diegosouzapw#13069 landed first. Rather than stacking two implementations, the tip's was kept and this PR was trimmed to what the tip still lacked. **Dropped, already on the tip:** - non-streaming credential refresh and failure-state persistence → diegosouzapw#13069 (`applyProviderFailureClassification`); the `persistProviderFailureState` hook this PR added would have been dead code - body-derived rate-limit lock and non-JSON body message → already in the tip's pipeline (`chat-rate-limit-body-lock` passes there) - codex image-generation stringify of a sanitized error body → diegosouzapw#12945 (`stringifyImageErrorForLog`, which would otherwise be declared twice — TS2393) - the two test realignments (`hard-session-lease` inventory wording, kiro stream reader) → diegosouzapw#12945 **Kept, missing on the tip:** - **upstream error `code`/`type` in the pipeline error outcome** — ported onto the tip's implementation. Running this PR's own test against the tip returned `errorCode: undefined` instead of `missing_project_id`, so a config-class Antigravity 422 still degraded into an account cooldown. - legacy `call_logs` boot abort (index created after column healing) - malformed operator custom-models row no longer kills every `auto/*` pool (`virtualFactory.ts` 1219 → 1230, annotated) - realigned guards **Evidence on the reconciled tree** - 104 of 106 focused assertions. The 2 red (`models-catalog-route`, `provider-node-reserved-prefix`) fail identically on the pure tip. Against the tip, this PR turns 7 previously red cases green. - ESLint, `typecheck:core`, `check:open-sse-typecheck` (0 errors), `check:changelog-integrity`: all clean - changelog fragment rewritten to claim only what this PR still delivers Unblocking this also surfaced a repo-wide red: the eight llm.txt mirrors added by diegosouzapw#13660 kept the pre-diegosouzapw#13216/diegosouzapw#13248 counts, which failed the pre-commit `docs-sync` gate for everyone. Fixed separately in diegosouzapw#13674. `skills/cli-tunnel/SKILL.md` needed no change — diegosouzapw#13216 already landed the identical edit.⚠️ base-red inherited: diegosouzapw#12732
… test flake, pack provenance + pack policy (diegosouzapw#12959) Merged after salvaging what still applies. The doc-count half of this PR is superseded — it moved migrations 169 → 171 while the tip is already at 174, and the provider count landed via diegosouzapw#13216 — so every docs, diagram and llm.txt mirror change was reset to the tip's version and its changelog fragment dropped. Merging it as it stood would have regressed the counts. Kept, none of it on the tip: - `scripts/build/pack-artifact-policy.ts`: `@omniroute/opencode-plugin-v2/` added to the allowlist — diegosouzapw#12870 shipped the v2 plugin without widening it, so every packed file under it read as unexpected - `scripts/quality/validate-release-green.mjs`: points the pack provenance guard at `HEAD` instead of `origin/main`, which is structurally unreachable from a release branch mid-cycle - `12058-models-catalog-canonical-self-aliased.test.ts`: pins `CATALOG_BUILD_TIMEOUT_MS` out of the way of a cold catalog build on a loaded runner; assertions unchanged 54/54 across those three suites, ESLint exit 0, changelog integrity OK.⚠️ base-red inherited: diegosouzapw#12732
…w#12969) Merged after reconciling the whole stack onto the tip, operator-reviewed before merge. The core ownership fix for GHSA-wvxc-jp3v-5mg5 had already landed via diegosouzapw#13211 with a different implementation of the same endpoint. This branch carries a stricter one, built up in layers: this PR, diegosouzapw#13262 (explicit scope, audit log, atomic sweep), diegosouzapw#13297 (revoked, deactivated, banned or expired keys rejected) and diegosouzapw#13374 (owner-scoped file half, chunked instance sweep — SEC-C/SEC-D). The stack's implementation was kept over diegosouzapw#13211's because it is stricter on every point: - **route:** with diegosouzapw#13211, a request carrying BOTH a dashboard session cookie and an API key swept the whole instance. Here a presented key always scopes the sweep to that key; only a session without a key sweeps all tenants; neither returns 401. Instance-wide and row-deleting sweeps log at warn as an audit trail, and a failing sweep returns a sanitized 500. - **`deleteCompletedBatches`:** takes an explicit `{ apiKeyId } | { allTenants: true }`. An omitted or blank key throws instead of widening, and passing both throws. - **files:** a key sweep only soft-deletes files the caller owns (`deleteFileOwnedBy`), so a batch referencing another tenant's or an unowned file never nulls its content. - **transactions:** key mode is all-or-nothing across chunks; instance mode commits per 200-id chunk so a large sweep never holds one write lock on the table. diegosouzapw#13211's own test was aligned to the explicit-scope API with its assertions unchanged. Its seed now creates the file with the batch's owner, as an upload through that key does in production — without that, SEC-C correctly leaves the unowned file intact. - 51/51 across the six batch suites (diegosouzapw#13211's test, this stack's ownership and route-scope tests, `batch-deletion`, `batch-deletion-route-logic`, `files-delete-owned-by`) - ESLint, `typecheck:core`, complexity, cognitive-complexity, changelog integrity: clean⚠️ base-red inherited: diegosouzapw#12732
…apw#13286) (diegosouzapw#13418) Chains `npm run test:unit:serial` onto the plain `npm test` script, so the quarantined serial suite is no longer skipped when contributors run `npm test` (diegosouzapw#13286). The existing `test-serial-quarantine` guard now covers `test` too. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…uzapw#13273) (diegosouzapw#13401) Masks every `*-api-key` header spelling (`x-goog-api-key`, `api-key`, `xi-api-key`) in the request-log pipeline by matching on the hyphen-compacted key, and adds `xi-api-key` to the payload redaction set (diegosouzapw#13273). The new test drives the real `createRequestLogger` / `protectPayloadForLog` paths. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…iegosouzapw#13403) Fixes the stale `jina-ai/` prefix in the second Jina assertion of `models-catalog-route.test.ts`. The catalog emits `jina/…` (the first Jina test already expected it), so this clears a base red on the release branch. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…iegosouzapw#13308) (diegosouzapw#13404) Prunes `db_backups/` after the health-check-repair `VACUUM INTO` snapshot (diegosouzapw#13308). That path never ran retention, so every restart of a healthy database added another full-size copy. It now uses the same `DB_BACKUP_MAX_FILES` / `DB_BACKUP_RETENTION_DAYS` limits as `backup.ts`, importing `backupRetention` directly to avoid the import cycle. Maintainer additions: merged the current release branch and rebaselined `src/lib/db/core.ts` 1745→1767 in `file-size-baseline.json` with a dated annotation (legitimate growth). Chosen over diegosouzapw#13540, which did the same with a fire-and-forget dynamic import. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…ction (diegosouzapw#12776) (diegosouzapw#13406) Carries `context_length` through the MCP `list_models_catalog` projection when the upstream model record has it, and omits it otherwise (diegosouzapw#12776). Covered by the new case in `mcp-model-catalog.test.ts`. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…#13409) "Test all models" no longer sends image/music/video generation-only models through a chat completion, which triggered real billable generations (diegosouzapw#13376). `detectTestKind` flags them via `isNonChatGeneration` and `runSingleModelTest` skips them; chat+image models, embeddings and models without metadata are unaffected (8 new cases plus updated `model-test-runner` shapes). Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…iegosouzapw#13412) Adds CJK quota-exhaustion messages (GLM/z.ai 5-hour window, Kimi, Qwen/DashScope, MiniMax, plus Japanese and Korean phrasings) to the 429 quota classifier. They are now `quota_exhausted` (cooldown + failover) instead of a transient `rate_limit` retry loop (diegosouzapw#13194). The patterns go into the recoverable `QUOTA_PATTERNS` only, not the terminal set, and a guard case keeps the Chinese transient "请求过于频繁" as `rate_limit`. Chosen over diegosouzapw#13536. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…otAll regex (diegosouzapw#13413) Eval runner: a case whose upstream call failed can no longer score as passed when the grading regex happens to match the error text (diegosouzapw#13137), and regex grading compiles with dotAll so `.` spans newlines in multi-line answers, for both string and `RegExp` patterns (diegosouzapw#13138). Chosen over diegosouzapw#13542 / diegosouzapw#13530, which each covered half. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…on (diegosouzapw#13414) The eval runner sends `x-omniroute-compression: off` and `x-omniroute-no-memory: true`, so cases measure the model rather than injected output styles or retrieved memory (diegosouzapw#13139). Both headers are the existing per-request opt-outs honored by `chatCore` (`open-sse/handlers/chatCore/headers.ts`). Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…iegosouzapw#13411) The media-providers web-search example card now sends `provider` in the request body. `POST /v1/search` selects the provider from `body.provider`, so the card was silently hitting the default provider (diegosouzapw#13245). Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…osouzapw#13410) De-duplicates the `agy` and `antigravity` model catalogs into `antigravitySharedModels.ts`, with an explicit per-surface add/remove delta (diegosouzapw#12724). Verified behavior-neutral: every exported catalog constant of both modules serializes byte-identically before and after (201-line JSON dump). Maintainer fix: `buildSurfaceCatalog` returned `readonly { id: string; [k: string]: unknown }[]`, which erased the element type. `name` became `unknown`, and the `RegistryEntry.models` assignments failed with 4× TS2322 under `check:open-sse-typecheck` (not covered by `typecheck:core`). It is now generic (`<T extends { id: string }>`), so the literal model shape flows through. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…ifting at messages[0] (diegosouzapw#13425) (diegosouzapw#13427) Memory injection merges into an Anthropic-shaped top-level `system` field (string or text-block array) instead of prepending a `role: "system"` message at `messages[0]`, which Anthropic rejects with a 400 (diegosouzapw#13425). Handled on both the system-first path (xiaomi-mimo) and the general path. Chosen over diegosouzapw#13549, which covered only the string case. Maintainer fix: widened `ChatRequest.system` to `string | Array<{ type; text?; … }>`. Assigning the block array to the `string`-typed field raised 2× TS2322 under `check:open-sse-typecheck`. Validated in one consolidated batch of this series (37 PRs boarded together on `release/v3.8.51`): `typecheck:core`, `check:open-sse-typecheck` and `check:dashboard-typecheck` clean; ESLint clean on every changed file; file-size, complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync and migration-numbering gates green (only the pre-existing `open-sse/utils/stream.ts` file-size red remains, inherited from the base); 3,743 focused `node:test` cases plus 34 vitest cases green. Thanks @KooshaPari!
…gosouzapw#13314) (diegosouzapw#13779) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…iegosouzapw#13306) (diegosouzapw#13778) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…iegosouzapw#13232) (diegosouzapw#13777) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
diegosouzapw#13089) (diegosouzapw#13776) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
diegosouzapw#13775) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…iegosouzapw#13022) (diegosouzapw#13772) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…ks (diegosouzapw#12968) (diegosouzapw#13771) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
diegosouzapw#13012) (diegosouzapw#13770) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
… start (diegosouzapw#13000) (diegosouzapw#13759) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…rect_access 403 (diegosouzapw#12958) (diegosouzapw#13758) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…diegosouzapw#12491) (diegosouzapw#13756) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…apw#12927) (diegosouzapw#13754) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
…tal_tokens (diegosouzapw#12692, diegosouzapw#12700) (diegosouzapw#13753) Merged in the 2026-09-16 sweep of the maintainer's own open PRs, at the owner's explicit instruction. No push was made to the PR branch: the merge took the head as the owning session left it (verified OPEN, non-draft and MERGEABLE against the release tip immediately before merging).
# Conflicts: # docs/i18n/am/llm.txt # docs/i18n/ar/llm.txt # docs/i18n/az/llm.txt # docs/i18n/bg/llm.txt # docs/i18n/bn/llm.txt # docs/i18n/cs/llm.txt # docs/i18n/da/llm.txt # docs/i18n/de/llm.txt # docs/i18n/el/llm.txt # docs/i18n/es/llm.txt # docs/i18n/et/llm.txt # docs/i18n/fa/llm.txt # docs/i18n/fi/llm.txt # docs/i18n/fr/llm.txt # docs/i18n/ga/llm.txt # docs/i18n/gu/llm.txt # docs/i18n/ha/llm.txt # docs/i18n/he/llm.txt # docs/i18n/hi/llm.txt # docs/i18n/hr/llm.txt # docs/i18n/hu/llm.txt # docs/i18n/hy/llm.txt # docs/i18n/id/llm.txt # docs/i18n/ig/llm.txt # docs/i18n/it/llm.txt # docs/i18n/ja/llm.txt # docs/i18n/ka/llm.txt # docs/i18n/km/llm.txt # docs/i18n/kn/llm.txt # docs/i18n/ko/llm.txt # docs/i18n/lt/llm.txt # docs/i18n/lv/llm.txt # docs/i18n/ml/llm.txt # docs/i18n/mr/llm.txt # docs/i18n/ms/llm.txt # docs/i18n/mt/llm.txt # docs/i18n/my/llm.txt # docs/i18n/ne/llm.txt # docs/i18n/nl/llm.txt # docs/i18n/no/llm.txt # docs/i18n/or/llm.txt # docs/i18n/pa/llm.txt # docs/i18n/phi/llm.txt # docs/i18n/pl/llm.txt # docs/i18n/pt-BR/llm.txt # docs/i18n/pt/llm.txt # docs/i18n/ro/llm.txt # docs/i18n/ru/llm.txt # docs/i18n/si/llm.txt # docs/i18n/sk/llm.txt # docs/i18n/sl/llm.txt # docs/i18n/sr/llm.txt # docs/i18n/sv/llm.txt # docs/i18n/sw/llm.txt # docs/i18n/ta/llm.txt # docs/i18n/te/llm.txt # docs/i18n/th/llm.txt # docs/i18n/tr/llm.txt # docs/i18n/uk-UA/llm.txt # docs/i18n/ur/llm.txt # docs/i18n/uz/llm.txt # docs/i18n/vi/llm.txt # docs/i18n/yo/llm.txt # docs/i18n/zh-CN/llm.txt # docs/i18n/zh-TW/llm.txt # src/i18n/messages/es.json
…ee-forever 52→53, free-tier entries 443→446)
diegosouzapw
merged commit Sep 16, 2026
cdcde97
into
diegosouzapw:release/v3.8.51
0 of 3 checks passed
diegosouzapw
added a commit
that referenced
this pull request
Sep 16, 2026
#13905) `APIKEY_PROVIDERS merges the 6 family files into 240 entries` fails on the release tip, taking a unit-test shard red on every open PR. Agnes AI China (#13399, cdcde97) added one `apikey/regional` entry, so the real count is 241 — confirmed at runtime: `Object.keys(APIKEY_PROVIDERS).length` is 241 and includes `agnes-cn`. The hardcoded number is deliberate, not an oversight: the test is a tripwire for silent loss or duplication across the six family files, and each bump is documented in the header with the provider and the PR that caused it. Kept that convention rather than deriving the count at runtime, which would make the test assert nothing.
diegosouzapw
added a commit
that referenced
this pull request
Sep 16, 2026
…3131) provider-node-reserved-prefix.test.ts's REGISTRY id+alias walk was already red on the base tip (414 vs. expected 412) from agnes-cn (#13399, +id/+alias). Removing chipotle's REGISTRY id/alias in this PR nets it back to 412, making the test pass again without a numeric edit — record why in a comment so it doesn't read as an untracked coincidence later.
diegosouzapw
added a commit
that referenced
this pull request
Sep 17, 2026
* fix(quality): clear the release/v3.8.51 base-reds 19 failing unit tests plus the API Route Typecheck and mutation-test-coverage gates, all reproduced on the clean tip before touching anything. Ten of the failures share one cause. #13452/#13798 made `*-compatible-*` buildUrl() refuse a connection with no baseUrl instead of quietly defaulting to the real OpenAI/Anthropic API — which would ship the operator's stored key to a public third party. The guard is right; three fixtures still built those connections unhydrated, and one of them put baseUrl at the top level of credentials, where the chat path never reads it. The rest: - modelDiscovery.ts missed the VertexModelMetadataProvenance cast that its read-path twin in db/models/synced.ts already had — both written by #12471. - A provider-test regexp carried raw 0x00/0x1f bytes, which makes git, GitHub and ripgrep treat the file as binary. Same character class, written with escapes instead of the bytes themselves. - #13399 (Agnes AI China) adds "agnes-cn" + "agnescn": the only two provider prefixes since the count was last set (412 -> 414). Everything else added in that range is model ids. - The free-tier budget card SVG was stale (443 -> 452 models); regenerated by its own script. - Three new tests were missing from stryker.conf.json tap.testFiles, so the mutants they kill did not count. Three guards asserted syntax rather than the invariant they protect, and broke when the source legitimately changed. Each was re-expressed and then verified by mutating the source back: - #2331 required modelEffort to head the rawEffort chain; #13556 deliberately put the server-selected force rule first. The real invariant is relative — modelEffort outranks the defaults a client injects — and it still trips when explicitReasoning is moved ahead of it. - The OAuth loopback guard matched the isLocalhost arm literally; #9944 added `&& !opts?.manualLoopback`. It now matches the arm whatever guards it, and still fails when the hint stops being built. - The i18n scanner flagged dynamically-built keys — t("effort." + mode) reaches it as a literal prefix, never a string. It now accepts a prefix that resolves to a namespace holding messages, and still fails when the namespace is gone. tests/unit/sse-auth.test.ts (#12080) expected a bare null where #13879 now returns the key-policy diagnostic — the same sentinel shape the terminal-state path has used since #12441. The assertion was rewritten to the constraint #12080 actually protects: nothing usable comes back and neither connection leaks. The contract risk that remains — those sentinels are truthy, and executeWebSearch treats any truthy value as a credential — is filed as #13945 rather than widened into this PR. Refs #13866 * fix(quality): clear the second wave of release/v3.8.51 base-reds The tip moved 13 commits while the first pass was running and brought its own reds. All reproduced locally on the merged tree first. vitest 4.1.11 -> 5.0.0 in the #13661 development-group bump is a major, and vitest 5 moved `vite` from a dependency to a peerDependency. This repo only ever declared `vite` under `overrides`, which pins a version but installs nothing, so `npm ci` stopped providing it and the Vitest job died at startup with ERR_MODULE_NOT_FOUND. Declared as the devDependency it actually is — the same ^8.0.16 the override already pinned, and what @vitejs/plugin-react asks for as a peer — and regenerated the lockfile: 684 lines added, none changed. #12909 filtered a mapped array with `toolCall is JsonRecord`, but the element type is the tool-call literal or null, and a predicate's type has to be assignable to the parameter's (TS2677). Narrowed by the element's own type instead; the literal still satisfies JsonRecord at the return. #12906 added `|| result.errorCode === "empty_response"` to the stream-failure condition and Prettier rewrapped it, so the #8928 probe — which located the branch by an exact four-line string — stopped finding it. It now matches on what the branch tests rather than how it is typeset, and still fails when the eviction call is removed. probe-7293 is the visible half of a real conflict, filed as #13948. #7293 merges a mid-array system into index 0; #12908, landed later, demotes it to "user" in place instead. Both target the same constraint and only one can win, and the combination also reorders: the pre-translation hoist moves the turn forward expecting it to stay a system message, then the demotion converts it where it now sits, ahead of the conversation. Choosing between the two strategies is a product call, not a base-red one, so the test was realigned to assert the half that protects the caller — the instruction survives, as a user turn — and pins the current ordering with a pointer to the issue, so the eventual decision shows up as a deliberate test change instead of a silent regression. Refs #13866, #13948 * fix(quality): allowlist vite, rebaseline tip growth, drop a dead import Third pass on the release/v3.8.51 base-reds. Declaring `vite` in the previous commit was correct but incomplete: check-deps is a human review point against typosquatting, so a newly declared package has to be vouched for by name. Recorded in dependency-allowlist.json with why it is needed — the official Vite build tool, already pinned through overrides, and a required peer of both vitest 5 and @vitejs/plugin-react. That also turns check-deps.test.ts green. check-file-size went red on nine files. One is mine: sse-auth.test.ts grew when the #12080 assertion was rewritten. Three of the four assertions I had added were redundant with the strict deepEqual that follows them, so they are gone and the file grows by 4 lines instead of 8; the cap absorbs the rest. The other eight are production and test files this PR does not touch, grown by other work and never rebaselined — which is the whole reason a base-red drain exists. Each is attributed to the commit that grew it: #12906 (chat.ts, chatHelpers.ts, proxyFetch.ts, stream.ts), #12904 + #12910 (chatCore.ts), and batch_api.test.ts from the same wave. Two of them predate the wave entirely and were already over cap on 3d5baf1 — imageGeneration.ts (#13748) and roundRobinCombo.ts (#13776) — so they were base-reds hiding behind a gate that only surfaced them once the tip was merged in. Both are recorded separately from the wave so the history stays honest about when each cap actually moved. Note for whoever reads the gate next: it counts one line more than `wc -l`, since it measures split length rather than newlines. Finally, #13290 replaced rmSync with cleanupTempDataDir in zcode-executor.test.ts but left the import behind, which the frozen-warning ESLint gate rejects. Removed. Refs #13866
diegosouzapw
added a commit
that referenced
this pull request
Sep 17, 2026
* fix(providers): remove the chipotle/pepper provider (#13131) amelia.chipotle.com (the reverse-engineered Amelia chat-widget backend chipotle/pepper-1 talked to) now returns 404 on every route, including root, from its Azure Application Gateway — confirmed live 2026-09-15. This regressed from a WS handshake timeout (#4037, June 2026) to a fully decommissioned host, so the upstream protocol cannot be fixed. Owner decided to retire the provider entirely (Option B), following the phind/kluster quiet-removal precedent: no REMOVED_PROVIDERS.md entry (reserved for operator takedowns), just a one-line note under FREE_TIERS.md "Removed / no free tier". Removed every surface: executor, registry entry, executors/index.ts and providers/index.ts wiring, noauth provider catalog entry, ProviderIcon generic-fallback set, the autoCombo exclusion-list comment, the chipotle_error code from the sanitizer allowlist, PROVIDER_REFERENCE.md (regenerated), and every doc/test reference. Regression test: tests/unit/issue-13131-chipotle-provider-removed.test.ts asserts the provider is fully gone from the executor registry, the provider REGISTRY and the noauth catalog, and that the executor module no longer resolves — not a live-network repro (flaky/third-party). Several existing tests used "chipotle" only as a generic noAuth-provider example (proxy scoping, error classification, onboarding, fallback text) with no chipotle-specific behavior under test; those were re-pointed at another still-existing noAuth provider (cloudflare-playground / duckduckgo-web) rather than weakened. * test(providers): document the agnes-cn/chipotle count coincidence (#13131) provider-node-reserved-prefix.test.ts's REGISTRY id+alias walk was already red on the base tip (414 vs. expected 412) from agnes-cn (#13399, +id/+alias). Removing chipotle's REGISTRY id/alias in this PR nets it back to 412, making the test pass again without a numeric edit — record why in a comment so it doesn't read as an untracked coincidence later.
Merged
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
diegosouzapw#13905) `APIKEY_PROVIDERS merges the 6 family files into 240 entries` fails on the release tip, taking a unit-test shard red on every open PR. Agnes AI China (diegosouzapw#13399, 517c4cf) added one `apikey/regional` entry, so the real count is 241 — confirmed at runtime: `Object.keys(APIKEY_PROVIDERS).length` is 241 and includes `agnes-cn`. The hardcoded number is deliberate, not an oversight: the test is a tripwire for silent loss or duplication across the six family files, and each bump is documented in the header with the provider and the PR that caused it. Kept that convention rather than deriving the count at runtime, which would make the test assert nothing.
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
* fix(quality): clear the release/v3.8.51 base-reds 19 failing unit tests plus the API Route Typecheck and mutation-test-coverage gates, all reproduced on the clean tip before touching anything. Ten of the failures share one cause. diegosouzapw#13452/diegosouzapw#13798 made `*-compatible-*` buildUrl() refuse a connection with no baseUrl instead of quietly defaulting to the real OpenAI/Anthropic API — which would ship the operator's stored key to a public third party. The guard is right; three fixtures still built those connections unhydrated, and one of them put baseUrl at the top level of credentials, where the chat path never reads it. The rest: - modelDiscovery.ts missed the VertexModelMetadataProvenance cast that its read-path twin in db/models/synced.ts already had — both written by diegosouzapw#12471. - A provider-test regexp carried raw 0x00/0x1f bytes, which makes git, GitHub and ripgrep treat the file as binary. Same character class, written with escapes instead of the bytes themselves. - diegosouzapw#13399 (Agnes AI China) adds "agnes-cn" + "agnescn": the only two provider prefixes since the count was last set (412 -> 414). Everything else added in that range is model ids. - The free-tier budget card SVG was stale (443 -> 452 models); regenerated by its own script. - Three new tests were missing from stryker.conf.json tap.testFiles, so the mutants they kill did not count. Three guards asserted syntax rather than the invariant they protect, and broke when the source legitimately changed. Each was re-expressed and then verified by mutating the source back: - diegosouzapw#2331 required modelEffort to head the rawEffort chain; diegosouzapw#13556 deliberately put the server-selected force rule first. The real invariant is relative — modelEffort outranks the defaults a client injects — and it still trips when explicitReasoning is moved ahead of it. - The OAuth loopback guard matched the isLocalhost arm literally; diegosouzapw#9944 added `&& !opts?.manualLoopback`. It now matches the arm whatever guards it, and still fails when the hint stops being built. - The i18n scanner flagged dynamically-built keys — t("effort." + mode) reaches it as a literal prefix, never a string. It now accepts a prefix that resolves to a namespace holding messages, and still fails when the namespace is gone. tests/unit/sse-auth.test.ts (diegosouzapw#12080) expected a bare null where diegosouzapw#13879 now returns the key-policy diagnostic — the same sentinel shape the terminal-state path has used since diegosouzapw#12441. The assertion was rewritten to the constraint diegosouzapw#12080 actually protects: nothing usable comes back and neither connection leaks. The contract risk that remains — those sentinels are truthy, and executeWebSearch treats any truthy value as a credential — is filed as diegosouzapw#13945 rather than widened into this PR. Refs diegosouzapw#13866 * fix(quality): clear the second wave of release/v3.8.51 base-reds The tip moved 13 commits while the first pass was running and brought its own reds. All reproduced locally on the merged tree first. vitest 4.1.11 -> 5.0.0 in the diegosouzapw#13661 development-group bump is a major, and vitest 5 moved `vite` from a dependency to a peerDependency. This repo only ever declared `vite` under `overrides`, which pins a version but installs nothing, so `npm ci` stopped providing it and the Vitest job died at startup with ERR_MODULE_NOT_FOUND. Declared as the devDependency it actually is — the same ^8.0.16 the override already pinned, and what @vitejs/plugin-react asks for as a peer — and regenerated the lockfile: 684 lines added, none changed. diegosouzapw#12909 filtered a mapped array with `toolCall is JsonRecord`, but the element type is the tool-call literal or null, and a predicate's type has to be assignable to the parameter's (TS2677). Narrowed by the element's own type instead; the literal still satisfies JsonRecord at the return. diegosouzapw#12906 added `|| result.errorCode === "empty_response"` to the stream-failure condition and Prettier rewrapped it, so the diegosouzapw#8928 probe — which located the branch by an exact four-line string — stopped finding it. It now matches on what the branch tests rather than how it is typeset, and still fails when the eviction call is removed. probe-7293 is the visible half of a real conflict, filed as diegosouzapw#13948. diegosouzapw#7293 merges a mid-array system into index 0; diegosouzapw#12908, landed later, demotes it to "user" in place instead. Both target the same constraint and only one can win, and the combination also reorders: the pre-translation hoist moves the turn forward expecting it to stay a system message, then the demotion converts it where it now sits, ahead of the conversation. Choosing between the two strategies is a product call, not a base-red one, so the test was realigned to assert the half that protects the caller — the instruction survives, as a user turn — and pins the current ordering with a pointer to the issue, so the eventual decision shows up as a deliberate test change instead of a silent regression. Refs diegosouzapw#13866, diegosouzapw#13948 * fix(quality): allowlist vite, rebaseline tip growth, drop a dead import Third pass on the release/v3.8.51 base-reds. Declaring `vite` in the previous commit was correct but incomplete: check-deps is a human review point against typosquatting, so a newly declared package has to be vouched for by name. Recorded in dependency-allowlist.json with why it is needed — the official Vite build tool, already pinned through overrides, and a required peer of both vitest 5 and @vitejs/plugin-react. That also turns check-deps.test.ts green. check-file-size went red on nine files. One is mine: sse-auth.test.ts grew when the diegosouzapw#12080 assertion was rewritten. Three of the four assertions I had added were redundant with the strict deepEqual that follows them, so they are gone and the file grows by 4 lines instead of 8; the cap absorbs the rest. The other eight are production and test files this PR does not touch, grown by other work and never rebaselined — which is the whole reason a base-red drain exists. Each is attributed to the commit that grew it: diegosouzapw#12906 (chat.ts, chatHelpers.ts, proxyFetch.ts, stream.ts), diegosouzapw#12904 + diegosouzapw#12910 (chatCore.ts), and batch_api.test.ts from the same wave. Two of them predate the wave entirely and were already over cap on 8a95ffa — imageGeneration.ts (diegosouzapw#13748) and roundRobinCombo.ts (diegosouzapw#13776) — so they were base-reds hiding behind a gate that only surfaced them once the tip was merged in. Both are recorded separately from the wave so the history stays honest about when each cap actually moved. Note for whoever reads the gate next: it counts one line more than `wc -l`, since it measures split length rather than newlines. Finally, diegosouzapw#13290 replaced rmSync with cleanupTempDataDir in zcode-executor.test.ts but left the import behind, which the frozen-warning ESLint gate rejects. Removed. Refs diegosouzapw#13866
muhamadgalihsaputra
pushed a commit
to niyatna/NiyatnaRoute
that referenced
this pull request
Sep 27, 2026
…) (diegosouzapw#13913) * fix(providers): remove the chipotle/pepper provider (diegosouzapw#13131) amelia.chipotle.com (the reverse-engineered Amelia chat-widget backend chipotle/pepper-1 talked to) now returns 404 on every route, including root, from its Azure Application Gateway — confirmed live 2026-09-15. This regressed from a WS handshake timeout (diegosouzapw#4037, June 2026) to a fully decommissioned host, so the upstream protocol cannot be fixed. Owner decided to retire the provider entirely (Option B), following the phind/kluster quiet-removal precedent: no REMOVED_PROVIDERS.md entry (reserved for operator takedowns), just a one-line note under FREE_TIERS.md "Removed / no free tier". Removed every surface: executor, registry entry, executors/index.ts and providers/index.ts wiring, noauth provider catalog entry, ProviderIcon generic-fallback set, the autoCombo exclusion-list comment, the chipotle_error code from the sanitizer allowlist, PROVIDER_REFERENCE.md (regenerated), and every doc/test reference. Regression test: tests/unit/issue-13131-chipotle-provider-removed.test.ts asserts the provider is fully gone from the executor registry, the provider REGISTRY and the noauth catalog, and that the executor module no longer resolves — not a live-network repro (flaky/third-party). Several existing tests used "chipotle" only as a generic noAuth-provider example (proxy scoping, error classification, onboarding, fallback text) with no chipotle-specific behavior under test; those were re-pointed at another still-existing noAuth provider (cloudflare-playground / duckduckgo-web) rather than weakened. * test(providers): document the agnes-cn/chipotle count coincidence (diegosouzapw#13131) provider-node-reserved-prefix.test.ts's REGISTRY id+alias walk was already red on the base tip (414 vs. expected 412) from agnes-cn (diegosouzapw#13399, +id/+alias). Removing chipotle's REGISTRY id/alias in this PR nets it back to 412, making the test pass again without a numeric edit — record why in a comment so it doesn't read as an untracked coincidence later.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Agnes sells two OpenAI-compatible hosts that do not share keys:
https://apihub.agnes-ai.com/v1(agnes)https://api.agnes-ai.cn/v1(newagnes-cn)Until now both lived under one
agnesregistry row whose default host is apihub. A China key imported on that card talks to apihub unless someone remembers the per-connection base-URL override. Combo routing on the live pool already splitsagnes-cn/agnes-intlby host; the product surface did not, so a new connection still defaults to the international catalog.This is the same shape as
glm-cn: sibling id, own host, own dashboard card, own/v1/modelsdiscovery. It is not a catalog bump. Agnes Image / Video stay on#13120(agnes).What
open-sse/config/providers/registry/agnes/cn/index.ts:id: "agnes-cn", aliasagnescn,baseUrl/modelsUrlonapi.agnes-ai.cn,executor: "default",passthroughModels+liveCatalogAuthoritative.glm_cnProvider.Agnes AI (China)afteragnesinsrc/shared/constants/providers/apikey/regional.ts. Visible (hiddenFromDashboardunset).hasFreewith the same free-tier note as intl (Permanently free, no API credit card required.).NAMED_OPENAI_STYLE_PROVIDERSkeeps tip's"agnes"(from#13120) and adds"agnes-cn"so China/v1/modelsis fetched on its own host.agnes-cn-freerows for 2.0 / 2.5 / 3.0 Flash. LiveGET https://api.agnes-ai.cn/v1/models(2026-09-12) listsagnes-3.0-flashand does not list retiredagnes-1.5-flash. Intlagnes-freerows, including 3.0, are untouched.ensays China keys come fromapi.agnes-ai.cnand apihub keys do not work.zh-CNis a Chinese sentence. The other 49 locales use the English sentence. Intlagnescopy is unchanged.PROVIDER_SEARCH_PAIRSandCATALOG_SIBLING_IDSmust not pairagneswithagnes-cn. Image and video registries stay withoutagnes-cn. Credential lookup foragnes-cnmust not return anagnesrow.Out of scope
#13120).agnesintl connections. Operators already split combos; this PR only gives the product a matching id.Tests
tests/unit/agnes-cn-provider.test.ts: 14 tests. Registry host, alias,parseModelprefixes, executor URL, discovery class, search-pair / sibling isolation, credential isolation, image/video absence, free-catalog 2.0/2.5/3.0, registry seed 3.0 not 1.5, dashboard card, translate-path golden, 51 onboarding keys.Merge intent
Please review and merge this contribution once the checks and conflict resolution are complete.