@chatpanel/bridge 0.2.7 → 0.2.8

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
@@ -14,16 +14,23 @@ the ones the bridge reports as available.
14
14
 
15
15
  ## Run it
16
16
 
17
- ### Option A — one-line install (macOS / Linux, no Node.js needed)
17
+ ### Option A — one-line install (no Node.js needed)
18
18
 
19
+ **macOS / Linux:**
19
20
  ```bash
20
- curl -fsSL https://raw.githubusercontent.com/chatpanel/chatpanel-bridge/main/scripts/install.sh | bash
21
+ curl -fsSL https://dl.chatpanel.net/bridge/install.sh | bash
21
22
  ```
22
23
 
23
- This downloads the standalone binary for your OS, installs it to `~/.local/bin`,
24
- and sets it to start at login. **Recommended** — installing via curl avoids the
25
- macOS "damaged / unidentified developer" prompt that browser downloads trigger.
26
- Then open the ChatPanel side panel and your agents appear.
24
+ **Windows (PowerShell):**
25
+ ```powershell
26
+ irm https://dl.chatpanel.net/bridge/install.ps1 | iex
27
+ ```
28
+
29
+ This downloads the standalone binary for your OS, installs it, and sets it to
30
+ start at login. **Recommended** — installing this way avoids the macOS "damaged"
31
+ and Windows SmartScreen prompts that browser downloads trigger. Re-running it is a
32
+ clean in-place upgrade (no duplicate installs). Then open the ChatPanel side panel
33
+ and your agents appear.
27
34
 
28
35
  Manage it: `chatpanel-bridge --status` · `--uninstall` · run with no flags to start
29
36
  once in the foreground.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/bridge",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "type": "module",
5
5
  "description": "Local bridge that exposes the AI coding agents installed on your machine — Claude Code (Agent SDK), Codex (CLI), and Gemini CLI — to the ChatPanel Chrome extension over a localhost SSE endpoint. Bring your own agent.",
