mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-09-20 13:52:28 +03:00
fix/12783-setup-opencode-key
67 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9af3ec5112 |
feat(video): redact transcript in the in-memory pending-request snapshot (#12430 item 6) (#12596)
* feat(video): redact transcript fields in the in-memory pending-request snapshot (#12430 item 6) trackPendingRequest (open-sse/handlers/chatCore.ts) stored the raw client body (with video transcript/audioTranscript cues) under `clientRequest`, live-exposed via /api/usage/call-logs (pendingDetails), /api/logs/[id] and /api/conversations while a request is in-flight. P2a redacted the persisted detailed-log snapshot but not this in-memory copy. Add redactPendingBody() to videoBridgeSnapshotRedaction.ts (sibling to logClientRawRequestRedacted from P2a): when videoBridgeObserved, returns the redacted clone from redactVideoTranscriptFieldsForLog; otherwise returns the exact same reference. Wire it into the trackPendingRequest call site (chatCore.ts:934), keeping the file within its frozen 5976-line budget (5971 -> 5974). * feat(video): substring-redact transcript in derived-prompt dispatch logs (#12430 item 4) Extend applyVideoBridgeLogRedaction with a string-content branch: pipeline-strategy stages, smart-auto-pipeline, and context-handoff summaries embed the transcript as a substring of a rendered prompt string rather than an exact array part, so the existing exact part-array match silently skipped them. Adds a mutually-exclusive string branch (Array.isArray vs typeof === "string") that does a replaceAll of the trusted fullText literal against a lazily cloned message, reusing the existing rootClone/clonedContainers/clonedMessages clone-on-write pattern so siblings keep original references and the input is never mutated. |
||
|
|
cb38bfa6ee |
feat(video): redact raw client-snapshot transcript fields in the detailed log (#12150 P2) (#12528)
* feat(video): redact raw client-snapshot transcript fields in the detailed log (#12150 P2) clientRawRequest.body is captured before the guardrail chain runs and persisted verbatim by reqLogger.logClientRawRequest, so it retained the client's raw transcript/audioTranscript cue text on video parts even after P1's description redaction. Add redactVideoTranscriptFieldsForLog (new, dependency-light module) and wire it at the logClientRawRequest call site, gated on videoBridgeObserved: redacts the structured transcript fields in the LOGGED copy only, never the body sent to the provider or returned to the client. * refactor(video): extract the guarded client-snapshot log call to keep chatCore within its size budget Fast Quality Gates check:file-size flagged chatCore.ts growing past its frozen ceiling (5985 > 5976) from the P2a wiring. Move the guarded logClientRawRequest call into logClientRawRequestRedacted (new export in videoBridgeSnapshotRedaction.ts, which already owns the redaction), collapsing the inline if-block at the chatCore.ts call site to a single call. Net -4 lines vs the pre-P2a base. Behavior unchanged: non-observed still logs the exact same clientRawRequest.body reference; observed still logs the redacted clone. |
||
|
|
6795783228 |
feat(providers): refresh Fable, Cursor, and Devin catalogs (#12367)
Validado em lote numa worktree combinada com #12524, #12538, #12277 e #12367 sobre o tip de release/v3.8.51: os quatro boardaram sem conflito (áreas disjuntas — zai-web, nvidia, clova, cursor/devin/fable). typecheck:core limpo, check:provider-consistency OK (272 entradas REGISTRY, 355 providers canônicos), check:known-symbols OK, e 305/305 nos testes tocados pelos quatro PRs. Os IDs de modelo adicionados foram conferidos individualmente. Obrigado, @backryun. |
||
|
|
cdd07df700 |
feat(providers): refresh NVIDIA hosted models (#12538)
Validado em lote numa worktree combinada com #12524, #12538, #12277 e #12367 sobre o tip de release/v3.8.51: os quatro boardaram sem conflito (áreas disjuntas — zai-web, nvidia, clova, cursor/devin/fable). typecheck:core limpo, check:provider-consistency OK (272 entradas REGISTRY, 355 providers canônicos), check:known-symbols OK, e 305/305 nos testes tocados pelos quatro PRs. Os IDs de modelo adicionados foram conferidos individualmente. Obrigado, @backryun. |
||
|
|
86e83d4138 |
fix(video): re-anchor transcript log-redaction so PII/credential maskers can't reopen the leak (#12150 P1 follow-up) (#12503)
* fix(video): re-anchor log-redaction fullText from the finished guardrail payload so PII/credential maskers can't reopen the transcript leak * docs(video): clarify P1 transcript-retention scope and re-anchor; list P2 surfaces (#12430) |
||
|
|
7ed8ada432 |
feat(providers): restore ChatGPT Web via clean-room browser transport (#12239)
Restores ChatGPT Web on a clean-room browser transport, merged on the operator's explicit decision. Worth stating precisely, because this touches a provenance decision: the PR does not revert #11754. It narrows RETIRED_COMMON_CHATGPT_WEB_PROVIDER_IDS to the single GPL-derived alias cgpt-web and registers chatgpt-web as a separate clean-room id. The old implementation stays retired and blocked; the retirement machinery, its error code and its 410 contract are untouched. All four retirement suites agree with that distinction and pass unchanged. The 44 protected agent-instruction surfaces this PR touches (AGENTS.md, llm.txt and its 42 mirrors, README) were verified rather than trusted: masking digits and comparing the removed and added line sets gives 264 lines on each side, identical — every change is a provider-count substitution, with no sentence added, removed or reworded. Reconciled on merge: clean against the tip, with the two chat chokepoints this PR grows (src/sse/handlers/chat.ts +40, open-sse/handlers/chatCore.ts +30) recorded in the file-size baseline under an annotation. Verified that exactly those two caps move and nothing else, so the #12411 ratchet holds. The rebaseline is carried on this branch rather than left in a validation worktree — the propagation mistake that put the 2026-09-02 merge waves base-red in #12434. Verified: 504/504 across the PR's 44 test files plus all four chatgpt-web retirement suites, check:provider-consistency OK (272 REGISTRY entries, 355 canonical providers), check-file-size OK, and every changed TypeScript file parses. Thanks @backryun — separating the clean-room id from the retired alias, instead of reopening the old one, is what made this reviewable. |
||
|
|
5ab1e9fe5c |
feat(video): redact transcript text from logs and durable memory (#12150 P1) (#12427)
P1 of #12150: transcript text no longer reaches call logs or durable memory in the clear. Reconciled on merge — the two persisted-requestBody assertions were failing, and the failure signature was misleading enough to be worth recording. They reported "expected: true, actual: false", which reads like the redaction not applying. It was not: pollForCallLog waited at most 120 tries x 20ms = 2.4s for the asynchronous SQLite write, then returned null, so assert.ok(row) failed before any redaction assertion ran. The observed durations were 5253ms and 4467ms against that 2.4s ceiling — a starved runner, not a leak. The control test failing alongside the positive one was the tell: a real redaction defect would break one direction, not both. Replaced the fixed try count with a 30s wall-clock deadline: far past any healthy write, still bounded, and a fast machine still returns on the first pass. A privacy test should not depend on how busy the box is. Verified: 4/4 three consecutive times under synthetic load, and 3/3 unloaded beforehand. Note the synthetic load reached ~7, below the ~38 where the original failure appeared, but the budget is now 12.5x larger and deadline-based rather than count-based. |
||
|
|
290f723ec0 |
fix(guardrails): keep auto combos exempt from the vision bridge credential guard (#12373)
getBestVisionModel() validates a configured fixedModel with hasUsableCredentialsForModel() before short-circuiting (#8430). auto / auto/* ids are virtual combos with no provider row, so that check always reported a confirmed false and the combo was silently discarded in favour of global auto-selection — it never got the chance to rotate its members. This mirrors the exemption the reroute guard in visionBridge.ts already carries; concrete fixedModel ids keep the #8430 fall-through unchanged. Validated in a combined worktree with all 25 PRs of this batch boarded together: typecheck:core clean, 443/443 node-runner tests plus 14/14 vitest across every test file the batch touches, and check-changelog-integrity, check:cycles (418 files), check:provider-consistency (272 REGISTRY entries, 355 canonical providers), check:docs-counts, check:docs-sync (42 locales) and check-file-size all green. Thanks @pacocartones. |
||
|
|
c1ac943c70 |
refactor(video): unify the JPEG frame data-URI contract (#12322)
The contact sheet, the dedup comparator and the drill-down each validated JPEG data-URIs independently. They now share src/lib/guardrails/videoBridgeFrameContract.ts. No behaviour change; the sibling tests that asserted a per-module message were aligned to the shared one. Closes the Standards-4 residue from the 2026-08-18 Video Bridge review. Verified in a combined worktree with three sibling PRs of this batch: typecheck:core clean, 134/134 focused tests (4 skipped), i18n UI coverage PASS across all 42 locales. |
||
|
|
6dd82b77de |
fix(guardrails): pass providerId to getResolvedModelCapabilities in checkComboVision (#12112) (#12169)
* fix(guardrails): pass providerId to getResolvedModelCapabilities in checkComboVision (#12112) Signed-off-by: Minxi Hou <houminxi@gmail.com> * chore(quality): register combo-vision providerId test in the stryker tap set --------- Signed-off-by: Minxi Hou <houminxi@gmail.com> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> |
||
|
|
36b7920db1 |
refactor(video): extract a Video Bridge pipeline with explicit ports (#12016)
Extracts videoBridge.ts's per-part loop body, whole-result cache identity/key helpers, and describeWithVisionModel into a new videoBridgePipeline.ts with explicit port boundaries (VideoMediaBrokerPort, VideoAudioTranscriptionPort, VideoDrilldownPort). videoBridge.ts shrinks 820→255 lines, now only handling request traversal, policy resolution, aggregation, and response payload. Moved as whole blocks, parameterized rather than rewritten — byte-for-byte traceable to the pre-extraction code. Rebased onto the tip after sibling #12009 (FU-05 core) landed first and bumped the result-cache version v4→v5 in videoBridge.ts — that same bump (plus its explanatory comment) is now carried into the extracted videoBridgePipeline.ts instead. Re-validated: 20/20 focused tests, typecheck clean. |
||
|
|
5fcd39bd6f |
feat(video): orchestrate Audio Bridge STT with one-download budgets (FU-06, #11654) (#12012)
FU-06 (Audio Bridge STT orchestration): one download, two extractions — takes already-downloaded video bytes and extracts bounded mono 16kHz PCM WAV via the loopback broker's new mode=audio operation, sharing the exact same queue/deadline/byte budgets as the frame path. Dual opt-in (operator setting default false + per-request), only reaches the STT call when both are on. Rebased onto the tip after sibling #12011 (subtitle mode) landed first, both touching the same broker route/client — combined additively so frames/audio/subtitles all share the one extractionQueue singleton. Re-validated: 59/59 focused tests pass. |
||
|
|
f30e5b2675 |
feat(video): connect tenant-bound drill-down lifecycle and multiresolution variants (FU-08) (#12006)
FU-08 (Refs #11655): drill-down producer/consumer lifecycle on top of the existing cache substrate, without modifying it — new VideoDrilldownLifecycle (opaque sha256 handles, principal-bound resolve/delete with no existence oracle, preview/standard/detail multiresolution variants, 8-frame/32MiB page budget) plus a new authenticated remote-consumer route, both opt-in (default false). |
||
|
|
ef668967f6 |
test(video): freeze FU-07/FU-09 promotion-evidence manifest, aggregator, evaluator and allowlist scaffold (#11656) (#12008)
FU-07/FU-09 promotion-evidence harness (Refs #11656): delivers the manifest schema, deterministic fixture recipes, metrics aggregator, and promotion-verdict evaluator #11656 asks for — deliberately does NOT deliver the promotion verdicts themselves (they require real models against real fixtures on a live host, HOLD with explicit reason instead of any fabricated result). New files only, no collision with sibling PRs. |
||
|
|
60dc242178 |
feat(video): derive embedded subtitle provenance in the protected broker (#11659) (#12011)
FU-05 subtitle adapter (Refs #11659 — deliberately not Closes: the adapter is not yet wired into the live describeVideoPart path, that composition point is sibling #12009 which just landed): server-owned, loopback-only ffprobe/ffmpeg subtitle extraction that legitimately earns the "embedded" provenance label, mirroring the existing frame-extraction lifecycle. Broker route now also serves ?subtitles=1, stamped with the shared broker fingerprint so the client-side adapter can verify the payload actually came from the trusted process. Bounded, ReDoS-safe WebVTT parser. |
||
|
|
3b00535d04 |
feat(guardrails): enforce video transcript provenance, budgets and reconciliation (#11652) (#12009)
FU-05 core (closes #11652): caller-supplied Video Bridge transcripts had no bounded, deterministic contract — a client could self-assert source: "embedded"/"audio-bridge" and it was accepted verbatim. normalizeVideoTranscript gained a code-only trustedSource seam unreachable from request-body JSON; without it, any cue declaring embedded/audio-bridge is reclassified to client. Added budgets (256 cues, 4096 code units/cue, 4KiB/cue, 64KiB total), malformed-surrogate rejection, focus-window scoping, deterministic cross-source reconciliation, and bumped the result-cache version v4→v5 so old-contract cache entries can never serve new-contract requests. All 187 videoBridge* tests pass (185 pass, 2 unrelated pre-existing skips). |
||
|
|
3d4f3e4960 |
test(infra): retry recursive temp-dir removal instead of failing a shard on ENOTEMPTY (#11966) (#11968)
* test(infra): retry recursive temp-dir removal instead of failing a shard on ENOTEMPTY (#11966) Two shards on release/v3.8.51 went red in one day with the same signature — "ENOTEMPTY, Directory not empty: /tmp/omniroute-<test>-XXXXXX" — from combo-same-provider-cascade (Unit Tests fast-path 4/4, on a PR that touches only .github/) and auth-policy-embeddings-webfetch-7785 (the 20k-test TIA step). Both pass alone and on re-run: the cleanup races something still writing into the directory (SQLite WAL/-shm checkpoint, a worker, the backup) and under a loaded hosted runner the window opens. 1154 test files do their own cleanup with fs.rmSync(dir, { recursive: true, force: true }); 57 already asked for retries. One-shot codemod (scripts/ad-hoc/codemod-rm-maxretries.mjs, kept for the record): every rm / rmSync / rmdirSync option object with `recursive: true` and no `maxRetries` gains `maxRetries: 5, retryDelay: 100` — Node itself then retries ENOTEMPTY/EBUSY/EPERM for up to ~0.5 s before giving up. 2243 call sites in 1292 files under tests/, the shared tests/_setup/isolateDataDir.ts exit hook included. Only the option object changes: no call site, assertion or import is touched. Validation: prettier and ESLint (with the frozen suppressions) clean on all 1292 files; a random 20-file sample runs green (quota-redis-store hangs identically on the untouched tree — it needs a Redis on localhost, an environment matter). The four unit shards on this PR are the full run. * fix(quality): let check-forgotten-sibling-tests read a 1,000-file diff The gate shells out to `git diff` through execFileSync with Node's default 1 MB maxBuffer; the 1,292-file codemod in this PR is the first diff large enough to overflow it, and the gate died with `spawnSync git ENOBUFS` before comparing anything. 64 MB is far above any real PR and costs nothing when unused. |
||
|
|
13afbfafb2 |
fix(vision-bridge): honor authoritative live catalogs (#11813)
Reconciles Vision Bridge auto-selection with each provider's authoritative live model catalog, revalidating cached selections and preserving routable aliases / live-catalog IDs / registered effort variants, with fail-open behavior kept when the catalog is unavailable or non-authoritative. Closes #11767. One test-side fix applied before merge: "accepts a registry model whose liveCatalogIds match upstream" used `cgpt-web` (ChatGPT Web) as its fixture provider — retired by #11754 after this PR was authored, which removed every live registry entry populating `liveCatalogIds` and made the test's expected model unreachable (null, not the retired id). Swapped the fixture to a synthetic PROVIDER_MODELS entry (the registry Proxy is writable and reverted in `finally`) so the same production predicate is exercised without depending on since-deleted registry data. 16/16 focused tests passing on the current tip. Thanks for the fix! |
||
|
|
46b8e7a9b7 |
fix(video-bridge): preserve fused timeline ordering (#11681)
Merged via /merge-batch (v3.8.51). Boarded and validated in a combined worktree alongside the batch's other in-flight PRs — full gate suite green (typecheck:core, lint, complexity/cognitive-complexity, file-size, changelog-integrity, focused tests including the video-bridge fusion/transcript suites). Thank you. |
||
|
|
04dba0460e |
fix(responses-continuation): recover a real id/output for passthrough and translate-mode replies (#11434)
Retargetado para release/v3.8.51 (release/v3.8.50 está congelada — freeze issue #11439). Validado em lote combinado (batch-0824h2, junto de #11435/#11436/#11437) contra o tip de release/v3.8.51: typecheck:core limpo, gates estáticos OK, 127/127 testes focados passando. Investigação sólida com repro real via container isolado, três causas independentes identificadas e corrigidas com testes de regressão dedicados para cada uma. Obrigado pela contribuição! |
||
|
|
137e49e393 |
feat(search): first-class X Search via SuperGrok x_search (#10988)
⭐5 — Provider x-search de primeira classe (SuperGrok/xAI x_search) em POST /v1/search e MCP omniroute_x_search. Fallback de credenciais xai-oauth→xao→xai; distinto de web search e do X Developer MCP. Reconciliado com o release tip (que já incluía #10981 "skip catalog-default SearXNG" deste mesmo lote): merge trouxe 5 conflitos reais de contagem gerada (llm.txt/README.md/AGENTS.md/PROVIDER_REFERENCE.md/SVGs/46 mirrors i18n, todos verificados como bump puro 347→348, sem perda de conteúdo do HEAD) + 1 conflito real de mergeable=CONFLICTING. Durante a validação, os 3 testes novos de SearXNG expuseram um bug real de interação com #10981: `isUnconfiguredLoopbackSearchProvider()` checava o baseUrl ESTÁTICO do catálogo em vez do baseUrl efetivo (após override de `provider_options.baseUrl` ou `providerSpecificData.baseUrl` da conexão), então QUALQUER request a searxng-search — mesmo com override customizado — era rejeitado como se fosse o default não-configurado. Corrigido em `open-sse/handlers/search.ts` (resolve o baseUrl efetivo via `resolveSearchBaseUrl()` antes do skip-check, tanto para o provider primário quanto o alternate). Um teste do próprio #10988 que assumia o comportamento pré-#10981 (default localhost:8888 sempre atendido) foi atualizado para refletir o comportamento já mesclado e intencional (503 quando não configurado). Validação completa: typecheck limpo, 70/70 testes unit (search-route/search-registry/x-search-provider/searxng-loopback-default), 24/24 vitest MCP, 14/14 integration (search-providers-catalog), lint limpo nos arquivos tocados, docs-counts-sync OK (2 drifts soft pré-existentes, não relacionados), gates estáticos (file-size/complexity/cognitive/dead-code/changelog) todos OK. |
||
|
|
3805494250 |
feat(vision-bridge): consolidate vision bridge fixes (catalog verdict, creds, cache key, CC vision) (#10859)
Validado no worktree combinado do lote: typecheck:core, lint, gates de qualidade (file-size rebaselineado com justificativa — crescimento legítimo em modelCapabilities.ts/commandCode.ts) e os 97+9 testes focados (vision-bridge, command-code vision, model-select-field-catalog-vision) todos verdes. Duas correções reais (#10808/#10809) bem documentadas. CI vermelho neste PR é o base-red já rastreado em #9985. Obrigado! |
||
|
|
f0bf6d2a93 |
fix(guardrails): resolve provider alias before credential check in Vision Bridge (#10702) (#10760)
Co-authored-by: Markus Hartung <mail@hartmark.se> |
||
|
|
458ab1aac0 |
fix(vision): preserve high detail for inline images (#10554)
* fix(vision): preserve high detail for inline images * fix(vision): scope high-detail image default to OpenCode clients defaultImageDetail() was applied at prepareUpstreamBody, the shared upstream-body prep path for every provider and format, not just the OpenCode path the fix targets. Gate it on isOpencodeClient (the existing User-Agent/x-opencode-* header signal already used for bypassDefaultToolLimit at this call site) so non-OpenCode callers keep the provider's own image detail default. Adds a regression test covering a non-OpenCode caller against the same opencode-zen provider. * fix(vision): document and test the global vs OpenCode-only detail scope The OpenCode-only high-detail default in chatCore/upstreamBody.ts (defaultImageDetail, gated on isOpencodeClient) forwards the caller's own image_url.detail and was already correctly scoped in a prior commit on this branch. The internal vision-bridge describe self-loop (visionBridgeHelpers.ts) is architecturally global: VisionBridgeGuardrail runs for every caller/provider whenever the target model lacks vision support, and there is no client-identity signal at that layer to gate on. Its describe prompt explicitly asks the vision model to transcribe visible text, so requesting "high" detail unconditionally is justified on its own merits (OCR accuracy), independent of the OpenCode motivation. Adds a compatibility assertion proving the Anthropic wire-format branch of the same describe self-loop carries no `detail` field (it has no such concept) and is therefore unaffected by this default, and documents the split (OpenCode-only forwarding vs. global describe default) in docs/security/GUARDRAILS.md. Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> --------- Co-authored-by: rinseaid <rinseaid@rinseaid.net> Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com> |
||
|
|
e7858d7165 |
feat(video): cap the drill-down cache with a global byte budget
The per-session drill-down cache now tracks decoded bytes per entry and evicts least-recently-used entries until an aggregate maxTotalBytes budget fits (route sets 256 MiB); an entry larger than the whole budget is rejected. Prevents the previous worst case of 64 x 32 MiB (~2 GiB) pinned in memory. |
||
|
|
533e5c6ec7 |
feat(video): surface audio/video fusion telemetry and degrade invalid audio to partial
The fusion result's availability, partial and failure fields now reach DescribedVideo.fusion, the guardrail meta (audioFusionRuns/Partials/ FailureCodes), the result-cache metadata and bridge stats. Audio transcript validation moved inside the fusion's audio branch, so an invalid audioTranscript records failures.audio and keeps the visual description instead of failing the whole video. |
||
|
|
ffb0cbc10b | fix(video): include audioTranscript and focus window in the result cache key | ||
|
|
68b3fe715a | feat(video): add timestamped contact sheets | ||
|
|
bb22eeba8d | feat(video): add isolated drill-down cache | ||
|
|
edb3abf323 | feat(video): add segment-aware sampling | ||
|
|
350b161620 | feat(video): add optional audio fusion timeline | ||
|
|
ad9384c3ea | feat(video): preserve transcript provenance | ||
|
|
ffa6849cc8 | feat(video): add validated focus windows | ||
|
|
596a1035c3 | feat(video): add conservative frame deduplication | ||
|
|
2c33638643 | feat(video): add scene-aware sampling fallback | ||
|
|
91ea94fb50 | feat(video): cache full video-bridge results with metadata | ||
|
|
b75f7dde93 |
fix(guardrails): reroute zero-vision combos through the vision bridge (#10415)
* fix(guardrails): reroute zero-vision combos through the vision bridge Named combos whose model targets all lack vision support are never reroute-eligible: the bridge only attempts the describe path, and when describing cannot run or fails the raw images stay in the payload and the request dies in the combo capability filter with capability_mismatch. getComboVisionBridgeDecision now returns a "no-vision" verdict for combos with zero vision-capable targets, and preCall treats it as reroute-eligible with the same credential guards as single text-only models, falling back to describe only when no usable reroute target exists. * chore(changelog): fragment for #10415 vision bridge combo reroute * fix(guardrails): extend allNull stub fallback to no-vision combos Reviewer follow-up (#10415): the allNull stub-text fallback at the end of preCall only fired for comboVisionBridgeDecision === 'process'. In the compound-failure case for a zero-vision combo — reroute target without usable credentials AND every describe call failing — raw images were preserved and the original capability_mismatch recurred, because a no-vision combo has no target that can consume images. Include 'no-vision' in the guard: stub text is strictly better than raw bytes no combo target can consume. Adds a double-failure unit test. * ci: re-run dast-smoke (Build CLI bundle runner timeout flake) * fix(build): bound and retry the opencode-plugin npm install in prepublish The plugin's node_modules is gitignored, so every fresh CI checkout runs a full npm install inside @omniroute/opencode-plugin during build:cli. npm's unbounded fetch retries turn a stalled registry CDN connection (the recurring onnxruntime-class ETIMEDOUT flake) into a 20-30 minute hang — the DAST 'Build CLI bundle' step has been cancelled at the 30m cap repeatedly. - Bound npm fetch: --fetch-timeout 60s, 2 retries with capped backoff — a stalled connection now fails fast instead of hanging the job. - Retry the install up to 3 times with a 10s pause between attempts, so transient CDN failures recover in-build. Net effect: the step either completes (network OK) or fails quickly with a clear error (network down) — it can no longer eat the whole job budget. * ci(dast): use existing npm-ci-retry action instead of bare npm ci dast-smoke died at 'Run npm ci' with connect ETIMEDOUT to the onnxruntime-node binary CDN (Microsoft 150.171.x.x) — the same transient CDN flake class that has hit Vitest/Quality Gates before. quality.yml already wraps npm ci in ./.github/actions/npm-ci-retry (3 attempts, exponential backoff); dast-smoke was the one workflow still using a bare install. Use the existing action for consistency. * ci(quality): use the npm-ci-retry action on every install step Fast Quality Gates failed on the recurring onnxruntime-node postinstall ETIMEDOUT (Microsoft CDN 150.171.x.x) - the same transient flake that has hit Vitest and dast-smoke today. Only the Build job used the retry action; the other five jobs (Docs, Fast Quality Gates, Vitest, Unit Tests, changelog) still ran a bare install and die on any CDN hiccup. Use the existing retry action (3 attempts, exponential backoff) on every install step for consistency. --------- Co-authored-by: Rouzbeh <rqzbeh@users.noreply.github.com> |
||
|
|
b1d710d45b | fix(video-bridge): route captions through provider connections | ||
|
|
5379493bed |
feat: add Video Bridge frame sampling (#10483)
Implements the secure, opt-in Video Bridge for issue #9760, including bounded FFmpeg frame extraction, capability-aware routing, telemetry, settings UI, localization, documentation, and regression coverage. |
||
|
|
dc185e5aab |
fix(guardrails): support Responses input images in Vision Bridge (#10202)
* fix(guardrails): bridge Responses input images * docs(changelog): add #10202 Vision Bridge fix fragment |
||
|
|
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> |
||
|
|
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> |
||
|
|
f5ce51a9ff |
feat(providers): add Conol (conol.ai) web session provider (#8974)
* feat(providers): add Conol web support
* fix(conol): preserve sessions and image turns
* fix(conol): pin session model and effort via /model endpoint
Conol ignores agentModel/agentEffort on POST /api/sessions, so every
session silently ran on the downgraded account default (the create
response reports modelDowngraded: true / effectiveModel).
Sessions are now created empty and configured out-of-band against
POST /api/sessions/{id}/model before the first turn is submitted, in the
order the web client uses: modelPreset, then agentModel, then agentEffort.
The ordering is load-bearing because the model call resets agentEffort to
null server-side.
Effort now defaults to xhigh when the caller does not pin one via the
-<effort> model suffix, and is clamped onto the ladder each model actually
advertises, so xhigh degrades to high on claude-sonnet-5 and is skipped
entirely for models without an effort ladder such as openrouter/fusion.
Model and effort are also dropped from the session binding key so switching
models re-pins the existing session instead of stranding it and losing the
conversation history. Re-pinning only happens on an actual change, so
steady-state follow-ups cost no extra round trips.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
1f45cf885c |
fix(vision): preserve images for text-only routes (#9037)
* fix(vision): preserve images for text-only routes * fix(i18n): complete Vietnamese vision bridge copy * fix(ci): drain prerelease tag input --------- Co-authored-by: rinseaid <rinseaid@rinseaid.net> |
||
|
|
4d0182daa0 |
feat: bridge audio inputs for text-only models (#9807)
* feat(modality-bridge): resolve audio input capability * feat(modality-bridge): resolve audio runtime settings * feat(modality-bridge): add audio transcription helpers * feat(modality-bridge): add Audio Bridge guardrail * feat(dashboard): make Modality Bridge audio tab functional * docs(guardrails): document Audio Bridge runtime * fix(modality-bridge): harden audio catalog and response header * chore(changelog): record audio modality bridge --------- Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com> |
||
|
|
d7d98fe356 |
fix(guardrails): vision bridge reroute/pool/self-loop fixes (#9946)
- auto/best-vision and auto/pro-vision now resolve to the vision CATEGORY (candidate filter by capability) instead of the flat smart variant, so the vision-bridge describe/reroute target can actually see images (resolveBuiltinAutoSpec in builtinCatalog). - vision candidate pool excludes registry entries whose catalog OVERSTATES vision support (opencode-go/opencode-zen/tokenrouter are forced through the vision bridge by isVisionBridgeForcedModel) in both the auto-combo candidate filter (suffixComposition) and the vision router (visionBridgeRouter). - reroute guard: an auto/* target is a virtual combo; a missing 'auto' provider row (hasUsableCredentials=false) must never block the reroute. - claude-wire backends (minimax, zai, ...) reject remote image URLs (MiniMax 403 2013): ensureBase64ImagesForClaudeWire resolves URLs to base64 before rerouting, and the describe self-loop normalizes to base64 for those targets (isClaudeWireFormatModel). - self-loop describe uses a real DB-backed key (resolveSelfLoopApiKey) instead of the sk_omniroute sentinel rejected by REQUIRE_API_KEY instances, and bypasses the runtime's hooked global fetch via undici (ProxyFetch with a dead local proxy would otherwise break every describe); compression is disabled on the self-loop sub-request so image payloads are never mangled. Tests: vision-bridge-auto-reroute (2), vision-bridge-selfloop-key (4), vision-bridge-claude-wire (6), builtin-vision-spec (4), vision-filter-excludes-forced (4). Co-authored-by: herjarsa <herjarsa@users.noreply.github.com> |
||
|
|
e62516364c |
fix(types): validate Vision Bridge combo names (#9565)
Merge-train validated (tip 6ce4effef8). Vitest failures confirmed as base-red (#9679). |
||
|
|
c40d4b17ee |
fix(ci): clear the NEW base-reds from the 08-06 merge batch (migration collision #2 + broken import) (#9688)
* test(base): realign six suites with contracts that #9100/#8990/#9009 deliberately changed Continuing the base-red drain — every one of these reproduces on the pure tip. - tests/snapshots/provider/translate-path.json: regenerated via UPDATE_GOLDEN=1. The diff is ADDITION-ONLY — the unorouter block from #9009; no existing provider entry changed. 3/3. - tests/unit/provider-models-route.test.ts: |
||
|
|
813dbb6e03 |
fix(vision): prevent bridge streaming and normalize OMP effort (#8945)
Validated in post-merge-train sweep (boards clean on release/v3.8.50 tip) |
||
|
|
8180b49ce1 |
fix(quality): 2 production bugs + 24 unit base-reds + measured gate ceilings (#9529)
* fix(quality): resolve net-new lint errors and allowlist #9343 assert rewrite Two `no-explicit-any` errors landed with #9407 and #9320 after the suppressions inventory was generated. Project policy is to fix new violations rather than freeze them, so both are typed instead: - #9407: `executor as unknown as Record<string, unknown>` - #9320: `(k: { name?: string })` Also allowlists the net-assert reduction in web-tools-translation-2820 (39->35). #9343 inverted the contract — bare JSON must no longer be promoted to tool_calls without an explicit <tool> envelope — so the tests were rewritten to assert non-promotion, which costs fewer asserts than validating a promoted object. More restrictive, not weaker. * fix(quality): raise integration ceiling to 40min and unpin codex-cli version in test The integration gate's 20min ceiling killed a healthy run: measured 22m08s hermetic on an idle 16-core box (935 tests across 112 files, strictly serial at --test-concurrency=1 because ~16 of them bind a port or share a DB). The "~3-10min" estimate in the code was stale by ~3x. 40min keeps the ceiling's real purpose — turning a genuine hang into a visible failure — without failing a long-but-healthy suite. Also fixes a base-red in chat-pipeline: |