fix(models): honor MODELS_DEV_SYNC_ENABLED=0 over dashboard settings - #10299
fix(models): honor MODELS_DEV_SYNC_ENABLED=0 over dashboard settings#10299RaviTharuma wants to merge 8 commits into
Conversation
…ouzapw#189, diegosouzapw#190) Bumps: nanoid ^3.3.17 (was transitive, now overridden), dompurify ^3.4.13 (with monaco-editor scoped override). Closes Dependabot diegosouzapw#189, diegosouzapw#190. Remaining diegosouzapw#182-diegosouzapw#188 (js-yaml + mermaid) already closed by diegosouzapw#9651 merge — awaiting Dependabot re-scan. npm audit → 0 vulnerabilities.
…egosouzapw#190 Closes Dependabot diegosouzapw#189 (dompurify 3.4.13) and diegosouzapw#190 (nanoid 3.3.17). npm audit → 0.
_tasks is a SEPARATE nested git repo (gitignored). The pattern _tasks/ (trailing slash) ignores only a directory, not a SYMLINK named _tasks. A self-referential _tasks symlink can slip in via git add -A and, once pulled, checkout materializes it over the real _tasks repo (destroying plans/specs/hands-off). Anchored /_tasks ignores the symlink too, preventing re-capture.
…pw#10026) Mirror the request-time exclusion rule (provider_specific_data.excludedModels) in the unified catalog builder: a model is hidden when its provider has connections but none of them is eligible for it. Applied across the PROVIDER_MODELS, synced, custom, alias-backed, and managed-fallback loops so ghost models no longer appear as available. Co-authored-by: ritheshcn25 <ritheshcn25@users.noreply.github.com>
…osouzapw#10055) * fix(models): memoize getModelsDevPricing for /v1/models catalog resolveCatalogPricing called getModelsDevPricing once per model while building GET /v1/models. Each call re-scanned models_dev_pricing and JSON.parsed every row (~10k SQL scans + multi-GB parse work), pegging the event loop so even /healthz timed out (diegosouzapw#9685, diegosouzapw#10052). Memoize the parsed map until saveModelsDevPricing / clearModelsDevPricing and add a unit test for invalidation. Signed-off-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com> * fix(db): invalidate modelsDevPricing cache on DB reset (diegosouzapw#10055) Copilot review fixes: 1. Register invalidateModelsDevPricingCache() with DB state reset system so resetDbInstance() clears the process-local memo, preventing stale pricing data from surviving across DB reset/restore operations. 2. Add test assertion verifying DB reset bypasses the memo (Copilot diegosouzapw#10055). The process-local memo at modelsDevSync.ts:204 caches getModelsDevPricing() results until saveModelsDevPricing()/clearModelsDevPricing() to avoid re-scanning all pricing rows on every /v1/models request. Without this hook, backup restore and test DB resets would serve stale cached data from the previous connection. Tests: npm run test:unit:serial -- tests/unit/modelsDevSync-extended.test.ts --------- Signed-off-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com> Co-authored-by: Ravi Tharuma <RaviTharuma@users.noreply.github.com> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
The file header already advertised this env var but nothing read it. When catalog/compression pin the event loop, the dashboard (same process) cannot turn models.dev sync off. Let 0/false/off win over sqlite so an operator can recover with env + restart. Skip getModelsDevPricing SQL scans while the kill switch is set.
|
Follow-up links (filed after this PR):
No secrets / hostnames in this comment. |
|
Thanks for chasing this down — the underlying diagnosis is right, and I confirmed two real gaps still exist on That said, since this branch was opened, Could you rebase onto the current tip and trim the diff down to just the two pieces that are still missing — the
Once it's rebased and scoped down to those two hunks this should be a quick, valuable merge. |
Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
Babysit summary — CI greenRoot cause: stale verdict, not a defect. The branch was 2280 commits behind What landed (pushed to
Validation: focused Final Ready for human review & merge. |
Summary
src/lib/modelsDevSync.tsalready said opt-in viaMODELS_DEV_SYNC_ENABLED=true. Nothing in the file read that env var. Periodic sync only looked atsettings.modelsDevSyncEnabledin sqlite.GET /v1/modelsor long-context compression pins the Node event loop, the dashboard is the same process.GET /healthzandGET /dashboardboth stop answering (0 bytes / client timeout). Operators cannot open Settings → AI to turn models.dev sync off. That is a catch-22 (fix(ops): /healthz (and other HTTP) times out while event loop is busy (k8s probes flap) #10052, dashboard freeze).MODELS_DEV_SYNC_ENABLED=0|false|off|noa hard kill switch that wins over the DB. Init skips periodic sync.getModelsDevPricing()returns{}without the SQL +JSON.parsescan so leftovermodels_dev_pricingrows cannot re-wedge the loop. Unset still honors the dashboard setting.1|true|on|yesforces sync on.docs/reference/ENVIRONMENT.md. Unit test covers env=0 vs settings=true.Related Issues
Validation
Tests Added Or Updated
tests/unit/modelsDevSync-extended.test.tsMODELS_DEV_SYNC_ENABLED=0 kills init and getModelsDevPricing even when settings are onCoverage Notes
initModelsDevSync+getModelsDevPricing+applyModelsDevSyncSection.Reviewer Notes
MODELS_DEV_SYNC_ENABLED=0and restart. No dashboard, no PATCH /api/settings, no sqlite surgery required.Test plan
getModelsDevPricing()is{}even with rows savedMODELS_DEV_SYNC_ENABLED=0on a box withmodelsDevSyncEnabled=truein sqlite → logs[MODELS_DEV] Disabled (MODELS_DEV_SYNC_ENABLED=0),/healthzstays ms-level