Commit Graph

2915 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza
c8d7d9dd27 fix(video-bridge): harden transcript retention boundaries 2026-08-26 13:11:16 -03:00
Diego Rodrigues de Sa e Souza
691f8e4173 feat(video-bridge): derive embedded transcript provenance 2026-08-26 10:37:11 -03:00
Xiangzhe
7448780cbd fix(cli): restore the full health view for the loopback CLI (check:pack-boot)
check:pack-boot booted the packed tarball fine but failed its version
assertion: `version "undefined" (expected "3.8.50")`. The artifact was
not broken — the health payload was.

#11040 (GHSA-mvf8-qc78-5mxm) reduced GET /api/monitoring/health to a
liveness-only view for non-management callers. But that route is
classified PUBLIC (src/shared/constants/publicApiRoutes.ts:67) and
runAuthzPipeline deletes CLI_TOKEN_HEADER from the forwarded headers for
EVERY route class (src/server/authz/pipeline.ts), so a handler can only
learn that a local CLI authenticated from the subject the policy stamped.
publicPolicy stamped `anonymous` unconditionally, so requireManagementAuth
in the route 401'd even for a valid loopback machine token and every
caller got `{status, setupComplete}` — no `version`.

Verified on the installed tarball before the fix: the same token that
returns 200 on /api/cli/whoami (MANAGEMENT, where the pipeline does stamp
the subject) got the anonymous body on /api/monitoring/health.

publicPolicy now stamps the same loopback-gated `local-cli-token` subject
the MANAGEMENT policy already produced. The shared verdict (peer-locality
resolution + constant-time token compare) moves to
src/server/authz/peerContext.ts so both policies use one implementation —
no behavior change on the MANAGEMENT side. Anonymous callers keep the
liveness-only view.

