feat(deploy): keep optional deps on update (--include=optional) (#4260)

Keep optional deps on update: add --include=optional to the CLI update, auto-updater, and source-update scripts so optionalDependencies (better-sqlite3, keytar, tls-client, llmlingua SLM stack) survive an omit=optional config. Test-guarded (RED→GREEN). Integrated into release/v3.8.29.
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-06-19 03:16:58 -03:00
committed by GitHub
parent 526e5df32a
commit 4ba7f3296e
4 changed files with 21 additions and 4 deletions

View File

@@ -142,7 +142,7 @@ export async function runUpdateCommand(opts = {}) {
}
if (dryRun) {
console.log("\n [DRY RUN] Would run: npm install -g omniroute@latest");
console.log("\n [DRY RUN] Would run: npm install -g omniroute@latest --include=optional");
if (!skipBackup) console.log(" [DRY RUN] Would create backup in ~/.omniroute/backups/");
return 0;
}
@@ -174,7 +174,9 @@ export async function runUpdateCommand(opts = {}) {
printInfo("Updating OmniRoute...");
try {
const { execSync } = await import("child_process");
execSync("npm install -g omniroute@latest", { stdio: "inherit" });
// --include=optional keeps the optionalDependencies (better-sqlite3, keytar,
// tls-client, llmlingua SLM stack) on update so an omit=optional config can't drop them.
execSync("npm install -g omniroute@latest --include=optional", { stdio: "inherit" });
printSuccess(`Updated to version ${latest}`);
printInfo("Run `omniroute --version` to verify.");
return 0;

View File

@@ -266,6 +266,13 @@ Before shipping any v3.8.x release, verify these additional items:
- [ ] `omniroute --tray` boots on Windows (PowerShell NotifyIcon, no extra binaries)
- [ ] `omniroute config tray enable` creates autostart entry; disable removes it
- [ ] `npm install -g omniroute@<this-version>` runs postinstall without fatal exit
- [ ] Update path keeps optional deps: `omniroute update --apply` and the auto-updater
run `npm install -g … --include=optional` so `optionalDependencies` (better-sqlite3,
keytar, tls-client, and the llmlingua SLM stack: `@atjsh/llmlingua-2`,
`@tensorflow/tfjs`, `js-tiktoken`) survive an update. The ultra `modelPath` SLM tier
additionally needs `@huggingface/transformers@3.5.2` (pinned — llmlingua-2 uses the 3.x
tokenizer API) and the tinybert model, auto-downloaded to `${DATA_DIR}/models/llmlingua`
on first use.
- [ ] `omniroute status` works with no `.env` (CLI token path, loopback only)
- [ ] `curl http://localhost:20128/api/shutdown` returns 401 (always-protected route)
- [ ] `curl -H "host: evil.com" http://localhost:20128/api/mcp/sse` returns 401 (loopback guard)

View File

@@ -232,7 +232,10 @@ export async function ensureGitTagExists(
export function buildNpmUpdateScript(latest: string): string {
return [
"set -eu",
`npm install -g omniroute@${latest} --ignore-scripts --legacy-peer-deps`,
// --include=optional keeps the optionalDependencies (better-sqlite3, keytar,
// tls-client, and the llmlingua SLM stack) installed on every update so an
// `omit=optional` config / .npmrc cannot silently drop them.
`npm install -g omniroute@${latest} --include=optional --ignore-scripts --legacy-peer-deps`,
"if command -v pm2 >/dev/null 2>&1; then",
" pm2 restart omniroute || true",
"fi",
@@ -254,7 +257,7 @@ export function buildSourceUpdateScript(latest: string, gitRemote = "origin"): s
'backup_branch="pre-update/$(git rev-parse --short HEAD)-$(date +%Y%m%d-%H%M%S)"',
'git branch "$backup_branch" 2>/dev/null || true',
`git checkout "${targetTag}"`,
"npm install --legacy-peer-deps",
"npm install --include=optional --legacy-peer-deps",
"node scripts/dev/sync-env.mjs 2>/dev/null || true",
"npm run build",
"if command -v pm2 >/dev/null 2>&1; then",

View File

@@ -248,12 +248,17 @@ test("ensureGitTagExists verifies refs/tags paths and throws a clear error when
test("auto update script builders generate npm, source, and docker-compose scripts with quoting and patch commits", () => {
const npmScript = autoUpdate.buildNpmUpdateScript("3.6.0");
assert.match(npmScript, /npm install -g omniroute@3.6.0/);
// Optional deps (better-sqlite3, keytar, tls-client, and the llmlingua SLM stack)
// must survive an update — install them explicitly so an `omit=optional` config
// cannot silently drop them.
assert.match(npmScript, /--include=optional/);
assert.match(npmScript, /pm2 restart omniroute \|\| true/);
assert.match(npmScript, /Successfully updated to v3.6.0/);
const sourceScript = autoUpdate.buildSourceUpdateScript("3.6.0", "upstream");
assert.match(sourceScript, /git fetch --tags 'upstream'/);
assert.match(sourceScript, /git stash --include-untracked/);
assert.match(sourceScript, /npm install --include=optional --legacy-peer-deps/);
assert.match(sourceScript, /node scripts\/dev\/sync-env\.mjs 2>\/dev\/null \|\| true/);
assert.match(sourceScript, /Successfully updated to v3\.6\.0/);