squeezr-ai 1.16.1 → 1.16.3
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/bin/squeezr.js +121 -13
- package/package.json +1 -1
package/bin/squeezr.js
CHANGED
|
@@ -16,6 +16,64 @@ const pkg = require(path.join(ROOT, 'package.json'))
|
|
|
16
16
|
const args = process.argv.slice(2)
|
|
17
17
|
const command = args[0]
|
|
18
18
|
|
|
19
|
+
// ── update check (non-blocking) ───────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
const UPDATE_CHECK_FILE = path.join(os.homedir(), '.squeezr', 'update-check.json')
|
|
22
|
+
const UPDATE_CHECK_INTERVAL = 4 * 60 * 60 * 1000 // 4 hours
|
|
23
|
+
|
|
24
|
+
// Fire and forget — runs in background, never blocks CLI
|
|
25
|
+
const updateCheckPromise = (async () => {
|
|
26
|
+
try {
|
|
27
|
+
// Read cached check
|
|
28
|
+
let cached = null
|
|
29
|
+
try { cached = JSON.parse(fs.readFileSync(UPDATE_CHECK_FILE, 'utf-8')) } catch {}
|
|
30
|
+
if (cached && Date.now() - cached.checkedAt < UPDATE_CHECK_INTERVAL) {
|
|
31
|
+
return cached.latest !== pkg.version ? cached.latest : null
|
|
32
|
+
}
|
|
33
|
+
// Fetch latest from npm (with timeout)
|
|
34
|
+
const { get } = await import('https')
|
|
35
|
+
const latest = await new Promise((resolve, reject) => {
|
|
36
|
+
const req = get('https://registry.npmjs.org/squeezr-ai/latest', { timeout: 3000 }, res => {
|
|
37
|
+
let data = ''
|
|
38
|
+
res.on('data', chunk => { data += chunk })
|
|
39
|
+
res.on('end', () => {
|
|
40
|
+
try { resolve(JSON.parse(data).version) } catch { resolve(null) }
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
req.on('error', () => resolve(null))
|
|
44
|
+
req.setTimeout(3000, () => { req.destroy(); resolve(null) })
|
|
45
|
+
})
|
|
46
|
+
if (!latest) return null
|
|
47
|
+
// Cache result
|
|
48
|
+
const dir = path.dirname(UPDATE_CHECK_FILE)
|
|
49
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true })
|
|
50
|
+
fs.writeFileSync(UPDATE_CHECK_FILE, JSON.stringify({ latest, checkedAt: Date.now() }))
|
|
51
|
+
return latest !== pkg.version ? latest : null
|
|
52
|
+
} catch { return null }
|
|
53
|
+
})()
|
|
54
|
+
|
|
55
|
+
async function showUpdateBanner() {
|
|
56
|
+
try {
|
|
57
|
+
const latest = await Promise.race([updateCheckPromise, new Promise(r => setTimeout(() => r(null), 500))])
|
|
58
|
+
if (latest) {
|
|
59
|
+
console.log('')
|
|
60
|
+
console.log(` ╭─────────────────────────────────────────────────────────╮`)
|
|
61
|
+
console.log(` │ Update available: v${pkg.version} → v${latest}${' '.repeat(Math.max(0, 30 - pkg.version.length - latest.length))}│`)
|
|
62
|
+
console.log(` │ Run: npm install -g squeezr-ai │`)
|
|
63
|
+
console.log(` ╰─────────────────────────────────────────────────────────╯`)
|
|
64
|
+
}
|
|
65
|
+
} catch {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function getPortFromToml() {
|
|
69
|
+
try {
|
|
70
|
+
const toml = fs.readFileSync(path.join(ROOT, 'squeezr.toml'), 'utf-8')
|
|
71
|
+
const m = toml.match(/^port\s*=\s*(\d+)/m)
|
|
72
|
+
if (m) return parseInt(m[1])
|
|
73
|
+
} catch {}
|
|
74
|
+
return null
|
|
75
|
+
}
|
|
76
|
+
|
|
19
77
|
function getMitmPort(port) {
|
|
20
78
|
const envMitm = process.env.SQUEEZR_MITM_PORT
|
|
21
79
|
if (envMitm) return parseInt(envMitm)
|
|
@@ -27,6 +85,10 @@ function getMitmPort(port) {
|
|
|
27
85
|
return Number(port) + 1
|
|
28
86
|
}
|
|
29
87
|
|
|
88
|
+
function getPort() {
|
|
89
|
+
return process.env.SQUEEZR_PORT || getPortFromToml() || 8080
|
|
90
|
+
}
|
|
91
|
+
|
|
30
92
|
const HELP = `
|
|
31
93
|
Squeezr v${pkg.version} — AI context compressor for Claude Code, Codex, Aider, Gemini CLI and Ollama
|
|
32
94
|
|
|
@@ -68,7 +130,7 @@ async function startDaemon() {
|
|
|
68
130
|
}
|
|
69
131
|
|
|
70
132
|
// Check if already running — and if the version matches
|
|
71
|
-
const port =
|
|
133
|
+
const port = getPort()
|
|
72
134
|
const runningVersion = await new Promise(resolve => {
|
|
73
135
|
const req = http.get(`http://localhost:${port}/squeezr/health`, res => {
|
|
74
136
|
let data = ''
|
|
@@ -134,7 +196,7 @@ function showLogs() {
|
|
|
134
196
|
}
|
|
135
197
|
|
|
136
198
|
function stopProxy() {
|
|
137
|
-
const port =
|
|
199
|
+
const port = getPort()
|
|
138
200
|
const mitmPort = getMitmPort(port)
|
|
139
201
|
const ports = [port, mitmPort]
|
|
140
202
|
let killed = false
|
|
@@ -179,7 +241,7 @@ function stopProxy() {
|
|
|
179
241
|
}
|
|
180
242
|
|
|
181
243
|
async function checkStatus() {
|
|
182
|
-
const port =
|
|
244
|
+
const port = getPort()
|
|
183
245
|
const mitmPort = getMitmPort(port)
|
|
184
246
|
return new Promise(resolve => {
|
|
185
247
|
const req = http.get(`http://localhost:${port}/squeezr/health`, res => {
|
|
@@ -284,15 +346,59 @@ async function configurePorts() {
|
|
|
284
346
|
try { execSync(`setx HTTPS_PROXY "http://localhost:${finalMitm}"`, { stdio: 'pipe' }) } catch {}
|
|
285
347
|
console.log('Environment variables updated. Restart your terminal for changes to take effect.')
|
|
286
348
|
} else {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
349
|
+
// Update shell profiles directly
|
|
350
|
+
const profiles = [
|
|
351
|
+
path.join(os.homedir(), '.zshrc'),
|
|
352
|
+
path.join(os.homedir(), '.bashrc'),
|
|
353
|
+
path.join(os.homedir(), '.bash_profile'),
|
|
354
|
+
]
|
|
355
|
+
const envBlock = [
|
|
356
|
+
`export SQUEEZR_PORT=${finalPort}`,
|
|
357
|
+
`export SQUEEZR_MITM_PORT=${finalMitm}`,
|
|
358
|
+
`export ANTHROPIC_BASE_URL=http://localhost:${finalPort}`,
|
|
359
|
+
`export GEMINI_API_BASE_URL=http://localhost:${finalPort}`,
|
|
360
|
+
`export HTTPS_PROXY=http://localhost:${finalMitm}`,
|
|
361
|
+
].join('\n')
|
|
362
|
+
for (const p of profiles) {
|
|
363
|
+
try {
|
|
364
|
+
let content = fs.readFileSync(p, 'utf-8')
|
|
365
|
+
if (content.includes('# squeezr env vars')) {
|
|
366
|
+
// Replace existing block (from marker to the closing fi)
|
|
367
|
+
content = content.replace(
|
|
368
|
+
/# squeezr env vars[\s\S]*?fi/,
|
|
369
|
+
`# squeezr env vars\n${envBlock}\n# squeezr auto-heal\nif ! curl -sf http://localhost:${finalPort}/squeezr/health > /dev/null 2>&1; then squeezr start > /dev/null 2>&1; fi`
|
|
370
|
+
)
|
|
371
|
+
fs.writeFileSync(p, content)
|
|
372
|
+
console.log(` [ok] Updated ${p}`)
|
|
373
|
+
}
|
|
374
|
+
} catch {}
|
|
375
|
+
}
|
|
376
|
+
// Also update env for WSL setx if on WSL
|
|
377
|
+
try {
|
|
378
|
+
const procVersion = fs.readFileSync('/proc/version', 'utf-8')
|
|
379
|
+
if (/microsoft|wsl/i.test(procVersion)) {
|
|
380
|
+
const setx = '/mnt/c/Windows/System32/setx.exe'
|
|
381
|
+
try { execSync(`"${setx}" SQUEEZR_PORT "${finalPort}"`, { stdio: 'pipe' }) } catch {}
|
|
382
|
+
try { execSync(`"${setx}" SQUEEZR_MITM_PORT "${finalMitm}"`, { stdio: 'pipe' }) } catch {}
|
|
383
|
+
try { execSync(`"${setx}" ANTHROPIC_BASE_URL "http://localhost:${finalPort}"`, { stdio: 'pipe' }) } catch {}
|
|
384
|
+
try { execSync(`"${setx}" GEMINI_API_BASE_URL "http://localhost:${finalPort}"`, { stdio: 'pipe' }) } catch {}
|
|
385
|
+
try { execSync(`"${setx}" HTTPS_PROXY "http://localhost:${finalMitm}"`, { stdio: 'pipe' }) } catch {}
|
|
386
|
+
}
|
|
387
|
+
} catch {}
|
|
292
388
|
}
|
|
293
389
|
|
|
294
|
-
|
|
295
|
-
|
|
390
|
+
// Apply to current process so stop/start works immediately
|
|
391
|
+
process.env.SQUEEZR_PORT = String(finalPort)
|
|
392
|
+
process.env.SQUEEZR_MITM_PORT = String(finalMitm)
|
|
393
|
+
process.env.ANTHROPIC_BASE_URL = `http://localhost:${finalPort}`
|
|
394
|
+
process.env.HTTPS_PROXY = `http://localhost:${finalMitm}`
|
|
395
|
+
|
|
396
|
+
// Auto stop + start
|
|
397
|
+
console.log('')
|
|
398
|
+
stopProxy()
|
|
399
|
+
await new Promise(r => setTimeout(r, 1500))
|
|
400
|
+
await startDaemon()
|
|
401
|
+
console.log(`\nOpen a new terminal for env vars to apply to other tools.`)
|
|
296
402
|
}
|
|
297
403
|
|
|
298
404
|
// ── squeezr uninstall ─────────────────────────────────────────────────────────
|
|
@@ -393,7 +499,7 @@ function setupWindows() {
|
|
|
393
499
|
console.log('Setting up Squeezr for Windows...\n')
|
|
394
500
|
|
|
395
501
|
// 1. Set env vars permanently via setx (user scope, no admin needed)
|
|
396
|
-
const port =
|
|
502
|
+
const port = getPort()
|
|
397
503
|
const mitmPort = getMitmPort(port)
|
|
398
504
|
const caPath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'ca.crt')
|
|
399
505
|
const vars = {
|
|
@@ -548,7 +654,7 @@ function setupUnix() {
|
|
|
548
654
|
|
|
549
655
|
// 1. Set env vars + auto-heal guard in shell profile
|
|
550
656
|
const distIndex = path.join(ROOT, 'dist', 'index.js')
|
|
551
|
-
const port =
|
|
657
|
+
const port = getPort()
|
|
552
658
|
const mitmPort = getMitmPort(port)
|
|
553
659
|
const bundlePath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'bundle.crt')
|
|
554
660
|
const shellBlock = [
|
|
@@ -681,7 +787,7 @@ function setupWSL() {
|
|
|
681
787
|
// The guard checks if the proxy is alive on terminal open. If not, it starts
|
|
682
788
|
// it in the background. This is the safety net for WSL2 where systemd and
|
|
683
789
|
// Task Scheduler may both fail.
|
|
684
|
-
const port =
|
|
790
|
+
const port = getPort()
|
|
685
791
|
const mitmPort = getMitmPort(port)
|
|
686
792
|
const bundlePath = path.join(os.homedir(), '.squeezr', 'mitm-ca', 'bundle.crt')
|
|
687
793
|
const shellBlock = [
|
|
@@ -890,3 +996,5 @@ switch (command) {
|
|
|
890
996
|
console.log(HELP)
|
|
891
997
|
process.exit(1)
|
|
892
998
|
}
|
|
999
|
+
|
|
1000
|
+
await showUpdateBanner()
|
package/package.json
CHANGED