6
6
  "keywords": [
@@ -0,0 +1,39 @@
1
+ # ChatPanel Bridge installer (Windows) - no Node.js required.
2
+ #
3
+ # irm https://dl.chatpanel.net/bridge/install.ps1 | iex
4
+ $ErrorActionPreference = 'Stop'
5
+ $ProgressPreference = 'SilentlyContinue' # IWR fallback: skip the slow progress bar
6
+
7
+ $url = 'https://dl.chatpanel.net/bridge/windows-x64.exe'
8
+ $dir = Join-Path $env:LOCALAPPDATA 'ChatPanel'
9
+ $bin = Join-Path $dir 'chatpanel-bridge.exe'
10
+ $tmp = "$bin.new"
11
+
12
+ Write-Host ""
13
+ Write-Host "Installing ChatPanel Bridge" -ForegroundColor Cyan
14
+
15
+ # Stop any running bridge + its scheduled task so the .exe isn't locked (clean
16
+ # in-place upgrade, no duplicate installs).
17
+ schtasks /End /TN ChatPanelBridge *> $null
18
+ Get-Process -Name 'chatpanel-bridge' -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
19
+ Start-Sleep -Milliseconds 600
20
+
21
+ New-Item -ItemType Directory -Force -Path $dir | Out-Null
22
+
23
+ Write-Host " Downloading the bridge (~60 MB)..." -ForegroundColor Gray
24
+ $curl = Get-Command curl.exe -ErrorAction SilentlyContinue
25
+ if ($curl) {
26
+ & curl.exe -fL --progress-bar -o $tmp $url # fast, with a real progress bar
27
+ } else {
28
+ Invoke-WebRequest -Uri $url -OutFile $tmp -UseBasicParsing
29
+ }
30
+ Unblock-File -Path $tmp -ErrorAction SilentlyContinue # no SmartScreen mark-of-the-web
31
+ Move-Item -Force $tmp $bin
32
+
33
+ Write-Host " Setting it to start at login..." -ForegroundColor Gray
34
+ & $bin --install
35
+
36
+ Write-Host ""
37
+ Write-Host "Done. ChatPanel Bridge is running and starts at login." -ForegroundColor Green
38
+ Write-Host "Open the ChatPanel side panel - your agents appear automatically."
39
+ Write-Host "Manage it: `"$bin`" --status | --uninstall"
@@ -8,7 +8,6 @@
8
8
  # "damaged / unidentified developer" prompt that browser downloads trigger.
9
9
  set -euo pipefail
10
10
 
11
- REPO="chatpanel/chatpanel-bridge"
12
11
  os="$(uname -s)"
13
12
  arch="$(uname -m)"
14
13
  asset=""
@@ -16,14 +15,14 @@ asset=""
16
15
  case "$os" in
17
16
  Darwin)
18
17
  if [ "$arch" = "arm64" ]; then
19
- asset="chatpanel-bridge-macos-arm64"
18
+ asset="bridge/macos-arm64"
20
19
  else
21
20
  echo "Intel Mac detected - no x64 binary yet. Use: npx @chatpanel/bridge (needs Node.js 18+)"
22
21
  exit 1
23
22
  fi
24
23
  ;;
25
24
  Linux)
26
- asset="chatpanel-bridge-linux-x64"
25
+ asset="bridge/linux-x64"
27
26
  ;;
28
27
  *)
29
28
  echo "Unsupported OS ($os). Use: npx @chatpanel/bridge (needs Node.js 18+)"
@@ -31,16 +30,21 @@ case "$os" in
31
30
  ;;
32
31
  esac
33
32
 
34
- url="https://github.com/${REPO}/releases/latest/download/${asset}"
33
+ url="https://dl.chatpanel.net/${asset}"
35
34
  dest="${HOME}/.local/bin"
36
35
  bin="${dest}/chatpanel-bridge"
37
36
  mkdir -p "$dest"
38
37
 
39
- echo "Downloading ${asset} ..."
40
- curl -fsSL "$url" -o "$bin"
38
+ echo "Downloading ChatPanel Bridge (~60 MB)..."
39
+ curl -fL --progress-bar "$url" -o "$bin" # show a progress bar (not silent)
41
40
  chmod +x "$bin"
42
41
  xattr -c "$bin" 2>/dev/null || true # belt-and-suspenders; curl files aren't quarantined
43
42
 
43
+ # Clean upgrade: stop any running bridge (incl. a stray npx one) so the new
44
+ # install replaces it in place — same path, same service, no duplicates.
45
+ pkill -f 'chatpanel-bridge' 2>/dev/null || true
46
+ sleep 1
47
+
44
48
  echo "Installed to ${bin}"
45
49
  "$bin" --install
46
50
  echo
@@ -9,6 +9,8 @@
9
9
 
10
10
  import path from 'node:path';
11
11
  import os from 'node:os';
12
+ import { existsSync } from 'node:fs';
13
+ import { findAgentBin, isCompiledBinary } from '../env.js';
12
14
 
13
15
  let sdkPromise = null;
14
16
  function loadSdk() {
@@ -16,14 +18,37 @@ function loadSdk() {
16
18
  return sdkPromise;
17
19
  }
18
20
 
21
+ // Where the Claude Code CLI lives. The SDK ships a bundled cli.js, but inside a
22
+ // compiled binary that file is on a virtual FS that child processes can't reach
23
+ // (it fails on Windows as "B:\~BUN\cli.js"). So in a binary we point the SDK at
24
+ // the user's INSTALLED Claude Code instead — preferring the real cli.js next to
25
+ // the npm shim (modern Node won't spawn a .cmd directly).
26
+ function claudeExecutable() {
27
+ if (process.env.CHATPANEL_CLAUDE_PATH) return process.env.CHATPANEL_CLAUDE_PATH;
28
+ if (!isCompiledBinary()) return undefined; // under node/bun the bundled cli.js works
29
+ const bin = findAgentBin('claude');
30
+ if (!bin) return undefined;
31
+ const dir = path.dirname(bin);
32
+ const candidates = [
33
+ path.join(dir, 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
34
+ path.join(dir, '..', 'lib', 'node_modules', '@anthropic-ai', 'claude-code', 'cli.js'),
35
+ ];
36
+ for (const c of candidates) if (existsSync(c)) return c;
37
+ return bin;
38
+ }
39
+
19
40
  export async function available() {
20
41
  const sdk = await loadSdk();
21
42
  if (!sdk) {
22
43
  return { ok: false, reason: 'Agent SDK not installed (npm i in bridge/)' };
23
44
  }
24
- if (!process.env.ANTHROPIC_API_KEY) {
25
- // Not fatal the SDK can use your local Claude Code login.
26
- return { ok: true };
45
+ // In a compiled binary the bundled CLI is unreachable, so Claude Code must be
46
+ // installed locally. (Under node/bun the bundled CLI works, so this is skipped.)
47
+ if (isCompiledBinary() && !process.env.CHATPANEL_CLAUDE_PATH && !findAgentBin('claude')) {
48
+ return {
49
+ ok: false,
50
+ reason: 'Claude Code not found. Install it (npm i -g @anthropic-ai/claude-code), or run the bridge with `npx @chatpanel/bridge`.',
51
+ };
27
52
  }
28
53
  return { ok: true };
29
54
  }
@@ -85,6 +110,7 @@ export async function chat({ messages, system, options }, emit) {
85
110
  ? { type: 'preset', preset: 'claude_code', append: system }
86
111
  : { type: 'preset', preset: 'claude_code' },
87
112
  ...(options.model ? { model: options.model } : {}),
113
+ ...(claudeExecutable() ? { pathToClaudeCodeExecutable: claudeExecutable() } : {}),
88
114
  ...(process.env.CHATPANEL_MAX_TURNS ? { maxTurns: Number(process.env.CHATPANEL_MAX_TURNS) } : {}),
89
115
  },
90
116
  });
@@ -140,6 +166,7 @@ export async function complete({ prompt, system, model }) {
140
166
  settingSources: [], // skip CLAUDE.md / MCP for a tiny completion
141
167
  systemPrompt: system || "Continue the user's text briefly. Reply with only the continuation.",
142
168
  model: model || 'haiku',
169
+ ...(claudeExecutable() ? { pathToClaudeCodeExecutable: claudeExecutable() } : {}),
143
170
  },
144
171
  });
145
172
  for await (const message of iterator) {
package/src/env.js CHANGED
@@ -26,15 +26,27 @@ function onPath(name) {
26
26
  // "is it installed/findable", NOT "does `--version` exit 0" (which can fail for
27
27
  // reasons unrelated to installation, e.g. the CLI needs login).
28
28
  export function findAgentBin(name) {
29
+ // On Windows, CLIs are usually <name>.cmd / .exe / .bat (npm shims).
30
+ const exts = process.platform === 'win32' ? ['', '.cmd', '.exe', '.bat', '.ps1'] : [''];
29
31
  const dirs = (process.env.PATH || '').split(path.delimiter);
30
32
  for (const d of dirs) {
31
33
  if (!d) continue;
32
- const p = path.join(d, name);
33
- if (existsSync(p) || existsSync(p + '.exe')) return p;
34
+ for (const ext of exts) {
35
+ const p = path.join(d, name + ext);
36
+ if (existsSync(p)) return p;
37
+ }
34
38
  }
35
39
  return shellWhich(name) || null;
36
40
  }
37
41
 
42
+ // True when running as a Bun/Node single-file compiled binary (not under a
43
+ // node/bun interpreter). Inside such a binary, bundled JS files live on a virtual
44
+ // FS that child processes can't reach — notably the Claude SDK's CLI on Windows.
45
+ export function isCompiledBinary() {
46
+ const base = path.basename(process.execPath).toLowerCase();
47
+ return !(base.startsWith('node') || base.startsWith('bun'));
48
+ }
49
+
38
50
  // Ask the user's login shell to locate a command — no hardcoded locations, works
39
51
  // wherever the user actually installed it.
40
52
  function shellWhich(name) {
package/src/server.js CHANGED
@@ -22,7 +22,7 @@ import * as gemini from './engines/gemini.js';
22
22
  import { installService, uninstallService, serviceStatus } from './service.js';
23
23
  import { enrichPath, findAgentBin } from './env.js';
24
24
 
25
- const VERSION = '0.2.7';
25
+ const VERSION = '0.2.8';
26
26
  const HOST = process.env.CHATPANEL_BRIDGE_HOST || '127.0.0.1';
27
27
  const PORT = Number(process.env.CHATPANEL_BRIDGE_PORT) || 4319;
28
28