@chatpanel/gateway 0.6.94 → 0.6.96

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
@@ -62,7 +62,10 @@ chatpanel-gateway
62
62
 
63
63
  On Windows, if `chatpanel-gateway` is "not recognized" right after `npm i -g`, npm's global bin
64
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
65
+ `node "$(npm root -g)/@chatpanel/gateway/bin/chatpanel-gateway.js" --install`. **Updating on
66
+ Windows:** stop the running gateway first, or npm fails with `EBUSY` on `onnxruntime_binding.node`
67
+ (a loaded DLL cannot be overwritten) —
68
+ `chatpanel-gateway --stop; npm i -g @chatpanel/gateway; chatpanel-gateway --install`. npm may also warn
66
69
  that `boolean@3.2.0` is deprecated and that `onnxruntime-node` / `sharp` / `protobufjs` run install
67
70
  scripts: all three come through `@huggingface/transformers` (the native model runtime) and are
68
71
  expected.
@@ -10,6 +10,7 @@
10
10
  // chatpanel-gateway connect point your CLI agents (Codex, Claude Code, …) at this server
11
11
  // chatpanel-gateway --install register login auto-start + start now
12
12
  // chatpanel-gateway --uninstall remove login auto-start
13
+ // chatpanel-gateway --stop stop the running gateway (before an npm update on Windows)
13
14
  // chatpanel-gateway --status is auto-start registered?
14
15
  // chatpanel-gateway --version print version
15
16
  // chatpanel-gateway --bridge run the embedded bridge (the supervisor's child; not for hands)
