@elvatis_com/openclaw-cli-bridge-elvatis 1.3.2 → 1.3.4

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.
@@ -1,8 +1,8 @@
1
1
  # STATUS — openclaw-cli-bridge-elvatis
2
2
 
3
- ## Current Version: 1.0.0 (npm + ClawHub + GitHub) ✅ RELEASED
3
+ ## Current Version: 1.3.3 (npm + ClawHub + GitHub) ✅ RELEASED
4
4
 
5
- ## All 4 Providers LIVETested 2026-03-11 22:24
5
+ ## All 4 Providers Availableon-demand via /xxx-login
6
6
  | Provider | Status | Models | Command |
7
7
  |---|---|---|---|
8
8
  | Grok | ✅ | web-grok/grok-3, grok-3-fast, grok-3-mini, grok-3-mini-fast | /grok-login |
@@ -10,26 +10,35 @@
10
10
  | Gemini | ✅ | web-gemini/gemini-2-5-pro, gemini-2-5-flash, gemini-3-pro, gemini-3-flash | /gemini-login |
11
11
  | ChatGPT | ✅ | web-chatgpt/gpt-4o, gpt-4o-mini, gpt-o3, gpt-o4-mini, gpt-5 | /chatgpt-login |
12
12
 
13
- Live test: "What is the capital of France?"
14
- - Grok: "Paris" ✅
15
- - Claude: "Paris" ✅
16
- - Gemini: "Paris" ✅
17
- - ChatGPT: "Paris" ✅
18
-
19
13
  ## Stats
20
14
  - 22 total models, 16 web-session models
21
15
  - 96/96 tests green (8 test files)
22
- - 0 zombie Chromium processes (singleton CDP, cleanupBrowsers on stop)
16
+ - 0 zombie Chromium processes at startup (browsers on-demand only)
23
17
  - Cookie expiry tracking for all 4 providers
18
+ - Singleton guard on ensureAllProviderContexts (no concurrent spawns)
19
+
20
+ ## Architecture: Browser Lifecycle
21
+ - **On plugin start:** NO browser launched automatically
22
+ - **On /xxx-login:** launches persistent Chromium for that provider only
23
+ - **On request (no context):** returns null → caller sees "not logged in" error
24
+ - **On /xxx-logout:** closes context + deletes session file
25
+
26
+ ## Known Issues
27
+ - Cloudflare may block headless Chromium for Claude/Gemini without a valid CDP session
28
+ → Workaround: have OpenClaw browser open on the provider's page, then /xxx-login
24
29
 
25
- ## Known Issue: Browser persistence after Gateway restart
26
- After SIGUSR1/full restart, OpenClaw browser is gone (CDP ECONNREFUSED).
27
- Workaround: manually open browser + 4 provider pages lazy connect takes over.
28
- Fix needed: auto-start browser on plugin init, or keep-alive ping.
30
+ ## Release History
31
+ - v1.3.3 (2026-03-12): Remove startup auto-connect browsers on-demand only (OOM fix)
32
+ - v1.3.2 (2026-03-12): Singleton guard on ensureAllProviderContexts (resource leak fix)
33
+ - v1.3.1 (2026-03-11): Cookie baking into persistent profiles on login
34
+ - v1.3.0 (2026-03-11): Browser auto-reconnect after gateway restart
35
+ - v1.2.0 (2026-03-11): Fresh page per request + ChatGPT model switching
36
+ - v1.1.0 (2026-03-11): Auto-connect on startup + /bridge-status
37
+ - v1.0.0 (2026-03-11): All 4 providers headless (Grok/Claude/Gemini/ChatGPT) — 96/96 tests
38
+ - v0.2.x: Grok (v0.2.26-28), Claude (v0.2.29), Gemini (v0.2.30)
39
+ - v0.2.25: Sleep-resilient token refresh + staged /cli-* switching
29
40
 
