@elvatis_com/openclaw-cli-bridge-elvatis 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.
@@ -6,15 +6,15 @@ _Last updated: 2026-03-07_
6
6
 
7
7
  | Component | Version | Build | Tests | Status |
8
8
  |-----------|---------|-------|-------|--------|
9
- | openclaw-cli-bridge-elvatis | 0.2.6 | ✅ | 5/5 ✅ | ✅ Stable |
9
+ | openclaw-cli-bridge-elvatis | 0.2.7 | ✅ | 5/5 ✅ | ✅ Stable |
10
10
 
11
11
  ## 🚀 Release State
12
12
 
13
13
  | Platform | Version | Status |
14
14
  |----------|---------|--------|
15
- | GitHub | v0.2.6 | ✅ Tagged + Release |
16
- | npm | 0.2.6 | ✅ Published |
17
- | ClawHub | 0.2.6 | ✅ Published |
15
+ | GitHub | v0.2.7 | ✅ Tagged + Release |
16
+ | npm | 0.2.7 | ✅ Published |
17
+ | ClawHub | 0.2.7 | ✅ Published |
18
18
 
19
19
  ## 📋 Open Tasks
20
20
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  _Last updated: 2026-03-07 by Akido (claude-sonnet-4-6)_
4
4
 
5
- ## Current Version: 0.2.6 — STABLE
5
+ ## Current Version: 0.2.7 — STABLE
6
6
 
7
7
  ## What is done
8
8
 
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > OpenClaw plugin that bridges locally installed AI CLIs (Codex, Gemini, Claude Code) as model providers — with slash commands for instant model switching, restore, and health testing.
4
4
 
5
- **Current version:** `0.2.6`
5
+ **Current version:** `0.2.7`
6
6
 
7
7
  ---
8
8
 
package/index.ts CHANGED
@@ -354,9 +354,24 @@ const plugin = {
354
354
  let proxyServer: import("node:http").Server | null = null;
355
355
 
356
356
  if (enableProxy) {
357
- // Retry up to 3 times with 600ms delay to handle the race condition where
358
- // a previous plugin instance's server.close() hasn't released the port yet.
359
- const startWithRetry = async (attemptsLeft: number): Promise<void> => {
357
+ // Before binding, evict any stale process holding our port.
358
+ // Port 31337 is exclusively ours — it's safe to kill whatever is on it.
359
+ // This handles the systemd restart race: new process starts before the old
360
+ // one's socket is fully released.
361
+ const evictPort = async (): Promise<void> => {
362
+ try {
363
+ const { execSync } = await import("node:child_process");
364
+ // fuser -k sends SIGKILL to whatever holds the TCP port
365
+ execSync(`fuser -k ${port}/tcp 2>/dev/null || true`, { stdio: "ignore" });
366
+ // Give the OS ~200ms to release the socket
367
+ await new Promise((r) => setTimeout(r, 200));
368
+ api.logger.info(`[cli-bridge] evicted stale listener on port ${port}`);
369
+ } catch {
370
+ // fuser not available or port was already free — ignore
371
+ }
372
+ };
373
+
374
+ const startProxy = async (): Promise<void> => {
360
375
  try {
361
376
  const server = await startProxyServer({
362
377
  port,
@@ -377,15 +392,26 @@ const plugin = {
377
392
  }
378
393
  } catch (err: unknown) {
379
394
  const msg = (err as Error).message ?? String(err);
380
- if (attemptsLeft > 1 && msg.includes("EADDRINUSE")) {
381
- api.logger.warn(`[cli-bridge] port ${port} busy, retrying in 600ms (${attemptsLeft - 1} left)…`);
382
- await new Promise((r) => setTimeout(r, 600));
383
- return startWithRetry(attemptsLeft - 1);
395
+ if (msg.includes("EADDRINUSE")) {
396
+ // fuser didn't work (e.g. not installed) one last retry after 800ms
397
+ api.logger.warn(`[cli-bridge] port ${port} still busy after evict, retrying in 800ms…`);
398
+ await new Promise((r) => setTimeout(r, 800));
399
+ const server = await startProxyServer({
400
+ port,
401
+ apiKey,
402
+ timeoutMs,
403
+ log: (msg) => api.logger.info(msg),
404
+ warn: (msg) => api.logger.warn(msg),
405
+ });
406
+ proxyServer = server;
407
+ api.logger.info(`[cli-bridge] proxy ready on :${port} (retry)`);
408
+ } else {
409
+ api.logger.warn(`[cli-bridge] proxy failed to start on port ${port}: ${msg}`);
384
410
  }
385
- api.logger.warn(`[cli-bridge] proxy failed to start on port ${port}: ${msg}`);
386
411
  }
387
412
  };
388
- startWithRetry(3).catch(() => {});
413
+
414
+ evictPort().then(startProxy).catch(() => {});
389
415
  }
390
416
 
391
417
  // ── Cleanup: close proxy server on plugin stop (hot-reload / gateway restart) ──
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-cli-bridge-elvatis",
3
3
  "name": "OpenClaw CLI Bridge",
4
- "version": "0.2.7",
4
+ "version": "0.2.8",
5
5
  "description": "Phase 1: openai-codex auth bridge. Phase 2: local HTTP proxy routing model calls through gemini/claude CLIs (vllm provider).",
6
6
  "providers": [
7
7
  "openai-codex"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elvatis_com/openclaw-cli-bridge-elvatis",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "Bridges gemini, claude, and codex CLI tools as OpenClaw model providers. Reads existing CLI auth without re-login.",
5
5
  "type": "module",
6
6
  "openclaw": {