squeezr-ai 1.13.1 → 1.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/bin/squeezr.js +97 -24
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -564,8 +564,30 @@ The installer configures Squeezr to start automatically on login:
|
|
|
564
564
|
| macOS | launchd (`~/Library/LaunchAgents/com.squeezr.plist`) | Shell auto-heal |
|
|
565
565
|
| Linux | systemd user service (`~/.config/systemd/user/squeezr.service`) | Shell auto-heal |
|
|
566
566
|
| Windows | Task Scheduler (runs at login, restarts on failure) | — |
|
|
567
|
+
| Windows (robust) | **NSSM Windows Service** (auto-restart on crash) | — |
|
|
567
568
|
| **WSL2** | systemd → Task Scheduler (cascade) | Shell auto-heal |
|
|
568
569
|
|
|
570
|
+
### Windows: NSSM (recommended over Task Scheduler)
|
|
571
|
+
|
|
572
|
+
The built-in Task Scheduler setup requires admin on every reinstall and does **not** restart Squeezr if it crashes mid-session (e.g. due to `ECONNRESET`). For a more robust setup, use [NSSM](https://nssm.cc) to run Squeezr as a proper Windows service:
|
|
573
|
+
|
|
574
|
+
```powershell
|
|
575
|
+
# Install NSSM
|
|
576
|
+
winget install nssm
|
|
577
|
+
|
|
578
|
+
# Create the service (run as Administrator, adjust paths if needed)
|
|
579
|
+
$node = (where.exe node | Select-Object -First 1)
|
|
580
|
+
$script = "$(npm root -g)\squeezr-ai\bin\squeezr.js"
|
|
581
|
+
nssm install SqueezrProxy $node $script
|
|
582
|
+
nssm set SqueezrProxy AppExit Default Restart
|
|
583
|
+
nssm set SqueezrProxy AppRestartDelay 3000
|
|
584
|
+
nssm start SqueezrProxy
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
NSSM gives you: auto-start on boot, automatic restart on crash, stdout/stderr logs, and control via `services.msc`.
|
|
588
|
+
|
|
589
|
+
See [NSSM_WINDOWS_SERVICE.md](./NSSM_WINDOWS_SERVICE.md) for the full guide including log setup, troubleshooting, and uninstall steps.
|
|
590
|
+
|
|
569
591
|
### WSL2 support
|
|
570
592
|
|
|
571
593
|
`squeezr setup` detects WSL2 automatically and configures both sides:
|
package/bin/squeezr.js
CHANGED
|
@@ -190,10 +190,16 @@ function setupWindows() {
|
|
|
190
190
|
console.log('Setting up Squeezr for Windows...\n')
|
|
191
191
|
|
|
192
192
|
// 1. Set env vars permanently via setx (user scope, no admin needed)
|
|
193
|
+
const port = process.env.SQUEEZR_PORT || 8080
|
|
194
|
+
const mitmPort = Number(port) + 1
|
|
195
|
+
const caPath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'ca.crt')
|
|
193
196
|
const vars = {
|
|
194
|
-
ANTHROPIC_BASE_URL:
|
|
195
|
-
openai_base_url:
|
|
196
|
-
GEMINI_API_BASE_URL:
|
|
197
|
+
ANTHROPIC_BASE_URL: `http://localhost:${port}`,
|
|
198
|
+
openai_base_url: `http://localhost:${port}`,
|
|
199
|
+
GEMINI_API_BASE_URL: `http://localhost:${port}`,
|
|
200
|
+
HTTPS_PROXY: `http://localhost:${mitmPort}`,
|
|
201
|
+
// Node.js does NOT use the Windows Certificate Store — this makes Codex (Node.js) trust the MITM CA
|
|
202
|
+
NODE_EXTRA_CA_CERTS: caPath,
|
|
197
203
|
}
|
|
198
204
|
for (const [key, value] of Object.entries(vars)) {
|
|
199
205
|
try {
|
|
@@ -204,29 +210,65 @@ function setupWindows() {
|
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
|
|
207
|
-
// 2.
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
const ps = [
|
|
212
|
-
`$e = Get-ScheduledTask -TaskName '${taskName}' -ErrorAction SilentlyContinue`,
|
|
213
|
-
`if ($e) { Unregister-ScheduledTask -TaskName '${taskName}' -Confirm:$false }`,
|
|
214
|
-
`$a = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-WindowStyle Hidden -NonInteractive -Command "${nodeArg}"' -WorkingDirectory '${ROOT}'`,
|
|
215
|
-
`$t = New-ScheduledTaskTrigger -AtLogon`,
|
|
216
|
-
`$s = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 0 -RestartCount 5 -RestartInterval (New-TimeSpan -Minutes 1)`,
|
|
217
|
-
`Register-ScheduledTask -TaskName '${taskName}' -Action $a -Trigger $t -Settings $s -RunLevel Highest -Force | Out-Null`,
|
|
218
|
-
].join('; ')
|
|
213
|
+
// 2. Auto-start: try NSSM (Windows service, survives crashes) → fallback to Task Scheduler
|
|
214
|
+
const logDir = path.join(os.homedir(), '.squeezr')
|
|
215
|
+
const serviceName = 'SqueezrProxy'
|
|
216
|
+
let autoStartOk = false
|
|
219
217
|
|
|
220
|
-
|
|
221
|
-
execSync(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
218
|
+
const nssmAvailable = (() => {
|
|
219
|
+
try { execSync('where nssm', { stdio: 'pipe' }); return true } catch { return false }
|
|
220
|
+
})()
|
|
221
|
+
|
|
222
|
+
if (nssmAvailable) {
|
|
223
|
+
try {
|
|
224
|
+
// Remove existing service if present (ignore errors)
|
|
225
|
+
try { execSync(`nssm stop ${serviceName}`, { stdio: 'pipe' }) } catch {}
|
|
226
|
+
try { execSync(`nssm remove ${serviceName} confirm`, { stdio: 'pipe' }) } catch {}
|
|
227
|
+
|
|
228
|
+
execSync(`nssm install ${serviceName} "${nodeExe}" "${distIndex}"`, { stdio: 'pipe' })
|
|
229
|
+
execSync(`nssm set ${serviceName} AppDirectory "${ROOT}"`, { stdio: 'pipe' })
|
|
230
|
+
execSync(`nssm set ${serviceName} AppStdout "${logDir}\\service-stdout.log"`, { stdio: 'pipe' })
|
|
231
|
+
execSync(`nssm set ${serviceName} AppStderr "${logDir}\\service-stderr.log"`, { stdio: 'pipe' })
|
|
232
|
+
execSync(`nssm set ${serviceName} AppRotateFiles 1`, { stdio: 'pipe' })
|
|
233
|
+
execSync(`nssm set ${serviceName} AppRotateSeconds 86400`, { stdio: 'pipe' })
|
|
234
|
+
execSync(`nssm set ${serviceName} AppExit Default Restart`, { stdio: 'pipe' })
|
|
235
|
+
execSync(`nssm set ${serviceName} AppRestartDelay 3000`, { stdio: 'pipe' })
|
|
236
|
+
execSync(`nssm set ${serviceName} Description "Squeezr AI token compression proxy on port 8080"`, { stdio: 'pipe' })
|
|
237
|
+
execSync(`nssm start ${serviceName}`, { stdio: 'pipe' })
|
|
238
|
+
console.log(` [ok] Auto-start registered as Windows service via NSSM (auto-restart on crash)`)
|
|
239
|
+
autoStartOk = true
|
|
240
|
+
} catch (err) {
|
|
241
|
+
const msg = err.stderr?.toString() || err.message || ''
|
|
242
|
+
if (msg.includes('Access') || msg.includes('admin') || msg.includes('5')) {
|
|
243
|
+
console.log(` [warn] NSSM requires admin — run as Administrator for service install`)
|
|
244
|
+
} else {
|
|
245
|
+
console.log(` [warn] NSSM install failed: ${msg.trim().split('\n')[0]}`)
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (!autoStartOk) {
|
|
251
|
+
// Fallback: Task Scheduler (no crash recovery, but no admin needed for user tasks)
|
|
252
|
+
const taskName = 'Squeezr'
|
|
253
|
+
const nodeArg = `${nodeExe} \`"${distIndex}\`"`
|
|
254
|
+
const ps = [
|
|
255
|
+
`$e = Get-ScheduledTask -TaskName '${taskName}' -ErrorAction SilentlyContinue`,
|
|
256
|
+
`if ($e) { Unregister-ScheduledTask -TaskName '${taskName}' -Confirm:$false }`,
|
|
257
|
+
`$a = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument '-WindowStyle Hidden -NonInteractive -Command "${nodeArg}"' -WorkingDirectory '${ROOT}'`,
|
|
258
|
+
`$t = New-ScheduledTaskTrigger -AtLogon`,
|
|
259
|
+
`$s = New-ScheduledTaskSettingsSet -ExecutionTimeLimit 0 -RestartCount 5 -RestartInterval (New-TimeSpan -Minutes 1)`,
|
|
260
|
+
`Register-ScheduledTask -TaskName '${taskName}' -Action $a -Trigger $t -Settings $s -RunLevel Highest -Force | Out-Null`,
|
|
261
|
+
].join('; ')
|
|
262
|
+
try {
|
|
263
|
+
execSync(`powershell -NoProfile -Command "${ps}"`, { stdio: 'pipe' })
|
|
264
|
+
console.log(` [ok] Auto-start registered in Task Scheduler (install NSSM for crash recovery)`)
|
|
265
|
+
} catch {
|
|
266
|
+
console.log(` [warn] Auto-start failed — install NSSM or run as admin: https://nssm.cc`)
|
|
267
|
+
}
|
|
225
268
|
}
|
|
226
269
|
|
|
227
270
|
// 3. Start Squeezr right now as a detached background process (no window)
|
|
228
271
|
// Logs go to ~/.squeezr/squeezr.log
|
|
229
|
-
const logDir = path.join(os.homedir(), '.squeezr')
|
|
230
272
|
const logFile = path.join(logDir, 'squeezr.log')
|
|
231
273
|
fs.mkdirSync(logDir, { recursive: true })
|
|
232
274
|
const logFd = fs.openSync(logFile, 'a')
|
|
@@ -241,18 +283,49 @@ function setupWindows() {
|
|
|
241
283
|
console.log(` [ok] Squeezr started in background (pid ${child.pid})`)
|
|
242
284
|
console.log(` [ok] Logs → ${logFile}`)
|
|
243
285
|
|
|
244
|
-
|
|
286
|
+
// 4. Trust MITM CA in Windows Certificate Store (for native apps like browsers)
|
|
287
|
+
// Node.js apps (Codex) use NODE_EXTRA_CA_CERTS set above instead.
|
|
288
|
+
// The CA is generated on first proxy start — wait briefly for it to appear
|
|
289
|
+
const waitForCa = (retries = 10, interval = 500) => new Promise(resolve => {
|
|
290
|
+
const check = (n) => {
|
|
291
|
+
if (fs.existsSync(caPath)) return resolve(true)
|
|
292
|
+
if (n <= 0) return resolve(false)
|
|
293
|
+
setTimeout(() => check(n - 1), interval)
|
|
294
|
+
}
|
|
295
|
+
check(retries)
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
waitForCa().then(found => {
|
|
299
|
+
if (!found) {
|
|
300
|
+
console.log(` [warn] MITM CA not found yet — run 'squeezr setup' again after first start`)
|
|
301
|
+
printDone()
|
|
302
|
+
return
|
|
303
|
+
}
|
|
304
|
+
try {
|
|
305
|
+
execSync(`certutil -addstore -f Root "${caPath}"`, { stdio: 'pipe' })
|
|
306
|
+
console.log(` [ok] MITM CA trusted in Windows Certificate Store (Codex TLS interception ready)`)
|
|
307
|
+
} catch {
|
|
308
|
+
console.log(` [warn] Could not trust MITM CA — run as Administrator or trust manually:`)
|
|
309
|
+
console.log(` certutil -addstore -f Root "${caPath}"`)
|
|
310
|
+
}
|
|
311
|
+
printDone()
|
|
312
|
+
})
|
|
313
|
+
|
|
314
|
+
function printDone() {
|
|
315
|
+
console.log(`
|
|
245
316
|
Done!
|
|
246
317
|
|
|
247
|
-
Squeezr is running on http://localhost
|
|
318
|
+
Squeezr is running on http://localhost:${port}
|
|
319
|
+
MITM proxy on http://localhost:${mitmPort} (Codex TLS interception)
|
|
248
320
|
All CLIs (Claude Code, Codex, Aider, Gemini, Ollama) are configured.
|
|
249
321
|
|
|
250
|
-
Restart your terminal
|
|
322
|
+
Restart your terminal once for the env vars to take effect.
|
|
251
323
|
After that, everything is automatic — Squeezr starts silently on every login.
|
|
252
324
|
|
|
253
325
|
squeezr status — check it's running
|
|
254
326
|
squeezr gain — see token savings
|
|
255
327
|
`)
|
|
328
|
+
}
|
|
256
329
|
}
|
|
257
330
|
|
|
258
331
|
function setupUnix() {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.
|
|
1
|
+
export declare const VERSION = "1.14.2";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '1.
|
|
1
|
+
export const VERSION = '1.14.2';
|
package/package.json
CHANGED