alanbox 0.1.2 → 0.1.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/0boxer/AGENTS.md +26 -0
- package/0boxer/src/AGENTS.md +16 -0
- package/0boxer/src/cli.js +53 -0
- package/0boxer/src/commands/AGENTS.md +16 -0
- package/{0commondflowv1 → 0boxer}/src/commands/install.js +56 -0
- package/{0commondflowv1 → 1swarmer}/AGENTS.md +14 -12
- package/1swarmer/src/AGENTS.md +28 -0
- package/{0commondflowv1 → 1swarmer}/src/args.js +8 -1
- package/{0commondflowv1 → 1swarmer}/src/cli.js +27 -17
- package/1swarmer/src/commands/AGENTS.md +31 -0
- package/{0commondflowv1 → 1swarmer}/src/commands/doctor.js +2 -2
- package/1swarmer/src/commands/review-file.js +997 -0
- package/{0commondflowv1 → 1swarmer}/src/core/AGENTS.md +2 -2
- package/{0commondflowv1 → 1swarmer}/src/core/prompt-templates.js +1 -1
- package/{0commondflowv1 → 1swarmer}/src/core/storage.js +1 -1
- package/{0commondflowv1 → 1swarmer}/src/prompt/AGENTS.md +1 -1
- package/{0commondflowv1 → 1swarmer}/src/prompt/default.md +1 -1
- package/{0commondflowv1 → 1swarmer}/src/prompt/synthesizer.md +1 -1
- package/{0commondflowv1 → 1swarmer}/src/prompt/verifier.md +1 -1
- package/{0commondflowv1 → 1swarmer}/src/runner/AGENTS.md +4 -3
- package/{0commondflowv1 → 1swarmer}/src/runner/codex-runner.js +23 -3
- package/2designer/README.md +42 -0
- package/2designer/dist/cdp-engine-4AIWSWXO.js +314 -0
- package/2designer/dist/cdp-engine-4AIWSWXO.js.map +1 -0
- package/2designer/dist/cdp-engine-SG4K2BCX.js +10 -0
- package/2designer/dist/cdp-engine-SG4K2BCX.js.map +1 -0
- package/2designer/dist/chunk-7X7PTLZH.js +185 -0
- package/2designer/dist/chunk-7X7PTLZH.js.map +1 -0
- package/2designer/dist/chunk-DPOWNFOH.js +313 -0
- package/2designer/dist/chunk-DPOWNFOH.js.map +1 -0
- package/2designer/dist/chunk-ISUUIOO7.js +58 -0
- package/2designer/dist/chunk-ISUUIOO7.js.map +1 -0
- package/2designer/dist/chunk-NLYFLQ3C.js +74 -0
- package/2designer/dist/chunk-NLYFLQ3C.js.map +1 -0
- package/2designer/dist/chunk-UVKSRKXR.js +71 -0
- package/2designer/dist/chunk-UVKSRKXR.js.map +1 -0
- package/2designer/dist/cli.js +748 -0
- package/2designer/dist/cli.js.map +1 -0
- package/2designer/dist/index.d.ts +118 -0
- package/2designer/dist/index.js +37 -0
- package/2designer/dist/index.js.map +1 -0
- package/2designer/dist/playwright-engine-YXBY3KEN.js +186 -0
- package/2designer/dist/playwright-engine-YXBY3KEN.js.map +1 -0
- package/2designer/dist/playwright-engine-YXGDTSZ5.js +8 -0
- package/2designer/dist/playwright-engine-YXGDTSZ5.js.map +1 -0
- package/2designer/dist/tint-UD4CJ7S2.js +7 -0
- package/2designer/dist/tint-UD4CJ7S2.js.map +1 -0
- package/2designer/dist/tint-YN63MLVN.js +60 -0
- package/2designer/dist/tint-YN63MLVN.js.map +1 -0
- package/2designer/package.json +56 -0
- package/4reporter/README.md +24 -0
- package/4reporter/dist/cli.js +464 -0
- package/4reporter/dist/cli.js.map +1 -0
- package/4reporter/dist/index.d.ts +108 -0
- package/4reporter/dist/index.js +445 -0
- package/4reporter/dist/index.js.map +1 -0
- package/4reporter/package.json +39 -0
- package/README.md +20 -9
- package/bin/alanbox.js +11 -0
- package/bin/designer.js +10 -0
- package/bin/reporter.js +11 -0
- package/bin/swarmer.js +11 -0
- package/cli.js +178 -0
- package/hooks/hooks.json +1 -1
- package/mcp/README.md +7 -1
- package/mcp/config.toml +4 -0
- package/package.json +28 -11
- package/plugin/AGENTS.md +2 -2
- package/plugin/plugin.json +7 -7
- package/shared/AGENTS.md +15 -0
- package/shared/package-args.js +68 -0
- package/skills/AGENTS.md +9 -5
- package/skills/aitool/SKILL.md +36 -0
- package/skills/desginer/SKILL.md +142 -0
- package/skills/swarmer/SKILL.md +146 -0
- package/0commondflowv1/src/AGENTS.md +0 -26
- package/0commondflowv1/src/commands/AGENTS.md +0 -29
- package/bin/multirunagent.js +0 -15
- package/skills/aibox-swam/SKILL.md +0 -77
- package/skills/sub-codex-doctor/SKILL.md +0 -27
- package/skills/sub-codex-swarm/SKILL.md +0 -56
- /package/{0commondflowv1 → 1swarmer}/res/three-lens-review.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/commands/info.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/auto.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/custom.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/index.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/core/handoff.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/core/prompt-builder.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/core/swarm-executor.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/core/workers.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/core/workflow-planner.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/core/workflow-storage.js +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/prompt/reviewer.md +0 -0
- /package/{0commondflowv1 → 1swarmer}/src/runner/config.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## core
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`1swarmer/src/core` 存放 worker 编排协议、handoff 协议、prompt 构造和本地结果存储辅助函数,是 `swarm` 使用的核心逻辑。
|
|
4
4
|
|
|
5
5
|
**Important:** 这里的输出格式、prompt 协议和路径会被命令、skills、README 和用户历史 run 依赖。改协议或存储结构前,要考虑旧结果读取兼容,并同步更新说明文档。
|
|
6
6
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
- `swarm-executor.js` — 普通 swarm 和 auto workflow 共用的 task graph 执行器;负责 runner 调用、结果写入和 handoff 汇总,`swarm --parallel-workers` 也走这里。
|
|
11
11
|
- `workflow-planner.js` — 本地最小 GOAP planner;把自然语言目标、`-a` agent spec 和 `-p` plan hint 转成 phases/actions/dependencies。
|
|
12
12
|
- `workflow-storage.js` — auto workflow 的 AgentDB-lite 文件存储;写入 run/plan/state/steps JSON,不替代旧 swarm results/memory。
|
|
13
|
-
- `prompt-templates.js` — 从 `
|
|
13
|
+
- `prompt-templates.js` — 从 `1swarmer/src/prompt/<role>.md` 读取 auto workflow role 模板并安全 fallback。
|
|
14
14
|
- `handoff.js` — 构造 prior results context,并解析 / 生成 `HANDOFF_JSON`。
|
|
15
15
|
- `prompt-builder.js` — 构造 role、worker、platform、namespace、context、skill 和 task 的最终 prompt。
|
|
16
16
|
- `storage.js` — 写入 worker markdown 输出和 memory JSON;默认根目录是 `%USERPROFILE%\.multirunagent`。
|
|
@@ -73,7 +73,7 @@ function updateMemoryIndex(memoryDir, entry) {
|
|
|
73
73
|
function getUserStateRoot() {
|
|
74
74
|
const homeDir = process.env.USERPROFILE || process.env.HOME;
|
|
75
75
|
if (!homeDir) {
|
|
76
|
-
throw new Error('cannot resolve user home directory for
|
|
76
|
+
throw new Error('cannot resolve user home directory for alanbox state');
|
|
77
77
|
}
|
|
78
78
|
return path.join(homeDir, '.multirunagent');
|
|
79
79
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## runner
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`1swarmer/src/runner` 负责读取 provider 配置、解析 CLI 命令参数,并通过子进程启动 Codex 或 Claude。这里决定是否使用原生 CLI home,或在显式配置时启用隔离 home。
|
|
4
4
|
|
|
5
5
|
**Important:** 默认必须使用原生 Codex / Claude CLI 登录态,不设置 `CODEX_HOME` 或 `CLAUDE_CONFIG_DIR`。只有显式配置 `accountsDir`、worker account 或 home 时才启用隔离。
|
|
6
6
|
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
- 不要把个人 Antigravity cockpit 路径、全局 npm 安装路径或本机私有 home 写成通用默认配置。
|
|
17
17
|
- `info` 输出可以展示 `<native>`、`<not inherited>`、command、commandArgs 这类排查信息,但不要打印 secret。
|
|
18
18
|
- Windows `.cmd`、`.bat`、`.ps1`、PowerShell 路径和 Node `spawn` 参数需要实际考虑;provider 裸命令应通过 PATH/PATHEXT 解析后再启动,不要把用户本机 npm shim 绝对路径写进默认配置。
|
|
19
|
+
- Windows 超时清理必须结束完整 provider 进程树;`codex.CMD` 可能继续派生 `node` 和 `codex.exe`,只杀父进程会导致 review-file 或 swarm 卡住。
|
|
19
20
|
|
|
20
21
|
### Verification
|
|
21
22
|
|
|
22
|
-
- 从包根目录运行:`node bin/
|
|
23
|
-
- 检查默认 provider:`node bin/
|
|
23
|
+
- 从包根目录运行:`node bin/alanbox.js doctor` 或 `node bin/swarmer.js doctor`
|
|
24
|
+
- 检查默认 provider:`node bin/swarmer.js info`
|
|
24
25
|
- 注意:`--dry-run` 已移除,检查子 worker 命令构造请用 `info`(已无 swarm dry-run 预览)。
|
|
@@ -213,6 +213,9 @@ function summarizePromptTransport(invocation) {
|
|
|
213
213
|
|
|
214
214
|
function buildClaudePrintArgs(config, options) {
|
|
215
215
|
const args = ['-p'];
|
|
216
|
+
if (Array.isArray(options.claudeArgs) && options.claudeArgs.length > 0) {
|
|
217
|
+
args.push(...options.claudeArgs);
|
|
218
|
+
}
|
|
216
219
|
const model = options.model || config.defaultModel;
|
|
217
220
|
if (model) {
|
|
218
221
|
args.push('--model', model);
|
|
@@ -277,7 +280,7 @@ function runCodex(args, options = {}) {
|
|
|
277
280
|
const timer = timeoutMs > 0
|
|
278
281
|
? setTimeout(() => {
|
|
279
282
|
timedOut = true;
|
|
280
|
-
child.
|
|
283
|
+
killProcessTree(child.pid);
|
|
281
284
|
}, timeoutMs)
|
|
282
285
|
: null;
|
|
283
286
|
|
|
@@ -332,6 +335,24 @@ function writeStreamChunk(stream, text, prefix = '') {
|
|
|
332
335
|
}
|
|
333
336
|
}
|
|
334
337
|
|
|
338
|
+
function killProcessTree(pid) {
|
|
339
|
+
if (!pid) return;
|
|
340
|
+
if (process.platform === 'win32') {
|
|
341
|
+
const killer = spawn('taskkill.exe', ['/pid', String(pid), '/t', '/f'], {
|
|
342
|
+
stdio: 'ignore',
|
|
343
|
+
windowsHide: true,
|
|
344
|
+
});
|
|
345
|
+
killer.on('error', () => {});
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
try {
|
|
350
|
+
process.kill(pid, 'SIGTERM');
|
|
351
|
+
} catch {
|
|
352
|
+
// Process may already be gone.
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
335
356
|
async function execPrompt(prompt, options = {}) {
|
|
336
357
|
if (!prompt || !prompt.trim()) {
|
|
337
358
|
throw new Error('prompt is required');
|
|
@@ -513,7 +534,6 @@ module.exports = {
|
|
|
513
534
|
buildLaunch,
|
|
514
535
|
resolveCommandArgs,
|
|
515
536
|
writeStreamChunk,
|
|
537
|
+
killProcessTree,
|
|
516
538
|
};
|
|
517
539
|
|
|
518
|
-
|
|
519
|
-
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# designer
|
|
2
|
+
|
|
3
|
+
Runtime UI measurement CLI for AI agents. The active command surface is intentionally small:
|
|
4
|
+
|
|
5
|
+
- `measure` — read element bbox, computed CSS, and optional child layout as JSON.
|
|
6
|
+
- `screenshot` — capture a full page or selected element as PNG.
|
|
7
|
+
- `overlay` — tint a design screenshot magenta and composite it over the runtime page.
|
|
8
|
+
- `changelist` — output changed-region JSON and side-by-side comparison PNGs from design/runtime screenshots.
|
|
9
|
+
|
|
10
|
+
The CLI is bundled through `alanbox` as both `designer` and `alanbox designer ...`.
|
|
11
|
+
|
|
12
|
+
## Commands
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
designer measure --url "http://localhost:3000" --selector ".dialog"
|
|
16
|
+
designer screenshot --url "http://localhost:3000" --selector ".dialog" --output runtime.png
|
|
17
|
+
designer overlay --design design.png --url "http://localhost:3000" --selector ".dialog" --output overlay.png
|
|
18
|
+
designer changelist --design design.png --runtime runtime.png --output changes.json --annotated changes.png --regions-dir regions
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
For Axure or iframe-based designs:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
designer measure --url "http://127.0.0.1:32767/start.html" --frame "#mainFrame" --selector "#u0" --depth 0 --cdp 127.0.0.1:8000
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Structure
|
|
28
|
+
|
|
29
|
+
- `src/` — active implementation.
|
|
30
|
+
- `dist/` — built runtime shipped by `alanbox`.
|
|
31
|
+
- `res/overlay/` — archived interactive overlay UI, not part of the active CLI.
|
|
32
|
+
- `res/designer-main-legacy/` — archived old commands and references, not part of the active CLI.
|
|
33
|
+
|
|
34
|
+
## Development
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pnpm install
|
|
38
|
+
pnpm build
|
|
39
|
+
pnpm test
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The active workflow is guided by `../skills/desginer/SKILL.md`; keep command options there in sync with `src/cli.ts`.
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
MEASURE_RETRY_INTERVAL_MS,
|
|
5
|
+
MEASURE_WAIT_TIMEOUT_MS,
|
|
6
|
+
RELEVANT_PROPS,
|
|
7
|
+
REQUIRED_MEASURE_PROPS
|
|
8
|
+
} from "./chunk-NLYFLQ3C.js";
|
|
9
|
+
|
|
10
|
+
// src/engine/cdp/cdp-client.ts
|
|
11
|
+
import WebSocket from "ws";
|
|
12
|
+
async function listTargets(host, port) {
|
|
13
|
+
const res = await fetch(`http://${host}:${port}/json`);
|
|
14
|
+
if (!res.ok) throw new Error(`CDP target list failed: ${res.status}`);
|
|
15
|
+
return res.json();
|
|
16
|
+
}
|
|
17
|
+
var CdpClient = class _CdpClient {
|
|
18
|
+
ws;
|
|
19
|
+
nextId = 1;
|
|
20
|
+
pending = /* @__PURE__ */ new Map();
|
|
21
|
+
ready;
|
|
22
|
+
constructor(wsUrl) {
|
|
23
|
+
this.ws = new WebSocket(wsUrl);
|
|
24
|
+
this.ready = new Promise((resolve, reject) => {
|
|
25
|
+
this.ws.once("open", resolve);
|
|
26
|
+
this.ws.once("error", reject);
|
|
27
|
+
});
|
|
28
|
+
this.ws.on("message", (data) => {
|
|
29
|
+
const payload = JSON.parse(data.toString());
|
|
30
|
+
if (payload.id != null) {
|
|
31
|
+
const p = this.pending.get(payload.id);
|
|
32
|
+
if (p) {
|
|
33
|
+
this.pending.delete(payload.id);
|
|
34
|
+
if (payload.error) {
|
|
35
|
+
p.reject(new Error(`CDP: ${payload.error.message}`));
|
|
36
|
+
} else {
|
|
37
|
+
p.resolve(payload.result);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
this.ws.on("close", () => {
|
|
43
|
+
for (const p of this.pending.values()) {
|
|
44
|
+
p.reject(new Error("CDP connection closed"));
|
|
45
|
+
}
|
|
46
|
+
this.pending.clear();
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
static async connect(target) {
|
|
50
|
+
const client = new _CdpClient(target.webSocketDebuggerUrl);
|
|
51
|
+
await client.ready;
|
|
52
|
+
await client.call("DOM.enable");
|
|
53
|
+
await client.call("CSS.enable");
|
|
54
|
+
await client.call("Page.enable");
|
|
55
|
+
await client.call("Runtime.enable");
|
|
56
|
+
return client;
|
|
57
|
+
}
|
|
58
|
+
async call(method, params, timeout = 3e4) {
|
|
59
|
+
const id = this.nextId++;
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
const timer = setTimeout(() => {
|
|
62
|
+
this.pending.delete(id);
|
|
63
|
+
reject(new Error(`CDP call '${method}' timed out after ${timeout}ms`));
|
|
64
|
+
}, timeout);
|
|
65
|
+
this.pending.set(id, {
|
|
66
|
+
resolve: (v) => {
|
|
67
|
+
clearTimeout(timer);
|
|
68
|
+
resolve(v);
|
|
69
|
+
},
|
|
70
|
+
reject: (e) => {
|
|
71
|
+
clearTimeout(timer);
|
|
72
|
+
reject(e);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
this.ws.send(JSON.stringify({ id, method, params }));
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
close() {
|
|
79
|
+
this.ws.close();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
async function connectToPage(host, port, urlFilter) {
|
|
83
|
+
const targets = await listTargets(host, port);
|
|
84
|
+
const pages = targets.filter((t) => t.type === "page");
|
|
85
|
+
if (pages.length === 0) throw new Error("No page targets found");
|
|
86
|
+
const target = urlFilter ? pages.find((t) => t.url.includes(urlFilter)) ?? pages[0] : pages[0];
|
|
87
|
+
const client = await CdpClient.connect(target);
|
|
88
|
+
return { client, target };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/engine/cdp/cdp-engine.ts
|
|
92
|
+
function buildClip(model, viewport, padding = 0) {
|
|
93
|
+
const q = model.border?.quad ?? model.content.quad;
|
|
94
|
+
const minX = Math.min(q[0], q[2], q[4], q[6]);
|
|
95
|
+
const maxX = Math.max(q[0], q[2], q[4], q[6]);
|
|
96
|
+
const minY = Math.min(q[1], q[3], q[5], q[7]);
|
|
97
|
+
const maxY = Math.max(q[1], q[3], q[5], q[7]);
|
|
98
|
+
const x = Math.max(0, minX - padding);
|
|
99
|
+
const y = Math.max(0, minY - padding);
|
|
100
|
+
const width = Math.min(viewport.width, maxX + padding) - x;
|
|
101
|
+
const height = Math.min(viewport.height, maxY + padding) - y;
|
|
102
|
+
return { x, y, width, height };
|
|
103
|
+
}
|
|
104
|
+
var CdpEngine = class _CdpEngine {
|
|
105
|
+
constructor(client, pageUrl) {
|
|
106
|
+
this.client = client;
|
|
107
|
+
this.pageUrl = pageUrl;
|
|
108
|
+
}
|
|
109
|
+
client;
|
|
110
|
+
pageUrl;
|
|
111
|
+
static async create(host, port, urlFilter) {
|
|
112
|
+
const { client, target } = await connectToPage(host, port, urlFilter);
|
|
113
|
+
return new _CdpEngine(client, target.url);
|
|
114
|
+
}
|
|
115
|
+
async screenshot(options) {
|
|
116
|
+
if (options?.selector) {
|
|
117
|
+
const safeSelector = JSON.stringify(options.selector);
|
|
118
|
+
const { result } = await this.client.call("Runtime.evaluate", {
|
|
119
|
+
expression: `(() => {
|
|
120
|
+
const el = document.querySelector(${safeSelector});
|
|
121
|
+
if (!el) throw new Error('Element not found: ' + ${safeSelector});
|
|
122
|
+
return JSON.stringify(el.getBoundingClientRect());
|
|
123
|
+
})()`,
|
|
124
|
+
returnByValue: true
|
|
125
|
+
});
|
|
126
|
+
if (result.subtype === "error") {
|
|
127
|
+
throw new Error(result.description || `Element not found: ${options.selector}`);
|
|
128
|
+
}
|
|
129
|
+
const rect = JSON.parse(result.value);
|
|
130
|
+
const viewport = await this.getViewport();
|
|
131
|
+
const clip = {
|
|
132
|
+
x: Math.max(0, rect.x),
|
|
133
|
+
y: Math.max(0, rect.y),
|
|
134
|
+
width: Math.min(viewport.width - rect.x, rect.width),
|
|
135
|
+
height: Math.min(viewport.height - rect.y, rect.height),
|
|
136
|
+
scale: 1
|
|
137
|
+
};
|
|
138
|
+
const { data: data2 } = await this.client.call("Page.captureScreenshot", {
|
|
139
|
+
format: "png",
|
|
140
|
+
clip,
|
|
141
|
+
fromSurface: true
|
|
142
|
+
});
|
|
143
|
+
return Buffer.from(data2, "base64");
|
|
144
|
+
}
|
|
145
|
+
const { data } = await this.client.call("Page.captureScreenshot", {
|
|
146
|
+
format: "png",
|
|
147
|
+
fromSurface: true
|
|
148
|
+
});
|
|
149
|
+
return Buffer.from(data, "base64");
|
|
150
|
+
}
|
|
151
|
+
async measure(selector, depth = 1, frameSelector) {
|
|
152
|
+
const safeSelector = JSON.stringify(selector);
|
|
153
|
+
const safeFrameSelector = JSON.stringify(frameSelector);
|
|
154
|
+
const safeProps = JSON.stringify(RELEVANT_PROPS);
|
|
155
|
+
const safeRequiredProps = JSON.stringify(REQUIRED_MEASURE_PROPS);
|
|
156
|
+
const safeDepth = Number.isFinite(depth) ? Math.max(0, depth) : 1;
|
|
157
|
+
const js = `
|
|
158
|
+
(() => {
|
|
159
|
+
function toBBox(rect, origin) {
|
|
160
|
+
const originX = origin ? origin.x : 0;
|
|
161
|
+
const originY = origin ? origin.y : 0;
|
|
162
|
+
const originLeft = origin ? origin.left : 0;
|
|
163
|
+
const originTop = origin ? origin.top : 0;
|
|
164
|
+
return {
|
|
165
|
+
x: +(rect.x - originX).toFixed(1),
|
|
166
|
+
y: +(rect.y - originY).toFixed(1),
|
|
167
|
+
width: +rect.width.toFixed(1),
|
|
168
|
+
height: +rect.height.toFixed(1),
|
|
169
|
+
top: +(rect.top - originTop).toFixed(1),
|
|
170
|
+
right: +(rect.right - originLeft).toFixed(1),
|
|
171
|
+
bottom: +(rect.bottom - originTop).toFixed(1),
|
|
172
|
+
left: +(rect.left - originLeft).toFixed(1),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function isValidBBox(bbox) {
|
|
177
|
+
return Object.values(bbox).every(Number.isFinite);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function collectStyle(win, el) {
|
|
181
|
+
const cs = win.getComputedStyle(el);
|
|
182
|
+
const style = {};
|
|
183
|
+
${safeProps}.forEach(p => {
|
|
184
|
+
style[p] = p === 'font' ? cs.font : cs.getPropertyValue(p);
|
|
185
|
+
});
|
|
186
|
+
return style;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function hasRequiredStyle(style) {
|
|
190
|
+
return ${safeRequiredProps}.every(p => typeof style[p] === 'string' && style[p] !== '');
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function collectChildren(parent, parentRect, currentDepth, maxDepth) {
|
|
194
|
+
if (currentDepth >= maxDepth) return [];
|
|
195
|
+
const result = [];
|
|
196
|
+
for (const child of parent.children) {
|
|
197
|
+
const cr = child.getBoundingClientRect();
|
|
198
|
+
const node = {
|
|
199
|
+
tag: child.tagName.toLowerCase(),
|
|
200
|
+
className: (child.className || '').toString().substring(0, 120),
|
|
201
|
+
bbox: toBBox(cr, parentRect),
|
|
202
|
+
text: (child.textContent || '').substring(0, 80).trim() || undefined,
|
|
203
|
+
};
|
|
204
|
+
if (currentDepth + 1 < maxDepth && child.children.length > 0) {
|
|
205
|
+
node.children = collectChildren(child, cr, currentDepth + 1, maxDepth);
|
|
206
|
+
}
|
|
207
|
+
result.push(node);
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const sel = ${safeSelector};
|
|
213
|
+
const frameSel = ${safeFrameSelector};
|
|
214
|
+
let doc = document;
|
|
215
|
+
let win = window;
|
|
216
|
+
if (frameSel) {
|
|
217
|
+
const frame = document.querySelector(frameSel);
|
|
218
|
+
if (!frame || !frame.contentDocument || !frame.contentWindow) return JSON.stringify(null);
|
|
219
|
+
doc = frame.contentDocument;
|
|
220
|
+
win = frame.contentWindow;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const el = doc.querySelector(sel);
|
|
224
|
+
if (!el) return JSON.stringify(null);
|
|
225
|
+
const r = el.getBoundingClientRect();
|
|
226
|
+
const bbox = toBBox(r);
|
|
227
|
+
const style = collectStyle(win, el);
|
|
228
|
+
if (!isValidBBox(bbox)) return JSON.stringify(null);
|
|
229
|
+
if (!hasRequiredStyle(style)) return JSON.stringify(null);
|
|
230
|
+
if (bbox.width <= 0 || bbox.height <= 0 || style.display === 'none' || style.visibility === 'hidden') {
|
|
231
|
+
return JSON.stringify(null);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return JSON.stringify({
|
|
235
|
+
bbox,
|
|
236
|
+
computedStyle: style,
|
|
237
|
+
children: ${safeDepth} > 0 ? collectChildren(el, r, 0, ${safeDepth}) : [],
|
|
238
|
+
});
|
|
239
|
+
})()
|
|
240
|
+
`;
|
|
241
|
+
const deadline = Date.now() + MEASURE_WAIT_TIMEOUT_MS;
|
|
242
|
+
let lastError;
|
|
243
|
+
while (Date.now() <= deadline) {
|
|
244
|
+
try {
|
|
245
|
+
const { result, exceptionDetails } = await this.client.call("Runtime.evaluate", {
|
|
246
|
+
expression: js,
|
|
247
|
+
returnByValue: true
|
|
248
|
+
});
|
|
249
|
+
if (exceptionDetails || result.subtype === "error") {
|
|
250
|
+
throw new Error(result.description || exceptionDetails?.text || "measure failed");
|
|
251
|
+
}
|
|
252
|
+
const parsed = JSON.parse(result.value);
|
|
253
|
+
if (parsed) {
|
|
254
|
+
return frameSelector ? { selector, frameSelector, ...parsed } : { selector, ...parsed };
|
|
255
|
+
}
|
|
256
|
+
lastError = new Error(
|
|
257
|
+
frameSelector ? `Element not ready or incomplete: ${selector} in frame ${frameSelector}` : `Element not ready or incomplete: ${selector}`
|
|
258
|
+
);
|
|
259
|
+
} catch (error) {
|
|
260
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
261
|
+
}
|
|
262
|
+
await new Promise((resolve) => setTimeout(resolve, MEASURE_RETRY_INTERVAL_MS));
|
|
263
|
+
}
|
|
264
|
+
throw lastError ?? new Error("measure failed");
|
|
265
|
+
}
|
|
266
|
+
async evaluate(expression) {
|
|
267
|
+
const { result } = await this.client.call("Runtime.evaluate", {
|
|
268
|
+
expression,
|
|
269
|
+
returnByValue: true
|
|
270
|
+
});
|
|
271
|
+
return result.value;
|
|
272
|
+
}
|
|
273
|
+
async injectOverlay(params) {
|
|
274
|
+
const { tintDesignImage } = await import("./tint-YN63MLVN.js");
|
|
275
|
+
const tintedBuf = await tintDesignImage(params.designImagePath);
|
|
276
|
+
const base64 = tintedBuf.toString("base64");
|
|
277
|
+
const js = `
|
|
278
|
+
(() => {
|
|
279
|
+
let overlay = document.getElementById('__design_ruler_overlay__');
|
|
280
|
+
if (!overlay) {
|
|
281
|
+
overlay = document.createElement('img');
|
|
282
|
+
overlay.id = '__design_ruler_overlay__';
|
|
283
|
+
overlay.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:auto;pointer-events:none;z-index:999999;';
|
|
284
|
+
document.body.appendChild(overlay);
|
|
285
|
+
}
|
|
286
|
+
overlay.src = 'data:image/png;base64,' + ${JSON.stringify(base64)};
|
|
287
|
+
overlay.style.opacity = String(${Number(params.opacity)});
|
|
288
|
+
overlay.style.transform = 'translate(' + ${Number(params.offsetX)} + 'px, ' + ${Number(params.offsetY)} + 'px) scale(' + ${Number(params.scale)} + ')';
|
|
289
|
+
overlay.style.transformOrigin = 'top left';
|
|
290
|
+
if (${Number(params.scrollY ?? 0)} > 0) {
|
|
291
|
+
window.scrollTo(0, ${Number(params.scrollY ?? 0)});
|
|
292
|
+
}
|
|
293
|
+
return 'overlay injected';
|
|
294
|
+
})()
|
|
295
|
+
`;
|
|
296
|
+
await this.evaluate(js);
|
|
297
|
+
}
|
|
298
|
+
async captureOverlay(options) {
|
|
299
|
+
return this.screenshot(options);
|
|
300
|
+
}
|
|
301
|
+
async close() {
|
|
302
|
+
this.client.close();
|
|
303
|
+
}
|
|
304
|
+
async getViewport() {
|
|
305
|
+
return this.evaluate(
|
|
306
|
+
"JSON.parse(JSON.stringify({ width: window.innerWidth, height: window.innerHeight }))"
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
export {
|
|
311
|
+
CdpEngine,
|
|
312
|
+
buildClip
|
|
313
|
+
};
|
|
314
|
+
//# sourceMappingURL=cdp-engine-4AIWSWXO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/engine/cdp/cdp-client.ts","../src/engine/cdp/cdp-engine.ts"],"sourcesContent":["import WebSocket from 'ws'\r\n\r\nexport interface CdpTarget {\r\n id: string\r\n title: string\r\n type: string\r\n url: string\r\n webSocketDebuggerUrl: string\r\n}\r\n\r\nexport async function listTargets(host: string, port: number): Promise<CdpTarget[]> {\r\n const res = await fetch(`http://${host}:${port}/json`)\r\n if (!res.ok) throw new Error(`CDP target list failed: ${res.status}`)\r\n return res.json() as Promise<CdpTarget[]>\r\n}\r\n\r\nexport class CdpClient {\r\n private ws: WebSocket\r\n private nextId = 1\r\n private pending = new Map<number, { resolve: (v: any) => void; reject: (e: Error) => void }>()\r\n private ready: Promise<void>\r\n\r\n private constructor(wsUrl: string) {\r\n this.ws = new WebSocket(wsUrl)\r\n this.ready = new Promise((resolve, reject) => {\r\n this.ws.once('open', resolve)\r\n this.ws.once('error', reject)\r\n })\r\n this.ws.on('message', (data: WebSocket.Data) => {\r\n const payload = JSON.parse(data.toString())\r\n if (payload.id != null) {\r\n const p = this.pending.get(payload.id)\r\n if (p) {\r\n this.pending.delete(payload.id)\r\n if (payload.error) {\r\n p.reject(new Error(`CDP: ${payload.error.message}`))\r\n } else {\r\n p.resolve(payload.result)\r\n }\r\n }\r\n }\r\n })\r\n this.ws.on('close', () => {\r\n for (const p of this.pending.values()) {\r\n p.reject(new Error('CDP connection closed'))\r\n }\r\n this.pending.clear()\r\n })\r\n }\r\n\r\n static async connect(target: CdpTarget): Promise<CdpClient> {\r\n const client = new CdpClient(target.webSocketDebuggerUrl)\r\n await client.ready\r\n await client.call('DOM.enable')\r\n await client.call('CSS.enable')\r\n await client.call('Page.enable')\r\n await client.call('Runtime.enable')\r\n return client\r\n }\r\n\r\n async call<T = any>(method: string, params?: Record<string, unknown>, timeout = 30000): Promise<T> {\r\n const id = this.nextId++\r\n return new Promise<T>((resolve, reject) => {\r\n const timer = setTimeout(() => {\r\n this.pending.delete(id)\r\n reject(new Error(`CDP call '${method}' timed out after ${timeout}ms`))\r\n }, timeout)\r\n this.pending.set(id, {\r\n resolve: (v) => { clearTimeout(timer); resolve(v) },\r\n reject: (e) => { clearTimeout(timer); reject(e) },\r\n })\r\n this.ws.send(JSON.stringify({ id, method, params }))\r\n })\r\n }\r\n\r\n close(): void {\r\n this.ws.close()\r\n }\r\n}\r\n\r\nexport async function connectToPage(\r\n host: string,\r\n port: number,\r\n urlFilter?: string,\r\n): Promise<{ client: CdpClient; target: CdpTarget }> {\r\n const targets = await listTargets(host, port)\r\n const pages = targets.filter(t => t.type === 'page')\r\n if (pages.length === 0) throw new Error('No page targets found')\r\n\r\n const target = urlFilter\r\n ? pages.find(t => t.url.includes(urlFilter)) ?? pages[0]\r\n : pages[0]\r\n\r\n const client = await CdpClient.connect(target)\r\n return { client, target }\r\n}\r\n","import type { RuntimeEngine, MeasureResult, ScreenshotOptions, OverlayParams } from '../types.js'\nimport {\n MEASURE_RETRY_INTERVAL_MS,\n MEASURE_WAIT_TIMEOUT_MS,\n RELEVANT_PROPS,\n REQUIRED_MEASURE_PROPS,\n} from '../constants.js'\nimport { CdpClient, connectToPage } from './cdp-client.js'\n\r\ninterface BoxModelQuad {\r\n quad: number[]\r\n}\r\n\r\nexport function buildClip(\r\n model: { content: BoxModelQuad; border?: BoxModelQuad },\r\n viewport: { width: number; height: number },\r\n padding = 0,\r\n): { x: number; y: number; width: number; height: number } {\r\n const q = model.border?.quad ?? model.content.quad\r\n const minX = Math.min(q[0], q[2], q[4], q[6])\r\n const maxX = Math.max(q[0], q[2], q[4], q[6])\r\n const minY = Math.min(q[1], q[3], q[5], q[7])\r\n const maxY = Math.max(q[1], q[3], q[5], q[7])\r\n\r\n const x = Math.max(0, minX - padding)\r\n const y = Math.max(0, minY - padding)\r\n const width = Math.min(viewport.width, maxX + padding) - x\r\n const height = Math.min(viewport.height, maxY + padding) - y\r\n\r\n return { x, y, width, height }\r\n}\r\n\r\nexport class CdpEngine implements RuntimeEngine {\r\n private constructor(\r\n private client: CdpClient,\r\n private pageUrl: string,\r\n ) {}\r\n\r\n static async create(host: string, port: number, urlFilter?: string): Promise<CdpEngine> {\r\n const { client, target } = await connectToPage(host, port, urlFilter)\r\n return new CdpEngine(client, target.url)\r\n }\r\n\r\n async screenshot(options?: ScreenshotOptions): Promise<Buffer> {\r\n if (options?.selector) {\r\n // Use JSON.stringify to safely escape the selector\r\n const safeSelector = JSON.stringify(options.selector)\r\n const { result } = await this.client.call<any>('Runtime.evaluate', {\r\n expression: `(() => {\r\n const el = document.querySelector(${safeSelector});\r\n if (!el) throw new Error('Element not found: ' + ${safeSelector});\r\n return JSON.stringify(el.getBoundingClientRect());\r\n })()`,\r\n returnByValue: true,\r\n })\r\n if (result.subtype === 'error') {\r\n throw new Error(result.description || `Element not found: ${options.selector}`)\r\n }\r\n const rect = JSON.parse(result.value)\r\n const viewport = await this.getViewport()\r\n const clip = {\r\n x: Math.max(0, rect.x),\r\n y: Math.max(0, rect.y),\r\n width: Math.min(viewport.width - rect.x, rect.width),\r\n height: Math.min(viewport.height - rect.y, rect.height),\r\n scale: 1,\r\n }\r\n const { data } = await this.client.call<{ data: string }>('Page.captureScreenshot', {\r\n format: 'png',\r\n clip,\r\n fromSurface: true,\r\n })\r\n return Buffer.from(data, 'base64')\r\n }\r\n\r\n const { data } = await this.client.call<{ data: string }>('Page.captureScreenshot', {\r\n format: 'png',\r\n fromSurface: true,\r\n })\r\n return Buffer.from(data, 'base64')\r\n }\r\n\r\n async measure(selector: string, depth = 1, frameSelector?: string): Promise<MeasureResult> {\n // All user inputs passed via JSON.stringify to prevent injection\n const safeSelector = JSON.stringify(selector)\n const safeFrameSelector = JSON.stringify(frameSelector)\n const safeProps = JSON.stringify(RELEVANT_PROPS)\n const safeRequiredProps = JSON.stringify(REQUIRED_MEASURE_PROPS)\n const safeDepth = Number.isFinite(depth) ? Math.max(0, depth) : 1\n\n const js = `\n (() => {\n function toBBox(rect, origin) {\n const originX = origin ? origin.x : 0;\n const originY = origin ? origin.y : 0;\n const originLeft = origin ? origin.left : 0;\n const originTop = origin ? origin.top : 0;\n return {\n x: +(rect.x - originX).toFixed(1),\n y: +(rect.y - originY).toFixed(1),\n width: +rect.width.toFixed(1),\n height: +rect.height.toFixed(1),\n top: +(rect.top - originTop).toFixed(1),\n right: +(rect.right - originLeft).toFixed(1),\n bottom: +(rect.bottom - originTop).toFixed(1),\n left: +(rect.left - originLeft).toFixed(1),\n };\n }\n\n function isValidBBox(bbox) {\n return Object.values(bbox).every(Number.isFinite);\n }\n\n function collectStyle(win, el) {\n const cs = win.getComputedStyle(el);\n const style = {};\n ${safeProps}.forEach(p => {\n style[p] = p === 'font' ? cs.font : cs.getPropertyValue(p);\n });\n return style;\n }\n\n function hasRequiredStyle(style) {\n return ${safeRequiredProps}.every(p => typeof style[p] === 'string' && style[p] !== '');\n }\n\n function collectChildren(parent, parentRect, currentDepth, maxDepth) {\n if (currentDepth >= maxDepth) return [];\n const result = [];\n for (const child of parent.children) {\n const cr = child.getBoundingClientRect();\n const node = {\r\n tag: child.tagName.toLowerCase(),\n className: (child.className || '').toString().substring(0, 120),\n bbox: toBBox(cr, parentRect),\n text: (child.textContent || '').substring(0, 80).trim() || undefined,\n };\n if (currentDepth + 1 < maxDepth && child.children.length > 0) {\n node.children = collectChildren(child, cr, currentDepth + 1, maxDepth);\r\n }\r\n result.push(node);\r\n }\r\n return result;\n }\n\n const sel = ${safeSelector};\n const frameSel = ${safeFrameSelector};\n let doc = document;\n let win = window;\n if (frameSel) {\n const frame = document.querySelector(frameSel);\n if (!frame || !frame.contentDocument || !frame.contentWindow) return JSON.stringify(null);\n doc = frame.contentDocument;\n win = frame.contentWindow;\n }\n\n const el = doc.querySelector(sel);\n if (!el) return JSON.stringify(null);\n const r = el.getBoundingClientRect();\n const bbox = toBBox(r);\n const style = collectStyle(win, el);\n if (!isValidBBox(bbox)) return JSON.stringify(null);\n if (!hasRequiredStyle(style)) return JSON.stringify(null);\n if (bbox.width <= 0 || bbox.height <= 0 || style.display === 'none' || style.visibility === 'hidden') {\n return JSON.stringify(null);\n }\n\n return JSON.stringify({\n bbox,\n computedStyle: style,\n children: ${safeDepth} > 0 ? collectChildren(el, r, 0, ${safeDepth}) : [],\n });\n })()\n `\n\n const deadline = Date.now() + MEASURE_WAIT_TIMEOUT_MS\n let lastError: Error | undefined\n while (Date.now() <= deadline) {\n try {\n const { result, exceptionDetails } = await this.client.call<any>('Runtime.evaluate', {\n expression: js,\n returnByValue: true,\n })\n if (exceptionDetails || result.subtype === 'error') {\n throw new Error(result.description || exceptionDetails?.text || 'measure failed')\n }\n\n const parsed = JSON.parse(result.value)\n if (parsed) {\n return frameSelector ? { selector, frameSelector, ...parsed } : { selector, ...parsed }\n }\n lastError = new Error(\n frameSelector\n ? `Element not ready or incomplete: ${selector} in frame ${frameSelector}`\n : `Element not ready or incomplete: ${selector}`,\n )\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error))\n }\n await new Promise(resolve => setTimeout(resolve, MEASURE_RETRY_INTERVAL_MS))\n }\n\n throw lastError ?? new Error('measure failed')\n }\n\r\n async evaluate<T = unknown>(expression: string): Promise<T> {\r\n const { result } = await this.client.call<any>('Runtime.evaluate', {\r\n expression,\r\n returnByValue: true,\r\n })\r\n return result.value as T\r\n }\r\n\r\n async injectOverlay(params: OverlayParams): Promise<void> {\r\n const { tintDesignImage } = await import('../../overlay/tint.js')\r\n const tintedBuf = await tintDesignImage(params.designImagePath)\r\n const base64 = tintedBuf.toString('base64')\r\n // Numeric params are safe, base64 is safe, no user strings interpolated\r\n const js = `\r\n (() => {\r\n let overlay = document.getElementById('__design_ruler_overlay__');\r\n if (!overlay) {\r\n overlay = document.createElement('img');\r\n overlay.id = '__design_ruler_overlay__';\r\n overlay.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:auto;pointer-events:none;z-index:999999;';\r\n document.body.appendChild(overlay);\r\n }\r\n overlay.src = 'data:image/png;base64,' + ${JSON.stringify(base64)};\r\n overlay.style.opacity = String(${Number(params.opacity)});\r\n overlay.style.transform = 'translate(' + ${Number(params.offsetX)} + 'px, ' + ${Number(params.offsetY)} + 'px) scale(' + ${Number(params.scale)} + ')';\r\n overlay.style.transformOrigin = 'top left';\r\n if (${Number(params.scrollY ?? 0)} > 0) {\r\n window.scrollTo(0, ${Number(params.scrollY ?? 0)});\r\n }\r\n return 'overlay injected';\r\n })()\r\n `\r\n await this.evaluate(js)\r\n }\r\n\r\n async captureOverlay(options?: import('../types.js').ScreenshotOptions): Promise<Buffer> {\r\n return this.screenshot(options)\r\n }\r\n\r\n async close(): Promise<void> {\r\n this.client.close()\r\n }\r\n\r\n private async getViewport(): Promise<{ width: number; height: number }> {\r\n return this.evaluate<{ width: number; height: number }>(\r\n 'JSON.parse(JSON.stringify({ width: window.innerWidth, height: window.innerHeight }))'\r\n )\r\n }\r\n}\r\n"],"mappings":"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","names":["data"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|