Tests: publicPolicy stamps the CLI subject only for a loopback peer with a
valid token (both negative controls asserted; the positive case fails on
the pre-fix policy), plus a health-route pin that a stamped local-CLI
caller receives `version`. check:pack-boot green end to end (boot #1,
machine-token contrast, sql.js round trip, boot #2 persistence).
2026-08-26 02:45:03 -03:00
Xiangzhe
7cde1163f2 fix(dashboard): restore expert-mode manual model entry in the combo builder
PR #8285 (global model search) replaced the expert-mode "Manual model"
block positionally with the new GlobalModelSearchPanel, dropping the only
way to type a provider/model pair by hand in expert mode. The supporting
state and handlers (manualModelInput, manualModelError,
manualModelHasDuplicate, handleAddManualModel) survived as dead code, so
neither typecheck nor lint flagged the loss.

Re-render the block above the search panel, unchanged from its pre-#8285
form. Regression guard: tests/e2e/combos-flow.spec.ts "expert mode shows
a single-page combo form with manual model entry", which had been failing
with a 180s timeout on locator.fill for combo-manual-model-input.
2026-08-25 21:30:43 -03:00
Xiangzhe
a11930ec44 fix(sse): honor per-step connection pins instead of rotating accounts on fallback
A combo step pinned with an explicit `connectionId` (or a request pinned via
`x-omniroute-connection`) is an operator instruction, not a hint. The generic
account-fallback branch in handleSingleModelChat excluded the pinned connection
after an upstream failure and re-selected a sibling account of the same provider,
so a priority combo repeating one provider/model with two different fixed accounts
ran both attempts under the FIRST step: the second step, with its own pin, never
executed and per-step attribution (comboStepId / comboExecutionKey) was wrong.

Gate the rotation on `!hasForcedConnection`, matching the antigravity
stream-readiness, pre-response-timeout and account-semaphore branches that already
let pinned steps fall through to combo orchestration. Cooldown recording via
markAccountUnavailable is unchanged, and unpinned selection still excludes burned
connections.

Refs tests/integration/combo-routing-e2e.test.ts
2026-08-25 19:56:31 -03:00
Xiangzhe
45fde4fd05 fix(api): restore the after() injection point for the /v1/models SWR refresh
`/v1/models` has passed a third argument to `getUnifiedModelsResponse()`
(`{ scheduleBackgroundRefresh: (task) => after(task) }`) ever since #10198, but
#9199 had already removed the parameter: the function takes two, so the object
was silently dropped and `catalogCache` kept scheduling the stale-while-
revalidate rebuild with `setTimeout(..., 0)`. The builder is overwhelmingly
synchronous under the single-threaded App Router, so it pinned the event loop
before the stale response was flushed — the #8728 guarantee did not exist.

- `catalogCache` now imports `after` from `next/server` and exposes
  `defaultBackgroundRefreshScheduler`, which defers to `after()` and falls back
  to a macrotask outside a Next request scope (instrumentation warm-up, tests).
- `resolveCachedCatalogResponse` takes `scheduleBackgroundRefresh` and
  `getStaleWhileRevalidateMs` on its existing options object.
- `getUnifiedModelsResponse` accepts the options object the route already passes
  and propagates the scheduler.

The excess argument was invisible to CI: `tsconfig.typecheck-core.json` is a
curated 27-file allowlist, `check:dashboard-typecheck` only covers
`src/app/(dashboard)`, and `next.config.mjs` sets `ignoreBuildErrors: true`.

Closes #11551
2026-08-25 19:56:30 -03:00
Xiangzhe
37d784b0fe fix(search): prefer the configured search connection over duckduckgo-free
When no explicit provider is requested and the auto-selected cheapest
provider has no credentials, executeWebSearch ran the fallbackOnly loop
first. duckduckgo-free (costPerQuery 0, authType none) always won there
with an empty credentials object, so a configured paid connection such as
serper-search was silently ignored and the caller got success:true with
zero results.

Move the sweep for other credentialed regular providers ahead of the
fallbackOnly loop (and exclude fallbackOnly ids from it, so a free
last-resort provider never outranks a configured one on cost). The
fallbackOnly loop stays as the true last resort.

The chat path only appeared correct because duckduckgo-free happened to
fail there and handleSearch retried the alternate provider; on
/v1/responses it "succeeded" with no results.

Closes #11524
2026-08-25 19:56:30 -03:00
Xiangzhe
79478a6676 test(vitest): pay heavy module imports at collection time, not out of the per-test budget
The remaining ui-shard reds were one class, not six bugs: every one of them did
`await import(<heavy component>)` INSIDE an `it()`, so Vite's transform of the
dependency graph was billed to that test's timeout. Measured costs against the
budgets they had to fit in:

  ProxyRegistryManager   86s import vs 30s / 60s / 5s budgets (render itself: 567ms)
  claudeTlsClient       ~12s import vs 5s default
  useProviderConnections  1050-line hook, whole dashboard graph, vs 5s default

That is why they looked like cross-file pollution: on an idle box the import
squeaked under the limit, and under the ui suite's 20 parallel workers it did not.
Running claudeTlsClient ALONE on a loaded box reproduces it — the trigger is CPU
contention, not a neighbouring file. The sibling chatgptTlsClient/grokTlsClient
tests import the same graph and never fail, because they import statically at
module scope, where the cost falls on the collection phase which has no per-test
budget. Every fix here does the same: static import or a beforeAll with its own
budget.

AutoComboCatalog also explains its own blast radius: the timeout aborted inside an
open act(), leaking an unbalanced act scope that then failed the file's three
remaining tests in ~20ms with 'overlapping act() calls'. One slow import, four reds.

CoolingConnectionsPanel is the one production change. It imported providerText from
the ../providerPageHelpers barrel, but that symbol is DEFINED in the
../providerCredentialText leaf and only re-exported by the barrel — which drags
providerRegistry (352 providers) and the rest of the provider-page graph into a
"use client" component for one string helper. Verified before accepting: the
component used nothing else from the barrel, the barrel has no top-level
side-effect to lose (the empty-registry hazard this repo has hit before does not
apply), typecheck:core is clean, and the panel's first test drops from ~4s to 95ms.
The import was suboptimal, never broken — the screen was not failing for users.

No assertion was weakened anywhere. expect() counts are unchanged (25/25, 4/4) or
up by one (AutoComboCatalog 11 -> 12); the #8855 autofill sentinels, the
data-1p-ignore / data-lpignore guards and the dead-status round-trip are intact.

The #5918 TDZ guard was proven still live by mutation, not by absence of red:
moving useProxyBatchOperations(load) above its const reproduced
'ReferenceError: Cannot access load before initialization' in 207ms, then the
production file was restored (diff empty).

tests/unit/ui under load: 17 failed files / 45 failed tests -> 4 failed files /
4 failed tests, none of them these. The four left are compression-guidance-7530,
compressionPanel, compressionUltraTier and lobe-provider-icons-stepfun, untouched
and uninvestigated.

Refs #10692
2026-08-25 10:27:32 -03:00
Xiangzhe
486a2650b9 fix(i18n): unstale trafficInspectorSubtitle across 32 locales and regenerate the omni-inference skill
Two gates in the Lint job, both inherited — each was hidden behind the one before it.

i18n value drift: #11283 rewrote sidebar.trafficInspectorSubtitle in en.json without
touching the 42 translations, so 32 locales kept serving a sentence the English no
longer says. Most take the documented __MISSING__: placeholder, which makes the
runtime serve the corrected English until the translation pipeline catches up.
Three do not:

  - vi cannot take a placeholder at all — tests/unit/i18n-vi-completeness.test.ts
    bans any __MISSING__/__TODO__ value outright, so it needs a real translation.
  - pt and pt-BR are translated for real rather than placeheld, because a placeholder
    there means this project's own maintainer reads the sidebar in English.

Each file changed by exactly one line; the JSON was not reserialised wholesale.

agent-skills-sync: skills/omni-inference/SKILL.md was missing the ElevenLabs voices
and speech-to-text routes added by #11312, so the generator reported one file out of
date and the gate exited 2. Regenerated — purely additive, 48 lines, no deletions.

Verified: check-ui-value-drift PASS, i18n:check-ui-coverage PASS (42 locales),
i18n-vi-completeness 5/5, check:agent-skills-sync 46 unchanged.

Refs #10692
2026-08-25 09:57:26 -03:00
Xiangzhe
dd3a0f0189 test(vitest): realign five sibling-test contracts unmasked by the green mcp shard
None of these are cycle regressions. The Vitest job runs test:vitest (mcp shard)
then test:vitest:ui; the mcp shard was failing on a missing glm-5.3-max and aborted
the job before the ui shard ever ran. Fixing that shard this cycle unmasked 34 ui
failures that had been broken since 18-23 Aug — four separate PRs that moved a
contract and updated their own tests but not their siblings.

- ProviderCard gained useRouter() in #10448; four test files render it without
  mocking next/navigation and died on 'invariant expected app router to be mounted'.
  The sibling created alongside #10448 already had the mock — it just was not
  applied to the other four consumers.

- SkillCoverage gained a required config category. The four fixtures in
  agent-skills-page still described only api/cli, so the component read
  config.have off undefined. Values were chosen per scenario rather than pasted:
  full coverage gets 2/2 so its bar stays emerald, the amber fixture gets 3/4 so it
  stays amber. CoverageBar renders api -> config -> cli, so the new bar lands in the
  MIDDLE and the cli assertions moved from index [1] to [2]; without that the cli
  checks would have passed while measuring the config bar. The aria test now pins
  all three bars.

- CliAgentsPage hardcoded AGENT_IDS, which had already drifted once (6 -> 8 with
  omp/letta, per its own comment) and drifted again with prime-agent (#11166). It is
  now derived from CLI_TOOLS. This is why an agent missing from that list is not
  cosmetic: it never enters the status map, defaults to not_installed, and adds a
  phantom card to the filter and count tests. Deriving keeps the fixture in sync by
  construction instead of waiting for the next agent.

- claudeTlsClient asserted proxyUrl was undefined inside a test literally named
  'falls back to env var when per-call proxyUrl not provided' — it pinned the old
  behaviour where testOverride bypassed proxy resolution. #10910 moved resolution
  ahead of the override on purpose ('so test overrides and the real path both see
  it'), so the assertion now checks the fallback the test name promises.

test:vitest:ui goes from 34 failures to 14. The remaining 14 sit in six files none
of this commit touches (AutoComboCatalog, CoolingConnectionsPanel, ProxyRegistryManager
x2, connectionsSearchFilter) plus one claudeTlsClient case that passes in isolation
and only fails in the full run — i.e. cross-file pollution. They need a clean
environment to judge: this devbox resolves part of its tree through a stray pnpm
store and has already produced one phantom failure count this cycle.

Refs #10692
2026-08-25 09:48:12 -03:00
diegosouzapw
1249f714fe fix(cli): do not treat a tmpfs mount as proof a config path reaches the host
hasBindMountAt() accepted ANY mount as evidence that a would-be CLI config
write reaches the operator's host: it matched on the mount point alone and
never looked at the filesystem type. An in-memory mount therefore cleared the
ephemeral flag, so guardCliConfigWrite() let the write through and both
POST /api/cli-tools/apply and the dashboard's guide-settings writer answered
200 instead of the safe 422 that #10057 added.

That is the exact case the guard exists to refuse, and the worst one: a
container running with `--tmpfs /tmp` (or a home on tmpfs) loses the file even
before the container is recreated, while the UI reports success.

Parse the filesystem type from mountinfo (the field after the lone "-"
separator) and skip mounts backed by RAM or kernel state. Real bind mounts
(ext4/xfs/nfs/virtiofs/fuse.*) still count, including one nested under a tmpfs
path, so the compose `host` profile is unaffected. A line carrying no
separator proves nothing and is skipped too.

Regression cover added to tests/unit/container-env-detect.test.ts; this also
un-reds tests/unit/cli-tools-apply-container-422.test.ts and
tests/unit/api/cli-tools/apply-container-guard.test.ts, which were failing on
any box whose /tmp is a tmpfs.
2026-08-25 08:12:51 +00:00
diegosouzapw
e3e188e993 fix(release): restore #10534 quota recovery and validate the volcengine connect bodies
Two base-reds on the v3.8.50 tip, found by the release pre-flight.

1. #11355 regressed #10534. It replaced the per-window recovery check with an
   unconditional `hasActiveCooldown()` stop, which is right for an
   upstream-derived cooldown but also blocks the case #10534 exists for: a
   Claude-subscription 429 persists a SYNTHETIC 1h rateLimitedUntil because the
   upstream sends no parseable reset. When the later poll shows every governing
   window has really reset with quota left, holding that synthetic cooldown just
   deadlocks the connection for an hour.

   The orphaned `windowStillExhaustedAfterRealReset()` helper and the three
   unused claudeExtraUsage imports that ESLint flagged were the fingerprint of
   this regression, not dead code: they are the two halves of the original gate.
   Re-wired as `isQuotaExhaustedCooldownReleasable()`, deliberately narrow —
   only lastErrorType "quota_exhausted" is eligible, one still-exhausted or
   unknown-reset window keeps the lock, and an extra-usage POLICY block stays
   locked even though its quota windows do look recovered in the same fetch.
   #11277/#11355 semantics are untouched (both guards still pass).

   Regression guard: tests/unit/provider-limits-recovery.test.ts already pinned
   this contract and was red on the tip. 15/15 now.

2. The three volcengine-plan connect routes read `request.json()` and handed the
   raw fields to a headless-browser login service after ad-hoc typeof checks
   (`check:route-validation:t06`, Hard Rule #7). `String(body.code ?? "")` turned
   123 into "123" and an absent code into "", both reaching the service as a
   plausible SMS code. Now parsed with Zod schemas, before the session lookup, so
   a malformed body answers 400 instead of a misleading 404.

   New: tests/unit/volcengine-plan-connect-validation.test.ts (8 cases, red
   before the fix). Gate: 687 route files scanned, PASS.

Also drops a genuinely dead import (formatVideoTimestamp in videoBridge.ts —
only used inside the helpers module that defines it).
2026-08-25 06:49:18 +00:00
Bob.Hou
59dccdd9e1 fix(security): sanitize agent-card topology, anti-spoof login rate-limit peer IP, and add 429 Retry-After (#S1 #S2 #S4) (#11418)
Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (S1/S2/S4, tests/unit/security-s1-s2-s4.test.ts, 9/9).

Boa integração com o padrão já existente de peer IP stamped por HMAC (resolveStampedPeer/OMNIROUTE_PEER_STAMP_TOKEN) — reusa em vez de reimplementar, e o header confiável só é honrado quando o stamp token está configurado. S2 remove corretamente a disclosure de topologia hardcoded do agent-card. Obrigado pela contribuição!
2026-08-24 17:24:08 -03:00
PhuongDoan
9464792cfc feat(sse): add glm-5.3-max explicit effort tier (#11415)
Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (23/23 do PR entre glm-5.3-catalog-and-effort-tiers.test.ts e zai-catalog-glm52.test.ts).

Aditivo, espelha exatamente o padrão já existente glm-5.2-max. Obrigado pela contribuição, primeira PR bem-vinda!
2026-08-24 17:23:58 -03:00
Marcelo Karval
11cbd7d4e0 fix(models): normalize media endpoint metadata (#11397)
Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (endpoint/parser/schema/static-model + catálogo).

Canonicaliza metadados de endpoint legados (video/audio) para IDs específicos por operação, mantendo compatibilidade retroativa via `normalizeModelSupportedEndpoints` (valores antigos `audio`/`video` continuam válidos como entrada e são normalizados na escrita). Obrigado pela contribuição, primeira PR bem-vinda!
2026-08-24 17:23:48 -03:00
Nguyen Thanh Dat
f93fecd86b fix(dashboard): honour the live WebSocket port the handshake reports (#11331) (#11388)
Validado em lote combinado (batch-0824g) contra o tip de release/v3.8.50: typecheck:core limpo, gates estáticos OK, 62/62 testes focados passando (incluindo tests/unit/live-ws-url-11331.test.ts, 11 casos + mutation-check).

Resolve o incidente real do #11331: o handshake já reportava a porta live real, mas o cliente descartava esse campo e ficava preso na porta compilada no bundle. Precedência clara (wsUrl explícito > publicUrl completo > porta/path do handshake aplicados ao default). Obrigado pela contribuição!
2026-08-24 17:23:38 -03:00
Nguyen Thanh Dat
d5d730c845 test(kimi): stop drawing the refresh window inside the assertion (#11380)
Validado em lote combinado (batch-0824g, junto de #11388/#11397/#11415/#11418) contra o tip de release/v3.8.50: typecheck:core limpo, file-size/changelog/complexity/cognitive-complexity OK, 62/62 testes focados passando.

Diagnóstico correto e bem documentado: a falha do nightly Node 26 era um teste que sorteia um número e depende do resultado, não uma quebra de compatibilidade. Comportamento de produção inalterado (a janela de jitter continua aleatória; só o teste ganhou controle sobre ela). Obrigado pela investigação detalhada!
2026-08-24 17:23:27 -03:00
Diego Rodrigues de Sa e Souza
bbc7bf4351 fix(authz): match exact public routes exactly, not as prefixes (#11417)
`isPublicApiRoute()` matched every entry of PUBLIC_API_ROUTE_PREFIXES with
`startsWith()`, but 11 of the 15 entries name ONE route, not a subtree. As a
prefix each also marked every adjacent path sharing its leading characters as
PUBLIC, which skips the MANAGEMENT auth gate.

That is reachable today: Next resolves `/api/usage/om-usage<anything>` to the
dynamic route `/api/usage/[connectionId]`, and that handler carries no auth of
its own — it relies entirely on being classified MANAGEMENT. An unauthenticated
caller therefore reaches `fetchAndPersistProviderLimits()`, which is an
existence oracle over connection ids (409/404/400/200) and, for a connection id
actually starting with `om-usage`, discloses live quota JSON and can drive an
OAuth token refresh (a write side effect) with no credentials.

Split the allowlist by shape:

- PUBLIC_API_ROUTE_PREFIXES keeps only genuine subtrees, every entry ending in
  "/" (asserted by a unit test, so the class cannot come back silently).
- PUBLIC_API_ROUTES_EXACT holds the single routes, matched exactly in both
  spellings.
- The three read-only "prefixes" were single routes too and move to
  PUBLIC_READONLY_CORS_API_ROUTES, matched exactly. classify.ts now asks
  `isPublicReadonlyCorsRoute()` instead of scanning the raw list, so the CORS
  origin relaxation pipeline.ts keys on cannot be inherited by a sibling either
  (`/api/monitoring/health-detail` was taking it).
- `/api/health` deliberately stays in its own set so it keeps classifying as
  `public_prefix`; folding it into the read-only set would widen CORS on it.

dashboardCsrf.ts had a second copy of the prefix scan; it now shares
`isPublicApiRoute()` so the client CSRF exemption and the server classification
cannot disagree. Side effect in the safe direction: the three LOCAL_ONLY oauth
auto-import routes were CSRF-exempt on the client while the server already
required the token — the client now attaches it.

Reported by @ntdat812 (GHSA-74g9-q8f6-793h), with the shape of the fix and the
two gotchas above called out in the report.

Closes GHSA-74g9-q8f6-793h

Co-authored-by: Xiangzhe <bakryun0718@proton.me>
Co-authored-by: Nguyen Thanh Dat <ntdat812.dev@gmail.com>
2026-08-24 15:47:34 -03:00
Jacob Stoner
56d64e29a4 fix(dashboard): expose custom mode-pack option (#11407)
Validado em lote combinado (batch-0824f, junto de #11399/#11400/#11402) contra o tip de release/v3.8.50: typecheck:core limpo, file-size/changelog/complexity/cognitive-complexity OK, 56/56 testes focados passando incluindo os deste PR (tests/unit/autocombo-unification.test.ts).

Baixo risco: expõe a opção "custom" já suportada em runtime (`getModePack("custom") === undefined`, cai de volta para os pesos explícitos dos sliders) no seletor compartilhado de mode-pack da UI. Obrigado pela contribuição!
2026-08-24 14:16:37 -03:00
Jacob Stoner
7b36e45df8 fix(dashboard): normalize explicit auto weights (#11402)
Validado em lote combinado (batch-0824f, junto de #11399/#11400/#11407) contra o tip de release/v3.8.50: typecheck:core limpo, file-size/changelog/complexity/cognitive-complexity OK, 56/56 testes focados passando incluindo os deste PR (tests/unit/combo-scoring-inspector.test.ts).

Baixo risco: normaliza pesos parciais/não-unitários no inspector de diagnóstico (`comboScoringInspector.ts`) reutilizando o normalizador já existente do motor real de scoring, mantendo diagnósticos consistentes com o runtime. Obrigado pela contribuição!
2026-08-24 14:16:20 -03:00
Markus Hartung
dfc5b5eec4 perf(providers): lazy validate provider schema on demand to reduce startup heap 2026-08-24 12:23:50 -03:00
ggdayup
93da24cd79 fix(providers): reject reserved provider prefixes on compatible-node create/update
A compatible node created with prefix "tokenrouter" was silently
unreachable: the runtime model resolver (src/sse/services/model.ts)
skips compatible-node lookup for built-in registry ids/aliases, so
"tokenrouter/qwen/..." routed to the built-in tokenrouter provider and
failed with "No active credentials for provider: tokenrouter" even
though the node itself worked when addressed by its internal id.

Reject reserved prefixes at the write path instead:

- new shared module src/shared/constants/reservedProviderPrefixes.ts
  (REGISTRY ids + aliases, case-sensitive, built lazily) — single
  source of truth consumed by both the runtime guard and the
  validation schemas so they can never drift apart
- createProviderNodeSchema / updateProviderNodeSchema now reject
  reserved prefixes with a clear message naming the colliding prefix
- src/sse/services/model.ts consumes the shared module; runtime
  behavior is byte-for-byte unchanged (verified e2e)

Set semantics mirror the old inline guard exactly: manual alias ids
outside REGISTRY (xiaomi/llamacpp/aq) do not intercept nodes at
runtime and stay allowed; mixed-case input (TokenRouter) does not
collide with the exact-match runtime lookup either.
2026-08-24 12:22:38 -03:00
deploy
8f15b79a84 feat(volcengine): phone/SMS auto-login for console with MFA + identity selection
- Session-based headless login service (volcengineConsoleAutoLogin)
- API: POST /connect {phone} + /code /status /cancel /resend /identity sub-routes
- Dashboard modal: phone → SMS code → MFA step-up → identity selection
- Falls back to the legacy headful manual flow on risk-control/TOTP-binding
- Route guard: connect subtree stays LOCAL_ONLY + spawn-capable
2026-08-24 12:22:00 -03:00
yangsiyuan.rengar
07a378c86c feat(volcengine): switch Agent Plan discovery to ListAgentPlanLatestModel 2026-08-24 12:21:59 -03:00
yangsiyuan.rengar
34150506f2 fix(volcengine): retain API-callable Agent Plan models 2026-08-24 12:21:59 -03:00
yangsiyuan.rengar
76ac1c8b7e feat(volcengine): live model discovery for Ark plan providers
Replace the static curated model lists for volcengine-agent-plan and
volcengine-coding-plan with live discovery from the console APIs
(GetAgentPlanModelMappingMeta / ListArkCodeLatestModel), authenticated by
the console cookie+csrf already captured at plan binding time.

- Add volcenginePlanModelDiscovery.ts: fetch + parse + capability enrichment
  (family->contextLength/vision/reasoning map, conservative default fallback).
  Console calls go through a dynamic undici import to bypass OmniRoute's
  global fetch patch (built for LLM provider traffic, reroutes console hits).
  Coding plan's ListArkCodeLatestModel needs {AccountId:<number>} extracted
  from the console cookie; agent plan's GetAgentPlanModelMappingMeta filters
  PlatformAllowStatus===true && Type==='llm'.
- Remove both plan ids from CURATED_MODEL_ONLY_PROVIDERS so synced models
  merge into /v1/models and the dashboard Sync Models button works.
- sync-models route: short-circuit to console discovery for plan providers
  (the chat API has no /models endpoint); persist via
  replaceSyncedAvailableModelsForConnection.
- volcenginePlanBinding: set autoSync:true on new plan connections so the
  24h modelSyncScheduler refreshes them automatically.
- volcPlanAutoSyncBackfill: idempotent boot-time backfill so pre-existing
  plan connections also enter the scheduler.

Verified end-to-end on local OmniRoute build against live Volcano console:
agent plan synced 7 LLMs, coding plan synced 11 models, /v1/models exposes
all of them (incl. new glm-5-3-260801 / deepseek-v4-flash-260801).
2026-08-24 12:21:59 -03:00
yangsiyuan.rengar
d732cf615d feat(volcengine): add Ark plan providers 2026-08-24 12:21:59 -03:00
Zius
2544ee9498 feat: enable Linux PATH inheritance for autostart & extend loginShellPath to Linux (#11372)
Merged via consolidated batch validation. Fixes autostart on Linux failing to inherit the user's shell PATH (CLI-dependent features like Kiro's Google OAuth broke). Resolved a conflict against a batch sibling in bin/cli/commands/doctor.mjs (kept the more complete prebuilds-aware candidate list) and setup-claude.mjs (formatting only). Own test (login-shell-path-3321.test.ts, 10/10) passes + typecheck:core clean. Thanks!
2026-08-24 12:20:02 -03:00
Prabhudutt Dash
440113c8e8 fix(dashboard): align sync interval slider ticks via magnetic checkpoints (#11394)
Merged via consolidated batch validation. Model Database sync-interval slider used two incompatible coordinate systems (evenly spaced labels vs a linear 1-168h scale); moves the slider to checkpoint-space so the thumb and labels agree. Own test passes.
2026-08-24 12:13:45 -03:00
Nguyen Thanh Dat
9f30b76057 fix(live-ws): resolve the public socket URL at runtime (#11377)
Merged via consolidated batch validation. Fixes live-ws public socket URL resolution for prebuilt Docker/npm images, where NEXT_PUBLIC_* is inlined at build time and can never carry an operator's runtime value. Own test passes.
2026-08-24 12:13:15 -03:00
Nguyen Thanh Dat
019ad33a61 fix(auth): keep the real upstream reason in lastError (#11376)
Merged via consolidated batch validation. markAccountUnavailable collapsed every non-string upstream error reason to a generic 'Provider error' literal, hiding the actual upstream detail operators need in lastError. Own test passes.
2026-08-24 12:13:11 -03:00
Rouzbeh†
6de542b9b6 fix(providers): mark Antigravity connects with no Cloud Code projectId as degraded (#11284) (#11358)
Merged via consolidated batch validation. Production evidence (VPS docker instance): Antigravity OAuth connects ending without a Cloud Code projectId were persisted as silently active while every model call failed; now persisted as degraded. Own tests pass.
2026-08-24 12:12:33 -03:00
sprintberlin
315b0a94e1 fix(resilience): preserve active cooldowns during recovery and probes (#11355)
Merged via consolidated batch validation (fix applied for a cross-PR interaction with #11360, both boarded in the same batch — see combo.ts reconciliation commit). Startup crash recovery cleared every non-terminal transient cooldown unconditionally, erasing legitimate multi-day weekly quota cooldowns on restart. Now only clears expired/unparseable ones. Own repro tests pass.
2026-08-24 12:12:30 -03:00
Diego Rodrigues de Sa e Souza
9df3f8923d fix(build): stop bundling the better-sqlite3 stub at runtime (#11343) (#11391)
Merged via consolidated batch validation (worktree `.claude/worktrees/batch-0824e`, 27-PR batch). Critical fix: next.config.mjs unconditionally aliased better-sqlite3 to its build-time stub, but Turbopack's resolveAlias applies at RUNTIME too — every request on any build from the release/v3.8.50 tip answered HTTP 500 because the real driver was never loaded. Gates green; own tests pass.
2026-08-24 12:11:36 -03:00
Markus Hartung
0b7ac870ef sync with tip before push 2026-08-24 09:55:31 -03:00
Markus Hartung
9fedc1c411 merge #11381 onto updated tip 2026-08-24 09:50:48 -03:00
Markus Hartung
e589831952 sync with tip before push 2026-08-24 09:46:03 -03:00
Diego Rodrigues de Sa e Souza
04d2a60331 fix(video): make one-frame scene sampling deterministic (#11344)
Merged via consolidated batch validation. Makes scene_aware Video Bridge sampling deterministic for a one-frame budget: falls back to the midpoint of the active full-video/focus window and reports policyEffective: uniform (a single scene candidate can't preserve both temporal ends). Adds opt-in real-FFmpeg fixture matrix (rapid edge cuts, one-frame budget, static/gradual scenes, sub-second clips, detector failure). Static gates green; own regression suite (videoBridgeSampler.test.ts, video-bridge-sampler-ffmpeg.test.ts) passed in the combined-batch run. Related to #9760. Thanks!
2026-08-24 09:44:50 -03:00
Markus Hartung
d23bfefec0 merge #11383 onto updated tip 2026-08-24 09:44:36 -03:00
Markus Hartung
c8ad44e018 merge #11350 onto updated tip 2026-08-24 09:41:55 -03:00
Diego Rodrigues de Sa e Souza
c83116e634 fix(video): isolate drill-down cache by principal (#11369)
Merged via consolidated batch validation (worktree `.claude/worktrees/batch-0824d`). Video Bridge FU-08 drill-down cache substrate hardening (explicitly PARTIAL per the PR body — no production producer/callsite feeds this cache yet): canonical isolation by principalId+sessionId+videoRef, loopback broker auth, strict Zod contracts, per-principal + global LRU quotas, full JPEG decode/re-encode with truncated-scan and polyglot-tail rejection, cancellation-safe atomic replacement. Static gates green; own regression suite (videoBridgeDrilldown.test.ts, video-bridge-drilldown-authz.test.ts, video-bridge-drilldown-route.test.ts) passed in the combined-batch run. Thanks!
2026-08-24 09:39:40 -03:00
Diego Rodrigues de Sa e Souza
7715825cb8 fix(video): harden visual frame deduplication (#11382)
Merged via consolidated batch validation (worktree `.claude/worktrees/batch-0824d`), stacked on the just-merged #11362 as documented. Moves the Video Bridge frame cap to post-dedup, bounds the perceptual candidate pool to at most 2x budget (max 16), includes the dedup policy/version in result-cache identity, adds cooperative abort checks to the comparator loop. Static gates green; own dedup/cache-version regression suite passed in the combined-batch run (grayscale-16x16-mean-cells-v2 policy, real fixtures). Thanks!
2026-08-24 09:31:00 -03:00
Diego Rodrigues de Sa e Souza
761d38f433 fix(video): harden result cache identity and coalescing (#11362)
Merged via consolidated batch validation (worktree `.claude/worktrees/batch-0824d`). Completes the Video Bridge FU-01 cache-hardening slice: fingerprints authorized video bytes + result-affecting dimensions before a persistent cache hit, strict metadata validation with corrupt-entry recompute, TTL/LRU bounds by count/entry-bytes/aggregate-bytes, coalesced protected HTTPS downloads isolated by tenant, deadline/abort-bounded model selection. Static gates green; own regression suite (tests/unit/guardrails/videoBridgeResultCache.test.ts) passed in the combined-batch run. Thanks!
2026-08-24 09:26:06 -03:00
Diego Rodrigues de Sa e Souza
12b8df02dd fix(catalog): keep large builds event-loop responsive (#11367)
Merged via consolidated batch validation (worktree `.claude/worktrees/batch-0824d`, 11-PR video-bridge/catalog/ops batch, tip `dafb4ae8`). Fixes the #9147 catalog-scale event-loop regression: reuses one build-local capability snapshot, yields cooperatively during catalog/virtual-pool construction, reads only persisted TTL settings. Static gates: typecheck:core, file-size, changelog-integrity, complexity, cognitive-complexity all green. Own regression test (tests/unit/9147-catalog-eventloop-yield.test.ts) reproduced the RED→GREEN transition in isolated runs per the PR's own evidence; under current shared-devbox load (10-15, multiple parallel sessions) the test intermittently reports INFRA-RED exactly as the PR body pre-disclosed (documented starvation signature, not a code defect). Thanks for the careful RED/GREEN + INFRA-RED discipline.
2026-08-24 09:24:59 -03:00
Diego Rodrigues de Sa e Souza
93135f8e18 feat(guardrails): add focused video analysis mode 2026-08-24 07:30:28 -03:00
Diego Rodrigues de Sa e Souza
22086a73fa fix(video-bridge): validate structural segment sampling 2026-08-24 06:35:58 -03:00
Diego Rodrigues de Sa e Souza
d4ade9d1d3 fix(video): separate tenant scope from download hash 2026-08-24 05:55:00 -03:00
Diego Rodrigues de Sa e Souza
f54c93c879 fix(video): key download flights with process HMAC 2026-08-24 05:16:13 -03:00
Diego Rodrigues de Sa e Souza
d2cea0811a fix(video): harden result cache identity and bounds 2026-08-24 04:31:27 -03:00
Diego Rodrigues de Sa e Souza
38969ad16b fix(video-bridge): render timestamped contact sheets 2026-08-24 03:20:43 -03:00