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.
Files changed (94) hide show
  1. package/0boxer/AGENTS.md +26 -0
  2. package/0boxer/src/AGENTS.md +16 -0
  3. package/0boxer/src/cli.js +53 -0
  4. package/0boxer/src/commands/AGENTS.md +16 -0
  5. package/{0commondflowv1 → 0boxer}/src/commands/install.js +56 -0
  6. package/{0commondflowv1 → 1swarmer}/AGENTS.md +14 -12
  7. package/1swarmer/src/AGENTS.md +28 -0
  8. package/{0commondflowv1 → 1swarmer}/src/args.js +8 -1
  9. package/{0commondflowv1 → 1swarmer}/src/cli.js +27 -17
  10. package/1swarmer/src/commands/AGENTS.md +31 -0
  11. package/{0commondflowv1 → 1swarmer}/src/commands/doctor.js +2 -2
  12. package/1swarmer/src/commands/review-file.js +997 -0
  13. package/{0commondflowv1 → 1swarmer}/src/core/AGENTS.md +2 -2
  14. package/{0commondflowv1 → 1swarmer}/src/core/prompt-templates.js +1 -1
  15. package/{0commondflowv1 → 1swarmer}/src/core/storage.js +1 -1
  16. package/{0commondflowv1 → 1swarmer}/src/prompt/AGENTS.md +1 -1
  17. package/{0commondflowv1 → 1swarmer}/src/prompt/default.md +1 -1
  18. package/{0commondflowv1 → 1swarmer}/src/prompt/synthesizer.md +1 -1
  19. package/{0commondflowv1 → 1swarmer}/src/prompt/verifier.md +1 -1
  20. package/{0commondflowv1 → 1swarmer}/src/runner/AGENTS.md +4 -3
  21. package/{0commondflowv1 → 1swarmer}/src/runner/codex-runner.js +23 -3
  22. package/2designer/README.md +42 -0
  23. package/2designer/dist/cdp-engine-4AIWSWXO.js +314 -0
  24. package/2designer/dist/cdp-engine-4AIWSWXO.js.map +1 -0
  25. package/2designer/dist/cdp-engine-SG4K2BCX.js +10 -0
  26. package/2designer/dist/cdp-engine-SG4K2BCX.js.map +1 -0
  27. package/2designer/dist/chunk-7X7PTLZH.js +185 -0
  28. package/2designer/dist/chunk-7X7PTLZH.js.map +1 -0
  29. package/2designer/dist/chunk-DPOWNFOH.js +313 -0
  30. package/2designer/dist/chunk-DPOWNFOH.js.map +1 -0
  31. package/2designer/dist/chunk-ISUUIOO7.js +58 -0
  32. package/2designer/dist/chunk-ISUUIOO7.js.map +1 -0
  33. package/2designer/dist/chunk-NLYFLQ3C.js +74 -0
  34. package/2designer/dist/chunk-NLYFLQ3C.js.map +1 -0
  35. package/2designer/dist/chunk-UVKSRKXR.js +71 -0
  36. package/2designer/dist/chunk-UVKSRKXR.js.map +1 -0
  37. package/2designer/dist/cli.js +748 -0
  38. package/2designer/dist/cli.js.map +1 -0
  39. package/2designer/dist/index.d.ts +118 -0
  40. package/2designer/dist/index.js +37 -0
  41. package/2designer/dist/index.js.map +1 -0
  42. package/2designer/dist/playwright-engine-YXBY3KEN.js +186 -0
  43. package/2designer/dist/playwright-engine-YXBY3KEN.js.map +1 -0
  44. package/2designer/dist/playwright-engine-YXGDTSZ5.js +8 -0
  45. package/2designer/dist/playwright-engine-YXGDTSZ5.js.map +1 -0
  46. package/2designer/dist/tint-UD4CJ7S2.js +7 -0
  47. package/2designer/dist/tint-UD4CJ7S2.js.map +1 -0
  48. package/2designer/dist/tint-YN63MLVN.js +60 -0
  49. package/2designer/dist/tint-YN63MLVN.js.map +1 -0
  50. package/2designer/package.json +56 -0
  51. package/4reporter/README.md +24 -0
  52. package/4reporter/dist/cli.js +464 -0
  53. package/4reporter/dist/cli.js.map +1 -0
  54. package/4reporter/dist/index.d.ts +108 -0
  55. package/4reporter/dist/index.js +445 -0
  56. package/4reporter/dist/index.js.map +1 -0
  57. package/4reporter/package.json +39 -0
  58. package/README.md +20 -9
  59. package/bin/alanbox.js +11 -0
  60. package/bin/designer.js +10 -0
  61. package/bin/reporter.js +11 -0
  62. package/bin/swarmer.js +11 -0
  63. package/cli.js +178 -0
  64. package/hooks/hooks.json +1 -1
  65. package/mcp/README.md +7 -1
  66. package/mcp/config.toml +4 -0
  67. package/package.json +28 -11
  68. package/plugin/AGENTS.md +2 -2
  69. package/plugin/plugin.json +7 -7
  70. package/shared/AGENTS.md +15 -0
  71. package/shared/package-args.js +68 -0
  72. package/skills/AGENTS.md +9 -5
  73. package/skills/aitool/SKILL.md +36 -0
  74. package/skills/desginer/SKILL.md +142 -0
  75. package/skills/swarmer/SKILL.md +146 -0
  76. package/0commondflowv1/src/AGENTS.md +0 -26
  77. package/0commondflowv1/src/commands/AGENTS.md +0 -29
  78. package/bin/multirunagent.js +0 -15
  79. package/skills/aibox-swam/SKILL.md +0 -77
  80. package/skills/sub-codex-doctor/SKILL.md +0 -27
  81. package/skills/sub-codex-swarm/SKILL.md +0 -56
  82. /package/{0commondflowv1 → 1swarmer}/res/three-lens-review.js +0 -0
  83. /package/{0commondflowv1 → 1swarmer}/src/commands/info.js +0 -0
  84. /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/auto.js +0 -0
  85. /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/custom.js +0 -0
  86. /package/{0commondflowv1 → 1swarmer}/src/commands/swarm/index.js +0 -0
  87. /package/{0commondflowv1 → 1swarmer}/src/core/handoff.js +0 -0
  88. /package/{0commondflowv1 → 1swarmer}/src/core/prompt-builder.js +0 -0
  89. /package/{0commondflowv1 → 1swarmer}/src/core/swarm-executor.js +0 -0
  90. /package/{0commondflowv1 → 1swarmer}/src/core/workers.js +0 -0
  91. /package/{0commondflowv1 → 1swarmer}/src/core/workflow-planner.js +0 -0
  92. /package/{0commondflowv1 → 1swarmer}/src/core/workflow-storage.js +0 -0
  93. /package/{0commondflowv1 → 1swarmer}/src/prompt/reviewer.md +0 -0
  94. /package/{0commondflowv1 → 1swarmer}/src/runner/config.json +0 -0
