@chatpanel/gateway 0.6.92 → 0.6.94

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 CHANGED
@@ -60,6 +60,13 @@ chatpanel-gateway
60
60
  # bridge : starting the embedded bridge (v0.11.20)
61
61
  ```
62
62
 
63
+ On Windows, if `chatpanel-gateway` is "not recognized" right after `npm i -g`, npm's global bin
64
+ folder is not on that shell's PATH yet: open a new PowerShell, or run it by path —
65
+ `node "$(npm root -g)/@chatpanel/gateway/bin/chatpanel-gateway.js" --install`. npm may also warn
66
+ that `boolean@3.2.0` is deprecated and that `onnxruntime-node` / `sharp` / `protobufjs` run install
67
+ scripts: all three come through `@huggingface/transformers` (the native model runtime) and are
68
+ expected.
69
+
63
70
  `GET /health` says which bridge it runs: `bridge.mode` is `embedded`, `standalone`,
64
71
  `adopted` or `off`. `CHATPANEL_BRIDGE_MANAGED=off` (or `bridge.managed: false`) turns the
65
72
  supervision off for a host that runs its own bridge — the desktop app does. A
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/gateway",
3
- "version": "0.6.92",
3
+ "version": "0.6.94",
4
4
  "description": "Local privacy gateway — redacts PII out of OpenAI/Anthropic API traffic before it reaches a model, then restores it in the reply. Point opencode, codex, aider, Claude Code, etc. at it.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,7 @@
27
27
  "node": ">=18"
28
28
  },
29
29
  "dependencies": {
30
- "@chatpanel/bridge": "^0.11.20",
30
+ "@chatpanel/bridge": "^0.11.21",
31
31
  "@chatpanel/pii": "^0.7.4",
32
32
  "@huggingface/transformers": "^4.2.0",
33
33
  "onnxruntime-web": "1.26.0-dev.20260416-b7804b056c",
package/src/bridge.js CHANGED
@@ -158,13 +158,25 @@ export async function openBridgeChat({ bridgeUrl, agent, token, messages, system
158
158
  options: options || {},
159
159
  ...(Array.isArray(specs) && specs.length ? { pageTools: { specs } } : {}),
160
160
  }), signal, tokenPath);
161
- if (!res.ok || !res.body) {
162
- const detail = await res.text().catch(() => '');
163
- throw new Error(`bridge /chat HTTP ${res.status}${detail ? `: ${detail.slice(0, 200)}` : ''}`);
164
- }
161
+ if (!res.ok || !res.body) throw new Error(await bridgeRefusal(res));
165
162
  return res;
166
163
  }
167
164
 
165
+ /**
166
+ * What the bridge said when it refused a turn, as a sentence. The bridge answers
167
+ * `{ error: { message } }` — and for the commonest first-run failure that message is the
168
+ * whole story ("Claude Code isn't signed in … run `claude`, type `/login` …"). Wrapping it in
169
+ * `bridge /chat HTTP 503: {"error":{"message":"…` and cutting it at 200 characters turned the
170
+ * one useful sentence into JSON debris.
171
+ */
172
+ export async function bridgeRefusal(res) {
173
+ const text = await res.text().catch(() => '');
174
+ let message = '';
175
+ try { const j = JSON.parse(text); message = String(j?.error?.message || j?.error || j?.message || '').trim(); } catch { /* not JSON */ }
176
+ if (message) return message.slice(0, 600);
177
+ return `bridge /chat HTTP ${res.status}${text ? `: ${text.slice(0, 200)}` : ''}`;
178
+ }
179
+
168
180
  // Stream a turn through the bridge. Calls onText(restorableChunk) for each delta, and
169
181
  // onActivity(event) for everything else the agent reports — status lines, the working
170
182
  // directory, tool calls, reasoning.
@@ -177,10 +189,7 @@ export async function streamBridgeChat({ bridgeUrl, agent, token, messages, syst
177
189
  options: options || {},
178
190
  }), signal, tokenPath);
179
191
 
180
- if (!res.ok || !res.body) {
181
- const detail = await res.text().catch(() => '');
182
- throw new Error(`bridge /chat HTTP ${res.status}${detail ? `: ${detail.slice(0, 200)}` : ''}`);
183
- }
192
+ if (!res.ok || !res.body) throw new Error(await bridgeRefusal(res));
184
193
 
185
194
  const reader = res.body.getReader();
186
195
  const decoder = new TextDecoder();
package/src/server.js CHANGED
@@ -63,7 +63,7 @@ import * as openai from './openai.js';
63
63
  import * as responses from './responses.js';
64
64
  import * as anthropic from './anthropic.js';
65
65
 
66
- export const VERSION = '0.6.92';
66
+ export const VERSION = '0.6.94';
67
67
 
68
68
  // WARM search tier — SQLite + FTS5 record store (falls back to an encrypted-JSON
69
69
  // store if SQLite can't load), fed by the extension's ingest sync + backup-ingest.
package/src/service.js CHANGED
@@ -81,6 +81,19 @@ const WIN_RUN_KEY = 'HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run';
81
81
  const WIN_RUN_NAME = 'ChatPanelGateway';
82
82
  const winVbs = () => path.join(os.homedir(), '.chatpanel', 'gateway-launch.vbs');
83
83
 
84
+ /**
85
+ * Stop every running gateway process — the exe, the npm build under node, and the embedded
86
+ * bridge child (`--bridge`) — except this one. Matched on the command line, because on the
87
+ * npm path the process is `node.exe` and `taskkill /IM chatpanel-gateway.exe` never saw it.
88
+ * launchd restarts the macOS service for us; Windows has no supervisor, so `--install` after an
89
+ * update used to launch a second instance that died on the busy port while the OLD build kept
90
+ * answering /health with its old version.
91
+ */
92
+ function winStopRunning() {
93
+ const ps = `Get-CimInstance Win32_Process | Where-Object { $_.CommandLine -match 'chatpanel-gateway' -and $_.ProcessId -ne ${process.pid} } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }`;
94
+ run('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps], { timeout: 15000 });
95
+ run('taskkill', ['/IM', 'chatpanel-gateway.exe', '/F']); // belt and braces for the exe
96
+ }
84
97
  function winInstall() {
85
98
  const { program, args } = resolveLaunch();
86
99
  const parts = [program, ...args].map((p) => `""${p}""`).join(' ');
@@ -89,11 +102,14 @@ function winInstall() {
89
102
  writeFileSync(vbs, `CreateObject("WScript.Shell").Run "${parts}", 0, False\r\n`);
90
103
  const r = run('reg', ['add', WIN_RUN_KEY, '/v', WIN_RUN_NAME, '/t', 'REG_SZ', '/d', `wscript.exe "${vbs}"`, '/f']);
91
104
  if (r.status !== 0) throw new Error((r.stderr || '').trim() || 'reg add failed');
105
+ winStopRunning();
106
+ // Give the port a moment to be released before the new instance binds it.
107
+ run('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', 'Start-Sleep -Milliseconds 800']);
92
108
  run('wscript.exe', [vbs]);
93
109
  }
94
110
  function winUninstall() {
95
111
  run('reg', ['delete', WIN_RUN_KEY, '/v', WIN_RUN_NAME, '/f']);
96
- run('taskkill', ['/IM', 'chatpanel-gateway.exe', '/F']);
112
+ winStopRunning();
97
113
  }
98
114
  function winStatus() {
99
115
  return run('reg', ['query', WIN_RUN_KEY, '/v', WIN_RUN_NAME]).status === 0;