squeezr-ai 1.16.3 → 1.16.5

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.
Files changed (3) hide show
  1. package/README.md +1 -0
  2. package/bin/squeezr.js +114 -23
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -172,6 +172,7 @@ Squeezr uses cheap/free models for AI compression (the deterministic layer is pu
172
172
  ```bash
173
173
  squeezr setup # configure env vars, auto-start, CA trust
174
174
  squeezr start # start the proxy (auto-restarts if version mismatch after update)
175
+ squeezr update # kill old processes, install latest from npm, restart
175
176
  squeezr stop # stop the proxy
176
177
  squeezr status # check if proxy is running
177
178
  squeezr logs # show last 50 log lines
package/bin/squeezr.js CHANGED
@@ -59,7 +59,7 @@ async function showUpdateBanner() {
59
59
  console.log('')
60
60
  console.log(` ╭─────────────────────────────────────────────────────────╮`)
61
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 │`)
62
+ console.log(` │ Run: squeezr update │`)
63
63
  console.log(` ╰─────────────────────────────────────────────────────────╯`)
64
64
  }
65
65
  } catch {}
@@ -104,6 +104,7 @@ Usage:
104
104
  squeezr status Check if proxy is running
105
105
  squeezr config Print config file path and current settings
106
106
  squeezr ports Change HTTP and MITM proxy ports
107
+ squeezr update Kill old processes, install latest from npm, restart
107
108
  squeezr uninstall Remove Squeezr completely (env vars, CA, auto-start, logs)
108
109
  squeezr version Print version
109
110
  squeezr help Show this help
@@ -444,6 +445,16 @@ async function uninstall() {
444
445
  }
445
446
  } catch {}
446
447
  }
448
+ // Also clean .profile
449
+ const profilePath = path.join(os.homedir(), '.profile')
450
+ try {
451
+ const content = fs.readFileSync(profilePath, 'utf-8')
452
+ if (content.includes('# squeezr env vars')) {
453
+ const cleaned = content.replace(/\n?# squeezr env vars[^\n]*(\nexport [^\n]*)*/g, '')
454
+ fs.writeFileSync(profilePath, cleaned)
455
+ console.log(` [ok] Cleaned ${profilePath}`)
456
+ }
457
+ } catch {}
447
458
  }
448
459
 
449
460
  // 3. Remove CA from certificate stores
@@ -672,6 +683,33 @@ function setupUnix() {
672
683
  `fi`,
673
684
  ].join('\n')
674
685
  const marker = '# squeezr env vars'
