@seemseam/ccb 8.4.3 → 8.5.0

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/ar.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **نسّق Codex وClaude وGemini وغيرهم من وكلاء CLI ضمن سير عمل مرئي وقابل للتحكم والتدخل المباشر**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ ccb update mobile
182
182
  <details>
183
183
  <summary><b>تفاصيل Mobile App وحدود الأمان والمصدر</b></summary>
184
184
 
185
- يتضمن CCB 8.4.3 مصدر Flutter الخاص بـ CCB Mobile داخل [`mobile/`](../mobile/) وينشر Android APK عبر GitHub Releases:
185
+ يتضمن CCB 8.5.0 مصدر Flutter الخاص بـ CCB Mobile داخل [`mobile/`](../mobile/) وينشر Android APK عبر GitHub Releases:
186
186
 
187
- - [تنزيل CCB Mobile v8.4.3 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [تنزيل CCB Mobile v8.5.0 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - مصدر التطبيق: [`mobile/app`](../mobile/app)
189
189
  - مصدر gateway الخادم: [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/de.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Koordiniere Codex, Claude, Gemini und andere CLI-Agenten in sichtbaren, steuerbaren Workflows, die du direkt uebernehmen kannst**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ Dieser Befehl fuehrt durch Installation und Konfiguration.
182
182
  <details>
183
183
  <summary><b>Mobile-App-Details, Sicherheitsgrenze und Source</b></summary>
184
184
 
185
- CCB 8.4.3 enthaelt den Flutter-Quellcode von CCB Mobile in [`mobile/`](../mobile/) und veroeffentlicht das Android APK ueber GitHub Releases:
185
+ CCB 8.5.0 enthaelt den Flutter-Quellcode von CCB Mobile in [`mobile/`](../mobile/) und veroeffentlicht das Android APK ueber GitHub Releases:
186
186
 
187
- - [CCB Mobile v8.4.3 APK herunterladen](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [CCB Mobile v8.5.0 APK herunterladen](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - App-Source: [`mobile/app`](../mobile/app)
189
189
  - Server-gateway-Source: [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/es.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Coordina Codex, Claude, Gemini y otros agentes CLI en flujos visibles y controlables que puedes tomar directamente**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ Este comando guía la instalación y configuración.
182
182
  <details>
183
183
  <summary><b>Detalles de Mobile App, límite de seguridad y fuente</b></summary>
184
184
 
185
- CCB 8.4.3 incluye el código Flutter de CCB Mobile en [`mobile/`](../mobile/) y publica el APK Android mediante GitHub Releases:
185
+ CCB 8.5.0 incluye el código Flutter de CCB Mobile en [`mobile/`](../mobile/) y publica el APK Android mediante GitHub Releases:
186
186
 
187
- - [Descargar CCB Mobile v8.4.3 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [Descargar CCB Mobile v8.5.0 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - Fuente de la app: [`mobile/app`](../mobile/app)
189
189
  - Fuente del gateway del servidor: [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/fr.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Coordonne Codex, Claude, Gemini et d'autres agents CLI dans des workflows visibles, contrôlables et reprenables directement**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ Cette commande guide l'installation et la configuration.
182
182
  <details>
183
183
  <summary><b>Détails de l'app mobile, frontière de sécurité et source</b></summary>
184
184
 
185
- CCB 8.4.3 inclut le code source Flutter de CCB Mobile dans [`mobile/`](../mobile/) et publie l'APK Android via GitHub Releases :
185
+ CCB 8.5.0 inclut le code source Flutter de CCB Mobile dans [`mobile/`](../mobile/) et publie l'APK Android via GitHub Releases :
186
186
 
187
- - [Télécharger l'APK CCB Mobile v8.4.3](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [Télécharger l'APK CCB Mobile v8.5.0](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - Source de l'app : [`mobile/app`](../mobile/app)
189
189
  - Source du gateway serveur : [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/ja.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Codex、Claude、Gemini などの CLI Agent を、見える・制御できる・直接引き継げるワークフローで連携**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ ccb update mobile
182
182
  <details>
183
183
  <summary><b>Mobile App の詳細、安全境界、ソース</b></summary>
184
184
 
185
- CCB 8.4.3 では Flutter 版 CCB Mobile のソースが [`mobile/`](../mobile/) に含まれ、Android APK は GitHub Releases で公開されています。
185
+ CCB 8.5.0 では Flutter 版 CCB Mobile のソースが [`mobile/`](../mobile/) に含まれ、Android APK は GitHub Releases で公開されています。
186
186
 
187
- - [CCB Mobile v8.4.3 APK をダウンロード](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [CCB Mobile v8.5.0 APK をダウンロード](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - App ソース:[`mobile/app`](../mobile/app)
189
189
  - サーバー gateway ソース:[`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/ko.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Codex, Claude, Gemini 등 CLI Agent를 보이고 제어 가능하며 직접 이어받을 수 있는 워크플로로 조율**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ ccb update mobile
182
182
  <details>
183
183
  <summary><b>Mobile App 세부 정보, 안전 경계, 소스</b></summary>
184
184
 
185
- CCB 8.4.3은 Flutter CCB Mobile 소스를 [`mobile/`](../mobile/)에 포함하며 Android APK를 GitHub Releases로 배포합니다.
185
+ CCB 8.5.0은 Flutter CCB Mobile 소스를 [`mobile/`](../mobile/)에 포함하며 Android APK를 GitHub Releases로 배포합니다.
186
186
 
187
- - [CCB Mobile v8.4.3 APK 다운로드](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [CCB Mobile v8.5.0 APK 다운로드](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - 앱 소스: [`mobile/app`](../mobile/app)
189
189
  - 서버 gateway 소스: [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/pt.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Coordene Codex, Claude, Gemini e outros agentes CLI em fluxos visíveis e controláveis que você pode assumir diretamente**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ Esse comando orienta a instalação e a configuração.
182
182
  <details>
183
183
  <summary><b>Detalhes do Mobile App, limite de segurança e fonte</b></summary>
184
184
 
185
- O CCB 8.4.3 inclui o código Flutter do CCB Mobile em [`mobile/`](../mobile/) e publica o APK Android pelo GitHub Releases:
185
+ O CCB 8.5.0 inclui o código Flutter do CCB Mobile em [`mobile/`](../mobile/) e publica o APK Android pelo GitHub Releases:
186
186
 
187
- - [Baixar CCB Mobile v8.4.3 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [Baixar CCB Mobile v8.5.0 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - Fonte do app: [`mobile/app`](../mobile/app)
189
189
  - Fonte do gateway servidor: [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/ru.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Координируйте Codex, Claude, Gemini и другие CLI Agent в видимых и управляемых процессах, которые можно напрямую взять под контроль**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -182,9 +182,9 @@ ccb update mobile
182
182
  <details>
183
183
  <summary><b>Детали Mobile App, граница безопасности и исходники</b></summary>
184
184
 
185
- CCB 8.4.3 включает Flutter source CCB Mobile в [`mobile/`](../mobile/) и публикует Android APK через GitHub Releases:
185
+ CCB 8.5.0 включает Flutter source CCB Mobile в [`mobile/`](../mobile/) и публикует Android APK через GitHub Releases:
186
186
 
187
- - [Скачать CCB Mobile v8.4.3 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
187
+ - [Скачать CCB Mobile v8.5.0 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
188
188
  - Исходники app: [`mobile/app`](../mobile/app)
189
189
  - Исходники server gateway: [`lib/mobile_gateway`](../lib/mobile_gateway)
190
190
 
package/README/zh.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **让 Codex、Claude、Gemini 等 CLI Agent 可见、可控、可接管地协同工作**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -211,9 +211,9 @@ ccb update mobile
211
211
  <details>
212
212
  <summary><b>Mobile App 详情、安全边界和源码</b></summary>
213
213
 
214
- CCB 8.4.3 已把 Flutter 版 CCB Mobile 源码放入 [`mobile/`](../mobile/),并在 GitHub Release 中发布 Android APK:
214
+ CCB 8.5.0 已把 Flutter 版 CCB Mobile 源码放入 [`mobile/`](../mobile/),并在 GitHub Release 中发布 Android APK:
215
215
 
216
- - [下载 CCB Mobile v8.4.3 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
216
+ - [下载 CCB Mobile v8.5.0 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
217
217
  - App 源码:[`mobile/app`](../mobile/app)
218
218
  - 服务端 gateway 源码:[`lib/mobile_gateway`](../lib/mobile_gateway)
219
219
 
@@ -300,6 +300,18 @@ CCB 支持 [Agent Roles Spec](https://github.com/SeemSeam/agent-roles-spec):
300
300
  ## 新版本记录
301
301
 
302
302
  <details open>
303
+ <summary><b>v8.5.0</b> - 精确 Pi/OMP 终止、自修复 npm 运行时、同步 Mobile 活动与更安全的托管资源</summary>
304
+
305
+ - 将 Pi 完成信号绑定到最新的 `agent_settled`,将 OMP 完成信号绑定到 `agent_end.isTerminal=true`,并在进程退出且输出关闭后才进入终态。
306
+ - 对缺少原生终止证据、缺少最终结果、JSONL 损坏或截断、Provider 错误和非零退出安全拒绝;OMP 的终态 `yield` 仍作为受支持的成功结果。
307
+ - 安装时自动创建并修复 npm 托管 Python 环境,正式版运行依赖不再依靠不完整的系统 Python 兜底;linked Git worktree 仍会被正确识别为源码安装。
308
+ - 让 sidebar 设置入口能够恢复正式版受管运行时,并可靠打开 Config UI。
309
+ - 将 Mobile 的 ask/Provider 活动与服务端精确状态同步,稳定完成通知,并隐藏自动重连过程中的无意义提示。
310
+ - 收紧托管 Provider 资源的单向投影边界,并加入内置 Qoder 控制技能,托管侧不会获得改写用户全局状态的通道。
311
+
312
+ </details>
313
+
314
+ <details>
303
315
  <summary><b>v8.4.3</b> - Provider 认证隔离、必备控制技能与可靠的 Mobile 配对和终端恢复</summary>
304
316
 
305
317
  - 将可变认证、账号、session 和存储状态隔离到每个托管 Provider 的私有 home,visible 与 headless 执行使用同一边界。
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  **Coordinate Codex, Claude, Gemini, and other CLI agents in visible, controllable workflows you can take over**
7
7
 
8
8
  <p>
9
- <img src="https://img.shields.io/badge/version-8.4.3-orange.svg" alt="version">
9
+ <img src="https://img.shields.io/badge/version-8.5.0-orange.svg" alt="version">
10
10
  <img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WSL-lightgrey.svg" alt="platform">
11
11
  <img src="https://img.shields.io/badge/providers-17%20CLI%20families-0B7285.svg" alt="providers">
12
12
  </p>
@@ -220,9 +220,9 @@ This command guides installation and configuration.
220
220
  <details>
221
221
  <summary><b>Mobile App details, safety boundary, and source</b></summary>
222
222
 
223
- CCB 8.4.3 includes the Flutter CCB Mobile source in [`mobile/`](mobile/) and publishes the Android APK through GitHub Releases:
223
+ CCB 8.5.0 includes the Flutter CCB Mobile source in [`mobile/`](mobile/) and publishes the Android APK through GitHub Releases:
224
224
 
225
- - [Download CCB Mobile v8.4.3 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.4.3/ccb-mobile-v8.4.3.apk)
225
+ - [Download CCB Mobile v8.5.0 APK](https://github.com/SeemSeam/claude_codex_bridge/releases/download/v8.5.0/ccb-mobile-v8.5.0.apk)
226
226
  - App source: [`mobile/app`](mobile/app)
227
227
  - Server gateway source: [`lib/mobile_gateway`](lib/mobile_gateway)
228
228
 
@@ -309,6 +309,18 @@ Thanks to [tmux-agent-sidebar](https://github.com/hiroppy/tmux-agent-sidebar) fo
309
309
  ## Release Notes
310
310
 
311
311
  <details open>
312
+ <summary><b>v8.5.0</b> - Exact Pi/OMP completion, self-healing npm runtime, synchronized Mobile activity, and safer managed assets</summary>
313
+
314
+ - Bound Pi completion to the latest `agent_settled` event and OMP completion to `agent_end.isTerminal=true`, while waiting for process exit and output closure before terminalizing.
315
+ - Failed closed on missing native terminal evidence, missing final outcomes, malformed or truncated JSONL, provider errors, and nonzero exits; terminal OMP `yield` remains a supported successful result.
316
+ - Bootstrapped and repaired the npm-managed Python environment during install, so release runtime dependencies no longer depend on an incomplete system Python fallback; linked Git worktrees remain correctly classified as source installs.
317
+ - Made the sidebar settings launcher recover its release-managed runtime and reliably open Config UI.
318
+ - Synchronized Mobile ask/provider activity with exact server-side state, stable completion notifications, and quieter automatic reconnect behavior.
319
+ - Tightened one-way managed Provider asset projection and added packaged Qoder control skills without exposing user-global state to managed mutation.
320
+
321
+ </details>
322
+
323
+ <details>
312
324
  <summary><b>v8.4.3</b> - Isolated Provider auth, guaranteed control skills, and reliable Mobile pairing and terminal recovery</summary>
313
325
 
314
326
  - Isolated mutable authentication, account, session, and storage state inside each managed Provider home for visible and headless execution.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 8.4.3
1
+ 8.5.0
@@ -12,6 +12,19 @@ const root = path.resolve(__dirname, "..");
12
12
  const manifest = require(path.join(root, "package.json"));
13
13
  const version = manifest.version;
14
14
  const vendorRoot = path.join(root, ".ccb-release");
15
+ const installLock = path.join(root, ".ccb-install.lock");
16
+ const runtimeProbe = [
17
+ "import sys",
18
+ "if sys.version_info < (3, 10):",
19
+ " raise SystemExit(1)",
20
+ "try:",
21
+ " import tomllib",
22
+ "except ModuleNotFoundError:",
23
+ " import tomli",
24
+ "import aiohttp",
25
+ "from cryptography.hazmat.primitives.asymmetric import ed25519, x25519",
26
+ "from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305",
27
+ ].join("\n");
15
28
 
16
29
  function artifactForHost() {
17
30
  if (process.platform === "darwin") {
@@ -42,14 +55,39 @@ function executablePath(command = "ccb") {
42
55
  return command === "ccb" ? path.join(base, "ccb") : path.join(base, "bin", command);
43
56
  }
44
57
 
45
- function isInstalled(info) {
58
+ function runtimePythonPath(info) {
59
+ return path.join(installDir(info), ".venv", "bin", "python");
60
+ }
61
+
62
+ function isReleaseInstalled(info) {
46
63
  const dir = installDir(info);
47
64
  const versionFile = path.join(dir, "VERSION");
48
65
  const ccbPath = path.join(dir, "ccb");
49
66
  if (!fs.existsSync(versionFile) || !fs.existsSync(ccbPath)) {
50
67
  return false;
51
68
  }
52
- return fs.readFileSync(versionFile, "utf8").trim() === version;
69
+ try {
70
+ fs.accessSync(ccbPath, fs.constants.X_OK);
71
+ return fs.readFileSync(versionFile, "utf8").trim() === version;
72
+ } catch (_error) {
73
+ return false;
74
+ }
75
+ }
76
+
77
+ function isRuntimeReady(info) {
78
+ const pythonPath = runtimePythonPath(info);
79
+ if (!fs.existsSync(pythonPath)) {
80
+ return false;
81
+ }
82
+ const completed = childProcess.spawnSync(pythonPath, ["-c", runtimeProbe], {
83
+ stdio: "ignore",
84
+ timeout: 15000,
85
+ });
86
+ return !completed.error && completed.status === 0;
87
+ }
88
+
89
+ function isInstalled(info) {
90
+ return isReleaseInstalled(info) && isRuntimeReady(info);
53
91
  }
54
92
 
55
93
  function download(url, destination, redirects = 0) {
@@ -100,9 +138,10 @@ function sha256File(filePath) {
100
138
  return hash.digest("hex");
101
139
  }
102
140
 
103
- function run(command, args) {
141
+ function run(command, args, options = {}) {
104
142
  const completed = childProcess.spawnSync(command, args, {
105
143
  stdio: "inherit",
144
+ ...options,
106
145
  });
107
146
  if (completed.error) {
108
147
  throw completed.error;
@@ -112,16 +151,119 @@ function run(command, args) {
112
151
  }
113
152
  }
114
153
 
115
- async function install() {
116
- const info = artifactForHost();
117
- if (isInstalled(info)) {
118
- return;
154
+ function bootstrapRuntime(info) {
155
+ const dir = installDir(info);
156
+ const installerPath = path.join(dir, "install.sh");
157
+ if (!isReleaseInstalled(info)) {
158
+ throw new Error(`Cannot bootstrap an incomplete CCB release at ${dir}`);
119
159
  }
120
- if (process.env.CCB_NPM_SKIP_DOWNLOAD === "1") {
121
- console.warn("Skipping CCB release download because CCB_NPM_SKIP_DOWNLOAD=1.");
122
- return;
160
+ if (!fs.existsSync(installerPath)) {
161
+ throw new Error(`CCB runtime bootstrap installer not found at ${installerPath}`);
162
+ }
163
+
164
+ const env = {
165
+ ...process.env,
166
+ CODEX_INSTALL_PREFIX: dir,
167
+ CODEX_BIN_DIR: path.join(dir, ".npm-runtime-bin"),
168
+ CCB_SOURCE_KIND: "release",
169
+ CCB_USE_MANAGED_VENV: "1",
170
+ CCB_INSTALL_TOMLI: "1",
171
+ CCB_INSTALL_MOBILE_RELAY_DEPS: "1",
172
+ CCB_INSTALL_ROLES: "0",
173
+ CCB_INSTALL_NEOVIM: "0",
174
+ };
175
+ run("bash", [installerPath, "runtime-bootstrap"], { env });
176
+ if (!isRuntimeReady(info)) {
177
+ throw new Error(`CCB managed Python runtime is not usable at ${runtimePythonPath(info)}`);
178
+ }
179
+ }
180
+
181
+ function sleep(milliseconds) {
182
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
183
+ }
184
+
185
+ function processIsAlive(pid) {
186
+ if (!Number.isInteger(pid) || pid <= 0) {
187
+ return false;
188
+ }
189
+ try {
190
+ process.kill(pid, 0);
191
+ return true;
192
+ } catch (error) {
193
+ return error && error.code === "EPERM";
194
+ }
195
+ }
196
+
197
+ function readLockOwner() {
198
+ try {
199
+ return JSON.parse(fs.readFileSync(path.join(installLock, "owner.json"), "utf8"));
200
+ } catch (_error) {
201
+ return null;
202
+ }
203
+ }
204
+
205
+ function reclaimStaleInstallLock() {
206
+ const owner = readLockOwner();
207
+ if (owner && processIsAlive(Number(owner.pid))) {
208
+ return false;
209
+ }
210
+ try {
211
+ const ageMs = Date.now() - fs.statSync(installLock).mtimeMs;
212
+ if (!owner && ageMs < 30000) {
213
+ return false;
214
+ }
215
+ fs.rmSync(installLock, { recursive: true, force: true });
216
+ return true;
217
+ } catch (_error) {
218
+ return false;
219
+ }
220
+ }
221
+
222
+ async function acquireInstallLock() {
223
+ const configuredTimeout = Number(process.env.CCB_NPM_INSTALL_LOCK_TIMEOUT_MS);
224
+ const timeoutMs =
225
+ Number.isFinite(configuredTimeout) && configuredTimeout > 0
226
+ ? configuredTimeout
227
+ : 15 * 60 * 1000;
228
+ const deadline = Date.now() + timeoutMs;
229
+ const token = crypto.randomBytes(16).toString("hex");
230
+
231
+ while (true) {
232
+ try {
233
+ fs.mkdirSync(installLock);
234
+ } catch (error) {
235
+ if (!error || error.code !== "EEXIST") {
236
+ throw error;
237
+ }
238
+ if (reclaimStaleInstallLock()) {
239
+ continue;
240
+ }
241
+ if (Date.now() >= deadline) {
242
+ throw new Error(`Timed out waiting for CCB npm install lock: ${installLock}`);
243
+ }
244
+ await sleep(200);
245
+ continue;
246
+ }
247
+
248
+ try {
249
+ fs.writeFileSync(
250
+ path.join(installLock, "owner.json"),
251
+ JSON.stringify({ pid: process.pid, token, createdAt: new Date().toISOString() })
252
+ );
253
+ } catch (error) {
254
+ fs.rmSync(installLock, { recursive: true, force: true });
255
+ throw error;
256
+ }
257
+ return () => {
258
+ const owner = readLockOwner();
259
+ if (owner && owner.token === token) {
260
+ fs.rmSync(installLock, { recursive: true, force: true });
261
+ }
262
+ };
123
263
  }
264
+ }
124
265
 
266
+ async function downloadRelease(info) {
125
267
  const baseUrl =
126
268
  process.env.CCB_NPM_RELEASE_BASE_URL ||
127
269
  `https://github.com/SeemSeam/claude_codex_bridge/releases/download/v${version}`;
@@ -154,6 +296,32 @@ async function install() {
154
296
  }
155
297
  }
156
298
 
299
+ async function install() {
300
+ const info = artifactForHost();
301
+ if (isInstalled(info)) {
302
+ return;
303
+ }
304
+
305
+ const releaseLock = await acquireInstallLock();
306
+ try {
307
+ if (isInstalled(info)) {
308
+ return;
309
+ }
310
+ if (!isReleaseInstalled(info)) {
311
+ if (process.env.CCB_NPM_SKIP_DOWNLOAD === "1") {
312
+ console.warn("Skipping CCB release download because CCB_NPM_SKIP_DOWNLOAD=1.");
313
+ return;
314
+ }
315
+ await downloadRelease(info);
316
+ }
317
+ if (!isRuntimeReady(info)) {
318
+ bootstrapRuntime(info);
319
+ }
320
+ } finally {
321
+ releaseLock();
322
+ }
323
+ }
324
+
157
325
  if (require.main === module) {
158
326
  install().catch((error) => {
159
327
  console.error(error.message || error);
@@ -162,6 +330,13 @@ if (require.main === module) {
162
330
  }
163
331
 
164
332
  module.exports = {
333
+ artifactForHost,
334
+ bootstrapRuntime,
165
335
  executablePath,
166
336
  install,
337
+ installDir,
338
+ isInstalled,
339
+ isReleaseInstalled,
340
+ isRuntimeReady,
341
+ runtimePythonPath,
167
342
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seemseam/ccb",
3
- "version": "8.4.3",
3
+ "version": "8.5.0",
4
4
  "description": "Lightweight multi-agent TUI and stable cross-provider collaboration layer for Codex, Claude, Gemini, Grok, Kimi, DeepSeek, and other CLI agents.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "homepage": "https://github.com/SeemSeam/claude_codex_bridge#readme",