@weavetab/mcp 2.5.0-beta.2 → 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 +1 -1
- package/ARCHITECTURE.md +6 -6
- package/LICENSE +1 -1
- package/README.md +158 -961
- 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 +8 -4
- 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.js +24 -17
- package/dist/cli/updater.d.ts +1 -1
- package/dist/cli/updater.js +27 -7
- package/dist/config/loader.d.ts +8 -0
- package/dist/config/loader.js +41 -2
- package/dist/desktop/discovery.d.ts +44 -0
- package/dist/desktop/discovery.js +364 -0
- package/dist/index.js +95 -15
- 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 +76 -2
- package/dist/plugin/loader.d.ts +15 -1
- package/dist/plugin/loader.js +217 -70
- package/dist/plugin/pipeline.d.ts +75 -0
- package/dist/plugin/pipeline.js +183 -0
- package/dist/plugin/registry.js +3 -2
- 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 +428 -156
- 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 +50 -5
- package/dist/tools/burst.d.ts +17 -8
- package/dist/tools/burst.js +236 -77
- 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.js +29 -34
- 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 +14 -6
- 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 +21 -32
- package/docs/PLUGINS.md +121 -0
- package/docs/TOOLS.md +56 -0
- package/docs/architecture/blind-injection.md +83 -20
- package/docs/architecture/overview.md +49 -49
- package/docs/configuration/folders.md +55 -54
- package/docs/desktop-automation/electron-apps.md +217 -162
- package/docs/get-started/introduction.md +60 -60
- package/docs/intelligence/site-profiles.md +151 -0
- package/docs/tools/tools.md +631 -293
- 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/mcp.json +101 -67
- package/package.json +5 -6
- package/server.json +3 -3
- 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;
|
|
@@ -134,6 +151,17 @@ async function main() {
|
|
|
134
151
|
await runPluginCli(args.slice(1));
|
|
135
152
|
process.exit(0);
|
|
136
153
|
}
|
|
154
|
+
if (cmd === "skills") {
|
|
155
|
+
const { execSync: exec } = await import("node:child_process");
|
|
156
|
+
const subArgs = args.slice(1).join(" ");
|
|
157
|
+
try {
|
|
158
|
+
exec(`npx -y @weavetab/skills@latest ${subArgs}`.trim(), { stdio: "inherit" });
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
process.exit(1);
|
|
162
|
+
}
|
|
163
|
+
process.exit(0);
|
|
164
|
+
}
|
|
137
165
|
if (cmd === "init" || cmd === "create" || cmd === "build" || cmd === "manifest") {
|
|
138
166
|
console.log(pc.yellow(`\n[Weavetab] Plugin authoring commands are part of the developer SDK (@weavetab/sdk).`));
|
|
139
167
|
console.log(pc.dim("To scaffold a new plugin: ") + pc.cyan("npx -y @weavetab/sdk init <name>"));
|
|
@@ -406,6 +434,7 @@ async function main() {
|
|
|
406
434
|
}, "browserType"),
|
|
407
435
|
S.cf("Enable Weavetab browser extension?", "extension", true),
|
|
408
436
|
S.cf("Persist cookies across sessions?", "cookies", false),
|
|
437
|
+
S.cf("Sync browser data across profiles?", "syncDataAcrossBrowsers", false),
|
|
409
438
|
S.tx("Extra browser flags (space-separated)", "browserFlagsRaw", ""),
|
|
410
439
|
S.tx("Custom browser profile directory", "profileDir", ""),
|
|
411
440
|
])) === "back")
|
|
@@ -427,6 +456,8 @@ async function main() {
|
|
|
427
456
|
return "Positive integer."; }),
|
|
428
457
|
S.tx("Actionability timeout (ms)", "actionabilityTimeout", "500", (v) => { const n = parseInt(v ?? ""); if (isNaN(n) || n < 100)
|
|
429
458
|
return "Min 100 ms."; }),
|
|
459
|
+
S.tx("Ref cache TTL (ms) — stale element handle expiry", "refCacheTtlMs", "30000", (v) => { const n = parseInt(v ?? ""); if (isNaN(n) || n < 1000)
|
|
460
|
+
return "Min 1000 ms."; }),
|
|
430
461
|
])) === "back")
|
|
431
462
|
process.exit(0);
|
|
432
463
|
}
|
|
@@ -445,6 +476,10 @@ async function main() {
|
|
|
445
476
|
console.log(boxen(pc.cyan("SECTION D: STORAGE & PROXY"), { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
|
|
446
477
|
if ((await run([
|
|
447
478
|
S.tx("Download directory", "downloadDir", ""),
|
|
479
|
+
S.tx("PDF output directory", "pdfDir", ""),
|
|
480
|
+
S.tx("Snapshot directory (screenshots)", "snapshotDir", ""),
|
|
481
|
+
S.tx("Recording output directory", "recordingDir", ""),
|
|
482
|
+
S.tx("Design extraction directory", "designDir", ""),
|
|
448
483
|
S.tx("Proxy URL (or $WT_PROXY_URL)", "proxy", ""),
|
|
449
484
|
])) === "back")
|
|
450
485
|
process.exit(0);
|
|
@@ -492,6 +527,7 @@ async function main() {
|
|
|
492
527
|
browserType: a.browserType || "chromium",
|
|
493
528
|
extension: a.extension !== undefined ? a.extension : true,
|
|
494
529
|
cookies: a.cookies || false,
|
|
530
|
+
syncDataAcrossBrowsers: a.syncDataAcrossBrowsers || false,
|
|
495
531
|
browserFlags: a.browserFlags || [],
|
|
496
532
|
profileDir: a.profileDir || "",
|
|
497
533
|
sessionTimeout: parseInt(a.sessionTimeout) || 3600,
|
|
@@ -499,9 +535,14 @@ async function main() {
|
|
|
499
535
|
idleTimeout: parseInt(a.idleTimeout) || 60000,
|
|
500
536
|
maxActionsPerMinute: parseInt(a.maxActionsPerMinute) || 60,
|
|
501
537
|
actionabilityTimeout: parseInt(a.actionabilityTimeout) || 500,
|
|
538
|
+
refCacheTtlMs: parseInt(a.refCacheTtlMs) || 30000,
|
|
502
539
|
telemetry: a.telemetry || false,
|
|
503
540
|
githubCacheTtlMs: parseInt(a.githubCacheTtlMs) || 1800000,
|
|
504
541
|
downloadDir: a.downloadDir || "",
|
|
542
|
+
pdfDir: a.pdfDir || "",
|
|
543
|
+
snapshotDir: a.snapshotDir || "",
|
|
544
|
+
recordingDir: a.recordingDir || "",
|
|
545
|
+
designDir: a.designDir || "",
|
|
505
546
|
proxy: typeof a.proxy === "string" && a.proxy.trim() ? a.proxy.trim() : undefined,
|
|
506
547
|
policies: a.policies || [],
|
|
507
548
|
});
|
|
@@ -610,7 +651,40 @@ async function main() {
|
|
|
610
651
|
mcpConfigured = true;
|
|
611
652
|
}
|
|
612
653
|
}
|
|
613
|
-
// ── PHASE 5:
|
|
654
|
+
// ── PHASE 5: AGENT SKILLS ────────────────────────────────────────────────────
|
|
655
|
+
console.log(boxen(pc.blue("PHASE 5: AGENT SKILLS"), { padding: 1, borderStyle: 'round', borderColor: 'blue' }));
|
|
656
|
+
let skillsInstalled = false;
|
|
657
|
+
const installSkillsNow = await p.confirm({
|
|
658
|
+
message: "Install or update Weavetab agent skills? (domain guides for your AI agent)",
|
|
659
|
+
initialValue: true
|
|
660
|
+
});
|
|
661
|
+
if (!p.isCancel(installSkillsNow) && installSkillsNow) {
|
|
662
|
+
const agentFramework = await p.select({
|
|
663
|
+
message: "Select your target AI agent framework:",
|
|
664
|
+
options: [
|
|
665
|
+
{ value: ".agent", label: "Antigravity", hint: ".agent/skills/<domain>/SKILL.md" },
|
|
666
|
+
{ value: ".cursor", label: "Cursor IDE", hint: ".cursor/rules/weavetab-<domain>.mdc" },
|
|
667
|
+
{ value: ".clinerules", label: "Cline", hint: ".clinerules" },
|
|
668
|
+
{ value: ".windsurf", label: "Windsurf", hint: ".windsurf/rules/" },
|
|
669
|
+
{ value: ".openclaw", label: "OpenClaw", hint: ".openclaw/skills/" },
|
|
670
|
+
{ value: ".roocode", label: "RooCode", hint: ".roocode/rules/" },
|
|
671
|
+
{ value: "generic", label: "Raw Markdown", hint: "weavetab-skills/ directory" },
|
|
672
|
+
]
|
|
673
|
+
});
|
|
674
|
+
if (!p.isCancel(agentFramework)) {
|
|
675
|
+
const { execSync: exec } = await import("node:child_process");
|
|
676
|
+
p.note(`${pc.dim("Installing skills for")} ${pc.cyan(agentFramework)} ${pc.dim("via")} ${pc.cyan("npx @weavetab/skills@latest")}...`, "SKILLS INSTALLER");
|
|
677
|
+
console.log();
|
|
678
|
+
try {
|
|
679
|
+
exec(`npx -y @weavetab/skills@latest --framework ${agentFramework}`, { stdio: "inherit" });
|
|
680
|
+
skillsInstalled = true;
|
|
681
|
+
}
|
|
682
|
+
catch {
|
|
683
|
+
console.log(pc.yellow(`[WARN] Skills install failed — run 'npx @weavetab/skills@latest -f ${agentFramework}' manually`));
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
// ── PHASE 6: SUMMARY ───────────────────────────────────────────────────────
|
|
614
688
|
console.log(boxen(pc.green("CONFIGURATION COMPLETE"), { padding: 1, borderStyle: 'round', borderColor: 'green' }));
|
|
615
689
|
const summary = [
|
|
616
690
|
`${pc.dim("Browser:")} ${a.browser}`,
|
|
@@ -620,6 +694,7 @@ async function main() {
|
|
|
620
694
|
`${pc.dim("Max tabs:")} ${partialConfig.maxTabs}`,
|
|
621
695
|
`${pc.dim("Config location:")} ~/.weavetab/config.json`,
|
|
622
696
|
`${pc.dim("MCP Config:")} ${mcpConfigured ? pc.green("[OK] Configured") : pc.yellow("Pending")}`,
|
|
697
|
+
`${pc.dim("Skills:")} ${skillsInstalled ? pc.green("[OK] Installed") : pc.dim("Skipped")}`,
|
|
623
698
|
];
|
|
624
699
|
if (a.block?.length)
|
|
625
700
|
summary.push(`${pc.dim("Blocked:")} ${a.block.join(", ")}`);
|
|
@@ -970,7 +1045,7 @@ async function main() {
|
|
|
970
1045
|
const open = (await import("open")).default;
|
|
971
1046
|
const config = await loadConfig();
|
|
972
1047
|
const _require = createRequire(import.meta.url);
|
|
973
|
-
const version = _require("../package.json").version ||
|
|
1048
|
+
const version = _require("../package.json").version || WEAVETAB_VERSION;
|
|
974
1049
|
console.clear();
|
|
975
1050
|
await checkForUpdates();
|
|
976
1051
|
// Config resolution info
|
|
@@ -1001,7 +1076,7 @@ async function main() {
|
|
|
1001
1076
|
console.log(pc.bold("LINKS"));
|
|
1002
1077
|
console.log(` ${pc.cyan("[G]")} GitHub ${pc.dim("github.com/Weavetab")}`);
|
|
1003
1078
|
console.log(` ${pc.cyan("[N]")} NPM ${pc.dim("npmjs.com/package/Weavetab")}`);
|
|
1004
|
-
console.log(` ${pc.cyan("[W]")} Website ${pc.dim("weavetab.
|
|
1079
|
+
console.log(` ${pc.cyan("[W]")} Website ${pc.dim("weavetab.dev")}`);
|
|
1005
1080
|
console.log();
|
|
1006
1081
|
console.log(pc.dim("Awaiting command..."));
|
|
1007
1082
|
process.stdin.setRawMode(true);
|
|
@@ -1063,10 +1138,10 @@ async function main() {
|
|
|
1063
1138
|
runMainUI();
|
|
1064
1139
|
}
|
|
1065
1140
|
if (k === "g") {
|
|
1066
|
-
await open("https://github.com/
|
|
1141
|
+
await open("https://github.com/weavetab");
|
|
1067
1142
|
}
|
|
1068
1143
|
if (k === "n") {
|
|
1069
|
-
await open("https://npmjs.com/package/
|
|
1144
|
+
await open("https://www.npmjs.com/package/@weavetab/mcp");
|
|
1070
1145
|
}
|
|
1071
1146
|
if (k === "w") {
|
|
1072
1147
|
await open("https://github.com/weavetab/mcp");
|
|
@@ -1076,7 +1151,7 @@ async function main() {
|
|
|
1076
1151
|
}
|
|
1077
1152
|
function runHelp() {
|
|
1078
1153
|
const _require = createRequire(import.meta.url);
|
|
1079
|
-
const version = _require("../package.json").version ||
|
|
1154
|
+
const version = _require("../package.json").version || WEAVETAB_VERSION;
|
|
1080
1155
|
console.clear();
|
|
1081
1156
|
console.log(boxen(pc.cyan(`Weavetab v${version}`), { padding: 1, borderStyle: 'round', borderColor: 'cyan' }));
|
|
1082
1157
|
console.log(pc.dim("Production-grade MCP server for Chrome DevTools Protocol"));
|
|
@@ -1087,12 +1162,17 @@ async function main() {
|
|
|
1087
1162
|
console.log(pc.bold("COMMANDS"));
|
|
1088
1163
|
console.log(` ${pc.cyan("plugin")} Manage Weavetab plugins (add, list, remove, search, browse, verify)`);
|
|
1089
1164
|
console.log(` ${pc.cyan("config")} Launch the interactive configuration wizard`);
|
|
1165
|
+
console.log(` ${pc.cyan("skills")} Install or update AI agent skills (@weavetab/skills)`);
|
|
1090
1166
|
console.log(` ${pc.cyan("view")} Display the current active configuration`);
|
|
1091
1167
|
console.log(` ${pc.cyan("reset")} Purge browser profiles, lockfiles, and orphan processes`);
|
|
1092
1168
|
console.log(` ${pc.cyan("secrets")} Manage blind-injected credentials (set, list, rm)`);
|
|
1093
1169
|
console.log(` ${pc.cyan("reload-ext")} Send a reload signal to the browser extension`);
|
|
1094
1170
|
console.log(` ${pc.cyan("help")} Show this help message`);
|
|
1095
1171
|
console.log();
|
|
1172
|
+
console.log(pc.bold("AGENT SKILLS (@weavetab/skills)"));
|
|
1173
|
+
console.log(` ${pc.dim("Install/update skills:")} ${pc.cyan("npx -y @weavetab/skills@latest")}`);
|
|
1174
|
+
console.log(` ${pc.dim("Via CLI:")} ${pc.cyan("weavetab skills [options]")}`);
|
|
1175
|
+
console.log();
|
|
1096
1176
|
console.log(pc.bold("PLUGIN COMMANDS (User)"));
|
|
1097
1177
|
console.log(` ${pc.cyan("weavetab plugin add <pkg>")} Install a plugin (resolves official @weavetab/plugin- & community)`);
|
|
1098
1178
|
console.log(` ${pc.cyan("weavetab plugin browse")} Interactive terminal explorer to browse & 1-click install`);
|
|
@@ -1116,8 +1196,8 @@ async function main() {
|
|
|
1116
1196
|
console.log(` ${pc.cyan("WT_AGENT_ID")} Agent identifier (auto-generated if unset)`);
|
|
1117
1197
|
console.log();
|
|
1118
1198
|
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/
|
|
1199
|
+
console.log(` ${pc.cyan("GitHub:")} ${pc.dim("https://github.com/weavetab")}`);
|
|
1200
|
+
console.log(` ${pc.cyan("npm:")} ${pc.dim("https://www.npmjs.com/package/@weavetab/mcp")}`);
|
|
1121
1201
|
console.log(` ${pc.cyan("Website:")} ${pc.dim("https://github.com/weavetab/mcp")}`);
|
|
1122
1202
|
console.log();
|
|
1123
1203
|
}
|
|
@@ -1235,7 +1315,7 @@ async function runSecretsCommand(args) {
|
|
|
1235
1315
|
}
|
|
1236
1316
|
}
|
|
1237
1317
|
await secretStore.setSecret(key, value, domains);
|
|
1238
|
-
console.log(pc.green(`[OK] Secret "${key}" saved
|
|
1318
|
+
console.log(pc.green(`[OK] Secret "${key}" saved.`));
|
|
1239
1319
|
return;
|
|
1240
1320
|
}
|
|
1241
1321
|
console.log(pc.red(`[ERROR] Unknown secrets command: ${subcmd}`));
|
|
@@ -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;
|