@weavetab/mcp 2.5.0-beta.0
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 +48 -0
- package/ARCHITECTURE.md +590 -0
- package/LICENSE +631 -0
- package/README.md +909 -0
- package/SECURITY.md +196 -0
- package/TROUBLESHOOTING.md +365 -0
- package/dist/anticaptcha/detector.d.ts +49 -0
- package/dist/anticaptcha/detector.js +465 -0
- package/dist/anticaptcha/integration.d.ts +36 -0
- package/dist/anticaptcha/integration.js +123 -0
- package/dist/anticaptcha/solver.d.ts +27 -0
- package/dist/anticaptcha/solver.js +552 -0
- package/dist/audit/logger.d.ts +13 -0
- package/dist/audit/logger.js +177 -0
- package/dist/audit/telemetry.d.ts +36 -0
- package/dist/audit/telemetry.js +162 -0
- package/dist/cdp/bridge.d.ts +16 -0
- package/dist/cdp/bridge.js +826 -0
- package/dist/cdp/confirm.d.ts +26 -0
- package/dist/cdp/confirm.js +79 -0
- package/dist/cdp/connector.d.ts +37 -0
- package/dist/cdp/connector.js +661 -0
- package/dist/cdp/extension.d.ts +36 -0
- package/dist/cdp/extension.js +118 -0
- package/dist/cdp/finder.d.ts +1 -0
- package/dist/cdp/finder.js +2 -0
- package/dist/cdp/helpers.d.ts +11 -0
- package/dist/cdp/helpers.js +195 -0
- package/dist/cdp/label_cache.d.ts +12 -0
- package/dist/cdp/label_cache.js +51 -0
- package/dist/cdp/lock.d.ts +33 -0
- package/dist/cdp/lock.js +206 -0
- package/dist/cdp/omni_broker.d.ts +17 -0
- package/dist/cdp/omni_broker.js +119 -0
- package/dist/cdp/profiles.d.ts +1 -0
- package/dist/cdp/profiles.js +87 -0
- package/dist/cdp/pruner.d.ts +41 -0
- package/dist/cdp/pruner.js +263 -0
- package/dist/cdp/ref_cache.d.ts +101 -0
- package/dist/cdp/ref_cache.js +234 -0
- package/dist/cdp/retry.d.ts +5 -0
- package/dist/cdp/retry.js +39 -0
- package/dist/cdp/retry_enhanced.d.ts +44 -0
- package/dist/cdp/retry_enhanced.js +102 -0
- package/dist/cdp/security.d.ts +50 -0
- package/dist/cdp/security.js +237 -0
- package/dist/cdp/verify.d.ts +39 -0
- package/dist/cdp/verify.js +143 -0
- package/dist/cdp/walker.d.ts +91 -0
- package/dist/cdp/walker.js +896 -0
- package/dist/cdp/walker.test.d.ts +2 -0
- package/dist/cdp/walker.test.js +172 -0
- package/dist/cdp/websocket_transport.d.ts +15 -0
- package/dist/cdp/websocket_transport.js +118 -0
- package/dist/cli/plugin.d.ts +9 -0
- package/dist/cli/plugin.js +1134 -0
- package/dist/cli/updater.d.ts +1 -0
- package/dist/cli/updater.js +72 -0
- package/dist/config/loader.d.ts +120 -0
- package/dist/config/loader.js +704 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1248 -0
- package/dist/intelligence/hints.d.ts +11 -0
- package/dist/intelligence/hints.js +39 -0
- package/dist/intelligence/intent.d.ts +33 -0
- package/dist/intelligence/intent.js +171 -0
- package/dist/intelligence/sessionMemory.d.ts +66 -0
- package/dist/intelligence/sessionMemory.js +284 -0
- package/dist/intelligence/sessionMemory.test.d.ts +2 -0
- package/dist/intelligence/sessionMemory.test.js +62 -0
- package/dist/intelligence/trail.d.ts +64 -0
- package/dist/intelligence/trail.js +233 -0
- package/dist/intelligence/trail.test.d.ts +2 -0
- package/dist/intelligence/trail.test.js +110 -0
- package/dist/intelligence/vision.d.ts +24 -0
- package/dist/intelligence/vision.js +151 -0
- package/dist/lifecycle/mission_manager.d.ts +16 -0
- package/dist/lifecycle/mission_manager.js +44 -0
- package/dist/overlay/bubble.d.ts +16 -0
- package/dist/overlay/bubble.js +37 -0
- package/dist/overlay/ghost.d.ts +35 -0
- package/dist/overlay/ghost.js +508 -0
- package/dist/overlay/injector.d.ts +22 -0
- package/dist/overlay/injector.js +198 -0
- package/dist/plugin/interface.d.ts +134 -0
- package/dist/plugin/interface.js +1 -0
- package/dist/plugin/loader.d.ts +18 -0
- package/dist/plugin/loader.js +155 -0
- package/dist/plugin/registry.d.ts +50 -0
- package/dist/plugin/registry.js +234 -0
- package/dist/security/blacklist.d.ts +24 -0
- package/dist/security/blacklist.js +80 -0
- package/dist/security/filter.d.ts +2 -0
- package/dist/security/filter.js +20 -0
- package/dist/security/guard.d.ts +8 -0
- package/dist/security/guard.js +35 -0
- package/dist/security/ratelimit.d.ts +11 -0
- package/dist/security/ratelimit.js +57 -0
- package/dist/security/secrets.d.ts +75 -0
- package/dist/security/secrets.js +365 -0
- package/dist/sensors/actionability.d.ts +81 -0
- package/dist/sensors/actionability.js +303 -0
- package/dist/sensors/guard.d.ts +25 -0
- package/dist/sensors/guard.js +168 -0
- package/dist/sensors/mutations.d.ts +23 -0
- package/dist/sensors/mutations.js +93 -0
- package/dist/sensors/network.d.ts +67 -0
- package/dist/sensors/network.js +193 -0
- package/dist/sensors/operation_monitor.d.ts +80 -0
- package/dist/sensors/operation_monitor.js +203 -0
- package/dist/sensors/pacing.d.ts +44 -0
- package/dist/sensors/pacing.js +111 -0
- package/dist/sensors/thoughts.d.ts +2 -0
- package/dist/sensors/thoughts.js +59 -0
- package/dist/sensors/wait.d.ts +12 -0
- package/dist/sensors/wait.js +44 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +1687 -0
- package/dist/state/agent.d.ts +36 -0
- package/dist/state/agent.js +101 -0
- package/dist/state/cache.d.ts +16 -0
- package/dist/state/cache.js +92 -0
- package/dist/state/cache.test.d.ts +2 -0
- package/dist/state/cache.test.js +76 -0
- package/dist/state/delta.d.ts +71 -0
- package/dist/state/delta.js +234 -0
- package/dist/state/delta.test.d.ts +2 -0
- package/dist/state/delta.test.js +279 -0
- package/dist/state/groups.d.ts +15 -0
- package/dist/state/groups.js +80 -0
- package/dist/state/session.d.ts +30 -0
- package/dist/state/session.js +155 -0
- package/dist/tools/accessibility.d.ts +14 -0
- package/dist/tools/accessibility.js +32 -0
- package/dist/tools/ask.d.ts +14 -0
- package/dist/tools/ask.js +49 -0
- package/dist/tools/automation.d.ts +36 -0
- package/dist/tools/automation.js +218 -0
- package/dist/tools/browser_detect.d.ts +13 -0
- package/dist/tools/browser_detect.js +73 -0
- package/dist/tools/burst.d.ts +35 -0
- package/dist/tools/burst.js +344 -0
- package/dist/tools/canvas.d.ts +25 -0
- package/dist/tools/canvas.js +132 -0
- package/dist/tools/captcha.d.ts +38 -0
- package/dist/tools/captcha.js +209 -0
- package/dist/tools/click.d.ts +36 -0
- package/dist/tools/click.js +561 -0
- package/dist/tools/click_and_wait.d.ts +33 -0
- package/dist/tools/click_and_wait.js +149 -0
- package/dist/tools/clipboard.d.ts +29 -0
- package/dist/tools/clipboard.js +279 -0
- package/dist/tools/console.d.ts +21 -0
- package/dist/tools/console.js +107 -0
- package/dist/tools/cookies.d.ts +67 -0
- package/dist/tools/cookies.js +121 -0
- package/dist/tools/design_extract.d.ts +109 -0
- package/dist/tools/design_extract.js +641 -0
- package/dist/tools/dialog.d.ts +24 -0
- package/dist/tools/dialog.js +109 -0
- package/dist/tools/drag.d.ts +15 -0
- package/dist/tools/drag.js +29 -0
- package/dist/tools/emulation.d.ts +33 -0
- package/dist/tools/emulation.js +69 -0
- package/dist/tools/eval.d.ts +20 -0
- package/dist/tools/eval.js +92 -0
- package/dist/tools/fill.d.ts +41 -0
- package/dist/tools/fill.js +667 -0
- package/dist/tools/find.d.ts +30 -0
- package/dist/tools/find.js +60 -0
- package/dist/tools/geo.d.ts +19 -0
- package/dist/tools/geo.js +29 -0
- package/dist/tools/github/analyze.d.ts +4 -0
- package/dist/tools/github/analyze.js +113 -0
- package/dist/tools/github/cache.d.ts +21 -0
- package/dist/tools/github/cache.js +28 -0
- package/dist/tools/github/index.d.ts +4 -0
- package/dist/tools/github/index.js +4 -0
- package/dist/tools/github/issues.d.ts +9 -0
- package/dist/tools/github/issues.js +88 -0
- package/dist/tools/github/pr.d.ts +5 -0
- package/dist/tools/github/pr.js +88 -0
- package/dist/tools/github/rateLimiter.d.ts +4 -0
- package/dist/tools/github/rateLimiter.js +46 -0
- package/dist/tools/github/read.d.ts +34 -0
- package/dist/tools/github/read.js +74 -0
- package/dist/tools/github/repoContext.d.ts +20 -0
- package/dist/tools/github/repoContext.js +129 -0
- package/dist/tools/highlight.d.ts +20 -0
- package/dist/tools/highlight.js +140 -0
- package/dist/tools/hover.d.ts +19 -0
- package/dist/tools/hover.js +57 -0
- package/dist/tools/inspect.d.ts +17 -0
- package/dist/tools/inspect.js +125 -0
- package/dist/tools/integration.test.d.ts +2 -0
- package/dist/tools/integration.test.js +96 -0
- package/dist/tools/key.d.ts +25 -0
- package/dist/tools/key.js +173 -0
- package/dist/tools/macro_compiler.d.ts +7 -0
- package/dist/tools/macro_compiler.js +82 -0
- package/dist/tools/mouse.d.ts +21 -0
- package/dist/tools/mouse.js +62 -0
- package/dist/tools/navigate.d.ts +16 -0
- package/dist/tools/navigate.js +188 -0
- package/dist/tools/network_intercept.d.ts +17 -0
- package/dist/tools/network_intercept.js +151 -0
- package/dist/tools/office/index.d.ts +9 -0
- package/dist/tools/office/index.js +7 -0
- package/dist/tools/office/list.d.ts +15 -0
- package/dist/tools/office/list.js +41 -0
- package/dist/tools/office/parse.d.ts +20 -0
- package/dist/tools/office/parse.js +172 -0
- package/dist/tools/pdf.d.ts +22 -0
- package/dist/tools/pdf.js +42 -0
- package/dist/tools/performance.d.ts +12 -0
- package/dist/tools/performance.js +47 -0
- package/dist/tools/performance_test.d.ts +70 -0
- package/dist/tools/performance_test.js +128 -0
- package/dist/tools/plan.d.ts +39 -0
- package/dist/tools/plan.js +161 -0
- package/dist/tools/pointer.d.ts +35 -0
- package/dist/tools/pointer.js +522 -0
- package/dist/tools/read.d.ts +30 -0
- package/dist/tools/read.js +488 -0
- package/dist/tools/recording.d.ts +45 -0
- package/dist/tools/recording.js +124 -0
- package/dist/tools/response.d.ts +129 -0
- package/dist/tools/response.js +5 -0
- package/dist/tools/scrape.d.ts +24 -0
- package/dist/tools/scrape.js +140 -0
- package/dist/tools/screenshot.d.ts +40 -0
- package/dist/tools/screenshot.js +79 -0
- package/dist/tools/scroll.d.ts +23 -0
- package/dist/tools/scroll.js +196 -0
- package/dist/tools/select.d.ts +13 -0
- package/dist/tools/select.js +217 -0
- package/dist/tools/snapshot.d.ts +27 -0
- package/dist/tools/snapshot.js +99 -0
- package/dist/tools/storage.d.ts +18 -0
- package/dist/tools/storage.js +29 -0
- package/dist/tools/tabs.d.ts +77 -0
- package/dist/tools/tabs.js +342 -0
- package/dist/tools/thought.d.ts +16 -0
- package/dist/tools/thought.js +79 -0
- package/dist/tools/type.d.ts +65 -0
- package/dist/tools/type.js +1061 -0
- package/dist/tools/type_secret.d.ts +23 -0
- package/dist/tools/type_secret.js +229 -0
- package/dist/tools/upload.d.ts +19 -0
- package/dist/tools/upload.js +103 -0
- package/dist/tools/video_compiler.d.ts +24 -0
- package/dist/tools/video_compiler.js +199 -0
- package/dist/tools/viewport.d.ts +44 -0
- package/dist/tools/viewport.js +230 -0
- package/dist/tools/wait.d.ts +19 -0
- package/dist/tools/wait.js +202 -0
- package/dist/tools/wait_for.d.ts +23 -0
- package/dist/tools/wait_for.js +30 -0
- package/dist/tools/windows.d.ts +22 -0
- package/dist/tools/windows.js +57 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +12 -0
- package/docs/DEV_MODE.md +68 -0
- package/docs/DOCUMENTATION.md +532 -0
- package/docs/PLUGINS.md +538 -0
- package/docs/TOOLS.md +104 -0
- package/docs/dev_plugin.md +310 -0
- package/ext-dist/background.js +467 -0
- package/ext-dist/content.js +3089 -0
- package/ext-dist/dashboard.html +583 -0
- package/ext-dist/hud/hud.js +73 -0
- package/ext-dist/hud/index.html +20 -0
- package/ext-dist/manifest.json +77 -0
- package/ext-dist/sidepanel/sidepanel.js +25 -0
- package/ext-dist/sidepanel.html +547 -0
- package/ext-dist/styles.css +218 -0
- package/icon.png +0 -0
- package/mcp.json +796 -0
- package/package.json +113 -0
- package/server.json +23 -0
- package/smithery.yaml +11 -0
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* walker.test.ts — Phase 1.1
|
|
3
|
+
* Unit tests for walker.ts utility functions (no CDP session needed).
|
|
4
|
+
* buildActionMap and buildAXTreeMap require live browser — not tested here.
|
|
5
|
+
*/
|
|
6
|
+
import { test } from "node:test";
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { toRefEntries, findAllMatches, findBestMatch, toMarkdownTable, safeSelector, clearViewportCache, setShadowDomCache, clearShadowDomCache, clearAXTreeCache, resetFallbackIdCounter as resetIdCounter, } from "./walker.js";
|
|
9
|
+
function makeEl(overrides = {}) {
|
|
10
|
+
return {
|
|
11
|
+
id: "w:1",
|
|
12
|
+
role: "button",
|
|
13
|
+
label: "Submit",
|
|
14
|
+
group: "form",
|
|
15
|
+
fingerprint: "button:submit:form:1",
|
|
16
|
+
depth: 0,
|
|
17
|
+
...overrides,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
test("toRefEntries: converts ActionElements to RefEntries", () => {
|
|
21
|
+
const els = [
|
|
22
|
+
makeEl({ id: "w:1", label: "Sign In", role: "button", type: "submit", fingerprint: "a" }),
|
|
23
|
+
makeEl({ id: "w:2", label: "Email", role: "textbox", type: "email", fingerprint: "b" }),
|
|
24
|
+
];
|
|
25
|
+
const refs = toRefEntries(els);
|
|
26
|
+
assert.equal(refs.length, 2);
|
|
27
|
+
assert.equal(refs[0].id, "w:1");
|
|
28
|
+
assert.equal(refs[0].label, "Sign In");
|
|
29
|
+
assert.equal(refs[0].type, "submit");
|
|
30
|
+
assert.equal(refs[0].disabled, false);
|
|
31
|
+
assert.equal(refs[1].id, "w:2");
|
|
32
|
+
});
|
|
33
|
+
test("toRefEntries: empty array returns empty", () => {
|
|
34
|
+
assert.deepEqual(toRefEntries([]), []);
|
|
35
|
+
});
|
|
36
|
+
test("findAllMatches: exact label match", () => {
|
|
37
|
+
const els = [
|
|
38
|
+
makeEl({ id: "w:1", label: "Sign In" }),
|
|
39
|
+
makeEl({ id: "w:2", label: "Sign Out" }),
|
|
40
|
+
makeEl({ id: "w:3", label: "Email" }),
|
|
41
|
+
];
|
|
42
|
+
const matches = findAllMatches(els, "Sign In");
|
|
43
|
+
assert.equal(matches.length, 1);
|
|
44
|
+
assert.equal(matches[0].id, "w:1");
|
|
45
|
+
});
|
|
46
|
+
test("findAllMatches: partial label match", () => {
|
|
47
|
+
const els = [
|
|
48
|
+
makeEl({ id: "w:1", label: "Sign In" }),
|
|
49
|
+
makeEl({ id: "w:2", label: "Sign Out" }),
|
|
50
|
+
makeEl({ id: "w:3", label: "Email" }),
|
|
51
|
+
];
|
|
52
|
+
const matches = findAllMatches(els, "Sign");
|
|
53
|
+
assert.equal(matches.length, 2);
|
|
54
|
+
assert.ok(matches.find(m => m.id === "w:1"));
|
|
55
|
+
assert.ok(matches.find(m => m.id === "w:2"));
|
|
56
|
+
});
|
|
57
|
+
test("findAllMatches: case insensitive", () => {
|
|
58
|
+
const els = [makeEl({ id: "w:1", label: "SIGN IN" })];
|
|
59
|
+
const matches = findAllMatches(els, "sign in");
|
|
60
|
+
assert.equal(matches.length, 1);
|
|
61
|
+
});
|
|
62
|
+
test("findAllMatches: placeholder match", () => {
|
|
63
|
+
const els = [makeEl({ id: "w:1", label: "", placeholder: "Enter name" })];
|
|
64
|
+
const matches = findAllMatches(els, "Enter name");
|
|
65
|
+
assert.equal(matches.length, 1);
|
|
66
|
+
assert.equal(matches[0].id, "w:1");
|
|
67
|
+
});
|
|
68
|
+
test("findAllMatches: empty query returns empty", () => {
|
|
69
|
+
const els = [makeEl({ id: "w:1", label: "Submit" })];
|
|
70
|
+
assert.deepEqual(findAllMatches(els, ""), []);
|
|
71
|
+
assert.deepEqual(findAllMatches(els, " "), []);
|
|
72
|
+
assert.deepEqual(findAllMatches(els, "\t"), []);
|
|
73
|
+
});
|
|
74
|
+
test("findAllMatches: fuzzy multi-word match", () => {
|
|
75
|
+
const els = [
|
|
76
|
+
makeEl({ id: "w:1", label: "Create New Account" }),
|
|
77
|
+
makeEl({ id: "w:2", label: "Create Post" }),
|
|
78
|
+
];
|
|
79
|
+
const matches = findAllMatches(els, "Create Account");
|
|
80
|
+
assert.equal(matches.length, 1);
|
|
81
|
+
assert.equal(matches[0].id, "w:1");
|
|
82
|
+
});
|
|
83
|
+
test("findAllMatches: returns unique elements only", () => {
|
|
84
|
+
const els = [makeEl({ id: "w:1", label: "Submit" })];
|
|
85
|
+
// label and type both match "Submit"
|
|
86
|
+
const matches = findAllMatches(els, "Submit");
|
|
87
|
+
assert.equal(matches.length, 1);
|
|
88
|
+
});
|
|
89
|
+
test("findBestMatch: returns first match", () => {
|
|
90
|
+
const els = [
|
|
91
|
+
makeEl({ id: "w:1", label: "Sign In" }),
|
|
92
|
+
makeEl({ id: "w:2", label: "Sign Out" }),
|
|
93
|
+
];
|
|
94
|
+
const best = findBestMatch(els, "Sign");
|
|
95
|
+
assert.ok(best);
|
|
96
|
+
assert.equal(best.id, "w:1");
|
|
97
|
+
});
|
|
98
|
+
test("findBestMatch: undefined on no match", () => {
|
|
99
|
+
assert.equal(findBestMatch([], "nonexistent"), undefined);
|
|
100
|
+
});
|
|
101
|
+
test("toMarkdownTable: basic formatting", () => {
|
|
102
|
+
const els = [
|
|
103
|
+
makeEl({ id: "w:1", label: "Submit", role: "button", depth: 0 }),
|
|
104
|
+
makeEl({ id: "w:2", label: "Email", role: "textbox", depth: 0 }),
|
|
105
|
+
];
|
|
106
|
+
const md = toMarkdownTable(els, "https://example.com", "Test Page");
|
|
107
|
+
assert.ok(md.includes("https://example.com"));
|
|
108
|
+
assert.ok(md.includes("Test Page"));
|
|
109
|
+
assert.ok(md.includes("Submit"));
|
|
110
|
+
assert.ok(md.includes("Email"));
|
|
111
|
+
assert.ok(md.includes("(Btn)"));
|
|
112
|
+
assert.ok(md.includes("(Input)"));
|
|
113
|
+
});
|
|
114
|
+
test("toMarkdownTable: respects depth indentation", () => {
|
|
115
|
+
const els = [
|
|
116
|
+
makeEl({ id: "w:1", label: "Root", role: "button", depth: 0 }),
|
|
117
|
+
makeEl({ id: "w:2", label: "Child", role: "textbox", depth: 1 }),
|
|
118
|
+
];
|
|
119
|
+
const md = toMarkdownTable(els, "https://x.com", "X");
|
|
120
|
+
// child should be indented
|
|
121
|
+
const lines = md.split("\n");
|
|
122
|
+
const childLine = lines.find(l => l.includes("Child"));
|
|
123
|
+
assert.ok(childLine, "Child line should exist");
|
|
124
|
+
assert.ok(childLine.startsWith(" "), "Child should be indented");
|
|
125
|
+
});
|
|
126
|
+
test("toMarkdownTable: strips non-interactive elements without label", () => {
|
|
127
|
+
const els = [
|
|
128
|
+
makeEl({ id: "", label: "", role: "generic", depth: 0 }),
|
|
129
|
+
makeEl({ id: "w:1", label: "Real", role: "button", depth: 0 }),
|
|
130
|
+
];
|
|
131
|
+
const md = toMarkdownTable(els, "https://x.com", "X");
|
|
132
|
+
assert.ok(!md.includes("generic"), "Empty generic should be stripped");
|
|
133
|
+
assert.ok(md.includes("Real"));
|
|
134
|
+
});
|
|
135
|
+
test("safeSelector: returns selector when present", () => {
|
|
136
|
+
const el = makeEl({ selector: "#submit-btn" });
|
|
137
|
+
assert.equal(safeSelector(el), "#submit-btn");
|
|
138
|
+
});
|
|
139
|
+
test("safeSelector: returns undefined when no selector", () => {
|
|
140
|
+
assert.equal(safeSelector(makeEl()), undefined);
|
|
141
|
+
});
|
|
142
|
+
test("safeSelector: returns undefined on undefined input", () => {
|
|
143
|
+
assert.equal(safeSelector(undefined), undefined);
|
|
144
|
+
});
|
|
145
|
+
test("clearViewportCache: no-op smoke test", () => {
|
|
146
|
+
clearViewportCache("test-target");
|
|
147
|
+
assert.ok(true, "clearViewportCache should not throw");
|
|
148
|
+
});
|
|
149
|
+
test("resetFallbackIdCounter: no-op smoke test", () => {
|
|
150
|
+
resetIdCounter();
|
|
151
|
+
assert.ok(true, "resetFallbackIdCounter should not throw");
|
|
152
|
+
});
|
|
153
|
+
test("shadowDomCache: set and clear", () => {
|
|
154
|
+
setShadowDomCache("target-a", true);
|
|
155
|
+
setShadowDomCache("target-b", false);
|
|
156
|
+
clearShadowDomCache("target-a");
|
|
157
|
+
clearShadowDomCache("target-b");
|
|
158
|
+
assert.ok(true, "shadowDomCache should not throw");
|
|
159
|
+
});
|
|
160
|
+
test("clearAXTreeCache: no-op smoke test", () => {
|
|
161
|
+
clearAXTreeCache("any-target");
|
|
162
|
+
assert.ok(true, "clearAXTreeCache should not throw");
|
|
163
|
+
});
|
|
164
|
+
test("findAllMatches: type match fallback", () => {
|
|
165
|
+
const els = [
|
|
166
|
+
makeEl({ id: "w:1", label: "", type: "checkbox" }),
|
|
167
|
+
makeEl({ id: "w:2", label: "Checkbox", type: "text" }),
|
|
168
|
+
];
|
|
169
|
+
const matches = findAllMatches(els, "checkbox");
|
|
170
|
+
assert.equal(matches.length, 2);
|
|
171
|
+
});
|
|
172
|
+
//# sourceMappingURL=walker.test.js.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Transport, TransportSendOptions } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
2
|
+
import type { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
export declare function getWebSocketSecret(): string;
|
|
4
|
+
export declare class WebSocketServerTransport implements Transport {
|
|
5
|
+
private wss;
|
|
6
|
+
private activeSocket;
|
|
7
|
+
private authenticated;
|
|
8
|
+
onclose?: () => void;
|
|
9
|
+
onerror?: (error: Error) => void;
|
|
10
|
+
onmessage?: (message: JSONRPCMessage) => void;
|
|
11
|
+
constructor(port: number);
|
|
12
|
+
start(): Promise<void>;
|
|
13
|
+
send(message: JSONRPCMessage, options?: TransportSendOptions): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { WebSocketServer } from "ws";
|
|
2
|
+
import * as crypto from "node:crypto";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import * as fs from "node:fs";
|
|
6
|
+
// WebSocket authentication: generate or load a shared secret for authentication
|
|
7
|
+
const WS_SECRET_FILE = path.join(os.homedir(), ".weavetab-system", "ws-secret");
|
|
8
|
+
let wsSecret;
|
|
9
|
+
export function getWebSocketSecret() {
|
|
10
|
+
if (wsSecret)
|
|
11
|
+
return wsSecret;
|
|
12
|
+
try {
|
|
13
|
+
if (fs.existsSync(WS_SECRET_FILE)) {
|
|
14
|
+
wsSecret = fs.readFileSync(WS_SECRET_FILE, "utf-8").trim();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
wsSecret = crypto.randomBytes(32).toString("hex");
|
|
18
|
+
const dir = path.dirname(WS_SECRET_FILE);
|
|
19
|
+
if (!fs.existsSync(dir))
|
|
20
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
21
|
+
fs.writeFileSync(WS_SECRET_FILE, wsSecret, { mode: 0o600 });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
wsSecret = crypto.randomBytes(32).toString("hex");
|
|
26
|
+
}
|
|
27
|
+
return wsSecret;
|
|
28
|
+
}
|
|
29
|
+
export class WebSocketServerTransport {
|
|
30
|
+
wss;
|
|
31
|
+
activeSocket = null;
|
|
32
|
+
authenticated = false;
|
|
33
|
+
onclose;
|
|
34
|
+
onerror;
|
|
35
|
+
onmessage;
|
|
36
|
+
constructor(port) {
|
|
37
|
+
this.wss = new WebSocketServer({ port, maxPayload: 1024 * 1024 }); // 1MB limit
|
|
38
|
+
this.wss.on("connection", (ws) => {
|
|
39
|
+
if (this.activeSocket) {
|
|
40
|
+
ws.close(1013, "Only one concurrent connection allowed");
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Require authentication before accepting messages
|
|
44
|
+
this.authenticated = false;
|
|
45
|
+
ws.on("message", (data) => {
|
|
46
|
+
try {
|
|
47
|
+
const rawMessage = data.toString();
|
|
48
|
+
const message = JSON.parse(rawMessage);
|
|
49
|
+
// Check for authentication handshake
|
|
50
|
+
if (!this.authenticated) {
|
|
51
|
+
const msg = message;
|
|
52
|
+
if (msg.method === "authenticate" && msg.params && Array.isArray(msg.params)) {
|
|
53
|
+
const providedSecret = msg.params[0];
|
|
54
|
+
const expectedSecret = getWebSocketSecret();
|
|
55
|
+
if (providedSecret === expectedSecret) {
|
|
56
|
+
this.authenticated = true;
|
|
57
|
+
this.activeSocket = ws;
|
|
58
|
+
ws.send(JSON.stringify({ result: { authenticated: true }, id: msg.id }));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
ws.send(JSON.stringify({ error: { code: -32000, message: "Authentication failed" }, id: msg.id }));
|
|
63
|
+
ws.close(1008, "Authentication failed");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
ws.send(JSON.stringify({ error: { code: -32001, message: "Authentication required" }, id: msg.id }));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Only process messages after authentication
|
|
73
|
+
this.onmessage?.(message);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
this.onerror?.(err);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
ws.on("error", (err) => {
|
|
80
|
+
this.onerror?.(err);
|
|
81
|
+
});
|
|
82
|
+
ws.on("close", () => {
|
|
83
|
+
this.activeSocket = null;
|
|
84
|
+
this.authenticated = false;
|
|
85
|
+
this.onclose?.();
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
this.wss.on("error", (err) => {
|
|
89
|
+
this.onerror?.(err);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
async start() {
|
|
93
|
+
// Already started listening on construction
|
|
94
|
+
}
|
|
95
|
+
async send(message, options) {
|
|
96
|
+
if (!this.activeSocket) {
|
|
97
|
+
throw new Error("No active WebSocket connection");
|
|
98
|
+
}
|
|
99
|
+
const socket = this.activeSocket;
|
|
100
|
+
return new Promise((resolve, reject) => {
|
|
101
|
+
socket.send(JSON.stringify(message), (err) => {
|
|
102
|
+
if (err)
|
|
103
|
+
reject(err);
|
|
104
|
+
else
|
|
105
|
+
resolve();
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
async close() {
|
|
110
|
+
if (this.activeSocket) {
|
|
111
|
+
this.activeSocket.close();
|
|
112
|
+
this.activeSocket = null;
|
|
113
|
+
}
|
|
114
|
+
return new Promise((resolve) => {
|
|
115
|
+
this.wss.close(() => resolve());
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function runPluginAdd(inputName: string, args?: string[]): Promise<void>;
|
|
2
|
+
export declare function runPluginList(): Promise<void>;
|
|
3
|
+
export declare function runPluginSearch(query?: string): Promise<void>;
|
|
4
|
+
export declare function runPluginBrowse(): Promise<void>;
|
|
5
|
+
export declare function runPluginRemove(pkgName: string, args?: string[]): Promise<void>;
|
|
6
|
+
export declare function runPluginVerify(pkgName: string): Promise<void>;
|
|
7
|
+
export declare function runPluginInit(args?: string[]): Promise<void>;
|
|
8
|
+
export declare function runPluginBuild(args?: string[]): Promise<void>;
|
|
9
|
+
export declare function runPluginCli(args: string[]): Promise<void>;
|