@@ -49,8 +50,14 @@ try {
49
50
  process.stdout.write(formatConnect(connectAgents({ dryRun }), { dryRun }));
50
51
  } else {
51
52
  const { start, VERSION } = await import('../src/server.js');
52
- const { installService, uninstallService, serviceStatus } = await import('../src/service.js');
53
+ const { installService, uninstallService, serviceStatus, stopService } = await import('../src/service.js');
53
54
  switch (arg) {
55
+ case '--stop':
56
+ // Before `npm i -g` on Windows: a running gateway holds onnxruntime's DLL, and npm's
57
+ // copy of the new one fails with EBUSY. Stop, install, `--install`.
58
+ stopService();
59
+ console.log('ChatPanel Gateway: stopped (auto-start is still registered; `--install` or a login starts it again).');
60
+ break;
54
61
  case '--version':
55
62
  case '-v':
56
63
  console.log(VERSION);
@@ -70,7 +77,7 @@ try {
70
77
  start();
71
78
  break;
72
79
  default:
73
- console.error(`unknown option: ${arg}\nUsage: chatpanel-gateway [mcp|tools list|tools schema <tool>|call <tool> '<json>'|local|connect|--install|--uninstall|--status|--version|--bridge]`);
80
+ console.error(`unknown option: ${arg}\nUsage: chatpanel-gateway [mcp|tools list|tools schema <tool>|call <tool> '<json>'|local|connect|--install|--uninstall|--stop|--status|--version|--bridge]`);
74
81
  process.exit(2);
75
82
  }
76
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/gateway",
3
- "version": "0.6.94",
3
+ "version": "0.6.96",
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": {
@@ -275,6 +275,14 @@ export class PocketTTS {
275
275
 
276
276
  async load(bundle = DEFAULT_BUNDLE, { quant = '_int8', onProgress, log = () => {} } = {}) {
277
277
  const dir = await ensureBundle(bundle, quant, { onProgress, log });
278
+ // The built-in speakers come WITH the model. `ensureVoicesBin` existed and nothing called
279
+ // it: the eight names were listed as "downloads on first use", the default voice was one
280
+ // of them, and picking any of them failed with "unknown built-in voice" on every machine
281
+ // but the one where the file had been fetched by hand. Best-effort — a failed download
282
+ // costs the stock voices and leaves cloning untouched.
283
+ if (!voicesBinOnDisk(bundle)) {
284
+ try { await ensureVoicesBin(bundle, { onProgress, log }); } catch (e) { log(`[pocket-tts] built-in voices not downloaded (${e.message}) — cloning still works`); }
285
+ }
278
286
  const ort = await getOrt();
279
287
  this.meta = JSON.parse(readFileSync(join(dir, 'bundle.json'), 'utf8'));
280
288
  this.tok = new SentencePieceUnigram(new Uint8Array(readFileSync(join(dir, 'tokenizer.model'))));
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.94';
66
+ export const VERSION = '0.6.96';
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.
@@ -1502,6 +1502,7 @@ export function createGateway(cfg = loadConfig()) {
1502
1502
  // A model needing the native runtime is still LISTED on the binary, with the
1503
1503
  // reason — hiding it makes "why can't I clone my voice?" unanswerable.
1504
1504
  const nativeOk = rawOrtAvailable();
1505
+ const activeEntry = TTS_MODEL_CATALOG.find((m) => m.id === active) || null;
1505
1506
  const available = /** @type {any[]} */ (TTS_MODEL_CATALOG.map((m) => ({
1506
1507
  ...m,
1507
1508
  installed: ttsEngine.modelOnDisk(m.id),
@@ -1524,8 +1525,12 @@ export function createGateway(cfg = loadConfig()) {
1524
1525
  // a style bank, VITS/MMS is single-speaker. An empty list tells the UI to
1525
1526
  // hide the picker rather than offer choices that cannot take effect.
1526
1527
  arch: ttsEngine.arch(),
1527
- supportsVoices: ttsEngine.supportsVoices(),
1528
- supportsCustomVoices: ttsEngine.supportsCustomVoices(),
1528
+ // Until a model is LOADED the engine knows nothing, and answering "no voices"
1529
+ // for a model that has eight made the client hide its picker on every fresh
1530
+ // install (state 'off' → supportsVoices false → the single-speaker branch). Before
1531
+ // the first load, the catalog answers for the active model.
1532
+ supportsVoices: ttsEngine.arch() ? ttsEngine.supportsVoices() : (activeEntry ? activeEntry.arch === 'style-tts2' && !!activeEntry.voices : true),
1533
+ supportsCustomVoices: ttsEngine.arch() ? ttsEngine.supportsCustomVoices() : !!activeEntry?.customVoices,
1529
1534
  sampleRate: ttsEngine.sampleRate(),
1530
1535
  // Built-in voices belong to Kokoro alone. VITS is single-speaker and
1531
1536
  // SpeechT5 speaks only in a RECORDED voice, so offering Kokoro's list
package/src/service.js CHANGED
@@ -94,6 +94,14 @@ function winStopRunning() {
94
94
  run('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', ps], { timeout: 15000 });
95
95
  run('taskkill', ['/IM', 'chatpanel-gateway.exe', '/F']); // belt and braces for the exe
96
96
  }
97
+ /** Stop the running gateway (and its bridge child) on any platform — what an update needs first. */
98
+ export function stopService() {
99
+ if (process.platform === 'win32') return winStopRunning();
100
+ if (process.platform === 'darwin') { run('launchctl', ['bootout', `gui/${process.getuid?.() ?? ''}/${LABEL}`]); }
101
+ else run('systemctl', ['--user', 'stop', 'chatpanel-gateway.service']);
102
+ run('pkill', ['-f', 'chatpanel-gateway']);
103
+ return undefined;
104
+ }
97
105
  function winInstall() {
98
106
  const { program, args } = resolveLaunch();
99
107
  const parts = [program, ...args].map((p) => `""${p}""`).join(' ');
package/src/tts-models.js CHANGED
@@ -96,7 +96,7 @@ export const TTS_MODEL_CATALOG = [
96
96
  recommended: true,
97
97
  // Raw onnxruntime, which the standalone binary cannot provide.
98
98
  requiresNative: true,
99
- note: 'Kyutai Pocket TTS (MIT code, CC-BY-4.0 weights). Eight built-in voices, and it can clone yours. Fastest model here. 146 MB, plus 52 MB if you want the built-in voices. Needs the npm gateway.',
99
+ note: 'Kyutai Pocket TTS (MIT code, CC-BY-4.0 weights). Eight built-in voices (downloaded with the model), and it can clone yours. Fastest model here. ~200 MB. Needs the npm gateway.',
100
100
  },
101
101
  {
102
102
  id: 'Xenova/speecht5_tts',