@weavetab/mcp 2.5.0-beta.0 → 2.5.0-beta.2
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 -0
- package/LICENSE +2 -2
- package/README.md +208 -43
- package/SECURITY.md +3 -3
- package/TROUBLESHOOTING.md +1 -1
- package/dist/cdp/bridge.d.ts +10 -0
- package/dist/cdp/bridge.js +288 -68
- package/dist/cdp/connector.d.ts +5 -3
- package/dist/cdp/connector.js +188 -74
- package/dist/cdp/extension.js +0 -1
- package/dist/cdp/helpers.js +0 -2
- package/dist/cdp/lock.d.ts +9 -6
- package/dist/cdp/lock.js +72 -59
- package/dist/cdp/omni_broker.d.ts +1 -0
- package/dist/cdp/omni_broker.js +12 -6
- package/dist/cdp/profiles.d.ts +10 -0
- package/dist/cdp/profiles.js +65 -0
- package/dist/cdp/walker.js +50 -0
- package/dist/cli/plugin.d.ts +0 -2
- package/dist/cli/plugin.js +31 -683
- package/dist/cli/updater.js +2 -2
- package/dist/config/loader.d.ts +25 -6
- package/dist/config/loader.js +133 -20
- package/dist/index.js +48 -52
- package/dist/lifecycle/mission_manager.d.ts +0 -1
- package/dist/lifecycle/mission_manager.js +0 -3
- package/dist/overlay/ghost.d.ts +4 -0
- package/dist/overlay/ghost.js +118 -94
- package/dist/overlay/injector.d.ts +1 -1
- package/dist/overlay/injector.js +1 -15
- package/dist/plugin/extension_bridge.d.ts +40 -0
- package/dist/plugin/extension_bridge.js +158 -0
- package/dist/plugin/interface.d.ts +78 -16
- package/dist/plugin/loader.d.ts +4 -0
- package/dist/plugin/loader.js +178 -57
- package/dist/plugin/registry.js +11 -1
- package/dist/plugin/storage.d.ts +51 -0
- package/dist/plugin/storage.js +164 -0
- package/dist/server.js +217 -151
- package/dist/state/session.d.ts +2 -2
- package/dist/state/session.js +33 -13
- package/dist/tools/browser_detect.d.ts +2 -1
- package/dist/tools/browser_detect.js +6 -5
- package/dist/tools/burst.d.ts +1 -0
- package/dist/tools/burst.js +4 -6
- package/dist/tools/click.js +23 -28
- package/dist/tools/clipboard.js +31 -24
- package/dist/tools/navigate.d.ts +1 -1
- package/dist/tools/navigate.js +28 -10
- package/dist/tools/read.js +1 -1
- package/dist/tools/tabs.d.ts +10 -10
- package/dist/tools/tabs.js +47 -39
- package/dist/tools/type.js +2 -2
- package/docs/DOCUMENTATION.md +63 -6
- package/docs/architecture/blind-injection.md +20 -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 +54 -0
- package/docs/desktop-automation/electron-apps.md +162 -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/skills-ecosystem/skills-overview.md +35 -0
- package/docs/skills-ecosystem/skills-recipes.md +36 -0
- package/docs/tools/tools.md +293 -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/content.js +126 -101
- package/mcp.json +8 -15
- package/package.json +11 -5
- package/server.json +3 -3
- package/dist/tools/plan.d.ts +0 -39
- package/dist/tools/plan.js +0 -161
- package/docs/DEV_MODE.md +0 -68
- package/docs/PLUGINS.md +0 -538
- package/docs/TOOLS.md +0 -104
- package/docs/dev_plugin.md +0 -310
package/dist/overlay/ghost.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logDebug } from "../audit/logger.js";
|
|
2
|
-
import { getConfigHeadless
|
|
2
|
+
import { getConfigHeadless } from "../config/loader.js";
|
|
3
3
|
function sleep(ms) {
|
|
4
4
|
return new Promise(r => setTimeout(r, ms));
|
|
5
5
|
}
|
|
@@ -22,42 +22,87 @@ function wtCursor(session, x, y, state, opts) {
|
|
|
22
22
|
const trail = opts?.trail && opts.trail !== "off" ? getCursorTrail(opts.trail === "full" ? 20 : 8) : undefined;
|
|
23
23
|
sendToExtension(session, { type: 'Weavetab_STATE', cursor: { x, y, trail }, state }).catch(() => { });
|
|
24
24
|
}
|
|
25
|
+
let _wanderActive = false;
|
|
26
|
+
export async function ensureInitialCursorPosition(session) {
|
|
27
|
+
if (currentX >= 0 && currentY >= 0) {
|
|
28
|
+
return { x: currentX, y: currentY };
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const layout = await session.Page.getLayoutMetrics().catch(() => null);
|
|
32
|
+
if (layout?.visualViewport?.clientWidth && layout?.visualViewport?.clientHeight) {
|
|
33
|
+
currentX = Math.round(layout.visualViewport.clientWidth / 2);
|
|
34
|
+
currentY = Math.round(layout.visualViewport.clientHeight / 2);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const evalRes = await session.Runtime.evaluate({
|
|
38
|
+
expression: `({ x: Math.round(window.innerWidth / 2), y: Math.round(window.innerHeight / 2) })`,
|
|
39
|
+
returnByValue: true
|
|
40
|
+
}).catch(() => null);
|
|
41
|
+
if (evalRes?.result?.value?.x && evalRes?.result?.value?.y) {
|
|
42
|
+
currentX = evalRes.result.value.x;
|
|
43
|
+
currentY = evalRes.result.value.y;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
currentX = 640;
|
|
47
|
+
currentY = 400;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
currentX = 640;
|
|
53
|
+
currentY = 400;
|
|
54
|
+
}
|
|
55
|
+
wtCursor(session, currentX, currentY, "idle");
|
|
56
|
+
return { x: currentX, y: currentY };
|
|
57
|
+
}
|
|
25
58
|
async function wtThought(session, text) {
|
|
26
59
|
await sendToExtension(session, { type: 'Weavetab_STATE', hud: { action: text } }).catch(() => { });
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
60
|
+
if (currentX < 0 || currentY < 0) {
|
|
61
|
+
await ensureInitialCursorPosition(session);
|
|
62
|
+
}
|
|
63
|
+
// Add realistic wandering movement connected to thoughts (non-racing)
|
|
64
|
+
if (currentX > 0 && currentY > 0 && !_wanderActive && Math.random() > 0.3) {
|
|
65
|
+
_wanderActive = true;
|
|
66
|
+
const startX = currentX;
|
|
67
|
+
const startY = currentY;
|
|
68
|
+
const wanderDistance = 10 + Math.random() * 25;
|
|
30
69
|
const angle = Math.random() * Math.PI * 2;
|
|
31
|
-
const tx = Math.max(
|
|
32
|
-
const ty = Math.max(
|
|
33
|
-
const steps =
|
|
70
|
+
const tx = Math.max(20, startX + Math.cos(angle) * wanderDistance);
|
|
71
|
+
const ty = Math.max(20, startY + Math.sin(angle) * wanderDistance);
|
|
72
|
+
const steps = 12;
|
|
34
73
|
const waypoints = [];
|
|
35
|
-
const cp1X =
|
|
36
|
-
const cp1Y =
|
|
37
|
-
const cp2X =
|
|
38
|
-
const cp2Y =
|
|
74
|
+
const cp1X = startX + (tx - startX) * 0.3;
|
|
75
|
+
const cp1Y = startY + (ty - startY) * 0.3;
|
|
76
|
+
const cp2X = startX + (tx - startX) * 0.7;
|
|
77
|
+
const cp2Y = startY + (ty - startY) * 0.7;
|
|
39
78
|
for (let i = 1; i <= steps; i++) {
|
|
40
79
|
let t = i / steps;
|
|
41
80
|
t = 1 - Math.pow(1 - t, 3);
|
|
42
81
|
waypoints.push({
|
|
43
|
-
x: cubicBezier(t,
|
|
44
|
-
y: cubicBezier(t,
|
|
82
|
+
x: Math.round(cubicBezier(t, startX, cp1X, cp2X, tx)),
|
|
83
|
+
y: Math.round(cubicBezier(t, startY, cp1Y, cp2Y, ty))
|
|
45
84
|
});
|
|
46
85
|
}
|
|
47
86
|
sendToExtension(session, {
|
|
48
87
|
type: 'Weavetab_STATE',
|
|
49
|
-
cursor: { waypoints, duration_ms: steps *
|
|
88
|
+
cursor: { waypoints, duration_ms: steps * 25, x: startX, y: startY },
|
|
50
89
|
state: "thinking"
|
|
51
90
|
}).catch(() => { });
|
|
52
|
-
// Async physical dispatch to not block the main logic flow
|
|
53
91
|
(async () => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
92
|
+
try {
|
|
93
|
+
for (let i = 1; i <= steps; i++) {
|
|
94
|
+
if (!_wanderActive)
|
|
95
|
+
break;
|
|
96
|
+
const x = waypoints[i - 1].x;
|
|
97
|
+
const y = waypoints[i - 1].y;
|
|
98
|
+
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x, y, button: "none" }).catch(() => { });
|
|
99
|
+
currentX = x;
|
|
100
|
+
currentY = y;
|
|
101
|
+
await new Promise(r => setTimeout(r, 25));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
_wanderActive = false;
|
|
61
106
|
}
|
|
62
107
|
})();
|
|
63
108
|
}
|
|
@@ -139,6 +184,9 @@ targetSelector, profileName) {
|
|
|
139
184
|
let wordsSinceBreak = 0;
|
|
140
185
|
let wordCharCount = 0;
|
|
141
186
|
let prevChar = '';
|
|
187
|
+
if (currentX < 0 || currentY < 0) {
|
|
188
|
+
await ensureInitialCursorPosition(session);
|
|
189
|
+
}
|
|
142
190
|
wtCursor(session, currentX, currentY, "typing");
|
|
143
191
|
let currentGroupSize = Math.floor(Math.random() * (p.groupSize[1] - p.groupSize[0] + 1)) + p.groupSize[0];
|
|
144
192
|
let charsTypedInGroup = 0;
|
|
@@ -271,6 +319,10 @@ function cubicBezier(t, p0, p1, p2, p3) {
|
|
|
271
319
|
}
|
|
272
320
|
let _firstMoveDone = false;
|
|
273
321
|
export async function ghostMove(session, targetX, targetY, config, label, profile, cursorOpts) {
|
|
322
|
+
_wanderActive = false; // Stop any ongoing thought wander immediately
|
|
323
|
+
if (currentX < 0 || currentY < 0) {
|
|
324
|
+
await ensureInitialCursorPosition(session);
|
|
325
|
+
}
|
|
274
326
|
const resolvedProfile = profile || (getConfigHeadless(config) ? "instant" : "human");
|
|
275
327
|
if (resolvedProfile === "instant") {
|
|
276
328
|
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x: targetX, y: targetY, button: "none" });
|
|
@@ -290,9 +342,9 @@ export async function ghostMove(session, targetX, targetY, config, label, profil
|
|
|
290
342
|
return;
|
|
291
343
|
}
|
|
292
344
|
if (resolvedProfile === "fast") {
|
|
293
|
-
const steps =
|
|
294
|
-
const startX = currentX
|
|
295
|
-
const startY = currentY
|
|
345
|
+
const steps = 6;
|
|
346
|
+
const startX = currentX;
|
|
347
|
+
const startY = currentY;
|
|
296
348
|
for (let i = 1; i <= steps; i++) {
|
|
297
349
|
const t = i / steps;
|
|
298
350
|
const x = Math.round(startX + (targetX - startX) * t);
|
|
@@ -301,7 +353,7 @@ export async function ghostMove(session, targetX, targetY, config, label, profil
|
|
|
301
353
|
currentX = x;
|
|
302
354
|
currentY = y;
|
|
303
355
|
wtCursor(session, x, y, "moving", cursorOpts);
|
|
304
|
-
await sleep(
|
|
356
|
+
await sleep(6);
|
|
305
357
|
}
|
|
306
358
|
currentX = targetX;
|
|
307
359
|
currentY = targetY;
|
|
@@ -311,93 +363,61 @@ export async function ghostMove(session, targetX, targetY, config, label, profil
|
|
|
311
363
|
return;
|
|
312
364
|
}
|
|
313
365
|
if (!_firstMoveDone) {
|
|
314
|
-
logDebug(`[Weavetab Ghost] First mouse move → (${targetX}, ${targetY}) — CDP session active`);
|
|
366
|
+
logDebug(`[Weavetab Ghost] First mouse move from (${currentX}, ${currentY}) → (${targetX}, ${targetY}) — CDP session active`);
|
|
315
367
|
_firstMoveDone = true;
|
|
316
368
|
}
|
|
317
|
-
// Don't fake-init cursor position — injector.ts hides cursor until first real move
|
|
318
|
-
if (currentX === -1 && currentY === -1) {
|
|
319
|
-
currentX = targetX;
|
|
320
|
-
currentY = targetY;
|
|
321
|
-
wtCursor(session, targetX, targetY, "hover", cursorOpts);
|
|
322
|
-
recordCursorPosition(targetX, targetY);
|
|
323
|
-
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x: targetX, y: targetY, button: "none" });
|
|
324
|
-
await session.Runtime.evaluate({
|
|
325
|
-
expression: `(function(){
|
|
326
|
-
var el = document.elementFromPoint(${targetX}, ${targetY});
|
|
327
|
-
if (el) {
|
|
328
|
-
el.dispatchEvent(new MouseEvent('mouseover', {bubbles:true,cancelable:true,clientX:${targetX},clientY:${targetY}}));
|
|
329
|
-
el.dispatchEvent(new MouseEvent('mouseenter', {bubbles:false,cancelable:true,clientX:${targetX},clientY:${targetY}}));
|
|
330
|
-
}
|
|
331
|
-
})()`
|
|
332
|
-
}).catch(() => { });
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
369
|
const dx = targetX - currentX;
|
|
336
370
|
const dy = targetY - currentY;
|
|
337
371
|
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
338
|
-
|
|
339
|
-
if (label && distance >= 150 && getConfigVisuals(config) !== false) {
|
|
340
|
-
wtThought(session, `moving to ${label.slice(0, 40)}...`);
|
|
341
|
-
await sleep(80 + Math.random() * 120);
|
|
342
|
-
}
|
|
343
|
-
if (distance < 150) {
|
|
372
|
+
if (distance < 4) {
|
|
344
373
|
currentX = targetX;
|
|
345
374
|
currentY = targetY;
|
|
346
375
|
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x: targetX, y: targetY, button: "none" });
|
|
347
376
|
wtCursor(session, targetX, targetY, "hover", cursorOpts);
|
|
348
377
|
recordCursorPosition(targetX, targetY);
|
|
349
|
-
await session.Runtime.evaluate({
|
|
350
|
-
expression: `(function(){
|
|
351
|
-
var el = document.elementFromPoint(${targetX}, ${targetY});
|
|
352
|
-
if (el) {
|
|
353
|
-
el.dispatchEvent(new MouseEvent('mouseover', {bubbles:true,cancelable:true,clientX:${targetX},clientY:${targetY}}));
|
|
354
|
-
el.dispatchEvent(new MouseEvent('mouseenter', {bubbles:false,cancelable:true,clientX:${targetX},clientY:${targetY}}));
|
|
355
|
-
}
|
|
356
|
-
})()`
|
|
357
|
-
}).catch(() => { });
|
|
358
378
|
return;
|
|
359
379
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
const
|
|
367
|
-
const
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
const
|
|
371
|
-
const
|
|
372
|
-
const
|
|
373
|
-
const
|
|
374
|
-
const
|
|
375
|
-
|
|
380
|
+
wtCursor(session, currentX, currentY, label && distance >= 150 ? "searching" : "idle", cursorOpts);
|
|
381
|
+
if (label && distance >= 150) {
|
|
382
|
+
wtThought(session, `moving to ${label.slice(0, 40)}...`);
|
|
383
|
+
await sleep(60 + Math.random() * 80);
|
|
384
|
+
}
|
|
385
|
+
// Smooth, natural human hand curve
|
|
386
|
+
const duration = Math.max(120, Math.min(380, 80 + Math.sqrt(distance) * 12));
|
|
387
|
+
const steps = Math.max(8, Math.min(24, Math.floor(duration / 16)));
|
|
388
|
+
const stepDelay = Math.max(10, Math.floor(duration / steps));
|
|
389
|
+
// Gentle perpendicular curvature (arcing motion)
|
|
390
|
+
const nx = -dy / distance;
|
|
391
|
+
const ny = dx / distance;
|
|
392
|
+
const maxArc = Math.min(45, distance * 0.15);
|
|
393
|
+
const arcSign = (Math.random() > 0.5 ? 1 : -1);
|
|
394
|
+
const arcAmount = maxArc * arcSign * (0.4 + Math.random() * 0.6);
|
|
395
|
+
const cp1X = currentX + dx * 0.3 + nx * arcAmount;
|
|
396
|
+
const cp1Y = currentY + dy * 0.3 + ny * arcAmount;
|
|
397
|
+
const cp2X = currentX + dx * 0.7 + nx * (arcAmount * 0.6);
|
|
398
|
+
const cp2Y = currentY + dy * 0.7 + ny * (arcAmount * 0.6);
|
|
376
399
|
const waypoints = [];
|
|
377
400
|
for (let i = 1; i <= steps; i++) {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const
|
|
381
|
-
const actualTargetY = doOvershoot && i < steps * 0.8 ? overshootY : targetY;
|
|
401
|
+
const rawT = i / steps;
|
|
402
|
+
// Cubic ease-out for natural deceleration
|
|
403
|
+
const t = 1 - Math.pow(1 - rawT, 3);
|
|
382
404
|
waypoints.push({
|
|
383
|
-
x: cubicBezier(t, currentX, cp1X, cp2X,
|
|
384
|
-
y: cubicBezier(t, currentY, cp1Y, cp2Y,
|
|
405
|
+
x: Math.round(cubicBezier(t, currentX, cp1X, cp2X, targetX)),
|
|
406
|
+
y: Math.round(cubicBezier(t, currentY, cp1Y, cp2Y, targetY))
|
|
385
407
|
});
|
|
386
408
|
}
|
|
387
|
-
// Pre-announce
|
|
409
|
+
// Pre-announce waypoints for smooth client-side interpolation
|
|
388
410
|
sendToExtension(session, {
|
|
389
411
|
type: 'Weavetab_STATE',
|
|
390
|
-
cursor: { waypoints, duration_ms: steps *
|
|
412
|
+
cursor: { waypoints, duration_ms: steps * stepDelay, x: currentX, y: currentY },
|
|
391
413
|
state: "moving"
|
|
392
414
|
}).catch(() => { });
|
|
393
415
|
for (let i = 1; i <= steps; i++) {
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
wtCursor(session, x, y, "moving", cursorOpts);
|
|
400
|
-
await sleep(8);
|
|
416
|
+
const pt = waypoints[i - 1];
|
|
417
|
+
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x: pt.x, y: pt.y, button: "none" }).catch(() => { });
|
|
418
|
+
currentX = pt.x;
|
|
419
|
+
currentY = pt.y;
|
|
420
|
+
await sleep(stepDelay);
|
|
401
421
|
}
|
|
402
422
|
currentX = targetX;
|
|
403
423
|
currentY = targetY;
|
|
@@ -405,7 +425,7 @@ export async function ghostMove(session, targetX, targetY, config, label, profil
|
|
|
405
425
|
recordCursorPosition(targetX, targetY);
|
|
406
426
|
if (label)
|
|
407
427
|
wtClearThought(session);
|
|
408
|
-
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x: targetX, y: targetY, button: "none" });
|
|
428
|
+
await session.Input.dispatchMouseEvent({ type: "mouseMoved", x: targetX, y: targetY, button: "none" }).catch(() => { });
|
|
409
429
|
await session.Runtime.evaluate({
|
|
410
430
|
expression: `(function(){
|
|
411
431
|
var el = document.elementFromPoint(${targetX}, ${targetY});
|
|
@@ -501,8 +521,12 @@ export async function ghostClick(session, x, y, options) {
|
|
|
501
521
|
}).catch(() => { });
|
|
502
522
|
}
|
|
503
523
|
export function ghostWait(session) {
|
|
504
|
-
|
|
524
|
+
const x = currentX >= 0 ? currentX : 640;
|
|
525
|
+
const y = currentY >= 0 ? currentY : 400;
|
|
526
|
+
wtCursor(session, x, y, "waiting");
|
|
505
527
|
}
|
|
506
528
|
export function ghostIdle(session) {
|
|
507
|
-
|
|
529
|
+
const x = currentX >= 0 ? currentX : 640;
|
|
530
|
+
const y = currentY >= 0 ? currentY : 400;
|
|
531
|
+
wtCursor(session, x, y, "idle");
|
|
508
532
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* src/overlay/injector.ts
|
|
3
3
|
* Weavetab — Browser Presence Layer v3 (stripped)
|
|
4
4
|
*
|
|
5
|
-
* Kept:
|
|
5
|
+
* Kept: SPA nav detection,
|
|
6
6
|
* __wt_setConfig, __wt_status, favicon state.
|
|
7
7
|
* Removed: cursor (moved to content.js), chat panel, thought bubble,
|
|
8
8
|
* ask modal, screen glow, CSS keyframes, emoji system.
|
package/dist/overlay/injector.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logDebug } from "../audit/logger.js";
|
|
2
|
-
import {
|
|
2
|
+
import { getConfigDevMode } from "../config/loader.js";
|
|
3
3
|
// ─── Minimal Overlay Script ───────────────────────────────────────────────────
|
|
4
4
|
export function getMinimalOverlayScript() {
|
|
5
5
|
return `(function(){
|
|
@@ -52,23 +52,11 @@ export function getMinimalOverlayScript() {
|
|
|
52
52
|
document.addEventListener('NavigationEnd', function() { em('angular', location.href); });
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
// ── Mission plan dashboard ──────────────────────────────────────────────
|
|
56
|
-
window.__wt_plan_comments = window.__wt_plan_comments || [];
|
|
57
|
-
window.__wt_plan = function(action, goal, tasks) {
|
|
58
|
-
window.postMessage({ type: '__WT_PLAN', action: action, goal: goal, tasks: tasks }, '*');
|
|
59
|
-
};
|
|
60
|
-
|
|
61
55
|
// The message listeners below are guarded so they are registered exactly once
|
|
62
56
|
// per page, even when __wt_install_minimal() is called repeatedly (e.g. SPAs
|
|
63
57
|
// with frequent navigations).
|
|
64
58
|
if (!window.__wt_msg_installed) {
|
|
65
59
|
window.__wt_msg_installed = true;
|
|
66
|
-
window.addEventListener("message", function(e) {
|
|
67
|
-
if (e.data && e.data.type === "__WT_PLAN_COMMENT") {
|
|
68
|
-
window.__wt_plan_comments.push({ taskId: Number(e.data.taskId), comment: e.data.comment, time: Date.now() });
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
|
|
72
60
|
window.__wt_chat_queue = window.__wt_chat_queue || [];
|
|
73
61
|
window.addEventListener("message", function(e) {
|
|
74
62
|
if (e.data && e.data.type === "__WT_FEEDBACK") {
|
|
@@ -79,7 +67,6 @@ export function getMinimalOverlayScript() {
|
|
|
79
67
|
|
|
80
68
|
window.__wt_setConfig = function(c) {
|
|
81
69
|
if (c && c.devMode) window.__wt_devMode = true;
|
|
82
|
-
if (c && c.visuals !== undefined) window.__wt_showVisuals = !!c.visuals;
|
|
83
70
|
};
|
|
84
71
|
|
|
85
72
|
window.__wt_status = function() { return JSON.stringify({ rootInjected: true }); };
|
|
@@ -133,7 +120,6 @@ function buildConfigExpr(config) {
|
|
|
133
120
|
return `
|
|
134
121
|
if(window.__wt_setConfig)window.__wt_setConfig(${JSON.stringify({
|
|
135
122
|
...config,
|
|
136
|
-
visuals: getConfigVisuals(config) !== false,
|
|
137
123
|
})});
|
|
138
124
|
window.postMessage({type:'Weavetab-msg-in',data:${JSON.stringify(msg)}},'*');
|
|
139
125
|
`;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type CDP from "chrome-remote-interface";
|
|
2
|
+
import type { WeavetabPermissions } from "./interface.js";
|
|
3
|
+
export interface IPluginExtensionBridge {
|
|
4
|
+
send(session: CDP.Client, message: object): Promise<boolean>;
|
|
5
|
+
setHudState(session: CDP.Client, state: {
|
|
6
|
+
action?: string;
|
|
7
|
+
badge?: string;
|
|
8
|
+
badgeColor?: string;
|
|
9
|
+
groupState?: string;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
showThought(session: CDP.Client, text: string, options?: {
|
|
12
|
+
durationMs?: number;
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
clearThought(session: CDP.Client): Promise<void>;
|
|
15
|
+
injectStyles(session: CDP.Client, css: string): Promise<void>;
|
|
16
|
+
injectScript<T = any>(session: CDP.Client, js: string): Promise<T>;
|
|
17
|
+
hideOverlay(session: CDP.Client): Promise<void>;
|
|
18
|
+
restoreOverlay(session: CDP.Client): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare class PluginExtensionBridge implements IPluginExtensionBridge {
|
|
21
|
+
readonly pluginName: string;
|
|
22
|
+
private readonly permissions?;
|
|
23
|
+
constructor(pluginName: string, permissions?: WeavetabPermissions | undefined);
|
|
24
|
+
private checkPermission;
|
|
25
|
+
send(session: CDP.Client, message: object): Promise<boolean>;
|
|
26
|
+
setHudState(session: CDP.Client, state: {
|
|
27
|
+
action?: string;
|
|
28
|
+
badge?: string;
|
|
29
|
+
badgeColor?: string;
|
|
30
|
+
groupState?: string;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
showThought(session: CDP.Client, text: string, options?: {
|
|
33
|
+
durationMs?: number;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
clearThought(session: CDP.Client): Promise<void>;
|
|
36
|
+
injectStyles(session: CDP.Client, css: string): Promise<void>;
|
|
37
|
+
injectScript<T = any>(session: CDP.Client, js: string): Promise<T>;
|
|
38
|
+
hideOverlay(session: CDP.Client): Promise<void>;
|
|
39
|
+
restoreOverlay(session: CDP.Client): Promise<void>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { sendToExtension, hideWeaveTabOverlay, restoreWeaveTabOverlay } from "../cdp/helpers.js";
|
|
2
|
+
import { logDebug } from "../audit/logger.js";
|
|
3
|
+
export class PluginExtensionBridge {
|
|
4
|
+
pluginName;
|
|
5
|
+
permissions;
|
|
6
|
+
constructor(pluginName, permissions) {
|
|
7
|
+
this.pluginName = pluginName;
|
|
8
|
+
this.permissions = permissions;
|
|
9
|
+
}
|
|
10
|
+
checkPermission(category) {
|
|
11
|
+
if (!this.permissions || !this.permissions.extension)
|
|
12
|
+
return true; // Default permissive if not restricted
|
|
13
|
+
return this.permissions.extension[category] !== false;
|
|
14
|
+
}
|
|
15
|
+
async send(session, message) {
|
|
16
|
+
if (!session)
|
|
17
|
+
return false;
|
|
18
|
+
return await sendToExtension(session, {
|
|
19
|
+
...message,
|
|
20
|
+
plugin: this.pluginName,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
async setHudState(session, state) {
|
|
24
|
+
if (!this.checkPermission("hud")) {
|
|
25
|
+
logDebug(`[Weavetab PluginExtension] Plugin "${this.pluginName}" lacks permissions.extension.hud`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await this.send(session, {
|
|
29
|
+
type: "wt-hud-update",
|
|
30
|
+
action: state.action,
|
|
31
|
+
badge: state.badge,
|
|
32
|
+
badgeColor: state.badgeColor,
|
|
33
|
+
groupState: state.groupState,
|
|
34
|
+
timestamp: Date.now(),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async showThought(session, text, options) {
|
|
38
|
+
if (!this.checkPermission("hud"))
|
|
39
|
+
return;
|
|
40
|
+
if (!session || !session.Runtime)
|
|
41
|
+
return;
|
|
42
|
+
const duration = options?.durationMs || 4000;
|
|
43
|
+
const safeText = JSON.stringify(text);
|
|
44
|
+
try {
|
|
45
|
+
await session.Runtime.evaluate({
|
|
46
|
+
expression: `(function() {
|
|
47
|
+
var existing = document.getElementById('__wt_plugin_thought_${this.pluginName}');
|
|
48
|
+
if (existing) existing.remove();
|
|
49
|
+
|
|
50
|
+
var bubble = document.createElement('div');
|
|
51
|
+
bubble.id = '__wt_plugin_thought_${this.pluginName}';
|
|
52
|
+
bubble.className = 'wt-bubble';
|
|
53
|
+
bubble.setAttribute('data-wt-internal', 'true');
|
|
54
|
+
bubble.style.cssText = [
|
|
55
|
+
'position: fixed',
|
|
56
|
+
'bottom: 24px',
|
|
57
|
+
'right: 24px',
|
|
58
|
+
'background: linear-gradient(135deg, rgba(17, 24, 39, 0.95), rgba(30, 41, 59, 0.95))',
|
|
59
|
+
'color: #f8fafc',
|
|
60
|
+
'padding: 12px 18px',
|
|
61
|
+
'border-radius: 12px',
|
|
62
|
+
'font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
63
|
+
'font-size: 13px',
|
|
64
|
+
'font-weight: 500',
|
|
65
|
+
'box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.1)',
|
|
66
|
+
'z-index: 2147483647',
|
|
67
|
+
'backdrop-filter: blur(8px)',
|
|
68
|
+
'pointer-events: none',
|
|
69
|
+
'animation: wtThoughtFade 0.25s cubic-bezier(0.16, 1, 0.3, 1)',
|
|
70
|
+
'display: flex',
|
|
71
|
+
'align-items: center',
|
|
72
|
+
'gap: 8px'
|
|
73
|
+
].join(';');
|
|
74
|
+
|
|
75
|
+
var icon = document.createElement('span');
|
|
76
|
+
icon.textContent = '✨';
|
|
77
|
+
var textSpan = document.createElement('span');
|
|
78
|
+
textSpan.textContent = ${safeText};
|
|
79
|
+
|
|
80
|
+
bubble.appendChild(icon);
|
|
81
|
+
bubble.appendChild(textSpan);
|
|
82
|
+
document.body.appendChild(bubble);
|
|
83
|
+
|
|
84
|
+
setTimeout(function() {
|
|
85
|
+
if (bubble && bubble.parentNode) {
|
|
86
|
+
bubble.style.opacity = '0';
|
|
87
|
+
bubble.style.transition = 'opacity 0.3s ease';
|
|
88
|
+
setTimeout(function() { bubble.remove(); }, 300);
|
|
89
|
+
}
|
|
90
|
+
}, ${duration});
|
|
91
|
+
})()`,
|
|
92
|
+
returnByValue: false,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
logDebug(`[Weavetab PluginExtension] Failed to show thought:`, e);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async clearThought(session) {
|
|
100
|
+
if (!session || !session.Runtime)
|
|
101
|
+
return;
|
|
102
|
+
try {
|
|
103
|
+
await session.Runtime.evaluate({
|
|
104
|
+
expression: `(function() {
|
|
105
|
+
var existing = document.getElementById('__wt_plugin_thought_${this.pluginName}');
|
|
106
|
+
if (existing) existing.remove();
|
|
107
|
+
})()`,
|
|
108
|
+
returnByValue: false,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch { /* ignore */ }
|
|
112
|
+
}
|
|
113
|
+
async injectStyles(session, css) {
|
|
114
|
+
if (!this.checkPermission("styles")) {
|
|
115
|
+
throw new Error(`Permission Denied: Plugin "${this.pluginName}" does not have permissions.extension.styles`);
|
|
116
|
+
}
|
|
117
|
+
if (!session || !session.Runtime)
|
|
118
|
+
return;
|
|
119
|
+
const safeCss = JSON.stringify(css);
|
|
120
|
+
await session.Runtime.evaluate({
|
|
121
|
+
expression: `(function() {
|
|
122
|
+
var styleId = '__wt_plugin_styles_${this.pluginName}';
|
|
123
|
+
var style = document.getElementById(styleId) || document.createElement('style');
|
|
124
|
+
style.id = styleId;
|
|
125
|
+
style.textContent = ${safeCss};
|
|
126
|
+
if (!style.parentNode) document.head.appendChild(style);
|
|
127
|
+
})()`,
|
|
128
|
+
returnByValue: false,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async injectScript(session, js) {
|
|
132
|
+
if (!this.checkPermission("scripts")) {
|
|
133
|
+
throw new Error(`Permission Denied: Plugin "${this.pluginName}" does not have permissions.extension.scripts`);
|
|
134
|
+
}
|
|
135
|
+
if (!session || !session.Runtime)
|
|
136
|
+
throw new Error("No active CDP session available");
|
|
137
|
+
const res = await session.Runtime.evaluate({
|
|
138
|
+
expression: js,
|
|
139
|
+
returnByValue: true,
|
|
140
|
+
awaitPromise: true,
|
|
141
|
+
});
|
|
142
|
+
return res.result?.value ?? res;
|
|
143
|
+
}
|
|
144
|
+
async hideOverlay(session) {
|
|
145
|
+
if (!this.checkPermission("overlay"))
|
|
146
|
+
return;
|
|
147
|
+
if (!session)
|
|
148
|
+
return;
|
|
149
|
+
await hideWeaveTabOverlay(session);
|
|
150
|
+
}
|
|
151
|
+
async restoreOverlay(session) {
|
|
152
|
+
if (!this.checkPermission("overlay"))
|
|
153
|
+
return;
|
|
154
|
+
if (!session)
|
|
155
|
+
return;
|
|
156
|
+
await restoreWeaveTabOverlay(session);
|
|
157
|
+
}
|
|
158
|
+
}
|