@jackwener/opencli 1.2.5 → 1.2.6

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
@@ -328,6 +328,8 @@ npx vitest run tests/e2e/ # E2E tests
328
328
 
329
329
  - **"Extension not connected"**
330
330
  - Ensure the opencli Browser Bridge extension is installed and **enabled** in `chrome://extensions`.
331
+ - **"attach failed: Cannot access a chrome-extension:// URL"**
332
+ - Another Chrome extension (e.g. youmind, New Tab Override, or AI assistant extensions) may be interfering. Try **disabling other extensions** temporarily, then retry.
331
333
  - **Empty data returns or 'Unauthorized' error**
332
334
  - Your login session in Chrome might have expired. Open a normal Chrome tab, navigate to the target site, and log in or refresh the page.
333
335
  - **Node API errors**
package/README.zh-CN.md CHANGED
@@ -311,6 +311,8 @@ opencli cascade https://api.example.com/data
311
311
 
312
312
  - **"Extension not connected" 报错**
313
313
  - 确保你当前的 Chrome 已安装且**开启了** opencli Browser Bridge 扩展(在 `chrome://extensions` 中检查)。
314
+ - **"attach failed: Cannot access a chrome-extension:// URL" 报错**
315
+ - 其他 Chrome 扩展(如 youmind、New Tab Override 或 AI 助手类扩展)可能产生冲突。请尝试**暂时禁用其他扩展**后重试。
314
316
  - **返回空数据,或者报错 "Unauthorized"**
315
317
  - Chrome 里的登录态可能已经过期。请打开当前 Chrome 页面,在新标签页重新手工登录或刷新该页面。
316
318
  - **Node API 错误 (如 parseArgs, fs 等)**
