@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 +2 -0
- package/README.zh-CN.md +2 -0
- package/extension/dist/background.js +5 -14
- package/extension/manifest.json +1 -1
- package/extension/package.json +1 -1
- package/extension/src/background.ts +7 -23
- package/extension/src/cdp.ts +5 -2
- package/package.json +1 -1
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]
|
|
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
|
}
|
package/extension/manifest.json
CHANGED
package/extension/package.json
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
273
|
-
//
|
|
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
|
-
|
|
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
|
-
//
|
|
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;
|
package/extension/src/cdp.ts
CHANGED
|
@@ -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);
|