@@ -1,6 +1,6 @@
1
1
  ## core
2
2
 
3
- `0commondflowv1/src/core` 存放 worker 编排协议、handoff 协议、prompt 构造和本地结果存储辅助函数,是 `swarm` 使用的核心逻辑。
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` — 从 `0commondflowv1/src/prompt/<role>.md` 读取 auto workflow role 模板并安全 fallback。
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`。
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Auto workflow prompt 模板辅助函数。
3
- * 模板位于 0commondflowv1/src/prompt/<role>.md,role 会先清洗,找不到时回退到 default.md 或内联模板。
3
+ * 模板位于 1swarmer/src/prompt/<role>.md,role 会先清洗,找不到时回退到 default.md 或内联模板。
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -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 multirunagent state');
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
  ## prompt
2
2
 
3
- `0commondflowv1/src/prompt` 存放随源码维护的可复用提示词模板
3
+ `1swarmer/src/prompt` 存放随源码维护的可复用提示词模板
4
4
 
5
5
  ### Important files
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Default Agent Prompt
2
2
 
3
- 你是 multirunagent auto workflow 中的 {{role}} agent。
3
+ 你是 alanbox auto workflow 中的 {{role}} agent。
4
4
 
5
5
  ## 目标
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Synthesizer Prompt
2
2
 
3
- 你是 multirunagent auto workflow 的汇总 agent。
3
+ 你是 alanbox auto workflow 的汇总 agent。
4
4
 
5
5
  ## 总目标
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Verifier Prompt
2
2
 
3
- 你是 multirunagent auto workflow 的验证 agent。
3
+ 你是 alanbox auto workflow 的验证 agent。
4
4
 
5
5
  ## 总目标
6
6
 
@@ -1,6 +1,6 @@
1
1
  ## runner
2
2
 
3
- `0commondflowv1/src/runner` 负责读取 provider 配置、解析 CLI 命令参数,并通过子进程启动 Codex 或 Claude。这里决定是否使用原生 CLI home,或在显式配置时启用隔离 home。
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/multirunagent.js doctor`
23
- - 检查默认 provider:`node bin/multirunagent.js info`
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.kill('SIGTERM');
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,10 @@
1
+ import {
2
+ CdpEngine,
3
+ buildClip
4
+ } from "./chunk-DPOWNFOH.js";
5
+ import "./chunk-UVKSRKXR.js";
6
+ export {
7
+ CdpEngine,
8
+ buildClip
9
+ };
10
+ //# sourceMappingURL=cdp-engine-SG4K2BCX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}