30
- ## Next Steps (v1.1.x)
31
- - Auto-reconnect OpenClaw browser on plugin start
32
- - /status command showing all 4 providers at once
33
- - Context-window management for long conversations (new page per conversation)
34
- - Handle model-switching within chatgpt.com (dropdown selector)
35
- - Handle Gemini model switching (2.5 Pro vs Flash vs 3)
41
+ ## Next Steps
42
+ - Context-window management for long conversations
43
+ - Gemini model switching (2.5 Pro vs Flash vs 3) via UI
44
+ - /bridge-status: show per-provider login state + cookie expiry
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, health testing, and model listing.
4
4
 
5
- **Current version:** `1.3.1`
5
+ **Current version:** `1.3.4`
6
6
 
7
7
  ---
8
8
 
@@ -287,6 +287,20 @@ npm test # vitest run (45 tests)
287
287
 
288
288
  ## Changelog
289
289
 
290
+ ### v1.3.4
291
+ - **feat:** Safe sequential session restore on startup — if a saved profile exists, providers are reconnected automatically after gateway restart (one at a time, 3s delay between each, headless)
292
+ - **fix:** No manual `/xxx-login` needed after reboot if profile is already saved
293
+ - **safety:** Profile-gated — only restores if `~/.openclaw/<provider>-profile/` or cookie file exists; never spawns a browser for an uninitialized provider
294
+
295
+ ### v1.3.3
296
+ - **fix:** Removed auto-connect of all browser providers on plugin startup — caused OOM (load 195, 30GB RAM) by spawning 4+ persistent Chromium instances on every gateway start
297
+ - **fix:** Removed Grok session restore on startup — same root cause
298
+ - **behavior change:** Browsers are now started **on-demand only** via `/grok-login`, `/claude-login`, `/gemini-login`, `/chatgpt-login`
299
+
300
+ ### v1.3.2
301
+ - **fix:** Singleton promise guard on `ensureAllProviderContexts()` — concurrent requests no longer each spawn their own Chromium; extra callers await the existing run
302
+ - **fix:** Removed recursive `ensureAllProviderContexts()` fallback from all `connect*Context` proxy callbacks — no more exponential browser spawn on CDP failure
303
+
290
304
  ### v1.3.1
291
305
  - **fix:** /claude-login, /gemini-login, /chatgpt-login now bake cookies into persistent profile dirs
292
306
  - **fix:** After gateway restart, providers auto-reconnect from saved profile (no browser tabs needed)
package/index.ts CHANGED
@@ -746,13 +746,96 @@ const plugin = {
746
746
  const codexAuthPath = cfg.codexAuthPath ?? DEFAULT_CODEX_AUTH_PATH;
747
747
  const grokSessionPath = cfg.grokSessionPath ?? DEFAULT_SESSION_PATH;
748
748
 
749
- // ── Grok session restore (non-blocking) ───────────────────────────────────
750
- void tryRestoreGrokSession(grokSessionPath, (msg) => api.logger.info(msg));
751
-
752
- // ── Auto-connect all browser providers on startup (non-blocking) ──────────
749
+ // ── Safe session restore on startup (sequential, profile-gated, non-blocking) ──
750
+ // Restores provider sessions from saved persistent profiles — but ONLY if the
751
+ // profile directory already exists (i.e. user has logged in before).
752
+ // Providers are launched one at a time with a delay to avoid OOM.
753
753
  void (async () => {
754
- await new Promise(r => setTimeout(r, 3000)); // wait for proxy to start
755
- await ensureAllProviderContexts((msg) => api.logger.info(msg));
754
+ await new Promise(r => setTimeout(r, 5000)); // wait for proxy + gateway to settle
755
+ const { chromium } = await import("playwright");
756
+ const { existsSync } = await import("node:fs");
757
+
758
+ const profileProviders: Array<{
759
+ name: string;
760
+ profileDir: string;
761
+ cookieFile: string;
762
+ verifySelector: string;
763
+ homeUrl: string;
764
+ setCtx: (c: BrowserContext) => void;
765
+ getCtx: () => BrowserContext | null;
766
+ }> = [
767
+ {
768
+ name: "grok",
769
+ profileDir: GROK_PROFILE_DIR,
770
+ cookieFile: join(homedir(), ".openclaw", "grok-session.json"),
771
+ verifySelector: "textarea",
772
+ homeUrl: "https://grok.com",
773
+ getCtx: () => grokContext,
774
+ setCtx: (c) => { grokContext = c; },
775
+ },
776
+ {
777
+ name: "claude",
778
+ profileDir: join(homedir(), ".openclaw", "claude-profile"),
779
+ cookieFile: join(homedir(), ".openclaw", "claude-cookie-expiry.json"),
780
+ verifySelector: ".ProseMirror",
781
+ homeUrl: "https://claude.ai/new",
782
+ getCtx: () => claudeContext,
783
+ setCtx: (c) => { claudeContext = c; },
784
+ },
785
+ {
786
+ name: "gemini",
787
+ profileDir: join(homedir(), ".openclaw", "gemini-profile"),
788
+ cookieFile: join(homedir(), ".openclaw", "gemini-cookie-expiry.json"),
789
+ verifySelector: ".ql-editor",
790
+ homeUrl: "https://gemini.google.com/app",
791
+ getCtx: () => geminiContext,
792
+ setCtx: (c) => { geminiContext = c; },
793
+ },
794
+ {
795
+ name: "chatgpt",
796
+ profileDir: join(homedir(), ".openclaw", "chatgpt-profile"),
797
+ cookieFile: join(homedir(), ".openclaw", "chatgpt-cookie-expiry.json"),
798
+ verifySelector: "#prompt-textarea",
799
+ homeUrl: "https://chatgpt.com",
800
+ getCtx: () => chatgptContext,
801
+ setCtx: (c) => { chatgptContext = c; },
802
+ },
803
+ ];
804
+
805
+ for (const p of profileProviders) {
806
+ // Skip if no saved profile/session exists
807
+ if (!existsSync(p.profileDir) && !existsSync(p.cookieFile)) {
808
+ api.logger.info(`[cli-bridge:${p.name}] no saved profile — skipping startup restore`);
809
+ continue;
810
+ }
811
+ if (p.getCtx()) continue; // already connected
812
+
813
+ try {
814
+ api.logger.info(`[cli-bridge:${p.name}] restoring session from profile…`);
815
+ const ctx = await chromium.launchPersistentContext(p.profileDir, {
816
+ headless: true,
817
+ args: ["--no-sandbox", "--disable-setuid-sandbox"],
818
+ });
819
+ const page = await ctx.newPage();
820
+ await page.goto(p.homeUrl, { waitUntil: "domcontentloaded", timeout: 20_000 });
821
+ await new Promise(r => setTimeout(r, 3000));
822
+ const ok = await page.locator(p.verifySelector).isVisible().catch(() => false);
823
+ await page.close().catch(() => {});
824
+ if (ok) {
825
+ p.setCtx(ctx);
826
+ ctx.on("close", () => { p.setCtx(null as unknown as BrowserContext); });
827
+ api.logger.info(`[cli-bridge:${p.name}] session restored from profile ✅`);
828
+ } else {
829
+ await ctx.close().catch(() => {});
830
+ api.logger.info(`[cli-bridge:${p.name}] profile exists but not logged in — skipping`);
831
+ }
832
+ } catch (err) {
833
+ api.logger.warn(`[cli-bridge:${p.name}] startup restore failed: ${(err as Error).message}`);
834
+ }
835
+
836
+ // Sequential delay — avoid spawning all 4 Chromium instances at once
837
+ await new Promise(r => setTimeout(r, 3000));
838
+ }
756
839
  })();
757
840
 
758
841
  // ── Phase 1: openai-codex auth bridge ─────────────────────────────────────
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "openclaw-cli-bridge-elvatis",
3
3
  "name": "OpenClaw CLI Bridge",
4
- "version": "1.3.2",
4
+ "version": "1.3.4",
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": "1.3.2",
3
+ "version": "1.3.4",
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": {