686
+
687
+ // Env-only block (no auto-heal) for .profile — loaded by login shells
688
+ // before .bashrc's "case $-" interactive guard
689
+ const envOnlyBlock = [
690
+ `# squeezr env vars`,
691
+ `export ANTHROPIC_BASE_URL=http://localhost:${port}`,
692
+ `export openai_base_url=http://localhost:${port}`,
693
+ `export GEMINI_API_BASE_URL=http://localhost:${port}`,
694
+ `export HTTPS_PROXY=http://localhost:${mitmPort}`,
695
+ `export SSL_CERT_FILE=${bundlePath}`,
696
+ ].join('\n')
697
+
698
+ // Write env vars to ~/.profile (login shell — always loaded)
699
+ const profilePath = path.join(os.homedir(), '.profile')
700
+ try {
701
+ const profileContent = fs.existsSync(profilePath) ? fs.readFileSync(profilePath, 'utf-8') : ''
702
+ if (!profileContent.includes(marker)) {
703
+ fs.appendFileSync(profilePath, `\n${envOnlyBlock}\n`)
704
+ console.log(` [ok] Env vars added to ${profilePath}`)
705
+ } else {
706
+ const updated = profileContent.replace(/# squeezr env vars[\s\S]*?(?=\n(?!export )|\n*$)/, envOnlyBlock)
707
+ fs.writeFileSync(profilePath, updated)
708
+ console.log(` [ok] Env vars updated in ${profilePath}`)
709
+ }
710
+ } catch {}
711
+
712
+ // Write full block (env + auto-heal) to interactive shell profile
675
713
  const profiles = [
676
714
  path.join(os.homedir(), '.zshrc'),
677
715
  path.join(os.homedir(), '.bashrc'),
@@ -683,17 +721,12 @@ function setupUnix() {
683
721
  fs.appendFileSync(profile, `\n${shellBlock}\n`)
684
722
  console.log(` [ok] Env vars + auto-heal added to ${profile}`)
685
723
  } else {
686
- if (!existing.includes('SSL_CERT_FILE') || !existing.includes('squeezr MITM')) {
687
- // Re-write block to include MITM vars
688
- const updatedContent = existing.replace(
689
- /# squeezr env vars[\s\S]*?fi\n/,
690
- shellBlock + '\n'
691
- )
692
- fs.writeFileSync(profile, updatedContent)
693
- console.log(` [ok] Shell profile updated with MITM proxy vars`)
694
- } else {
695
- console.log(` [skip] Env vars + auto-heal already in ${profile}`)
696
- }
724
+ const updatedContent = existing.replace(
725
+ /# squeezr env vars[\s\S]*?fi\n?/,
726
+ shellBlock + '\n'
727
+ )
728
+ fs.writeFileSync(profile, updatedContent)
729
+ console.log(` [ok] Env vars + auto-heal updated in ${profile}`)
697
730
  }
698
731
 
699
732
  // 2a. macOS — launchd
@@ -804,6 +837,31 @@ function setupWSL() {
804
837
  `fi`,
805
838
  ].join('\n')
806
839
  const marker = '# squeezr env vars'
840
+
841
+ // Env-only block for .profile (loaded before .bashrc's interactive guard)
842
+ const envOnlyBlock = [
843
+ `# squeezr env vars`,
844
+ `export ANTHROPIC_BASE_URL=http://localhost:${port}`,
845
+ `export openai_base_url=http://localhost:${port}`,
846
+ `export GEMINI_API_BASE_URL=http://localhost:${port}`,
847
+ `export HTTPS_PROXY=http://localhost:${mitmPort}`,
848
+ `export SSL_CERT_FILE=${bundlePath}`,
849
+ ].join('\n')
850
+
851
+ const profilePath = path.join(os.homedir(), '.profile')
852
+ try {
853
+ const profileContent = fs.existsSync(profilePath) ? fs.readFileSync(profilePath, 'utf-8') : ''
854
+ if (!profileContent.includes(marker)) {
855
+ fs.appendFileSync(profilePath, `\n${envOnlyBlock}\n`)
856
+ console.log(` [ok] Env vars added to ${profilePath}`)
857
+ } else {
858
+ const updated = profileContent.replace(/# squeezr env vars[\s\S]*?(?=\n(?!export )|\n*$)/, envOnlyBlock)
859
+ fs.writeFileSync(profilePath, updated)
860
+ console.log(` [ok] Env vars updated in ${profilePath}`)
861
+ }
862
+ } catch {}
863
+
864
+ // Full block (env + auto-heal) in interactive shell profile
807
865
  const profiles = [
808
866
  path.join(os.homedir(), '.zshrc'),
809
867
  path.join(os.homedir(), '.bashrc'),
@@ -815,17 +873,12 @@ function setupWSL() {
815
873
  fs.appendFileSync(profile, `\n${shellBlock}\n`)
816
874
  console.log(` [ok] Env vars + auto-heal added to ${profile}`)
817
875
  } else {
818
- // Update existing block if missing MITM proxy vars
819
- if (!existing.includes('SSL_CERT_FILE') || !existing.includes('HTTPS_PROXY')) {
820
- const updatedContent = existing.replace(
821
- /# squeezr env vars[\s\S]*?fi\n/,
822
- shellBlock + '\n'
823
- )
824
- fs.writeFileSync(profile, updatedContent)
825
- console.log(` [ok] Shell profile updated with MITM proxy vars`)
826
- } else {
827
- console.log(` [skip] Env vars already in ${profile}`)
828
- }
876
+ const updatedContent = existing.replace(
877
+ /# squeezr env vars[\s\S]*?fi\n?/,
878
+ shellBlock + '\n'
879
+ )
880
+ fs.writeFileSync(profile, updatedContent)
881
+ console.log(` [ok] Env vars + auto-heal updated in ${profile}`)
829
882
  }
830
883
 
831
884
  // 2. Set Windows env vars via setx.exe (so Windows-launched CLIs see them)
@@ -949,6 +1002,44 @@ switch (command) {
949
1002
  else setupUnix()
950
1003
  break
951
1004
 
1005
+ case 'update':
1006
+ await (async () => {
1007
+ console.log('Stopping Squeezr...')
1008
+ stopProxy()
1009
+ // Also kill anything on the ports by brute force
1010
+ const uPort = getPort()
1011
+ const uMitmPort = getMitmPort(uPort)
1012
+ if (process.platform === 'win32') {
1013
+ try { execSync(`for /f "tokens=5" %a in ('netstat -ano ^| findstr ":${uPort} " ^| findstr LISTENING') do taskkill /F /PID %a`, { stdio: 'pipe', shell: 'cmd.exe' }) } catch {}
1014
+ try { execSync(`for /f "tokens=5" %a in ('netstat -ano ^| findstr ":${uMitmPort} " ^| findstr LISTENING') do taskkill /F /PID %a`, { stdio: 'pipe', shell: 'cmd.exe' }) } catch {}
1015
+ } else {
1016
+ try { execSync(`kill -9 $(lsof -ti:${uPort}) 2>/dev/null`, { stdio: 'pipe' }) } catch {}
1017
+ try { execSync(`kill -9 $(lsof -ti:${uMitmPort}) 2>/dev/null`, { stdio: 'pipe' }) } catch {}
1018
+ }
1019
+ await new Promise(r => setTimeout(r, 1000))
1020
+
1021
+ console.log('Installing latest version...')
1022
+ try {
1023
+ const npmCmd = process.platform === 'win32' ? 'npm' : 'HTTPS_PROXY= npm'
1024
+ execSync(`${npmCmd} install -g squeezr-ai@latest`, { stdio: 'inherit' })
1025
+ } catch (e) {
1026
+ // On Unix, might need sudo
1027
+ try {
1028
+ execSync('sudo HTTPS_PROXY= npm install -g squeezr-ai@latest', { stdio: 'inherit' })
1029
+ } catch {
1030
+ console.error('npm install failed. Try manually: npm install -g squeezr-ai')
1031
+ process.exit(1)
1032
+ }
1033
+ }
1034
+
1035
+ console.log('\nStarting Squeezr...')
1036
+ // Re-exec the new binary so we run the updated code
1037
+ const squeezrBin = process.argv[1]
1038
+ try {
1039
+ execSync(`node "${squeezrBin}" start`, { stdio: 'inherit' })
1040
+ } catch {}
1041
+ })()
1042
+ break
952
1043
  case 'stop':
953
1044
  stopProxy()
954
1045
  break
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squeezr-ai",
3
- "version": "1.16.3",
3
+ "version": "1.16.5",
4
4
  "description": "AI proxy that compresses Claude Code, Codex, Aider, Gemini CLI and Ollama context windows to save thousands of tokens per session",
5
5
  "keywords": [
6
6
  "claude",
@@ -50,6 +50,7 @@
50
50
  "devDependencies": {
51
51
  "@types/node": "^22.14.0",
52
52
  "@types/node-forge": "^1.3.14",
53
+ "@vitest/coverage-v8": "^4.1.2",
53
54
  "tsx": "^4.19.3",
54
55
  "typescript": "^5.8.3",
55
56
  "vitest": "^3.1.1"