@@ -36,6 +36,7 @@ async function ensureAttached(tabId) {
36
36
  await chrome.debugger.attach({ tabId }, "1.3");
37
37
  } catch (e) {
38
38
  const msg = e instanceof Error ? e.message : String(e);
39
+ const hint = msg.includes("chrome-extension://") ? ". Tip: another Chrome extension may be interfering — try disabling other extensions" : "";
39
40
  if (msg.includes("Another debugger is already attached")) {
40
41
  try {
41
42
  await chrome.debugger.detach({ tabId });
@@ -44,10 +45,10 @@ async function ensureAttached(tabId) {
44
45
  try {
45
46
  await chrome.debugger.attach({ tabId }, "1.3");
46
47
  } catch {
47
- throw new Error(`attach failed: ${msg}`);
48
+ throw new Error(`attach failed: ${msg}${hint}`);
48
49
  }
49
50
  } else {
50
- throw new Error(`attach failed: ${msg}`);
51
+ throw new Error(`attach failed: ${msg}${hint}`);
51
52
  }
52
53
  }
53
54
  attached.add(tabId);
@@ -310,7 +311,6 @@ async function resolveTabId(tabId, workspace) {
310
311
  if (tabId !== void 0) {
311
312
  try {
312
313
  const tab = await chrome.tabs.get(tabId);
313
- console.log(`[opencli] resolveTabId: explicit tabId=${tabId}, url=${tab.url}`);
314
314
  if (isDebuggableUrl(tab.url)) return tabId;
315
315
  console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
316
316
  } catch {
@@ -320,11 +320,7 @@ async function resolveTabId(tabId, workspace) {
320
320
  const windowId = await getAutomationWindow(workspace);
321
321
  const tabs = await chrome.tabs.query({ windowId });
322
322
  const debuggableTab = tabs.find((t) => t.id && isDebuggableUrl(t.url));
323
- if (debuggableTab?.id) {
324
- console.log(`[opencli] resolveTabId: found debuggable tab ${debuggableTab.id} (${debuggableTab.url})`);
325
- return debuggableTab.id;
326
- }
327
- console.warn(`[opencli] resolveTabId: no debuggable tabs found, tabs: ${tabs.map((t) => `${t.id}=${t.url}`).join(", ")}`);
323
+ if (debuggableTab?.id) return debuggableTab.id;
328
324
  const reuseTab = tabs.find((t) => t.id);
329
325
  if (reuseTab?.id) {
330
326
  await chrome.tabs.update(reuseTab.id, { url: "data:text/html,<html></html>" });
@@ -332,12 +328,7 @@ async function resolveTabId(tabId, workspace) {
332
328
  try {
333
329
  const updated = await chrome.tabs.get(reuseTab.id);
334
330
  if (isDebuggableUrl(updated.url)) return reuseTab.id;
335
- console.warn(`[opencli] about:blank was intercepted (${updated.url}), trying data: URI`);
336
- await chrome.tabs.update(reuseTab.id, { url: "data:text/html,<html></html>" });
337
- await new Promise((resolve) => setTimeout(resolve, 300));
338
- const updated2 = await chrome.tabs.get(reuseTab.id);
339
- if (isDebuggableUrl(updated2.url)) return reuseTab.id;
340
- console.warn(`[opencli] data: URI also intercepted, creating fresh tab`);
331
+ console.warn(`[opencli] data: URI was intercepted (${updated.url}), creating fresh tab`);
341
332
  } catch {
342
333
  }
343
334
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": 3,
3
3
  "name": "OpenCLI",
4
- "version": "1.2.5",
4
+ "version": "1.2.6",
5
5
  "description": "Bridge between opencli CLI and your browser — execute commands, read cookies, manage tabs.",
6
6
  "permissions": [
7
7
  "debugger",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencli-extension",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -88,7 +88,7 @@ function scheduleReconnect(): void {
88
88
  // ─── Automation window isolation ─────────────────────────────────────
89
89
  // All opencli operations happen in a dedicated Chrome window so the
90
90
  // user's active browsing session is never touched.
91
- // The window auto-closes after 30s of idle (no commands).
91
+ // The window auto-closes after 120s of idle (no commands).
92
92
 
93
93
  type AutomationSession = {
94
94
  windowId: number;
@@ -247,7 +247,6 @@ async function resolveTabId(tabId: number | undefined, workspace: string): Promi
247
247
  if (tabId !== undefined) {
248
248
  try {
249
249
  const tab = await chrome.tabs.get(tabId);
250
- console.log(`[opencli] resolveTabId: explicit tabId=${tabId}, url=${tab.url}`);
251
250
  if (isDebuggableUrl(tab.url)) return tabId;
252
251
  // Tab exists but URL is not debuggable — fall through to auto-resolve
253
252
  console.warn(`[opencli] Tab ${tabId} URL is not debuggable (${tab.url}), re-resolving`);
@@ -260,42 +259,27 @@ async function resolveTabId(tabId: number | undefined, workspace: string): Promi
260
259
  // Get (or create) the automation window
261
260
  const windowId = await getAutomationWindow(workspace);
262
261
 
263
- // Prefer an existing debuggable tab (about:blank, http://, https://, etc.)
262
+ // Prefer an existing debuggable tab
264
263
  const tabs = await chrome.tabs.query({ windowId });
265
264
  const debuggableTab = tabs.find(t => t.id && isDebuggableUrl(t.url));
266
- if (debuggableTab?.id) {
267
- console.log(`[opencli] resolveTabId: found debuggable tab ${debuggableTab.id} (${debuggableTab.url})`);
268
- return debuggableTab.id;
269
- }
270
- console.warn(`[opencli] resolveTabId: no debuggable tabs found, tabs: ${tabs.map(t => `${t.id}=${t.url}`).join(', ')}`);
265
+ if (debuggableTab?.id) return debuggableTab.id;
271
266
 
272
- // No debuggable tab found this typically happens when a "New Tab Override"
273
- // extension replaces about:blank with a chrome-extension:// page.
274
- // Reuse the first existing tab by navigating it to about:blank (avoids
275
- // accumulating orphan tabs if chrome.tabs.create is also intercepted).
267
+ // No debuggable tab — another extension may have hijacked the tab URL.
268
+ // Try to reuse by navigating to a data: URI (not interceptable by New Tab Override).
276
269
  const reuseTab = tabs.find(t => t.id);
277
270
  if (reuseTab?.id) {
278
271
  await chrome.tabs.update(reuseTab.id, { url: 'data:text/html,<html></html>' });
279
- // Wait for the navigation to take effect
280
272
  await new Promise(resolve => setTimeout(resolve, 300));
281
- // Verify the URL is actually debuggable (New Tab Override may have intercepted)
282
273
  try {
283
274
  const updated = await chrome.tabs.get(reuseTab.id);
284
275
  if (isDebuggableUrl(updated.url)) return reuseTab.id;
285
- // New Tab Override intercepted about:blank try data: URI instead
286
- console.warn(`[opencli] about:blank was intercepted (${updated.url}), trying data: URI`);
287
- await chrome.tabs.update(reuseTab.id, { url: 'data:text/html,<html></html>' });
288
- await new Promise(resolve => setTimeout(resolve, 300));
289
- const updated2 = await chrome.tabs.get(reuseTab.id);
290
- if (isDebuggableUrl(updated2.url)) return reuseTab.id;
291
- // data: URI also intercepted — create a brand new tab
292
- console.warn(`[opencli] data: URI also intercepted, creating fresh tab`);
276
+ console.warn(`[opencli] data: URI was intercepted (${updated.url}), creating fresh tab`);
293
277
  } catch {
294
278
  // Tab was closed during navigation
295
279
  }
296
280
  }
297
281
 
298
- // Window has no debuggable tabs — create one
282
+ // Fallback: create a new tab
299
283
  const newTab = await chrome.tabs.create({ windowId, url: 'data:text/html,<html></html>', active: true });
300
284
  if (!newTab.id) throw new Error('Failed to create tab in automation window');
301
285
  return newTab.id;
@@ -47,15 +47,18 @@ async function ensureAttached(tabId: number): Promise<void> {
47
47
  await chrome.debugger.attach({ tabId }, '1.3');
48
48
  } catch (e: unknown) {
49
49
  const msg = e instanceof Error ? e.message : String(e);
50
+ const hint = msg.includes('chrome-extension://')
51
+ ? '. Tip: another Chrome extension may be interfering — try disabling other extensions'
52
+ : '';
50
53
  if (msg.includes('Another debugger is already attached')) {
51
54
  try { await chrome.debugger.detach({ tabId }); } catch { /* ignore */ }
52
55
  try {
53
56
  await chrome.debugger.attach({ tabId }, '1.3');
54
57
  } catch {
55
- throw new Error(`attach failed: ${msg}`);
58
+ throw new Error(`attach failed: ${msg}${hint}`);
56
59
  }
57
60
  } else {
58
- throw new Error(`attach failed: ${msg}`);
61
+ throw new Error(`attach failed: ${msg}${hint}`);
59
62
  }
60
63
  }
61
64
  attached.add(tabId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jackwener/opencli",
3
- "version": "1.2.5",
3
+ "version": "1.2.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },