@elvatis_com/openclaw-cli-bridge-elvatis 1.6.4 → 1.6.5

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
@@ -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.6.4`
5
+ **Current version:** `1.6.5`
6
6
 
7
7
  ---
8
8
 
@@ -362,6 +362,9 @@ npm test # vitest run (83 tests)
362
362
 
363
363
  ## Changelog
364
364
 
365
+ ### v1.6.5
366
+ - **feat:** Automatic session keep-alive — every 20h, active browser sessions are silently refreshed by navigating to the provider home page. Prevents cookie expiry on providers like ChatGPT (7-day sessions) without storing credentials.
367
+
365
368
  ### v1.6.4
366
369
  - **chore:** version bump (1.6.3 was already published on npm with partial changes)
367
370
 
package/SKILL.md CHANGED
@@ -64,4 +64,4 @@ On gateway restart, if any session has expired, a **WhatsApp alert** is sent aut
64
64
 
65
65
  See `README.md` for full configuration reference and architecture diagram.
66
66
 
67
- **Version:** 1.6.4
67
+ **Version:** 1.6.5
package/index.ts CHANGED
@@ -249,6 +249,9 @@ let _cdpBrowserLaunchPromise: Promise<import("playwright").BrowserContext | null
249
249
  // Set to true after first run; hot-reloads see true and skip the restore loop.
250
250
  let _startupRestoreDone = false;
251
251
 
252
+ // Session keep-alive interval — refreshes browser cookies every 20h
253
+ let _keepAliveInterval: ReturnType<typeof setInterval> | null = null;
254
+
252
255
  /**
253
256
  * Connect to the OpenClaw managed browser (CDP port 18800).
254
257
  * Singleton: reuses the same connection. Falls back to persistent Chromium for Grok only.
@@ -435,8 +438,46 @@ async function getOrLaunchChatGPTContext(
435
438
  return _chatgptLaunchPromise;
436
439
  }
437
440
 
441
+ /** Session keep-alive — navigate to provider home pages to refresh cookies */
442
+ async function sessionKeepAlive(log: (msg: string) => void): Promise<void> {
443
+ const providers: Array<{
444
+ name: string;
445
+ homeUrl: string;
446
+ getCtx: () => BrowserContext | null;
447
+ scanExpiry: (ctx: BrowserContext) => Promise<{ expiresAt: number; loginAt: number; cookieName: string } | null>;
448
+ saveExpiry: (info: { expiresAt: number; loginAt: number; cookieName: string }) => void;
449
+ }> = [
450
+ { name: "grok", homeUrl: "https://grok.com", getCtx: () => grokContext, scanExpiry: scanCookieExpiry, saveExpiry: saveGrokExpiry },
451
+ { name: "gemini", homeUrl: "https://gemini.google.com/app", getCtx: () => geminiContext, scanExpiry: scanGeminiCookieExpiry, saveExpiry: saveGeminiExpiry },
452
+ { name: "claude-web", homeUrl: "https://claude.ai/new", getCtx: () => claudeWebContext, scanExpiry: scanClaudeCookieExpiry, saveExpiry: saveClaudeExpiry },
453
+ { name: "chatgpt", homeUrl: "https://chatgpt.com", getCtx: () => chatgptContext, scanExpiry: scanChatGPTCookieExpiry, saveExpiry: saveChatGPTExpiry },
454
+ ];
455
+
456
+ for (const p of providers) {
457
+ const ctx = p.getCtx();
458
+ if (!ctx) continue;
459
+ try {
460
+ const page = await ctx.newPage();
461
+ await page.goto(p.homeUrl, { waitUntil: "domcontentloaded", timeout: 15_000 });
462
+ await new Promise(r => setTimeout(r, 4000));
463
+ await page.close();
464
+ const expiry = await p.scanExpiry(ctx);
465
+ if (expiry) p.saveExpiry(expiry);
466
+ log(`[cli-bridge:${p.name}] session keep-alive touch ✅`);
467
+ } catch (err) {
468
+ log(`[cli-bridge:${p.name}] session keep-alive failed: ${(err as Error).message}`);
469
+ }
470
+ // Sequential — avoid spawning multiple pages at once
471
+ await new Promise(r => setTimeout(r, 2000));
472
+ }
473
+ }
474
+
438
475
  /** Clean up all browser resources — call on plugin teardown */
439
476
  async function cleanupBrowsers(log: (msg: string) => void): Promise<void> {
477
+ if (_keepAliveInterval) {
478
+ clearInterval(_keepAliveInterval);
479
+ _keepAliveInterval = null;
480
+ }
440
481
  if (grokContext) {
441
482
  try { await grokContext.close(); } catch { /* ignore */ }
442
483
  grokContext = null;
@@ -854,7 +895,7 @@ function proxyTestRequest(
854
895
  const plugin = {
855
896
  id: "openclaw-cli-bridge-elvatis",
856
897
  name: "OpenClaw CLI Bridge",
857
- version: "1.6.4",
898
+ version: "1.6.5",
858
899
  description:
859
900
  "Phase 1: openai-codex auth bridge. " +
860
901
  "Phase 2: HTTP proxy for gemini/claude CLIs. " +
@@ -991,6 +1032,13 @@ const plugin = {
991
1032
  }
992
1033
  }
993
1034
  })();
1035
+
1036
+ // Start session keep-alive interval (every 20h)
1037
+ if (!_keepAliveInterval) {
1038
+ _keepAliveInterval = setInterval(() => {
1039
+ void sessionKeepAlive((msg) => api.logger.info(msg));
1040
+ }, 72_000_000);
1041
+ }
994
1042
  }
995
1043
 
996
1044
  // ── 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.6.4",
4
+ "version": "1.6.5",
5
5
  "license": "MIT",
6
6
  "description": "Phase 1: openai-codex auth bridge. Phase 2: local HTTP proxy routing model calls through gemini/claude CLIs (vllm provider).",
7
7
  "providers": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elvatis_com/openclaw-cli-bridge-elvatis",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
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": {