@weavetab/mcp 2.5.0-beta.2 → 2.5.0-beta.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/AGENTS.md +1 -1
- package/ARCHITECTURE.md +6 -6
- package/LICENSE +216 -631
- package/README.md +153 -1074
- package/SECURITY.md +33 -22
- package/TROUBLESHOOTING.md +2 -2
- package/dist/cdp/bridge.js +2 -1
- package/dist/cdp/connector.d.ts +2 -0
- package/dist/cdp/connector.js +10 -6
- package/dist/cdp/helpers.d.ts +4 -0
- package/dist/cdp/helpers.js +181 -0
- package/dist/cdp/omni_broker.d.ts +1 -1
- package/dist/cdp/omni_broker.js +1 -1
- package/dist/cdp/walker.d.ts +25 -1
- package/dist/cdp/walker.js +304 -7
- package/dist/cli/plugin.d.ts +1 -0
- package/dist/cli/plugin.js +81 -18
- package/dist/cli/updater.d.ts +1 -1
- package/dist/cli/updater.js +27 -7
- package/dist/config/loader.d.ts +9 -1
- package/dist/config/loader.js +42 -3
- package/dist/desktop/discovery.d.ts +44 -0
- package/dist/desktop/discovery.js +364 -0
- package/dist/index.js +137 -21
- 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/injector.js +2 -2
- package/dist/plugin/interface.d.ts +88 -5
- package/dist/plugin/loader.d.ts +12 -1
- package/dist/plugin/loader.js +280 -70
- package/dist/plugin/pipeline.d.ts +75 -0
- package/dist/plugin/pipeline.js +183 -0
- package/dist/plugin/registry.d.ts +2 -1
- package/dist/plugin/registry.js +24 -14
- package/dist/security/secrets.d.ts +7 -0
- package/dist/security/secrets.js +37 -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 +453 -178
- 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 +6 -0
- package/dist/state/session.js +27 -0
- package/dist/tools/browser_detect.d.ts +16 -3
- package/dist/tools/browser_detect.js +52 -7
- package/dist/tools/burst.d.ts +17 -8
- package/dist/tools/burst.js +236 -77
- package/dist/tools/captcha.js +1 -1
- 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 +74 -70
- 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 +34 -39
- 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.js +15 -7
- 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 +107 -58
- 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 +37 -41
- package/docs/PLUGINS.md +121 -0
- package/docs/TOOLS.md +54 -0
- package/docs/architecture/blind-injection.md +83 -20
- package/docs/architecture/overview.md +49 -49
- package/docs/architecture/security.md +8 -7
- package/docs/architecture/transport.md +2 -2
- package/docs/cli/cli-commands.md +7 -1
- package/docs/cli/cli-flags.md +15 -7
- package/docs/cli/cli-scripting.md +6 -3
- package/docs/configuration/config-locations.md +3 -4
- package/docs/configuration/env-variables.md +4 -4
- package/docs/configuration/folders.md +55 -54
- package/docs/desktop-automation/electron-apps.md +214 -162
- package/docs/get-started/introduction.md +60 -60
- package/docs/get-started/setup-wizard.md +7 -6
- package/docs/intelligence/site-profiles.md +151 -0
- package/docs/tools/tools.md +631 -293
- package/docs/troubleshooting/trouble-browser.md +1 -1
- package/docs/troubleshooting/trouble-loop.md +31 -31
- package/ext-dist/background.js +10 -62
- package/ext-dist/content.js +333 -920
- package/ext-dist/hud/hud.js +9 -9
- package/ext-dist/manifest.json +2 -6
- package/ext-dist/styles.css +6 -1
- package/icon.png +0 -0
- package/mcp.json +87 -71
- package/package.json +118 -119
- package/server.json +5 -5
- package/ext-dist/sidepanel/sidepanel.js +0 -25
- package/ext-dist/sidepanel.html +0 -547
package/dist/index.js
CHANGED
|
@@ -11,6 +11,7 @@ import { createRequire } from "node:module";
|
|
|
11
11
|
import chalk from "chalk";
|
|
12
12
|
import boxen from "boxen";
|
|
13
13
|
import pc from "picocolors";
|
|
14
|
+
import { WEAVETAB_VERSION } from "./version.js";
|
|
14
15
|
// ─── Server-Process Singleton Lock ────────────────────────────────────────────
|
|
15
16
|
// When an IDE opens multiple windows or reconnects after a crash, it spawns a new
|
|
16
17
|
// `node dist/index.js` MCP process each time. Without a guard, these stack up
|
|
@@ -32,13 +33,29 @@ function _acquireServerLock() {
|
|
|
32
33
|
fs.mkdirSync(_SERVER_LOCK_DIR, { recursive: true });
|
|
33
34
|
if (fs.existsSync(_SERVER_LOCK_FILE)) {
|
|
34
35
|
const existingPid = parseInt(fs.readFileSync(_SERVER_LOCK_FILE, "utf-8").trim(), 10);
|
|
35
|
-
if (!isNaN(existingPid) && existingPid !== process.pid
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
if (!isNaN(existingPid) && existingPid !== process.pid) {
|
|
37
|
+
if (_isProcessAlive(existingPid)) {
|
|
38
|
+
process.stderr.write(`[Weavetab] Another Weavetab MCP server is running (PID ${existingPid}). Client session active.\n`);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Process is dead: reap stale PID lock
|
|
42
|
+
try {
|
|
43
|
+
fs.unlinkSync(_SERVER_LOCK_FILE);
|
|
44
|
+
}
|
|
45
|
+
catch { /* ignore */ }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// Also reap stale browser lock file if the recorded browser PID is dead
|
|
50
|
+
const browserLockFile = path.join(_SERVER_LOCK_DIR, ".weavetab.lock");
|
|
51
|
+
if (fs.existsSync(browserLockFile)) {
|
|
52
|
+
try {
|
|
53
|
+
const lockData = JSON.parse(fs.readFileSync(browserLockFile, "utf-8"));
|
|
54
|
+
if (lockData.pid && !_isProcessAlive(lockData.pid)) {
|
|
55
|
+
fs.unlinkSync(browserLockFile);
|
|
56
|
+
}
|
|
41
57
|
}
|
|
58
|
+
catch { /* malformed lock, ignore */ }
|
|
42
59
|
}
|
|
43
60
|
fs.writeFileSync(_SERVER_LOCK_FILE, String(process.pid), "utf-8");
|
|
44
61
|
return true;
|
|
@@ -81,6 +98,32 @@ function printBootBanner(port) {
|
|
|
81
98
|
async function main() {
|
|
82
99
|
assertNotRoot();
|
|
83
100
|
const args = process.argv.slice(2);
|
|
101
|
+
// Global flags: --version always works; --ws starts the WebSocket daemon.
|
|
102
|
+
if (args.includes("--version") || args.includes("-v")) {
|
|
103
|
+
const _v = createRequire(import.meta.url);
|
|
104
|
+
const ver = _v("../package.json").version || WEAVETAB_VERSION;
|
|
105
|
+
console.log(`@weavetab/mcp v${ver}`);
|
|
106
|
+
process.exit(0);
|
|
107
|
+
}
|
|
108
|
+
if (args.includes("--ws")) {
|
|
109
|
+
let wsPort = 3000;
|
|
110
|
+
const pi = args.findIndex((a) => a === "--port");
|
|
111
|
+
const eq = args.find((a) => a.startsWith("--port="));
|
|
112
|
+
const rawPort = pi >= 0 ? args[pi + 1] : eq ? eq.slice("--port=".length) : undefined;
|
|
113
|
+
if (rawPort !== undefined) {
|
|
114
|
+
const parsed = parseInt(rawPort, 10);
|
|
115
|
+
if (isNaN(parsed) || parsed < 1 || parsed > 65535) {
|
|
116
|
+
console.error(`[Weavetab] Invalid --port value: "${rawPort}" (1-65535).`);
|
|
117
|
+
process.exit(1);
|
|
118
|
+
}
|
|
119
|
+
wsPort = parsed;
|
|
120
|
+
}
|
|
121
|
+
const config = await loadConfig();
|
|
122
|
+
global.__wt_is_server = true;
|
|
123
|
+
await printBootBanner(wsPort);
|
|
124
|
+
await startServer(config, "ws", wsPort);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
84
127
|
// If NOT in a TTY environment (e.g. spawned by Claude Code as MCP server)
|
|
85
128
|
if (!isInteractive && args.length === 0) {
|
|
86
129
|
// Singleton guard — exit immediately if another MCP server is alive.
|
|
@@ -134,6 +177,17 @@ async function main() {
|
|
|
134
177
|
await runPluginCli(args.slice(1));
|
|
135
178
|
process.exit(0);
|
|
136
179
|
}
|
|
180
|
+
if (cmd === "skills") {
|
|
181
|
+
const { execSync: exec } = await import("node:child_process");
|
|
182
|
+
const subArgs = args.slice(1).join(" ");
|
|
183
|
+
try {
|
|
184
|
+
exec(`npx -y @weavetab/skills@latest ${subArgs}`.trim(), { stdio: "inherit" });
|
|
185
|
+
}
|
|
186
|
+
catch {
|
|
187
|
+
process.exit(1);
|
|
188
|
+
}
|
|
189
|
+
process.exit(0);
|
|
190
|
+
}
|
|
137
191
|
if (cmd === "init" || cmd === "create" || cmd === "build" || cmd === "manifest") {
|
|
138
192
|
console.log(pc.yellow(`\n[Weavetab] Plugin authoring commands are part of the developer SDK (@weavetab/sdk).`));
|
|
139
193
|
console.log(pc.dim("To scaffold a new plugin: ") + pc.cyan("npx -y @weavetab/sdk init <name>"));
|
|
@@ -335,6 +389,7 @@ async function main() {
|
|
|
335
389
|
S.sl("Role *", {
|
|
336
390
|
initialValue: "admin", options: [
|
|
337
391
|
{ value: "admin", label: "Admin", hint: "Full access to all tools" },
|
|
392
|
+
{ value: "operator", label: "Operator", hint: "Full access, standard agent role" },
|
|
338
393
|
{ value: "viewer", label: "Viewer", hint: "Read-only access (map, find, scrape, console)" },
|
|
339
394
|
{ value: "automation", label: "Automation", hint: "CI/CD mode (burst, plan, wait, map)" },
|
|
340
395
|
]
|
|
@@ -406,6 +461,7 @@ async function main() {
|
|
|
406
461
|
}, "browserType"),
|
|
407
462
|
S.cf("Enable Weavetab browser extension?", "extension", true),
|
|
408
463
|
S.cf("Persist cookies across sessions?", "cookies", false),
|
|
464
|
+
S.cf("Sync browser data across profiles?", "syncDataAcrossBrowsers", false),
|
|
409
465
|
S.tx("Extra browser flags (space-separated)", "browserFlagsRaw", ""),
|
|
410
466
|
S.tx("Custom browser profile directory", "profileDir", ""),
|
|
411
467
|
])) === "back")
|
|
@@ -427,6 +483,8 @@ async function main() {
|
|
|
427
483
|
return "Positive integer."; }),
|
|
428
484
|
S.tx("Actionability timeout (ms)", "actionabilityTimeout", "500", (v) => { const n = parseInt(v ?? ""); if (isNaN(n) || n < 100)
|
|
429
485
|
return "Min 100 ms."; }),
|
|
486
|
+
S.tx("Ref cache TTL (ms) — stale element handle expiry", "refCacheTtlMs", "30000", (v) => { const n = parseInt(v ?? ""); if (isNaN(n) || n < 1000)
|
|
487
|
+
return "Min 1000 ms."; }),
|
|
430
488
|
])) === "back")
|
|
431
489
|
process.exit(0);
|
|
432
490
|
}
|
|
@@ -445,6 +503,10 @@ async function main() {
|
|
|
445
503
|
console.log(boxen(pc.cyan("SECTION D: STORAGE & PROXY"), { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
|
|
446
504
|
if ((await run([
|
|
447
505
|
S.tx("Download directory", "downloadDir", ""),
|
|
506
|
+
S.tx("PDF output directory", "pdfDir", ""),
|
|
507
|
+
S.tx("Snapshot directory (screenshots)", "snapshotDir", ""),
|
|
508
|
+
S.tx("Recording output directory", "recordingDir", ""),
|
|
509
|
+
S.tx("Design extraction directory", "designDir", ""),
|
|
448
510
|
S.tx("Proxy URL (or $WT_PROXY_URL)", "proxy", ""),
|
|
449
511
|
])) === "back")
|
|
450
512
|
process.exit(0);
|
|
@@ -492,6 +554,7 @@ async function main() {
|
|
|
492
554
|
browserType: a.browserType || "chromium",
|
|
493
555
|
extension: a.extension !== undefined ? a.extension : true,
|
|
494
556
|
cookies: a.cookies || false,
|
|
557
|
+
syncDataAcrossBrowsers: a.syncDataAcrossBrowsers || false,
|
|
495
558
|
browserFlags: a.browserFlags || [],
|
|
496
559
|
profileDir: a.profileDir || "",
|
|
497
560
|
sessionTimeout: parseInt(a.sessionTimeout) || 3600,
|
|
@@ -499,9 +562,14 @@ async function main() {
|
|
|
499
562
|
idleTimeout: parseInt(a.idleTimeout) || 60000,
|
|
500
563
|
maxActionsPerMinute: parseInt(a.maxActionsPerMinute) || 60,
|
|
501
564
|
actionabilityTimeout: parseInt(a.actionabilityTimeout) || 500,
|
|
565
|
+
refCacheTtlMs: parseInt(a.refCacheTtlMs) || 30000,
|
|
502
566
|
telemetry: a.telemetry || false,
|
|
503
567
|
githubCacheTtlMs: parseInt(a.githubCacheTtlMs) || 1800000,
|
|
504
568
|
downloadDir: a.downloadDir || "",
|
|
569
|
+
pdfDir: a.pdfDir || "",
|
|
570
|
+
snapshotDir: a.snapshotDir || "",
|
|
571
|
+
recordingDir: a.recordingDir || "",
|
|
572
|
+
designDir: a.designDir || "",
|
|
505
573
|
proxy: typeof a.proxy === "string" && a.proxy.trim() ? a.proxy.trim() : undefined,
|
|
506
574
|
policies: a.policies || [],
|
|
507
575
|
});
|
|
@@ -610,7 +678,40 @@ async function main() {
|
|
|
610
678
|
mcpConfigured = true;
|
|
611
679
|
}
|
|
612
680
|
}
|
|
613
|
-
// ── PHASE 5:
|
|
681
|
+
// ── PHASE 5: AGENT SKILLS ────────────────────────────────────────────────────
|
|
682
|
+
console.log(boxen(pc.blue("PHASE 5: AGENT SKILLS"), { padding: 1, borderStyle: 'round', borderColor: 'blue' }));
|
|
683
|
+
let skillsInstalled = false;
|
|
684
|
+
const installSkillsNow = await p.confirm({
|
|
685
|
+
message: "Install or update Weavetab agent skills? (domain guides for your AI agent)",
|
|
686
|
+
initialValue: true
|
|
687
|
+
});
|
|
688
|
+
if (!p.isCancel(installSkillsNow) && installSkillsNow) {
|
|
689
|
+
const agentFramework = await p.select({
|
|
690
|
+
message: "Select your target AI agent framework:",
|
|
691
|
+
options: [
|
|
692
|
+
{ value: ".agent", label: "Antigravity", hint: ".agent/skills/<domain>/SKILL.md" },
|
|
693
|
+
{ value: ".cursor", label: "Cursor IDE", hint: ".cursor/rules/weavetab-<domain>.mdc" },
|
|
694
|
+
{ value: ".clinerules", label: "Cline", hint: ".clinerules" },
|
|
695
|
+
{ value: ".windsurf", label: "Windsurf", hint: ".windsurf/rules/" },
|
|
696
|
+
{ value: ".openclaw", label: "OpenClaw", hint: ".openclaw/skills/" },
|
|
697
|
+
{ value: ".roocode", label: "RooCode", hint: ".roocode/rules/" },
|
|
698
|
+
{ value: "generic", label: "Raw Markdown", hint: "weavetab-skills/ directory" },
|
|
699
|
+
]
|
|
700
|
+
});
|
|
701
|
+
if (!p.isCancel(agentFramework)) {
|
|
702
|
+
const { execSync: exec } = await import("node:child_process");
|
|
703
|
+
p.note(`${pc.dim("Installing skills for")} ${pc.cyan(agentFramework)} ${pc.dim("via")} ${pc.cyan("npx @weavetab/skills@latest")}...`, "SKILLS INSTALLER");
|
|
704
|
+
console.log();
|
|
705
|
+
try {
|
|
706
|
+
exec(`npx -y @weavetab/skills@latest --framework ${agentFramework}`, { stdio: "inherit" });
|
|
707
|
+
skillsInstalled = true;
|
|
708
|
+
}
|
|
709
|
+
catch {
|
|
710
|
+
console.log(pc.yellow(`[WARN] Skills install failed — run 'npx @weavetab/skills@latest -f ${agentFramework}' manually`));
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
// ── PHASE 6: SUMMARY ───────────────────────────────────────────────────────
|
|
614
715
|
console.log(boxen(pc.green("CONFIGURATION COMPLETE"), { padding: 1, borderStyle: 'round', borderColor: 'green' }));
|
|
615
716
|
const summary = [
|
|
616
717
|
`${pc.dim("Browser:")} ${a.browser}`,
|
|
@@ -620,6 +721,7 @@ async function main() {
|
|
|
620
721
|
`${pc.dim("Max tabs:")} ${partialConfig.maxTabs}`,
|
|
621
722
|
`${pc.dim("Config location:")} ~/.weavetab/config.json`,
|
|
622
723
|
`${pc.dim("MCP Config:")} ${mcpConfigured ? pc.green("[OK] Configured") : pc.yellow("Pending")}`,
|
|
724
|
+
`${pc.dim("Skills:")} ${skillsInstalled ? pc.green("[OK] Installed") : pc.dim("Skipped")}`,
|
|
623
725
|
];
|
|
624
726
|
if (a.block?.length)
|
|
625
727
|
summary.push(`${pc.dim("Blocked:")} ${a.block.join(", ")}`);
|
|
@@ -627,7 +729,7 @@ async function main() {
|
|
|
627
729
|
summary.push(`${pc.dim("Allowed:")} ${a.allow.join(", ")}`);
|
|
628
730
|
p.note(summary.join("\n"), "SUMMARY");
|
|
629
731
|
if (!mcpConfigured) {
|
|
630
|
-
console.log(pc.dim("\nTo configure MCP manually, run: weavetab config
|
|
732
|
+
console.log(pc.dim("\nTo configure MCP manually, run: weavetab config"));
|
|
631
733
|
}
|
|
632
734
|
p.outro(`${pc.green("Weavetab is ready!")} ${pc.dim("Run")} ${pc.cyan("weavetab help")} ${pc.dim("to see available commands.")}`);
|
|
633
735
|
}
|
|
@@ -970,7 +1072,7 @@ async function main() {
|
|
|
970
1072
|
const open = (await import("open")).default;
|
|
971
1073
|
const config = await loadConfig();
|
|
972
1074
|
const _require = createRequire(import.meta.url);
|
|
973
|
-
const version = _require("../package.json").version ||
|
|
1075
|
+
const version = _require("../package.json").version || WEAVETAB_VERSION;
|
|
974
1076
|
console.clear();
|
|
975
1077
|
await checkForUpdates();
|
|
976
1078
|
// Config resolution info
|
|
@@ -1001,7 +1103,7 @@ async function main() {
|
|
|
1001
1103
|
console.log(pc.bold("LINKS"));
|
|
1002
1104
|
console.log(` ${pc.cyan("[G]")} GitHub ${pc.dim("github.com/Weavetab")}`);
|
|
1003
1105
|
console.log(` ${pc.cyan("[N]")} NPM ${pc.dim("npmjs.com/package/Weavetab")}`);
|
|
1004
|
-
console.log(` ${pc.cyan("[W]")} Website ${pc.dim("weavetab.
|
|
1106
|
+
console.log(` ${pc.cyan("[W]")} Website ${pc.dim("weavetab.dev")}`);
|
|
1005
1107
|
console.log();
|
|
1006
1108
|
console.log(pc.dim("Awaiting command..."));
|
|
1007
1109
|
process.stdin.setRawMode(true);
|
|
@@ -1063,10 +1165,10 @@ async function main() {
|
|
|
1063
1165
|
runMainUI();
|
|
1064
1166
|
}
|
|
1065
1167
|
if (k === "g") {
|
|
1066
|
-
await open("https://github.com/
|
|
1168
|
+
await open("https://github.com/weavetab");
|
|
1067
1169
|
}
|
|
1068
1170
|
if (k === "n") {
|
|
1069
|
-
await open("https://npmjs.com/package/
|
|
1171
|
+
await open("https://www.npmjs.com/package/@weavetab/mcp");
|
|
1070
1172
|
}
|
|
1071
1173
|
if (k === "w") {
|
|
1072
1174
|
await open("https://github.com/weavetab/mcp");
|
|
@@ -1076,7 +1178,7 @@ async function main() {
|
|
|
1076
1178
|
}
|
|
1077
1179
|
function runHelp() {
|
|
1078
1180
|
const _require = createRequire(import.meta.url);
|
|
1079
|
-
const version = _require("../package.json").version ||
|
|
1181
|
+
const version = _require("../package.json").version || WEAVETAB_VERSION;
|
|
1080
1182
|
console.clear();
|
|
1081
1183
|
console.log(boxen(pc.cyan(`Weavetab v${version}`), { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
|
|
1082
1184
|
console.log(pc.dim("Production-grade MCP server for Chrome DevTools Protocol"));
|
|
@@ -1087,14 +1189,21 @@ async function main() {
|
|
|
1087
1189
|
console.log(pc.bold("COMMANDS"));
|
|
1088
1190
|
console.log(` ${pc.cyan("plugin")} Manage Weavetab plugins (add, list, remove, search, browse, verify)`);
|
|
1089
1191
|
console.log(` ${pc.cyan("config")} Launch the interactive configuration wizard`);
|
|
1192
|
+
console.log(` ${pc.cyan("skills")} Install or update AI agent skills (@weavetab/skills)`);
|
|
1090
1193
|
console.log(` ${pc.cyan("view")} Display the current active configuration`);
|
|
1091
1194
|
console.log(` ${pc.cyan("reset")} Purge browser profiles, lockfiles, and orphan processes`);
|
|
1092
|
-
console.log(` ${pc.cyan("secrets")} Manage blind-injected credentials (set, list, rm)`);
|
|
1195
|
+
console.log(` ${pc.cyan("secrets")} Manage blind-injected credentials (set, list, rm, init)`);
|
|
1093
1196
|
console.log(` ${pc.cyan("reload-ext")} Send a reload signal to the browser extension`);
|
|
1197
|
+
console.log(` ${pc.cyan("--ws")} Start the WebSocket daemon (default port 3000, override with --port)`);
|
|
1198
|
+
console.log(` ${pc.cyan("--version")} Print version and exit`);
|
|
1094
1199
|
console.log(` ${pc.cyan("help")} Show this help message`);
|
|
1095
1200
|
console.log();
|
|
1201
|
+
console.log(pc.bold("AGENT SKILLS (@weavetab/skills)"));
|
|
1202
|
+
console.log(` ${pc.dim("Install/update skills:")} ${pc.cyan("npx -y @weavetab/skills@latest")}`);
|
|
1203
|
+
console.log(` ${pc.dim("Via CLI:")} ${pc.cyan("weavetab skills [options]")}`);
|
|
1204
|
+
console.log();
|
|
1096
1205
|
console.log(pc.bold("PLUGIN COMMANDS (User)"));
|
|
1097
|
-
console.log(` ${pc.cyan("weavetab plugin add <pkg>")} Install a plugin (
|
|
1206
|
+
console.log(` ${pc.cyan("weavetab plugin add <pkg>")} Install a plugin from npm (or a local path: ./my-plugin)`);
|
|
1098
1207
|
console.log(` ${pc.cyan("weavetab plugin browse")} Interactive terminal explorer to browse & 1-click install`);
|
|
1099
1208
|
console.log(` ${pc.cyan("weavetab plugin search <query>")} Search plugins across registry & npm`);
|
|
1100
1209
|
console.log(` ${pc.cyan("weavetab plugin list")} List all installed Weavetab plugins and tools`);
|
|
@@ -1116,9 +1225,9 @@ async function main() {
|
|
|
1116
1225
|
console.log(` ${pc.cyan("WT_AGENT_ID")} Agent identifier (auto-generated if unset)`);
|
|
1117
1226
|
console.log();
|
|
1118
1227
|
console.log(pc.bold("LINKS"));
|
|
1119
|
-
console.log(` ${pc.cyan("GitHub:")} ${pc.dim("https://github.com/
|
|
1120
|
-
console.log(` ${pc.cyan("npm:")} ${pc.dim("https://npmjs.com/package/
|
|
1121
|
-
console.log(` ${pc.cyan("Website:")} ${pc.dim("https://
|
|
1228
|
+
console.log(` ${pc.cyan("GitHub:")} ${pc.dim("https://github.com/weavetab")}`);
|
|
1229
|
+
console.log(` ${pc.cyan("npm:")} ${pc.dim("https://www.npmjs.com/package/@weavetab/mcp")}`);
|
|
1230
|
+
console.log(` ${pc.cyan("Website:")} ${pc.dim("https://weavetab.dev")}`);
|
|
1122
1231
|
console.log();
|
|
1123
1232
|
}
|
|
1124
1233
|
}
|
|
@@ -1157,10 +1266,17 @@ async function runSecretsCommand(args) {
|
|
|
1157
1266
|
const { secretStore } = await import("./security/secrets.js");
|
|
1158
1267
|
const p = await import("@clack/prompts");
|
|
1159
1268
|
if (args.length === 0) {
|
|
1160
|
-
console.log(pc.red("[ERROR] Usage: weavetab secrets <set|list|rm> [key]"));
|
|
1269
|
+
console.log(pc.red("[ERROR] Usage: weavetab secrets <set|list|rm|init> [key]"));
|
|
1161
1270
|
process.exit(1);
|
|
1162
1271
|
}
|
|
1163
1272
|
const subcmd = args[0].toLowerCase();
|
|
1273
|
+
if (subcmd === "init") {
|
|
1274
|
+
const { initProjectSecrets } = await import("./security/secrets.js");
|
|
1275
|
+
const filePath = initProjectSecrets();
|
|
1276
|
+
console.log(pc.green(`[OK] Project secrets initialized: ${filePath}`));
|
|
1277
|
+
console.log(pc.dim("Keys in this file take precedence over ~/.weavetab/secrets.json when Weavetab runs from this directory."));
|
|
1278
|
+
return;
|
|
1279
|
+
}
|
|
1164
1280
|
if (subcmd === "list") {
|
|
1165
1281
|
const list = await secretStore.listSecrets();
|
|
1166
1282
|
console.log(boxen(pc.cyan("STORED SECRETS"), { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
|
|
@@ -1235,10 +1351,10 @@ async function runSecretsCommand(args) {
|
|
|
1235
1351
|
}
|
|
1236
1352
|
}
|
|
1237
1353
|
await secretStore.setSecret(key, value, domains);
|
|
1238
|
-
console.log(pc.green(`[OK] Secret "${key}" saved
|
|
1354
|
+
console.log(pc.green(`[OK] Secret "${key}" saved.`));
|
|
1239
1355
|
return;
|
|
1240
1356
|
}
|
|
1241
1357
|
console.log(pc.red(`[ERROR] Unknown secrets command: ${subcmd}`));
|
|
1242
|
-
console.log(pc.red("Usage: weavetab secrets <set|list|rm> [key]"));
|
|
1358
|
+
console.log(pc.red("Usage: weavetab secrets <set|list|rm|init> [key]"));
|
|
1243
1359
|
process.exit(1);
|
|
1244
1360
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Weavetab — intelligence/marks.ts
|
|
3
|
+
* Visual grounding mark cache.
|
|
4
|
+
*
|
|
5
|
+
* When browser_map runs with visual: true/auto, numbered SoM badges are
|
|
6
|
+
* injected over the page, a screenshot is taken, and each badge's position
|
|
7
|
+
* and optional DOM ref are stored here. Interaction tools (browser_click,
|
|
8
|
+
* browser_pointer, etc.) can then resolve a { mark: N } argument directly
|
|
9
|
+
* to pixel coordinates without any further DOM walk.
|
|
10
|
+
*
|
|
11
|
+
* Weavetab by fy2ne
|
|
12
|
+
*/
|
|
13
|
+
export interface MarkEntry {
|
|
14
|
+
/** Center X coordinate (viewport-relative pixels). */
|
|
15
|
+
x: number;
|
|
16
|
+
/** Center Y coordinate (viewport-relative pixels). */
|
|
17
|
+
y: number;
|
|
18
|
+
/** Width of the element bounding box. */
|
|
19
|
+
width: number;
|
|
20
|
+
/** Height of the element bounding box. */
|
|
21
|
+
height: number;
|
|
22
|
+
/** Volatile ref ID (w:NN) if the element is DOM-backed. Undefined for canvas/visual-only regions. */
|
|
23
|
+
ref?: string;
|
|
24
|
+
/** Visible text or aria-label, if available. */
|
|
25
|
+
label?: string;
|
|
26
|
+
/** Element type hint. */
|
|
27
|
+
type?: "button" | "input" | "link" | "select" | "canvas_region" | "unknown";
|
|
28
|
+
}
|
|
29
|
+
/** Write a full set of marks for a tab. Replaces any previous marks. */
|
|
30
|
+
export declare function marksSet(targetId: string, marks: Map<number, MarkEntry>): void;
|
|
31
|
+
/** Look up a single mark for a tab. Returns null if not found. */
|
|
32
|
+
export declare function marksGet(targetId: string, mark: number): MarkEntry | null;
|
|
33
|
+
/** Clear all marks for a tab (called on navigation). */
|
|
34
|
+
export declare function marksInvalidate(targetId: string): void;
|
|
35
|
+
/** Return all marks for a tab (used for debugging / list output). */
|
|
36
|
+
export declare function marksGetAll(targetId: string): Map<number, MarkEntry>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Weavetab — intelligence/marks.ts
|
|
3
|
+
* Visual grounding mark cache.
|
|
4
|
+
*
|
|
5
|
+
* When browser_map runs with visual: true/auto, numbered SoM badges are
|
|
6
|
+
* injected over the page, a screenshot is taken, and each badge's position
|
|
7
|
+
* and optional DOM ref are stored here. Interaction tools (browser_click,
|
|
8
|
+
* browser_pointer, etc.) can then resolve a { mark: N } argument directly
|
|
9
|
+
* to pixel coordinates without any further DOM walk.
|
|
10
|
+
*
|
|
11
|
+
* Weavetab by fy2ne
|
|
12
|
+
*/
|
|
13
|
+
/** Per-tab: Map<targetId, Map<markNumber, MarkEntry>> */
|
|
14
|
+
const store = new Map();
|
|
15
|
+
/** Write a full set of marks for a tab. Replaces any previous marks. */
|
|
16
|
+
export function marksSet(targetId, marks) {
|
|
17
|
+
store.set(targetId, marks);
|
|
18
|
+
}
|
|
19
|
+
/** Look up a single mark for a tab. Returns null if not found. */
|
|
20
|
+
export function marksGet(targetId, mark) {
|
|
21
|
+
return store.get(targetId)?.get(mark) ?? null;
|
|
22
|
+
}
|
|
23
|
+
/** Clear all marks for a tab (called on navigation). */
|
|
24
|
+
export function marksInvalidate(targetId) {
|
|
25
|
+
store.delete(targetId);
|
|
26
|
+
}
|
|
27
|
+
/** Return all marks for a tab (used for debugging / list output). */
|
|
28
|
+
export function marksGetAll(targetId) {
|
|
29
|
+
return store.get(targetId) ?? new Map();
|
|
30
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Weavetab — intelligence/patternCompiler.ts
|
|
3
|
+
*
|
|
4
|
+
* Compiles raw browser session trails (action sequences) into persistent,
|
|
5
|
+
* reusable site workflow patterns stored under ~/.weavetab-system/memory/sites/.
|
|
6
|
+
*
|
|
7
|
+
* Design invariants:
|
|
8
|
+
* - One file per origin (sanitized hostname). Never creates per-path or per-run files.
|
|
9
|
+
* - Pattern names are caller-supplied (snake_case). Duplicate calls for the same
|
|
10
|
+
* name on the same origin UPDATE the existing pattern rather than creating a new file.
|
|
11
|
+
* - Volatile / unstable selectors (auto-generated classes, nth-child paths) are
|
|
12
|
+
* stripped and replaced with semantic anchors where possible.
|
|
13
|
+
* - Never reads or writes to ~/.weavetab/ (user config space).
|
|
14
|
+
*/
|
|
15
|
+
export interface WorkflowStep {
|
|
16
|
+
/** MCP tool name, e.g. "browser_click", "browser_fill", "browser_navigate" */
|
|
17
|
+
tool: string;
|
|
18
|
+
/** Primary selector or URL target */
|
|
19
|
+
target?: string;
|
|
20
|
+
/** Optional value (text typed, option selected, etc.) */
|
|
21
|
+
value?: string;
|
|
22
|
+
/** Any extra args forwarded verbatim to browser_burst replay */
|
|
23
|
+
extra?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
export interface WorkflowPattern {
|
|
26
|
+
/** Caller-assigned name in snake_case, e.g. "login_flow", "pr_review" */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Compiled, stable steps ready for browser_burst replay */
|
|
29
|
+
steps: WorkflowStep[];
|
|
30
|
+
/** Optional CSS selector / URL fragment that confirms success */
|
|
31
|
+
success_indicator?: string;
|
|
32
|
+
/** URL path or pattern where this workflow starts, e.g. "/pull/:id/files" */
|
|
33
|
+
entry?: string;
|
|
34
|
+
/** Exponentially-weighted moving average of duration in ms */
|
|
35
|
+
avg_duration_ms?: number;
|
|
36
|
+
/** 0.0 – 1.0 reliability. Degrades on failures, climbs on successes. */
|
|
37
|
+
reliability: number;
|
|
38
|
+
/** Consecutive failure counter — 3 strikes triggers re-learn flag */
|
|
39
|
+
strikes: number;
|
|
40
|
+
/** ISO timestamp of last successful verified run */
|
|
41
|
+
last_verified: string;
|
|
42
|
+
/** Total times this pattern was executed */
|
|
43
|
+
total_executions: number;
|
|
44
|
+
/** Times the pattern completed without errors */
|
|
45
|
+
successful_executions: number;
|
|
46
|
+
}
|
|
47
|
+
export interface SiteQuirks {
|
|
48
|
+
cookie_banner?: {
|
|
49
|
+
selector: string;
|
|
50
|
+
action: string;
|
|
51
|
+
appears: "first_visit" | "always" | "random";
|
|
52
|
+
};
|
|
53
|
+
rate_limit?: {
|
|
54
|
+
threshold?: string;
|
|
55
|
+
recovery?: string;
|
|
56
|
+
};
|
|
57
|
+
modal_popups?: Array<{
|
|
58
|
+
trigger?: string;
|
|
59
|
+
dismiss_selector: string;
|
|
60
|
+
}>;
|
|
61
|
+
[key: string]: unknown;
|
|
62
|
+
}
|
|
63
|
+
export interface SiteProfile {
|
|
64
|
+
/** Full origin, e.g. "https://github.com" */
|
|
65
|
+
origin: string;
|
|
66
|
+
/** Detected JS framework: react, vue, angular, next, nuxt, svelte, etc. */
|
|
67
|
+
framework?: string;
|
|
68
|
+
/** True if the site uses Shadow DOM components */
|
|
69
|
+
shadowDom?: boolean;
|
|
70
|
+
/** How often this site presents CAPTCHA challenges */
|
|
71
|
+
captcha_frequency?: "none" | "rare" | "moderate" | "frequent";
|
|
72
|
+
/** Known site-level quirks to handle automatically */
|
|
73
|
+
quirks: SiteQuirks;
|
|
74
|
+
/** Named, compiled workflow patterns indexed by name */
|
|
75
|
+
patterns: Record<string, WorkflowPattern>;
|
|
76
|
+
/** ISO timestamp of last profile write */
|
|
77
|
+
updatedAt: string;
|
|
78
|
+
/** How many times this origin has been visited in automated sessions */
|
|
79
|
+
visitCount: number;
|
|
80
|
+
}
|
|
81
|
+
export declare function clearSiteProfileCache(): void;
|
|
82
|
+
/**
|
|
83
|
+
* Load a site profile from disk. Returns null if the site has never been profiled.
|
|
84
|
+
* Hits in-process cache first — no redundant disk reads within a session.
|
|
85
|
+
*/
|
|
86
|
+
export declare function getSiteProfile(origin: string): Promise<SiteProfile | null>;
|
|
87
|
+
/**
|
|
88
|
+
* Persist a site profile. Always deep-merges into existing data on disk — never
|
|
89
|
+
* blindly overwrites — so concurrent tool calls don't clobber each other.
|
|
90
|
+
*/
|
|
91
|
+
export declare function saveSiteProfile(profile: SiteProfile): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Learn or update a named workflow pattern for a given origin.
|
|
94
|
+
* - Duplicate name = merge/update, never duplicate file.
|
|
95
|
+
* - Volatile selectors in steps are dropped to keep patterns stable.
|
|
96
|
+
* - Anti-spam: skips disk write when content is identical to existing.
|
|
97
|
+
*/
|
|
98
|
+
export declare function learnPattern(origin: string, name: string, incoming: Partial<WorkflowPattern>): Promise<WorkflowPattern>;
|
|
99
|
+
/**
|
|
100
|
+
* Record the outcome of executing a named pattern.
|
|
101
|
+
* Updates reliability via EWMA (α=0.15) and tracks consecutive strikes.
|
|
102
|
+
* 3 strikes → reliability will naturally fall below 0.4, agent should re-explore.
|
|
103
|
+
*/
|
|
104
|
+
export declare function recordPatternExecution(origin: string, patternName: string, success: boolean, durationMs?: number): Promise<WorkflowPattern | null>;
|
|
105
|
+
/**
|
|
106
|
+
* Record or update a site quirk (cookie banner, rate limit, modal popup, etc.)
|
|
107
|
+
* Only writes if the stored data differs from incoming — prevents spam writes.
|
|
108
|
+
*/
|
|
109
|
+
export declare function recordQuirk(origin: string, quirkKey: string, quirkData: unknown): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* Returns the reliability score (0–1) of a named pattern, or -1 if unknown.
|
|
112
|
+
*/
|
|
113
|
+
export declare function getPatternReliability(origin: string, patternName: string): Promise<number>;
|
|
114
|
+
/**
|
|
115
|
+
* Formats a compact site profile hint string for agent system prompt injection.
|
|
116
|
+
* Called at session start when navigating to a known origin.
|
|
117
|
+
*/
|
|
118
|
+
export declare function formatSiteProfileHint(profile: SiteProfile): string;
|