@weavetab/mcp 2.5.0-beta.1 → 2.5.0-beta.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.
- package/AGENTS.md +2 -1
- package/ARCHITECTURE.md +6 -6
- package/LICENSE +1 -1
- package/README.md +164 -802
- package/SECURITY.md +33 -22
- package/TROUBLESHOOTING.md +3 -3
- package/dist/cdp/bridge.d.ts +10 -0
- package/dist/cdp/bridge.js +285 -78
- package/dist/cdp/connector.d.ts +7 -3
- package/dist/cdp/connector.js +196 -75
- package/dist/cdp/helpers.d.ts +4 -0
- package/dist/cdp/helpers.js +181 -0
- package/dist/cdp/lock.d.ts +9 -6
- package/dist/cdp/lock.js +72 -59
- package/dist/cdp/omni_broker.d.ts +2 -1
- package/dist/cdp/omni_broker.js +13 -7
- package/dist/cdp/profiles.d.ts +10 -0
- package/dist/cdp/profiles.js +65 -0
- package/dist/cdp/walker.d.ts +25 -1
- package/dist/cdp/walker.js +354 -7
- package/dist/cli/plugin.d.ts +0 -2
- package/dist/cli/plugin.js +51 -696
- package/dist/cli/updater.d.ts +1 -1
- package/dist/cli/updater.js +27 -7
- package/dist/config/loader.d.ts +33 -6
- package/dist/config/loader.js +174 -22
- package/dist/desktop/discovery.d.ts +44 -0
- package/dist/desktop/discovery.js +364 -0
- package/dist/index.js +140 -64
- package/dist/intelligence/marks.d.ts +36 -0
- package/dist/intelligence/marks.js +30 -0
- package/dist/intelligence/patternCompiler.d.ts +118 -0
- package/dist/intelligence/patternCompiler.js +259 -0
- package/dist/intelligence/sessionMemory.d.ts +2 -0
- package/dist/intelligence/sessionMemory.js +18 -8
- package/dist/overlay/ghost.js +2 -2
- package/dist/overlay/injector.js +3 -5
- package/dist/plugin/extension_bridge.d.ts +40 -0
- package/dist/plugin/extension_bridge.js +158 -0
- package/dist/plugin/interface.d.ts +151 -15
- package/dist/plugin/loader.d.ts +19 -1
- package/dist/plugin/loader.js +331 -63
- package/dist/plugin/pipeline.d.ts +75 -0
- package/dist/plugin/pipeline.js +183 -0
- package/dist/plugin/registry.js +12 -1
- package/dist/plugin/storage.d.ts +51 -0
- package/dist/plugin/storage.js +164 -0
- package/dist/security/secrets.d.ts +1 -0
- package/dist/security/secrets.js +13 -0
- package/dist/sensors/actionability.js +1 -2
- package/dist/sensors/guard.js +4 -10
- package/dist/sensors/mutations.js +12 -0
- package/dist/sensors/operation_monitor.js +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +600 -236
- package/dist/state/agent.d.ts +1 -0
- package/dist/state/agent.js +3 -0
- package/dist/state/delta.d.ts +12 -4
- package/dist/state/delta.js +67 -14
- package/dist/state/session.d.ts +8 -2
- package/dist/state/session.js +60 -13
- package/dist/tools/browser_detect.d.ts +16 -2
- package/dist/tools/browser_detect.js +54 -6
- package/dist/tools/burst.d.ts +17 -7
- package/dist/tools/burst.js +240 -83
- package/dist/tools/checkpoint.d.ts +38 -0
- package/dist/tools/checkpoint.js +271 -0
- package/dist/tools/click.d.ts +1 -0
- package/dist/tools/click.js +97 -98
- package/dist/tools/clipboard.js +31 -24
- package/dist/tools/design_extract.js +1 -1
- package/dist/tools/eval.js +1 -1
- package/dist/tools/fill.d.ts +20 -1
- package/dist/tools/fill.js +199 -40
- package/dist/tools/find.d.ts +16 -0
- package/dist/tools/find.js +67 -44
- package/dist/tools/github/index.d.ts +19 -4
- package/dist/tools/github/index.js +40 -4
- package/dist/tools/highlight.d.ts +6 -2
- package/dist/tools/highlight.js +158 -72
- package/dist/tools/inspect.js +1 -1
- package/dist/tools/key.js +65 -56
- package/dist/tools/navigate.d.ts +1 -1
- package/dist/tools/navigate.js +57 -44
- package/dist/tools/pdf.js +21 -13
- package/dist/tools/pointer.d.ts +18 -3
- package/dist/tools/pointer.js +89 -1
- package/dist/tools/read.d.ts +28 -8
- package/dist/tools/read.js +230 -56
- package/dist/tools/scrape.js +67 -13
- package/dist/tools/screenshot.js +21 -16
- package/dist/tools/scroll.js +6 -11
- package/dist/tools/select.js +8 -2
- package/dist/tools/snapshot.js +3 -34
- package/dist/tools/tabs.d.ts +10 -10
- package/dist/tools/tabs.js +55 -39
- package/dist/tools/thought.d.ts +2 -0
- package/dist/tools/thought.js +13 -14
- package/dist/tools/type.d.ts +2 -0
- package/dist/tools/type.js +109 -60
- package/dist/tools/type_secret.js +42 -76
- package/dist/tools/upload.js +1 -1
- package/dist/tools/video_compiler.d.ts +1 -1
- package/dist/tools/video_compiler.js +11 -12
- package/dist/version.d.ts +5 -0
- package/dist/version.js +5 -0
- package/docs/DOCUMENTATION.md +82 -36
- package/docs/PLUGINS.md +82 -499
- package/docs/TOOLS.md +51 -99
- package/docs/architecture/blind-injection.md +83 -0
- package/docs/architecture/dual-injection.md +32 -0
- package/docs/architecture/overview.md +49 -0
- package/docs/architecture/security.md +35 -0
- package/docs/architecture/transport.md +37 -0
- package/docs/captcha-stealth/captcha-solver.md +75 -0
- package/docs/captcha-stealth/stealth-physics.md +60 -0
- package/docs/cli/cli-commands.md +44 -0
- package/docs/cli/cli-flags.md +20 -0
- package/docs/cli/cli-introduction.md +20 -0
- package/docs/cli/cli-scripting.md +32 -0
- package/docs/cli/g-ide/ide-antigravity.md +24 -0
- package/docs/cli/g-ide/ide-claude-code.md +24 -0
- package/docs/cli/g-ide/ide-claude-desktop.md +32 -0
- package/docs/cli/g-ide/ide-cursor.md +31 -0
- package/docs/cli/g-ide/ide-generic.md +34 -0
- package/docs/cli/g-ide/ide-opencode.md +24 -0
- package/docs/cli/g-ide/ide-vscode-copilot.md +24 -0
- package/docs/cli/g-ide/ide-windsurf.md +24 -0
- package/docs/configuration/config-locations.md +24 -0
- package/docs/configuration/configuration.md +73 -0
- package/docs/configuration/env-variables.md +19 -0
- package/docs/configuration/folders.md +55 -0
- package/docs/desktop-automation/electron-apps.md +217 -0
- package/docs/get-started/installation.md +47 -0
- package/docs/get-started/introduction.md +60 -0
- package/docs/get-started/quickstart.md +54 -0
- package/docs/get-started/setup-wizard.md +26 -0
- package/docs/intelligence/site-profiles.md +151 -0
- package/docs/skills-ecosystem/skills-overview.md +35 -0
- package/docs/skills-ecosystem/skills-recipes.md +36 -0
- package/docs/tools/tools.md +631 -0
- package/docs/troubleshooting/trouble-browser.md +27 -0
- package/docs/troubleshooting/trouble-config.md +20 -0
- package/docs/troubleshooting/trouble-loop.md +31 -0
- package/ext-dist/background.js +10 -62
- package/ext-dist/content.js +333 -921
- package/ext-dist/hud/hud.js +9 -9
- package/ext-dist/manifest.json +2 -6
- package/ext-dist/styles.css +6 -1
- package/mcp.json +108 -72
- package/package.json +14 -9
- package/server.json +3 -3
- package/docs/DEV_MODE.md +0 -68
- package/docs/dev_plugin.md +0 -310
- package/ext-dist/sidepanel/sidepanel.js +0 -25
- package/ext-dist/sidepanel.html +0 -547
package/dist/tools/snapshot.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "fs/promises";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { getOutputDir, getConfigAgentId } from "../config/loader.js";
|
|
4
|
-
import { hideWeaveTabOverlay, restoreWeaveTabOverlay } from "../cdp/helpers.js";
|
|
4
|
+
import { hideWeaveTabOverlay, restoreWeaveTabOverlay, maskSecretFieldsForCapture, restoreSecretFieldsAfterCapture } from "../cdp/helpers.js";
|
|
5
5
|
import { clearTabCache } from "../state/cache.js";
|
|
6
6
|
import { clearSnapshot } from "../state/delta.js";
|
|
7
7
|
import { sessionRegistry } from "../state/session.js";
|
|
@@ -28,22 +28,7 @@ export async function browserSnapshot(session, options, config) {
|
|
|
28
28
|
}
|
|
29
29
|
// ── Blank secret field values before capture ──────────────────────────
|
|
30
30
|
// Prevents credential values from being embedded in the MHTML archive.
|
|
31
|
-
|
|
32
|
-
await session.Runtime.evaluate({
|
|
33
|
-
expression: `(function() {
|
|
34
|
-
var els = document.querySelectorAll('[data-wt-secret], input[type="password"]');
|
|
35
|
-
for (var i = 0; i < els.length; i++) {
|
|
36
|
-
var el = els[i];
|
|
37
|
-
el.__wt_snap_backup = el.value;
|
|
38
|
-
try { el.value = ''; } catch(e) {}
|
|
39
|
-
if (el.isContentEditable) {
|
|
40
|
-
el.__wt_snap_text_backup = el.textContent;
|
|
41
|
-
try { el.textContent = ''; } catch(e) {}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
})()`,
|
|
45
|
-
returnByValue: false,
|
|
46
|
-
}).catch(() => { });
|
|
31
|
+
await maskSecretFieldsForCapture(session);
|
|
47
32
|
let snapshotData;
|
|
48
33
|
try {
|
|
49
34
|
const res = await session.Page.captureSnapshot({ format: "mhtml" });
|
|
@@ -51,26 +36,10 @@ export async function browserSnapshot(session, options, config) {
|
|
|
51
36
|
}
|
|
52
37
|
finally {
|
|
53
38
|
// ── Restore secret field values after capture (always runs) ──────────
|
|
39
|
+
await restoreSecretFieldsAfterCapture(session);
|
|
54
40
|
if (shouldHide) {
|
|
55
41
|
await restoreWeaveTabOverlay(session);
|
|
56
42
|
}
|
|
57
|
-
await session.Runtime.evaluate({
|
|
58
|
-
expression: `(function() {
|
|
59
|
-
var els = document.querySelectorAll('[data-wt-secret], input[type="password"]');
|
|
60
|
-
for (var i = 0; i < els.length; i++) {
|
|
61
|
-
var el = els[i];
|
|
62
|
-
if (el.__wt_snap_backup !== undefined) {
|
|
63
|
-
try { el.value = el.__wt_snap_backup; } catch(e) {}
|
|
64
|
-
delete el.__wt_snap_backup;
|
|
65
|
-
}
|
|
66
|
-
if (el.__wt_snap_text_backup !== undefined) {
|
|
67
|
-
try { el.textContent = el.__wt_snap_text_backup; } catch(e) {}
|
|
68
|
-
delete el.__wt_snap_text_backup;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
})()`,
|
|
72
|
-
returnByValue: false,
|
|
73
|
-
}).catch(() => { });
|
|
74
43
|
}
|
|
75
44
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
76
45
|
await fs.writeFile(filePath, snapshotData, "utf8");
|
package/dist/tools/tabs.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { Config } from "../config/loader.js";
|
|
|
2
2
|
export declare function recordTabActivity(targetId: string): void;
|
|
3
3
|
export declare function lockTab(targetId: string): void;
|
|
4
4
|
export declare function unlockTab(targetId: string): void;
|
|
5
|
-
export declare function evaluateTabSemantics(targetId: string): Promise<void>;
|
|
5
|
+
export declare function evaluateTabSemantics(targetId: string, appName?: string): Promise<void>;
|
|
6
6
|
export interface TabInfo {
|
|
7
7
|
id: string;
|
|
8
8
|
title: string;
|
|
@@ -11,30 +11,30 @@ export interface TabInfo {
|
|
|
11
11
|
health: "alive" | "dead" | "unreachable";
|
|
12
12
|
score: number;
|
|
13
13
|
}
|
|
14
|
-
export declare function WeavetabOpen(url: string, config: Config, reuse?: boolean): Promise<{
|
|
14
|
+
export declare function WeavetabOpen(url: string, config: Config, reuse?: boolean, appName?: string): Promise<{
|
|
15
15
|
success: true;
|
|
16
16
|
tabId: string;
|
|
17
17
|
url: string;
|
|
18
18
|
reused?: boolean;
|
|
19
19
|
}>;
|
|
20
|
-
export declare function WeavetabSwitch(tabId: string, config: Config): Promise<{
|
|
20
|
+
export declare function WeavetabSwitch(tabId: string, config: Config, appName?: string): Promise<{
|
|
21
21
|
success: true;
|
|
22
22
|
tab_id: string;
|
|
23
23
|
title: string;
|
|
24
24
|
url: string;
|
|
25
25
|
contextSwitchCostMs: number;
|
|
26
26
|
}>;
|
|
27
|
-
export declare function WeavetabList(config: Config): Promise<{
|
|
27
|
+
export declare function WeavetabList(config: Config, appName?: string): Promise<{
|
|
28
28
|
tabs: TabInfo[];
|
|
29
29
|
}>;
|
|
30
|
-
export declare function WeavetabClose(tabId: string, config: Config, force?: boolean): Promise<{
|
|
30
|
+
export declare function WeavetabClose(tabId: string, config: Config, force?: boolean, appName?: string): Promise<{
|
|
31
31
|
success: true;
|
|
32
32
|
tab_id: string;
|
|
33
33
|
}>;
|
|
34
34
|
/**
|
|
35
35
|
* Batch close multiple tabs at once — saves multiple round-trips.
|
|
36
36
|
*/
|
|
37
|
-
export declare function WeavetabCloseBatch(tabIds: string[], config: Config, force?: boolean): Promise<{
|
|
37
|
+
export declare function WeavetabCloseBatch(tabIds: string[], config: Config, force?: boolean, appName?: string): Promise<{
|
|
38
38
|
success: true;
|
|
39
39
|
closed: string[];
|
|
40
40
|
skipped: string[];
|
|
@@ -42,7 +42,7 @@ export declare function WeavetabCloseBatch(tabIds: string[], config: Config, for
|
|
|
42
42
|
/**
|
|
43
43
|
* Consolidate: deduplicate tabs by URL, close duplicates.
|
|
44
44
|
*/
|
|
45
|
-
export declare function WeavetabConsolidate(config: Config): Promise<{
|
|
45
|
+
export declare function WeavetabConsolidate(config: Config, appName?: string): Promise<{
|
|
46
46
|
success: true;
|
|
47
47
|
tabs_before: number;
|
|
48
48
|
tabs_after: number;
|
|
@@ -51,7 +51,7 @@ export declare function WeavetabConsolidate(config: Config): Promise<{
|
|
|
51
51
|
/**
|
|
52
52
|
* Heal: check all tabs for crashed state and reload them.
|
|
53
53
|
*/
|
|
54
|
-
export declare function WeavetabHeal(config: Config): Promise<{
|
|
54
|
+
export declare function WeavetabHeal(config: Config, appName?: string): Promise<{
|
|
55
55
|
success: true;
|
|
56
56
|
healed: number;
|
|
57
57
|
tabs_checked: number;
|
|
@@ -68,10 +68,10 @@ export interface WindowInfo {
|
|
|
68
68
|
};
|
|
69
69
|
focused: boolean;
|
|
70
70
|
}
|
|
71
|
-
export declare function weaveWindowList(config: Config): Promise<{
|
|
71
|
+
export declare function weaveWindowList(config: Config, appName?: string): Promise<{
|
|
72
72
|
windows: WindowInfo[];
|
|
73
73
|
}>;
|
|
74
|
-
export declare function weaveFocusWindow(windowId: number, config: Config): Promise<{
|
|
74
|
+
export declare function weaveFocusWindow(windowId: number, config: Config, appName?: string): Promise<{
|
|
75
75
|
success: true;
|
|
76
76
|
windowId: number;
|
|
77
77
|
}>;
|
package/dist/tools/tabs.js
CHANGED
|
@@ -8,7 +8,13 @@ import { readLock } from "../cdp/lock.js";
|
|
|
8
8
|
import { resetLoopCounter } from "../intelligence/trail.js";
|
|
9
9
|
import { getConfigAgentId, getConfigMaxTabs } from "../config/loader.js";
|
|
10
10
|
/** Resolve the active CDP port — live > lock file */
|
|
11
|
-
function resolvePort(_config) {
|
|
11
|
+
function resolvePort(_config, appName) {
|
|
12
|
+
if (appName) {
|
|
13
|
+
const lock = readLock(appName);
|
|
14
|
+
if (lock && lock.port)
|
|
15
|
+
return lock.port;
|
|
16
|
+
throw new Error(`[!] No active session for Electron app "${appName}". Launch it first.`);
|
|
17
|
+
}
|
|
12
18
|
const port = getPort() || readLock()?.port;
|
|
13
19
|
if (!port)
|
|
14
20
|
throw new Error("[!] No active browser session. Run browser_go first.");
|
|
@@ -44,9 +50,9 @@ function calculateSemanticScore(url, title) {
|
|
|
44
50
|
score += 30;
|
|
45
51
|
return Math.min(score, 100);
|
|
46
52
|
}
|
|
47
|
-
export async function evaluateTabSemantics(targetId) {
|
|
53
|
+
export async function evaluateTabSemantics(targetId, appName) {
|
|
48
54
|
try {
|
|
49
|
-
const client = await connectToTab(targetId);
|
|
55
|
+
const client = await connectToTab(targetId, undefined, undefined, undefined, appName);
|
|
50
56
|
const result = await client.session.Runtime.evaluate({
|
|
51
57
|
expression: `JSON.stringify({ title: document.title, url: location.href })`,
|
|
52
58
|
returnByValue: true
|
|
@@ -104,17 +110,25 @@ async function enforceMaxTabs(config) {
|
|
|
104
110
|
logAction("browser_tabs", victim.id, `auto-closed idle tab: ${victim.title}`);
|
|
105
111
|
}
|
|
106
112
|
// ─── Tools ────────────────────────────────────────────────────────────────────
|
|
107
|
-
export async function WeavetabOpen(url, config, reuse = true) {
|
|
108
|
-
|
|
113
|
+
export async function WeavetabOpen(url, config, reuse = true, appName) {
|
|
114
|
+
// Infer appName from active session if omitted
|
|
115
|
+
let resolvedAppName = appName;
|
|
116
|
+
if (!resolvedAppName) {
|
|
117
|
+
const lastApp = sessionRegistry.getLastActiveApp();
|
|
118
|
+
if (lastApp) {
|
|
119
|
+
resolvedAppName = lastApp;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
const port = resolvePort(config, resolvedAppName);
|
|
109
123
|
// Tab reuse: if same URL is already open, focus it instead of duplicating
|
|
110
124
|
if (reuse && url) {
|
|
111
125
|
try {
|
|
112
|
-
const targets = await getTabList(getConfigAgentId(config));
|
|
126
|
+
const targets = await getTabList(getConfigAgentId(config), resolvedAppName);
|
|
113
127
|
const existing = targets.find((t) => t.url === url);
|
|
114
128
|
if (existing) {
|
|
115
|
-
const client = await connectToTab(existing.id);
|
|
129
|
+
const client = await connectToTab(existing.id, undefined, undefined, undefined, resolvedAppName);
|
|
116
130
|
await client.session.Target.activateTarget({ targetId: existing.id });
|
|
117
|
-
sessionRegistry.setActive(existing.id, getConfigAgentId(config));
|
|
131
|
+
sessionRegistry.setActive(existing.id, getConfigAgentId(config), resolvedAppName);
|
|
118
132
|
recordTabActivity(existing.id);
|
|
119
133
|
logAction("browser_tabs", url, `reused existing tab ${existing.id}`);
|
|
120
134
|
return { success: true, tabId: existing.id, url, reused: true };
|
|
@@ -122,22 +136,24 @@ export async function WeavetabOpen(url, config, reuse = true) {
|
|
|
122
136
|
}
|
|
123
137
|
catch { /* fall through to open new */ }
|
|
124
138
|
}
|
|
125
|
-
|
|
126
|
-
|
|
139
|
+
if (!resolvedAppName) {
|
|
140
|
+
await enforceMaxTabs(config);
|
|
141
|
+
}
|
|
142
|
+
const bctxId = resolvedAppName ? undefined : sessionRegistry.getBrowserContextIdForAgent(getConfigAgentId(config));
|
|
127
143
|
const metaSession = await CDP({ host: "127.0.0.1", port });
|
|
128
144
|
const { targetId } = await metaSession.Target.createTarget({ url, browserContextId: bctxId });
|
|
129
145
|
await metaSession.close();
|
|
130
146
|
recordTabActivity(targetId);
|
|
131
|
-
await connectToTab(targetId, port, getConfigAgentId(config), bctxId);
|
|
132
|
-
await evaluateTabSemantics(targetId);
|
|
147
|
+
await connectToTab(targetId, port, getConfigAgentId(config), bctxId, appName);
|
|
148
|
+
await evaluateTabSemantics(targetId, appName);
|
|
133
149
|
logAction("browser_tabs", url, `opened ${targetId}`);
|
|
134
150
|
return { success: true, tabId: targetId, url };
|
|
135
151
|
}
|
|
136
|
-
export async function WeavetabSwitch(tabId, config) {
|
|
137
|
-
const client = await connectToTab(tabId);
|
|
152
|
+
export async function WeavetabSwitch(tabId, config, appName) {
|
|
153
|
+
const client = await connectToTab(tabId, undefined, undefined, undefined, appName);
|
|
138
154
|
const startSwitch = Date.now();
|
|
139
155
|
await client.session.Target.activateTarget({ targetId: tabId });
|
|
140
|
-
sessionRegistry.setActive(tabId, getConfigAgentId(config));
|
|
156
|
+
sessionRegistry.setActive(tabId, getConfigAgentId(config), appName);
|
|
141
157
|
recordTabActivity(tabId);
|
|
142
158
|
const { frameTree } = await client.session.Page.getFrameTree();
|
|
143
159
|
let title = tabId;
|
|
@@ -154,9 +170,9 @@ export async function WeavetabSwitch(tabId, config) {
|
|
|
154
170
|
resetLoopCounter("tab_switch");
|
|
155
171
|
return { success: true, tab_id: tabId, title, url, contextSwitchCostMs: cost };
|
|
156
172
|
}
|
|
157
|
-
export async function WeavetabList(config) {
|
|
158
|
-
const targets = await getTabList(getConfigAgentId(config));
|
|
159
|
-
const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId;
|
|
173
|
+
export async function WeavetabList(config, appName) {
|
|
174
|
+
const targets = await getTabList(getConfigAgentId(config), appName);
|
|
175
|
+
const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config), appName)?.targetId;
|
|
160
176
|
const tabs = targets
|
|
161
177
|
.map((t) => ({
|
|
162
178
|
id: t.id,
|
|
@@ -174,12 +190,12 @@ export async function WeavetabList(config) {
|
|
|
174
190
|
}));
|
|
175
191
|
return { tabs };
|
|
176
192
|
}
|
|
177
|
-
export async function WeavetabClose(tabId, config, force = false) {
|
|
193
|
+
export async function WeavetabClose(tabId, config, force = false, appName) {
|
|
178
194
|
const score = semanticScores.get(tabId) ?? 10;
|
|
179
195
|
if (score >= 70 && !force) {
|
|
180
196
|
throw new Error(`[!] Tab Armor block: This tab is semantically protected (score: ${score}). It likely contains a login, checkout, or critical work. Do not close it! If the user explicitly requested this closure, pass force: true.`);
|
|
181
197
|
}
|
|
182
|
-
const port = resolvePort(config);
|
|
198
|
+
const port = resolvePort(config, appName);
|
|
183
199
|
await CDP.Close({ host: "127.0.0.1", port, id: tabId });
|
|
184
200
|
clearTabCache(tabId);
|
|
185
201
|
sessionRegistry.unregister(tabId);
|
|
@@ -192,12 +208,12 @@ export async function WeavetabClose(tabId, config, force = false) {
|
|
|
192
208
|
/**
|
|
193
209
|
* Batch close multiple tabs at once — saves multiple round-trips.
|
|
194
210
|
*/
|
|
195
|
-
export async function WeavetabCloseBatch(tabIds, config, force = false) {
|
|
211
|
+
export async function WeavetabCloseBatch(tabIds, config, force = false, appName) {
|
|
196
212
|
const closed = [];
|
|
197
213
|
const skipped = [];
|
|
198
214
|
for (const tabId of tabIds) {
|
|
199
215
|
try {
|
|
200
|
-
await WeavetabClose(tabId, config, force);
|
|
216
|
+
await WeavetabClose(tabId, config, force, appName);
|
|
201
217
|
closed.push(tabId);
|
|
202
218
|
}
|
|
203
219
|
catch {
|
|
@@ -209,14 +225,14 @@ export async function WeavetabCloseBatch(tabIds, config, force = false) {
|
|
|
209
225
|
/**
|
|
210
226
|
* Consolidate: deduplicate tabs by URL, close duplicates.
|
|
211
227
|
*/
|
|
212
|
-
export async function WeavetabConsolidate(config) {
|
|
213
|
-
const port = resolvePort(config);
|
|
228
|
+
export async function WeavetabConsolidate(config, appName) {
|
|
229
|
+
const port = resolvePort(config, appName);
|
|
214
230
|
const targets = await CDP.List({ host: "127.0.0.1", port });
|
|
215
|
-
const pages = targets.filter((t) => t.type === "page");
|
|
231
|
+
const pages = targets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app");
|
|
216
232
|
const tabsBefore = pages.length;
|
|
217
233
|
const seenUrls = new Set();
|
|
218
234
|
let closedDuplicates = 0;
|
|
219
|
-
const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId;
|
|
235
|
+
const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config), appName)?.targetId;
|
|
220
236
|
for (const page of pages) {
|
|
221
237
|
if (page.id === activeTargetId) {
|
|
222
238
|
seenUrls.add(page.url);
|
|
@@ -240,17 +256,17 @@ export async function WeavetabConsolidate(config) {
|
|
|
240
256
|
}
|
|
241
257
|
}
|
|
242
258
|
const afterTargets = await CDP.List({ host: "127.0.0.1", port });
|
|
243
|
-
const tabsAfter = afterTargets.filter((t) => t.type === "page").length;
|
|
259
|
+
const tabsAfter = afterTargets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app").length;
|
|
244
260
|
logAction("browser_tabs", "consolidate", `${tabsBefore}→${tabsAfter} (closed ${closedDuplicates} duplicates)`);
|
|
245
261
|
return { success: true, tabs_before: tabsBefore, tabs_after: tabsAfter, closed_duplicates: closedDuplicates };
|
|
246
262
|
}
|
|
247
263
|
/**
|
|
248
264
|
* Heal: check all tabs for crashed state and reload them.
|
|
249
265
|
*/
|
|
250
|
-
export async function WeavetabHeal(config) {
|
|
251
|
-
const port = resolvePort(config);
|
|
266
|
+
export async function WeavetabHeal(config, appName) {
|
|
267
|
+
const port = resolvePort(config, appName);
|
|
252
268
|
const targets = await CDP.List({ host: "127.0.0.1", port });
|
|
253
|
-
const pages = targets.filter((t) => t.type === "page");
|
|
269
|
+
const pages = targets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app");
|
|
254
270
|
let healed = 0;
|
|
255
271
|
const healthSummary = {};
|
|
256
272
|
for (const page of pages) {
|
|
@@ -269,7 +285,7 @@ export async function WeavetabHeal(config) {
|
|
|
269
285
|
continue;
|
|
270
286
|
}
|
|
271
287
|
try {
|
|
272
|
-
const client = await connectToTab(page.id);
|
|
288
|
+
const client = await connectToTab(page.id, undefined, undefined, undefined, appName);
|
|
273
289
|
const { result } = await client.session.Runtime.evaluate({
|
|
274
290
|
expression: `document.readyState`,
|
|
275
291
|
returnByValue: true,
|
|
@@ -292,10 +308,10 @@ export async function WeavetabHeal(config) {
|
|
|
292
308
|
logAction("browser_tabs", "heal", `healed ${healed}/${pages.length} tabs`);
|
|
293
309
|
return { success: true, healed, tabs_checked: pages.length, health_summary: healthSummary };
|
|
294
310
|
}
|
|
295
|
-
export async function weaveWindowList(config) {
|
|
296
|
-
const port = resolvePort(config);
|
|
311
|
+
export async function weaveWindowList(config, appName) {
|
|
312
|
+
const port = resolvePort(config, appName);
|
|
297
313
|
const targets = await CDP.List({ host: "127.0.0.1", port });
|
|
298
|
-
const pages = targets.filter((t) => t.type === "page");
|
|
314
|
+
const pages = targets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app");
|
|
299
315
|
// Group by process — each unique window has its own set of tabs
|
|
300
316
|
// We approximate via CDP Target.getTargets windowId if available
|
|
301
317
|
const windows = [];
|
|
@@ -307,7 +323,7 @@ export async function weaveWindowList(config) {
|
|
|
307
323
|
const { windowId, bounds } = await session.Browser.getWindowForTarget({ targetId: page.id });
|
|
308
324
|
if (!seenWindowIds.has(windowId)) {
|
|
309
325
|
seenWindowIds.add(windowId);
|
|
310
|
-
const activeId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId;
|
|
326
|
+
const activeId = sessionRegistry.getActive(getConfigAgentId(config), appName)?.targetId;
|
|
311
327
|
windows.push({
|
|
312
328
|
windowId,
|
|
313
329
|
state: bounds.windowState || "normal",
|
|
@@ -324,12 +340,12 @@ export async function weaveWindowList(config) {
|
|
|
324
340
|
}
|
|
325
341
|
return { windows };
|
|
326
342
|
}
|
|
327
|
-
export async function weaveFocusWindow(windowId, config) {
|
|
328
|
-
const port = resolvePort(config);
|
|
343
|
+
export async function weaveFocusWindow(windowId, config, appName) {
|
|
344
|
+
const port = resolvePort(config, appName);
|
|
329
345
|
const targets = await CDP.List({ host: "127.0.0.1", port });
|
|
330
|
-
const page = targets.find((t) => t.type === "page");
|
|
346
|
+
const page = targets.find((t) => t.type === "page" || t.type === "webview" || t.type === "app");
|
|
331
347
|
if (!page)
|
|
332
|
-
throw new Error("No page target found to focus window");
|
|
348
|
+
throw new Error("No page or window target found to focus window");
|
|
333
349
|
const session = await CDP({ host: "127.0.0.1", port, target: page.id });
|
|
334
350
|
try {
|
|
335
351
|
await session.Browser.setWindowBounds({ windowId, bounds: { windowState: "normal" } });
|
package/dist/tools/thought.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ import CDP from "chrome-remote-interface";
|
|
|
2
2
|
export interface ThoughtOptions {
|
|
3
3
|
action: "feedback" | "question";
|
|
4
4
|
message: string;
|
|
5
|
+
anchor?: string;
|
|
6
|
+
style?: "observation" | "decision" | "warning" | "question";
|
|
5
7
|
input?: "sentence" | "paragraph";
|
|
6
8
|
timeout?: number;
|
|
7
9
|
}
|
package/dist/tools/thought.js
CHANGED
|
@@ -7,32 +7,31 @@ function sleep(ms) {
|
|
|
7
7
|
return new Promise(r => setTimeout(r, ms));
|
|
8
8
|
}
|
|
9
9
|
export async function browserThought(session, args) {
|
|
10
|
-
const { action, message, input, timeout } = args;
|
|
10
|
+
const { action, message, input, timeout, anchor, style } = args;
|
|
11
11
|
logAction("browser_thought", action, message);
|
|
12
12
|
if (action === "feedback") {
|
|
13
|
-
|
|
14
|
-
type: 'Weavetab_STATE',
|
|
15
|
-
hud: { action: message },
|
|
16
|
-
stickyFeedback: true,
|
|
17
|
-
}).catch(() => { });
|
|
18
|
-
// Forward to sidepanel thought stream
|
|
13
|
+
// Forward thought event to extension
|
|
19
14
|
await sendToExtension(session, {
|
|
20
15
|
type: 'WT_THOUGHT',
|
|
21
16
|
text: message,
|
|
22
17
|
kind: 'thought',
|
|
18
|
+
anchor,
|
|
19
|
+
style: style || 'observation',
|
|
20
|
+
action: 'feedback',
|
|
23
21
|
}).catch(() => { });
|
|
24
22
|
return { success: true };
|
|
25
23
|
}
|
|
26
24
|
if (action === "question") {
|
|
27
25
|
const QUESTION_TIMEOUT_MS = Math.min((timeout || 20), 20) * 1000;
|
|
28
26
|
await sendToExtension(session, {
|
|
29
|
-
type: '
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
27
|
+
type: 'WT_THOUGHT',
|
|
28
|
+
text: message,
|
|
29
|
+
kind: 'question',
|
|
30
|
+
anchor,
|
|
31
|
+
style: style || 'question',
|
|
32
|
+
action: 'question',
|
|
33
|
+
input: input || "sentence",
|
|
34
|
+
timeout: Math.min((timeout || 20), 20),
|
|
36
35
|
}).catch(() => { });
|
|
37
36
|
const start = Date.now();
|
|
38
37
|
while (Date.now() - start < QUESTION_TIMEOUT_MS + 5000) {
|
package/dist/tools/type.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export declare function detectFramework(session: CDP.Client): Promise<'react' |
|
|
|
48
48
|
export declare function frameworkAwareType(session: CDP.Client, objectId: string, text: string, framework: 'react' | 'vue' | 'angular' | 'vanilla'): Promise<boolean>;
|
|
49
49
|
export declare function weaveType(session: CDP.Client, args: {
|
|
50
50
|
id?: string;
|
|
51
|
+
target?: string;
|
|
52
|
+
selector?: string;
|
|
51
53
|
label?: string;
|
|
52
54
|
intent?: string;
|
|
53
55
|
backendNodeId?: number;
|