tauri-agent-tools 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/tauri-agent-tools/SKILL.md +43 -6
- package/.agents/skills/tauri-bridge-setup/SKILL.md +1 -1
- package/AGENTS.md +6 -3
- package/README.md +41 -3
- package/dist/cli.js +6 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/diff.d.ts +2 -0
- package/dist/commands/diff.js +90 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/dom.d.ts +1 -0
- package/dist/commands/dom.js +63 -1
- package/dist/commands/dom.js.map +1 -1
- package/dist/commands/mutations.d.ts +21 -0
- package/dist/commands/mutations.js +144 -0
- package/dist/commands/mutations.js.map +1 -0
- package/dist/commands/snapshot.d.ts +3 -0
- package/dist/commands/snapshot.js +131 -0
- package/dist/commands/snapshot.js.map +1 -0
- package/package.json +2 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tauri-agent-tools
|
|
3
3
|
description: CLI for inspecting Tauri desktop apps — DOM queries, screenshots, IPC/console monitoring, storage, and page state
|
|
4
|
-
version: 0.
|
|
5
|
-
tags: [tauri, desktop, debugging, screenshot, dom, inspection]
|
|
4
|
+
version: 0.3.0
|
|
5
|
+
tags: [tauri, desktop, debugging, screenshot, dom, inspection, diff, mutations, snapshot]
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# tauri-agent-tools
|
|
@@ -32,10 +32,10 @@ npm install -g tauri-agent-tools
|
|
|
32
32
|
Some commands require the Rust dev bridge running inside the Tauri app. Others work standalone.
|
|
33
33
|
|
|
34
34
|
**Bridge required** (needs running Tauri app with bridge):
|
|
35
|
-
`screenshot --selector`, `dom`, `eval`, `wait --selector`, `wait --eval`, `ipc-monitor`, `console-monitor`, `storage`, `page-state`
|
|
35
|
+
`screenshot --selector`, `dom`, `eval`, `wait --selector`, `wait --eval`, `ipc-monitor`, `console-monitor`, `storage`, `page-state`, `mutations`, `snapshot`
|
|
36
36
|
|
|
37
37
|
**Standalone** (no bridge needed):
|
|
38
|
-
`screenshot --title` (full window only), `wait --title`, `list-windows`, `info`
|
|
38
|
+
`screenshot --title` (full window only), `wait --title`, `list-windows`, `info`, `diff`
|
|
39
39
|
|
|
40
40
|
The bridge auto-discovers via token files in `/tmp/tauri-dev-bridge-*.token`. No manual port/token configuration needed.
|
|
41
41
|
|
|
@@ -80,12 +80,46 @@ tauri-agent-tools storage --type local --json
|
|
|
80
80
|
tauri-agent-tools console-monitor --level error --duration 5000 --json
|
|
81
81
|
```
|
|
82
82
|
|
|
83
|
+
### Capture a full debug snapshot
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Screenshot + DOM + page state + storage in one call
|
|
87
|
+
tauri-agent-tools snapshot -o /tmp/debug --json
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Compare screenshots
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Pixel-level comparison
|
|
94
|
+
tauri-agent-tools diff /tmp/before.png /tmp/after.png --json
|
|
95
|
+
|
|
96
|
+
# Fail CI if more than 1% of pixels differ
|
|
97
|
+
tauri-agent-tools diff /tmp/expected.png /tmp/actual.png --threshold 1
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Watch DOM mutations
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
# Observe child additions/removals for 10 seconds
|
|
104
|
+
tauri-agent-tools mutations "#todo-list" --duration 10000 --json
|
|
105
|
+
|
|
106
|
+
# Also track attribute changes
|
|
107
|
+
tauri-agent-tools mutations ".sidebar" --attributes --duration 5000
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Find elements by text
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Search for elements containing text
|
|
114
|
+
tauri-agent-tools dom --text "Settings" --first --json
|
|
115
|
+
```
|
|
116
|
+
|
|
83
117
|
## Command Reference
|
|
84
118
|
|
|
85
119
|
| Command | Key Flags | Bridge? | Description |
|
|
86
120
|
|---------|-----------|---------|-------------|
|
|
87
121
|
| `screenshot` | `--selector <css>`, `--title <regex>`, `-o <path>`, `--max-width <n>` | selector: yes, title: no | Capture window or DOM element screenshot |
|
|
88
|
-
| `dom` | `[selector]`, `--depth <n>`, `--styles`, `--mode accessibility`, `--json` | yes | Query DOM structure |
|
|
122
|
+
| `dom` | `[selector]`, `--depth <n>`, `--styles`, `--text <pattern>`, `--mode accessibility`, `--json` | yes | Query DOM structure or find elements by text |
|
|
89
123
|
| `eval` | `<js-expression>` | yes | Evaluate JavaScript in webview |
|
|
90
124
|
| `wait` | `--selector <css>`, `--eval <js>`, `--title <regex>`, `--timeout <ms>` | selector/eval: yes | Wait for a condition |
|
|
91
125
|
| `list-windows` | `--tauri`, `--json` | no | List visible windows |
|
|
@@ -94,11 +128,14 @@ tauri-agent-tools console-monitor --level error --duration 5000 --json
|
|
|
94
128
|
| `console-monitor` | `--level <lvl>`, `--filter <regex>`, `--duration <ms>`, `--json` | yes | Monitor console output |
|
|
95
129
|
| `storage` | `--type <local\|session\|cookies\|all>`, `--key <name>`, `--json` | yes | Inspect browser storage |
|
|
96
130
|
| `page-state` | `--json` | yes | URL, title, viewport, scroll, document size |
|
|
131
|
+
| `diff` | `<image1> <image2>`, `-o <path>`, `--threshold <pct>`, `--json` | no | Compare two screenshots with difference metrics |
|
|
132
|
+
| `mutations` | `<selector>`, `--attributes`, `--duration <ms>`, `--json` | yes | Watch DOM mutations on a CSS selector |
|
|
133
|
+
| `snapshot` | `-o <prefix>`, `-s <css>`, `--dom-depth <n>`, `--eval <js>`, `--json` | yes | Capture screenshot + DOM + page state + storage in one shot |
|
|
97
134
|
|
|
98
135
|
## Important Notes
|
|
99
136
|
|
|
100
137
|
- **All read-only.** No commands modify app state, inject input, or write to storage.
|
|
101
138
|
- **Use `--json`** for structured, parseable output in automation.
|
|
102
|
-
- **Always use `--duration`** with `ipc-monitor
|
|
139
|
+
- **Always use `--duration`** with `ipc-monitor`, `console-monitor`, and `mutations` — without it, they run indefinitely.
|
|
103
140
|
- **`screenshot --selector`** requires both the bridge AND platform screenshot tools (`imagemagick`).
|
|
104
141
|
- **One bridge at a time.** Auto-discovery picks the first token file found. If multiple Tauri apps run simultaneously, use `--port` and `--token` explicitly.
|
package/AGENTS.md
CHANGED
|
@@ -8,7 +8,7 @@ This package includes two [Agent Skills](https://agentskills.io):
|
|
|
8
8
|
|
|
9
9
|
| Skill | Path | Purpose |
|
|
10
10
|
|-------|------|---------|
|
|
11
|
-
| `tauri-agent-tools` | `.agents/skills/tauri-agent-tools/SKILL.md` | Using the
|
|
11
|
+
| `tauri-agent-tools` | `.agents/skills/tauri-agent-tools/SKILL.md` | Using the 14 CLI commands to inspect Tauri apps |
|
|
12
12
|
| `tauri-bridge-setup` | `.agents/skills/tauri-bridge-setup/SKILL.md` | Adding the Rust dev bridge to a Tauri project |
|
|
13
13
|
|
|
14
14
|
## Quick Reference
|
|
@@ -21,10 +21,13 @@ This package includes two [Agent Skills](https://agentskills.io):
|
|
|
21
21
|
`list-windows`, `info`, `screenshot --title`, `wait --title`
|
|
22
22
|
|
|
23
23
|
**Bridge-required commands** (Tauri app must have dev bridge running):
|
|
24
|
-
`dom`, `eval`, `screenshot --selector`, `wait --selector/--eval`, `ipc-monitor`, `console-monitor`, `storage`, `page-state`
|
|
24
|
+
`dom`, `eval`, `screenshot --selector`, `wait --selector/--eval`, `ipc-monitor`, `console-monitor`, `storage`, `page-state`, `mutations`, `snapshot`
|
|
25
|
+
|
|
26
|
+
**Local-only commands** (no bridge needed):
|
|
27
|
+
`diff`
|
|
25
28
|
|
|
26
29
|
**Bridge auto-discovery:** The CLI finds the running bridge via token files in `/tmp/tauri-dev-bridge-*.token`. No manual configuration needed.
|
|
27
30
|
|
|
28
31
|
**Structured output:** Use `--json` on any command for machine-readable output.
|
|
29
32
|
|
|
30
|
-
**Monitors:** Always pass `--duration <ms>` to `ipc-monitor
|
|
33
|
+
**Monitors:** Always pass `--duration <ms>` to `ipc-monitor`, `console-monitor`, and `mutations` to avoid indefinite execution.
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
**Agent-driven inspection toolkit for Tauri desktop apps**
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
14 read-only commands to screenshot, inspect, and monitor Tauri apps from the CLI.
|
|
8
8
|
|
|
9
9
|
[](https://github.com/cesarandreslopez/tauri-agent-tools/actions/workflows/ci.yml)
|
|
10
10
|
[](https://www.npmjs.com/package/tauri-agent-tools)
|
|
@@ -107,6 +107,7 @@ Query DOM structure from the Tauri app.
|
|
|
107
107
|
| `--depth <number>` | Max child depth (default: 3) |
|
|
108
108
|
| `--tree` | Compact tree view (default) |
|
|
109
109
|
| `--styles` | Include computed styles |
|
|
110
|
+
| `--text <pattern>` | Find elements containing this text (case-insensitive) |
|
|
110
111
|
| `--count` | Just output match count |
|
|
111
112
|
| `--first` | Only return first match |
|
|
112
113
|
| `--json` | Full structured JSON output |
|
|
@@ -189,6 +190,43 @@ Query webview page state: URL, title, viewport, scroll position, document size,
|
|
|
189
190
|
|--------|-------------|
|
|
190
191
|
| `--json` | Output as JSON |
|
|
191
192
|
|
|
193
|
+
### `diff`
|
|
194
|
+
|
|
195
|
+
Compare two screenshots and output difference metrics.
|
|
196
|
+
|
|
197
|
+
| Option | Description |
|
|
198
|
+
|--------|-------------|
|
|
199
|
+
| `<image1>` | First image path |
|
|
200
|
+
| `<image2>` | Second image path |
|
|
201
|
+
| `-o, --output <path>` | Diff image output path |
|
|
202
|
+
| `--threshold <percent>` | Fail (exit code 1) if difference exceeds this percentage |
|
|
203
|
+
| `--json` | Output structured JSON |
|
|
204
|
+
|
|
205
|
+
### `mutations`
|
|
206
|
+
|
|
207
|
+
Watch DOM mutations on a CSS selector (read-only). Patches a `MutationObserver` into the webview, polls for changes, and cleans up on exit.
|
|
208
|
+
|
|
209
|
+
| Option | Description |
|
|
210
|
+
|--------|-------------|
|
|
211
|
+
| `<selector>` | CSS selector of the element to observe |
|
|
212
|
+
| `--attributes` | Also watch attribute changes |
|
|
213
|
+
| `--interval <ms>` | Poll interval in milliseconds (default: 500) |
|
|
214
|
+
| `--duration <ms>` | Auto-stop after N milliseconds |
|
|
215
|
+
| `--json` | Output one JSON object per line |
|
|
216
|
+
|
|
217
|
+
### `snapshot`
|
|
218
|
+
|
|
219
|
+
Capture screenshot + DOM tree + page state + storage in one shot. Writes multiple files with a shared prefix.
|
|
220
|
+
|
|
221
|
+
| Option | Description |
|
|
222
|
+
|--------|-------------|
|
|
223
|
+
| `-o, --output <prefix>` | Output path prefix (e.g. `/tmp/debug`) |
|
|
224
|
+
| `-s, --selector <css>` | CSS selector to screenshot (full window if omitted) |
|
|
225
|
+
| `-t, --title <regex>` | Window title to match (default: auto-discover) |
|
|
226
|
+
| `--dom-depth <number>` | DOM tree depth (default: 3) |
|
|
227
|
+
| `--eval <js>` | Additional JS to eval and save |
|
|
228
|
+
| `--json` | Output structured manifest |
|
|
229
|
+
|
|
192
230
|
## How It Works
|
|
193
231
|
|
|
194
232
|
```
|
|
@@ -253,7 +291,7 @@ This package ships [Agent Skills](https://agentskills.io) so AI coding agents ca
|
|
|
253
291
|
|
|
254
292
|
| Skill | Description |
|
|
255
293
|
|-------|-------------|
|
|
256
|
-
| `tauri-agent-tools` | Using all
|
|
294
|
+
| `tauri-agent-tools` | Using all 14 CLI commands to inspect Tauri apps |
|
|
257
295
|
| `tauri-bridge-setup` | Adding the Rust dev bridge to a Tauri project |
|
|
258
296
|
|
|
259
297
|
<details>
|
|
@@ -307,7 +345,7 @@ Full documentation is available at the [docs site](https://cesarandreslopez.gith
|
|
|
307
345
|
- [Installation](https://cesarandreslopez.github.io/tauri-agent-tools/getting-started/installation/) — system requirements and setup
|
|
308
346
|
- [Quick Start](https://cesarandreslopez.github.io/tauri-agent-tools/getting-started/quick-start/) — get running in 5 minutes
|
|
309
347
|
- [Bridge Setup](https://cesarandreslopez.github.io/tauri-agent-tools/getting-started/bridge-setup/) — integrate the Rust bridge into your Tauri app
|
|
310
|
-
- [Command Reference](https://cesarandreslopez.github.io/tauri-agent-tools/commands/) — all
|
|
348
|
+
- [Command Reference](https://cesarandreslopez.github.io/tauri-agent-tools/commands/) — all 14 commands with examples
|
|
311
349
|
- [Platform Support](https://cesarandreslopez.github.io/tauri-agent-tools/platform-support/) — X11, Wayland, macOS details
|
|
312
350
|
- [Architecture](https://cesarandreslopez.github.io/tauri-agent-tools/architecture/overview/) — how it works under the hood
|
|
313
351
|
|
package/dist/cli.js
CHANGED
|
@@ -17,6 +17,9 @@ import { registerIpcMonitor } from './commands/ipcMonitor.js';
|
|
|
17
17
|
import { registerPageState } from './commands/pageState.js';
|
|
18
18
|
import { registerStorage } from './commands/storage.js';
|
|
19
19
|
import { registerConsoleMonitor } from './commands/consoleMonitor.js';
|
|
20
|
+
import { registerMutations } from './commands/mutations.js';
|
|
21
|
+
import { registerSnapshot } from './commands/snapshot.js';
|
|
22
|
+
import { registerDiff } from './commands/diff.js';
|
|
20
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
21
24
|
const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'));
|
|
22
25
|
const program = new Command()
|
|
@@ -47,6 +50,9 @@ registerIpcMonitor(program);
|
|
|
47
50
|
registerPageState(program);
|
|
48
51
|
registerStorage(program);
|
|
49
52
|
registerConsoleMonitor(program);
|
|
53
|
+
registerMutations(program);
|
|
54
|
+
registerSnapshot(program, getAdapter);
|
|
55
|
+
registerDiff(program);
|
|
50
56
|
program.parseAsync().catch((err) => {
|
|
51
57
|
console.error(err instanceof Error ? err.message : String(err));
|
|
52
58
|
process.exitCode = 1;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { exec } from '../util/exec.js';
|
|
4
|
+
function formatResult(result) {
|
|
5
|
+
const lines = [
|
|
6
|
+
`Pixels different: ${result.pixelsDifferent}`,
|
|
7
|
+
`Total pixels: ${result.totalPixels}`,
|
|
8
|
+
`Difference: ${result.percentDifferent.toFixed(3)}%`,
|
|
9
|
+
];
|
|
10
|
+
if (result.diffImage) {
|
|
11
|
+
lines.push(`Diff image: ${result.diffImage}`);
|
|
12
|
+
}
|
|
13
|
+
return lines.join('\n');
|
|
14
|
+
}
|
|
15
|
+
export function registerDiff(program) {
|
|
16
|
+
const cmd = new Command('diff')
|
|
17
|
+
.description('Compare two screenshots and output difference metrics')
|
|
18
|
+
.argument('<image1>', 'First image path')
|
|
19
|
+
.argument('<image2>', 'Second image path')
|
|
20
|
+
.option('-o, --output <path>', 'Diff image output path')
|
|
21
|
+
.option('--threshold <percent>', 'Fail (exit code 1) if difference exceeds this percentage', parseFloat)
|
|
22
|
+
.option('--json', 'Output structured JSON');
|
|
23
|
+
cmd.action(async (image1, image2, opts) => {
|
|
24
|
+
// Verify files exist
|
|
25
|
+
for (const img of [image1, image2]) {
|
|
26
|
+
try {
|
|
27
|
+
await stat(img);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
throw new Error(`File not found: ${img}`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Get image dimensions for total pixel count
|
|
34
|
+
let totalPixels = 0;
|
|
35
|
+
try {
|
|
36
|
+
const { stdout } = await exec('identify', ['-format', '%w %h', image1]);
|
|
37
|
+
const [w, h] = stdout.toString().trim().split(' ').map(Number);
|
|
38
|
+
totalPixels = w * h;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
if (opts.threshold !== undefined) {
|
|
42
|
+
throw new Error('Cannot compute percentage: `identify` failed to read image dimensions');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Compare images
|
|
46
|
+
const diffOutput = opts.output ?? '/dev/null';
|
|
47
|
+
let pixelsDifferent = 0;
|
|
48
|
+
try {
|
|
49
|
+
// compare exits with code 1 when images differ (not an error)
|
|
50
|
+
const { stderr } = await exec('compare', [
|
|
51
|
+
'-metric', 'AE',
|
|
52
|
+
image1,
|
|
53
|
+
image2,
|
|
54
|
+
diffOutput,
|
|
55
|
+
]);
|
|
56
|
+
pixelsDifferent = parseInt(stderr.trim(), 10) || 0;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
// ImageMagick `compare` exits 1 when images differ — parse stderr
|
|
60
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
61
|
+
const match = msg.match(/(\d+)/);
|
|
62
|
+
if (match) {
|
|
63
|
+
pixelsDifferent = parseInt(match[1], 10);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
throw err;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const percentDifferent = totalPixels > 0
|
|
70
|
+
? (pixelsDifferent / totalPixels) * 100
|
|
71
|
+
: 0;
|
|
72
|
+
const result = {
|
|
73
|
+
pixelsDifferent,
|
|
74
|
+
totalPixels,
|
|
75
|
+
percentDifferent,
|
|
76
|
+
diffImage: opts.output ?? null,
|
|
77
|
+
};
|
|
78
|
+
if (opts.json) {
|
|
79
|
+
console.log(JSON.stringify(result, null, 2));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
console.log(formatResult(result));
|
|
83
|
+
}
|
|
84
|
+
if (opts.threshold !== undefined && percentDifferent > opts.threshold) {
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
program.addCommand(cmd);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/commands/diff.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/dom.d.ts
CHANGED
package/dist/commands/dom.js
CHANGED
|
@@ -66,7 +66,7 @@ function printTree(node, indent, maxDepth) {
|
|
|
66
66
|
}
|
|
67
67
|
return lines;
|
|
68
68
|
}
|
|
69
|
-
function buildSerializerScript(selector, depth, includeStyles) {
|
|
69
|
+
export function buildSerializerScript(selector, depth, includeStyles) {
|
|
70
70
|
return `(() => {
|
|
71
71
|
function serialize(el, d, maxD, styles) {
|
|
72
72
|
const r = el.getBoundingClientRect();
|
|
@@ -123,6 +123,7 @@ export function registerDom(program) {
|
|
|
123
123
|
.option('--depth <number>', 'Max child depth', parseInt, 3)
|
|
124
124
|
.option('--tree', 'Compact tree view (default)')
|
|
125
125
|
.option('--styles', 'Include computed styles')
|
|
126
|
+
.option('--text <pattern>', 'Find elements containing this text (case-insensitive)')
|
|
126
127
|
.option('--count', 'Just output match count')
|
|
127
128
|
.option('--first', 'Only return first match')
|
|
128
129
|
.option('--json', 'Full structured JSON output');
|
|
@@ -130,6 +131,67 @@ export function registerDom(program) {
|
|
|
130
131
|
cmd.action(async (selectorArg, opts) => {
|
|
131
132
|
const selector = opts.selector ?? selectorArg;
|
|
132
133
|
const bridge = await resolveBridge(opts);
|
|
134
|
+
// Find-by-text mode
|
|
135
|
+
if (opts.text) {
|
|
136
|
+
const escapedText = opts.text.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
137
|
+
const escapedSelector = selector.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
138
|
+
const textScript = `(() => {
|
|
139
|
+
var root = document.querySelector('${escapedSelector}') || document.body;
|
|
140
|
+
var pattern = '${escapedText}'.toLowerCase();
|
|
141
|
+
var walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null);
|
|
142
|
+
var seen = new Set();
|
|
143
|
+
var results = [];
|
|
144
|
+
while (walker.nextNode()) {
|
|
145
|
+
var textNode = walker.currentNode;
|
|
146
|
+
if (textNode.textContent && textNode.textContent.toLowerCase().includes(pattern)) {
|
|
147
|
+
var el = textNode.parentElement;
|
|
148
|
+
if (el && !seen.has(el)) {
|
|
149
|
+
seen.add(el);
|
|
150
|
+
var r = el.getBoundingClientRect();
|
|
151
|
+
var node = { tag: el.tagName.toLowerCase(), rect: { width: r.width, height: r.height } };
|
|
152
|
+
if (el.id) node.id = el.id;
|
|
153
|
+
var cls = Array.from(el.classList);
|
|
154
|
+
if (cls.length) node.classes = cls;
|
|
155
|
+
node.text = el.textContent.trim().substring(0, 100);
|
|
156
|
+
results.push(node);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return JSON.stringify(results);
|
|
161
|
+
})()`;
|
|
162
|
+
const raw = await bridge.eval(textScript);
|
|
163
|
+
const matches = JSON.parse(String(raw));
|
|
164
|
+
if (opts.count) {
|
|
165
|
+
console.log(String(matches.length));
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (opts.first) {
|
|
169
|
+
if (matches.length === 0) {
|
|
170
|
+
throw new Error(`No elements found containing "${opts.text}"`);
|
|
171
|
+
}
|
|
172
|
+
if (opts.json) {
|
|
173
|
+
console.log(JSON.stringify(matches[0], null, 2));
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
console.log(formatTreeLine(matches[0], 0));
|
|
177
|
+
}
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (opts.json) {
|
|
181
|
+
console.log(JSON.stringify(matches, null, 2));
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
if (matches.length === 0) {
|
|
185
|
+
console.log(`No elements found containing "${opts.text}"`);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
for (const node of matches) {
|
|
189
|
+
console.log(formatTreeLine(node, 0));
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
133
195
|
if (opts.mode === 'accessibility') {
|
|
134
196
|
const tree = await bridge.getAccessibilityTree(selector, opts.depth);
|
|
135
197
|
if (!tree) {
|
package/dist/commands/dom.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/commands/dom.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/commands/dom.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export interface MutationEntry {
|
|
3
|
+
type: string;
|
|
4
|
+
target: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
added?: Array<{
|
|
7
|
+
tag: string;
|
|
8
|
+
id?: string;
|
|
9
|
+
class?: string;
|
|
10
|
+
}>;
|
|
11
|
+
removed?: Array<{
|
|
12
|
+
tag: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
class?: string;
|
|
15
|
+
}>;
|
|
16
|
+
attribute?: string;
|
|
17
|
+
oldValue?: string | null;
|
|
18
|
+
newValue?: string | null;
|
|
19
|
+
}
|
|
20
|
+
export declare function formatEntry(entry: MutationEntry): string;
|
|
21
|
+
export declare function registerMutations(program: Command): void;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { addBridgeOptions, resolveBridge } from './shared.js';
|
|
3
|
+
function buildPatchScript(selector, watchAttributes) {
|
|
4
|
+
const escaped = selector.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
5
|
+
return `(() => {
|
|
6
|
+
if (window.__tauriDevToolsMutationPatched) return 'already_patched';
|
|
7
|
+
var target = document.querySelector('${escaped}');
|
|
8
|
+
if (!target) return 'not_found';
|
|
9
|
+
window.__tauriDevToolsMutationLog = [];
|
|
10
|
+
function describeEl(el) {
|
|
11
|
+
if (!el || el.nodeType !== 1) return null;
|
|
12
|
+
var d = { tag: el.tagName.toLowerCase() };
|
|
13
|
+
if (el.id) d.id = el.id;
|
|
14
|
+
var cls = Array.from(el.classList).join(' ');
|
|
15
|
+
if (cls) d.class = cls;
|
|
16
|
+
return d;
|
|
17
|
+
}
|
|
18
|
+
window.__tauriDevToolsMutationObserver = new MutationObserver(function(mutations) {
|
|
19
|
+
for (var i = 0; i < mutations.length; i++) {
|
|
20
|
+
var m = mutations[i];
|
|
21
|
+
var entry = { type: m.type, timestamp: Date.now() };
|
|
22
|
+
var t = m.target;
|
|
23
|
+
entry.target = (t.id ? '#' + t.id : '') || (t.className && typeof t.className === 'string' ? '.' + t.className.split(' ').join('.') : t.tagName ? t.tagName.toLowerCase() : '?');
|
|
24
|
+
if (m.type === 'childList') {
|
|
25
|
+
entry.added = Array.from(m.addedNodes).map(describeEl).filter(Boolean);
|
|
26
|
+
entry.removed = Array.from(m.removedNodes).map(describeEl).filter(Boolean);
|
|
27
|
+
} else if (m.type === 'attributes') {
|
|
28
|
+
entry.attribute = m.attributeName;
|
|
29
|
+
entry.oldValue = m.oldValue;
|
|
30
|
+
entry.newValue = m.target.getAttribute(m.attributeName);
|
|
31
|
+
}
|
|
32
|
+
window.__tauriDevToolsMutationLog.push(entry);
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
window.__tauriDevToolsMutationObserver.observe(target, {
|
|
36
|
+
childList: true,
|
|
37
|
+
subtree: true,
|
|
38
|
+
attributes: ${watchAttributes},
|
|
39
|
+
attributeOldValue: ${watchAttributes}
|
|
40
|
+
});
|
|
41
|
+
window.__tauriDevToolsMutationPatched = true;
|
|
42
|
+
return 'patched';
|
|
43
|
+
})()`;
|
|
44
|
+
}
|
|
45
|
+
const DRAIN_SCRIPT = `(() => {
|
|
46
|
+
var log = window.__tauriDevToolsMutationLog || [];
|
|
47
|
+
window.__tauriDevToolsMutationLog = [];
|
|
48
|
+
return JSON.stringify(log);
|
|
49
|
+
})()`;
|
|
50
|
+
const CLEANUP_SCRIPT = `(() => {
|
|
51
|
+
if (window.__tauriDevToolsMutationObserver) {
|
|
52
|
+
window.__tauriDevToolsMutationObserver.disconnect();
|
|
53
|
+
delete window.__tauriDevToolsMutationObserver;
|
|
54
|
+
delete window.__tauriDevToolsMutationLog;
|
|
55
|
+
delete window.__tauriDevToolsMutationPatched;
|
|
56
|
+
}
|
|
57
|
+
return 'cleaned';
|
|
58
|
+
})()`;
|
|
59
|
+
export function formatEntry(entry) {
|
|
60
|
+
const time = new Date(entry.timestamp).toISOString().slice(11, 23);
|
|
61
|
+
if (entry.type === 'childList') {
|
|
62
|
+
const parts = [];
|
|
63
|
+
if (entry.added?.length) {
|
|
64
|
+
parts.push(`+${entry.added.map(n => n.class ? `.${n.class.split(' ').join('.')}` : n.tag).join(', ')}`);
|
|
65
|
+
}
|
|
66
|
+
if (entry.removed?.length) {
|
|
67
|
+
parts.push(`-${entry.removed.map(n => n.class ? `.${n.class.split(' ').join('.')}` : n.tag).join(', ')}`);
|
|
68
|
+
}
|
|
69
|
+
return `[${time}] childList ${entry.target} ${parts.join(' ')}`;
|
|
70
|
+
}
|
|
71
|
+
if (entry.type === 'attributes') {
|
|
72
|
+
return `[${time}] attr ${entry.target} ${entry.attribute}: ${entry.oldValue} → ${entry.newValue}`;
|
|
73
|
+
}
|
|
74
|
+
return `[${time}] ${entry.type} ${entry.target}`;
|
|
75
|
+
}
|
|
76
|
+
async function cleanup(bridge) {
|
|
77
|
+
try {
|
|
78
|
+
await bridge.eval(CLEANUP_SCRIPT);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Best-effort cleanup
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
export function registerMutations(program) {
|
|
85
|
+
const cmd = new Command('mutations')
|
|
86
|
+
.description('Watch DOM mutations on a CSS selector (read-only)')
|
|
87
|
+
.argument('<selector>', 'CSS selector of the element to observe')
|
|
88
|
+
.option('--attributes', 'Also watch attribute changes')
|
|
89
|
+
.option('--interval <ms>', 'Poll interval in milliseconds', parseInt, 500)
|
|
90
|
+
.option('--duration <ms>', 'Auto-stop after N milliseconds', parseInt)
|
|
91
|
+
.option('--json', 'Output one JSON object per line');
|
|
92
|
+
addBridgeOptions(cmd);
|
|
93
|
+
cmd.action(async (selector, opts) => {
|
|
94
|
+
const bridge = await resolveBridge(opts);
|
|
95
|
+
const patchResult = await bridge.eval(buildPatchScript(selector, !!opts.attributes));
|
|
96
|
+
if (patchResult === 'not_found') {
|
|
97
|
+
throw new Error(`Element not found: ${selector}`);
|
|
98
|
+
}
|
|
99
|
+
if (patchResult === 'already_patched') {
|
|
100
|
+
console.error('Warning: mutation observer already active — draining existing log');
|
|
101
|
+
}
|
|
102
|
+
let stopped = false;
|
|
103
|
+
const onSignal = () => {
|
|
104
|
+
stopped = true;
|
|
105
|
+
};
|
|
106
|
+
process.on('SIGINT', onSignal);
|
|
107
|
+
process.on('SIGTERM', onSignal);
|
|
108
|
+
let timer;
|
|
109
|
+
if (opts.duration) {
|
|
110
|
+
timer = setTimeout(() => {
|
|
111
|
+
stopped = true;
|
|
112
|
+
}, opts.duration);
|
|
113
|
+
}
|
|
114
|
+
if (!opts.json) {
|
|
115
|
+
console.error(`Watching mutations on ${selector}... (Ctrl+C to stop)`);
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
while (!stopped) {
|
|
119
|
+
await new Promise((resolve) => setTimeout(resolve, opts.interval));
|
|
120
|
+
if (stopped)
|
|
121
|
+
break;
|
|
122
|
+
const raw = await bridge.eval(DRAIN_SCRIPT);
|
|
123
|
+
const entries = JSON.parse(String(raw));
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (opts.json) {
|
|
126
|
+
console.log(JSON.stringify(entry));
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.log(formatEntry(entry));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
if (timer)
|
|
136
|
+
clearTimeout(timer);
|
|
137
|
+
process.off('SIGINT', onSignal);
|
|
138
|
+
process.off('SIGTERM', onSignal);
|
|
139
|
+
await cleanup(bridge);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
program.addCommand(cmd);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=mutations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mutations.js","sourceRoot":"","sources":["../../src/commands/mutations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { writeFile } from 'node:fs/promises';
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { addBridgeOptions, resolveBridge } from './shared.js';
|
|
4
|
+
import { buildSerializerScript } from './dom.js';
|
|
5
|
+
import { computeCropRect, cropImage } from '../util/image.js';
|
|
6
|
+
const PAGE_STATE_SCRIPT = `(() => {
|
|
7
|
+
return JSON.stringify({
|
|
8
|
+
url: window.location.href,
|
|
9
|
+
title: document.title,
|
|
10
|
+
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
11
|
+
scroll: { x: Math.round(window.scrollX), y: Math.round(window.scrollY) },
|
|
12
|
+
document: { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight },
|
|
13
|
+
hasTauri: !!(window.__TAURI__)
|
|
14
|
+
});
|
|
15
|
+
})()`;
|
|
16
|
+
const STORAGE_SCRIPT = `(() => {
|
|
17
|
+
var local = Object.keys(localStorage).map(function(k) { return { key: k, value: localStorage.getItem(k) }; });
|
|
18
|
+
var session = Object.keys(sessionStorage).map(function(k) { return { key: k, value: sessionStorage.getItem(k) }; });
|
|
19
|
+
return JSON.stringify({ localStorage: local, sessionStorage: session });
|
|
20
|
+
})()`;
|
|
21
|
+
async function resolveWindowId(adapter, bridge, title) {
|
|
22
|
+
if (title)
|
|
23
|
+
return adapter.findWindow(title);
|
|
24
|
+
const docTitle = await bridge.getDocumentTitle();
|
|
25
|
+
if (!docTitle)
|
|
26
|
+
throw new Error('Could not get window title. Use --title.');
|
|
27
|
+
return adapter.findWindow(docTitle);
|
|
28
|
+
}
|
|
29
|
+
export function registerSnapshot(program, getAdapter) {
|
|
30
|
+
const cmd = new Command('snapshot')
|
|
31
|
+
.description('Capture screenshot + DOM + page state + storage in one shot')
|
|
32
|
+
.requiredOption('-o, --output <prefix>', 'Output path prefix (e.g. /tmp/debug)')
|
|
33
|
+
.option('-s, --selector <css>', 'CSS selector to screenshot (full window if omitted)')
|
|
34
|
+
.option('-t, --title <regex>', 'Window title to match (default: auto-discover)')
|
|
35
|
+
.option('--dom-depth <number>', 'DOM tree depth', parseInt, 3)
|
|
36
|
+
.option('--eval <js>', 'Additional JS to eval and save')
|
|
37
|
+
.option('--json', 'Output structured manifest');
|
|
38
|
+
addBridgeOptions(cmd);
|
|
39
|
+
cmd.action(async (opts) => {
|
|
40
|
+
const bridge = await resolveBridge(opts);
|
|
41
|
+
const adapter = await getAdapter();
|
|
42
|
+
const prefix = opts.output;
|
|
43
|
+
const format = 'png';
|
|
44
|
+
const files = {};
|
|
45
|
+
// 1. Screenshot
|
|
46
|
+
try {
|
|
47
|
+
const windowId = await resolveWindowId(adapter, bridge, opts.title);
|
|
48
|
+
let buffer;
|
|
49
|
+
if (opts.selector) {
|
|
50
|
+
const elementRect = await bridge.getElementRect(opts.selector);
|
|
51
|
+
if (!elementRect)
|
|
52
|
+
throw new Error(`Element not found: ${opts.selector}`);
|
|
53
|
+
const viewport = await bridge.getViewportSize();
|
|
54
|
+
const windowGeom = await adapter.getWindowGeometry(windowId);
|
|
55
|
+
buffer = await adapter.captureWindow(windowId, format);
|
|
56
|
+
const cropRect = computeCropRect(elementRect, viewport, {
|
|
57
|
+
width: windowGeom.width,
|
|
58
|
+
height: windowGeom.height,
|
|
59
|
+
});
|
|
60
|
+
buffer = await cropImage(buffer, cropRect, format);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
buffer = await adapter.captureWindow(windowId, format);
|
|
64
|
+
}
|
|
65
|
+
const path = `${prefix}-screenshot.png`;
|
|
66
|
+
await writeFile(path, buffer);
|
|
67
|
+
files.screenshot = path;
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
files.screenshot = `error: ${err instanceof Error ? err.message : String(err)}`;
|
|
71
|
+
}
|
|
72
|
+
// 2. DOM
|
|
73
|
+
try {
|
|
74
|
+
const raw = await bridge.eval(buildSerializerScript('body', opts.domDepth, false));
|
|
75
|
+
const path = `${prefix}-dom.json`;
|
|
76
|
+
await writeFile(path, JSON.stringify(JSON.parse(String(raw)), null, 2));
|
|
77
|
+
files.dom = path;
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
files.dom = `error: ${err instanceof Error ? err.message : String(err)}`;
|
|
81
|
+
}
|
|
82
|
+
// 3. Page state
|
|
83
|
+
try {
|
|
84
|
+
const raw = await bridge.eval(PAGE_STATE_SCRIPT);
|
|
85
|
+
const path = `${prefix}-page-state.json`;
|
|
86
|
+
await writeFile(path, JSON.stringify(JSON.parse(String(raw)), null, 2));
|
|
87
|
+
files.pageState = path;
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
files.pageState = `error: ${err instanceof Error ? err.message : String(err)}`;
|
|
91
|
+
}
|
|
92
|
+
// 4. Storage
|
|
93
|
+
try {
|
|
94
|
+
const raw = await bridge.eval(STORAGE_SCRIPT);
|
|
95
|
+
const path = `${prefix}-storage.json`;
|
|
96
|
+
await writeFile(path, JSON.stringify(JSON.parse(String(raw)), null, 2));
|
|
97
|
+
files.storage = path;
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
files.storage = `error: ${err instanceof Error ? err.message : String(err)}`;
|
|
101
|
+
}
|
|
102
|
+
// 5. Custom eval (optional)
|
|
103
|
+
if (opts.eval) {
|
|
104
|
+
try {
|
|
105
|
+
const raw = await bridge.eval(opts.eval);
|
|
106
|
+
const path = `${prefix}-eval.json`;
|
|
107
|
+
const parsed = typeof raw === 'string' ? (() => { try {
|
|
108
|
+
return JSON.parse(raw);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return raw;
|
|
112
|
+
} })() : raw;
|
|
113
|
+
await writeFile(path, JSON.stringify(parsed, null, 2));
|
|
114
|
+
files.eval = path;
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
files.eval = `error: ${err instanceof Error ? err.message : String(err)}`;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (opts.json) {
|
|
121
|
+
console.log(JSON.stringify(files, null, 2));
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
for (const [key, path] of Object.entries(files)) {
|
|
125
|
+
console.log(`${key}: ${path}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
program.addCommand(cmd);
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/commands/snapshot.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tauri-agent-tools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Agent-driven inspection toolkit for Tauri desktop apps",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@eslint/js": "^9.0.0",
|
|
50
50
|
"@types/node": "^22.0.0",
|
|
51
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
51
52
|
"eslint": "^9.0.0",
|
|
52
53
|
"typescript": "^5.8.0",
|
|
53
54
|
"typescript-eslint": "^8.0.0",
|