tauri-agent-tools 0.7.0 → 0.7.1
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 +1 -1
- package/.agents/skills/tauri-bridge-setup/SKILL.md +1 -1
- package/.agents/skills/tauri-debug-quickstart/SKILL.md +1 -1
- package/README.md +1 -1
- package/dist/bridge/tokenDiscovery.js +29 -29
- package/dist/bridge/tokenDiscovery.js.map +1 -1
- package/dist/commands/capture.js +1 -1
- package/dist/commands/invoke.js +14 -4
- package/dist/commands/invoke.js.map +1 -1
- package/dist/commands/ipcMonitor.d.ts +3 -0
- package/dist/commands/ipcMonitor.js +22 -10
- package/dist/commands/ipcMonitor.js.map +1 -1
- package/dist/commands/pageState.d.ts +1 -0
- package/dist/commands/pageState.js +2 -2
- package/dist/commands/pageState.js.map +1 -1
- package/dist/commands/snapshot.js +1 -1
- package/examples/tauri-bridge/src/dev_bridge.rs +112 -32
- package/package.json +1 -1
- package/rust-bridge/README.md +10 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tauri-agent-tools
|
|
3
3
|
description: CLI for inspecting and interacting with Tauri desktop apps — DOM queries, screenshots, interaction (click/type/scroll), IPC monitoring, store inspection, structured assertions, plus bridge-free diagnostics (OS logs, app paths, sidecar NDJSON tap/replay, forensic bundles) and the `diagnose` super-command for one-shot triage
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
tags: [tauri, desktop, debugging, screenshot, dom, inspection, diff, mutations, snapshot, interaction, click, type, scroll, invoke, probe, capture, check, store-inspect, forensics, os-logs, app-paths, sidecar, config-inspect, diagnose]
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tauri-bridge-setup
|
|
3
3
|
description: How to add the tauri-agent-tools Rust dev bridge to a Tauri application
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
tags: [tauri, rust, bridge, setup, integration, multi-window, process-tree, capabilities, devtools, health]
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: tauri-debug-quickstart
|
|
3
3
|
description: First-30-seconds triage for a broken Tauri desktop app. Pick the right command for the symptom you're seeing, with one-line escalations to deeper skills.
|
|
4
|
-
version: 0.7.
|
|
4
|
+
version: 0.7.1
|
|
5
5
|
tags: [tauri, debugging, triage, quickstart, decision-tree, forensics, diagnose]
|
|
6
6
|
---
|
|
7
7
|
|
package/README.md
CHANGED
|
@@ -161,7 +161,7 @@ List all visible windows, marking Tauri apps.
|
|
|
161
161
|
|
|
162
162
|
### `ipc-monitor`
|
|
163
163
|
|
|
164
|
-
Monitor Tauri IPC calls in real-time (read-only). Monkey-patches `window.__TAURI__.core.invoke` to capture calls, then polls and restores on exit.
|
|
164
|
+
Monitor Tauri IPC calls in real-time (read-only). Monkey-patches Tauri's invoke API (`window.__TAURI_INTERNALS__.invoke`, falling back to `window.__TAURI__.core.invoke`) to capture calls, then polls and restores on exit.
|
|
165
165
|
|
|
166
166
|
| Option | Description |
|
|
167
167
|
|--------|-------------|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readdir, readFile, unlink } from 'node:fs/promises';
|
|
2
2
|
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
3
4
|
import { TokenFileSchema } from '../schemas/bridge.js';
|
|
4
|
-
const
|
|
5
|
+
const FALLBACK_TOKEN_DIR = '/tmp';
|
|
5
6
|
const TOKEN_PREFIX = 'tauri-dev-bridge-';
|
|
6
7
|
const TOKEN_SUFFIX = '.token';
|
|
7
8
|
function isPidAlive(pid) {
|
|
@@ -13,18 +14,21 @@ function isPidAlive(pid) {
|
|
|
13
14
|
return false;
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
+
function getTokenDirs() {
|
|
18
|
+
return [...new Set([tmpdir(), FALLBACK_TOKEN_DIR])];
|
|
19
|
+
}
|
|
20
|
+
async function scanTokenDir(tokenDir) {
|
|
17
21
|
let files;
|
|
18
22
|
try {
|
|
19
|
-
files = await readdir(
|
|
23
|
+
files = await readdir(tokenDir);
|
|
20
24
|
}
|
|
21
25
|
catch {
|
|
22
|
-
return
|
|
26
|
+
return [];
|
|
23
27
|
}
|
|
24
28
|
const tokenFiles = files.filter((f) => f.startsWith(TOKEN_PREFIX) && f.endsWith(TOKEN_SUFFIX));
|
|
25
|
-
|
|
29
|
+
const found = [];
|
|
26
30
|
for (const file of tokenFiles) {
|
|
27
|
-
const filePath =
|
|
31
|
+
const filePath = join(tokenDir, file);
|
|
28
32
|
try {
|
|
29
33
|
const content = await readFile(filePath, 'utf-8');
|
|
30
34
|
const data = TokenFileSchema.parse(JSON.parse(content));
|
|
@@ -33,9 +37,10 @@ export async function discoverBridge() {
|
|
|
33
37
|
await unlink(filePath).catch(() => { });
|
|
34
38
|
continue;
|
|
35
39
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
40
|
+
found.push({
|
|
41
|
+
pid: data.pid,
|
|
42
|
+
config: { port: data.port, token: data.token },
|
|
43
|
+
});
|
|
39
44
|
}
|
|
40
45
|
catch {
|
|
41
46
|
// Skip malformed files
|
|
@@ -44,29 +49,24 @@ export async function discoverBridge() {
|
|
|
44
49
|
}
|
|
45
50
|
return found;
|
|
46
51
|
}
|
|
52
|
+
export async function discoverBridge() {
|
|
53
|
+
let first = null;
|
|
54
|
+
for (const tokenDir of getTokenDirs()) {
|
|
55
|
+
const bridges = await scanTokenDir(tokenDir);
|
|
56
|
+
if (!first && bridges.length > 0) {
|
|
57
|
+
first = bridges[0].config;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return first;
|
|
61
|
+
}
|
|
47
62
|
export async function discoverBridgesByPid() {
|
|
48
63
|
const result = new Map();
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return result;
|
|
55
|
-
}
|
|
56
|
-
const tokenFiles = files.filter((f) => f.startsWith(TOKEN_PREFIX) && f.endsWith(TOKEN_SUFFIX));
|
|
57
|
-
for (const file of tokenFiles) {
|
|
58
|
-
const filePath = `${TOKEN_DIR}/${file}`;
|
|
59
|
-
try {
|
|
60
|
-
const content = await readFile(filePath, 'utf-8');
|
|
61
|
-
const data = TokenFileSchema.parse(JSON.parse(content));
|
|
62
|
-
if (!isPidAlive(data.pid)) {
|
|
63
|
-
await unlink(filePath).catch(() => { });
|
|
64
|
-
continue;
|
|
64
|
+
for (const tokenDir of getTokenDirs()) {
|
|
65
|
+
const bridges = await scanTokenDir(tokenDir);
|
|
66
|
+
for (const bridge of bridges) {
|
|
67
|
+
if (!result.has(bridge.pid)) {
|
|
68
|
+
result.set(bridge.pid, bridge.config);
|
|
65
69
|
}
|
|
66
|
-
result.set(data.pid, { port: data.port, token: data.token });
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
continue;
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokenDiscovery.js","sourceRoot":"","sources":["../../src/bridge/tokenDiscovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,
|
|
1
|
+
{"version":3,"file":"tokenDiscovery.js","sourceRoot":"","sources":["../../src/bridge/tokenDiscovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,MAAM,YAAY,GAAG,mBAAmB,CAAC;AACzC,MAAM,YAAY,GAAG,QAAQ,CAAC;AAO9B,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,YAAY;IACnB,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAC9D,CAAC;IAEF,MAAM,KAAK,GAAuB,EAAE,CAAC;IAErC,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAClD,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAExD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,8CAA8C;gBAC9C,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;gBACvC,SAAS;YACX,CAAC;YAED,KAAK,CAAC,IAAI,CAAC;gBACT,GAAG,EAAE,IAAI,CAAC,GAAG;gBACb,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE;aAC/C,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;YACvB,SAAS;QACX,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,KAAK,GAAwB,IAAI,CAAC;IAEtC,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,KAAK,GAAG,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;IAE/C,KAAK,MAAM,QAAQ,IAAI,YAAY,EAAE,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC7C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/dist/commands/capture.js
CHANGED
|
@@ -13,7 +13,7 @@ const PAGE_STATE_SCRIPT = `(() => {
|
|
|
13
13
|
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
14
14
|
scroll: { x: Math.round(window.scrollX), y: Math.round(window.scrollY) },
|
|
15
15
|
document: { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight },
|
|
16
|
-
hasTauri: !!(window.__TAURI__)
|
|
16
|
+
hasTauri: !!(window.__TAURI_INTERNALS__ || window.__TAURI__)
|
|
17
17
|
});
|
|
18
18
|
})()`;
|
|
19
19
|
const STORAGE_SCRIPT = `(() => {
|
package/dist/commands/invoke.js
CHANGED
|
@@ -5,14 +5,24 @@ export function buildInvokeScript(command, args) {
|
|
|
5
5
|
const commandJson = JSON.stringify(command);
|
|
6
6
|
const argsJson = JSON.stringify(args);
|
|
7
7
|
return `(async () => {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
function getTauriInvoke() {
|
|
9
|
+
if (window.__TAURI_INTERNALS__ && typeof window.__TAURI_INTERNALS__.invoke === 'function') {
|
|
10
|
+
return window.__TAURI_INTERNALS__.invoke.bind(window.__TAURI_INTERNALS__);
|
|
11
|
+
}
|
|
12
|
+
if (window.__TAURI__ && window.__TAURI__.core && typeof window.__TAURI__.core.invoke === 'function') {
|
|
13
|
+
return window.__TAURI__.core.invoke.bind(window.__TAURI__.core);
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
var invoke = getTauriInvoke();
|
|
18
|
+
if (!invoke) {
|
|
19
|
+
return JSON.stringify({ success: false, command: ${commandJson}, error: 'Tauri invoke API not found: expected window.__TAURI_INTERNALS__.invoke or window.__TAURI__.core.invoke' });
|
|
10
20
|
}
|
|
11
21
|
try {
|
|
12
|
-
var result = await
|
|
22
|
+
var result = await invoke(${commandJson}, ${argsJson});
|
|
13
23
|
return JSON.stringify({ success: true, command: ${commandJson}, result: result });
|
|
14
24
|
} catch (e) {
|
|
15
|
-
return JSON.stringify({ success: false, command: ${commandJson}, error: e.message });
|
|
25
|
+
return JSON.stringify({ success: false, command: ${commandJson}, error: e && e.message ? e.message : String(e) });
|
|
16
26
|
}
|
|
17
27
|
})()`;
|
|
18
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../src/commands/invoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAa;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO
|
|
1
|
+
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../src/commands/invoke.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAG5D,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,IAAa;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO;;;;;;;;;;;;uDAY8C,WAAW;;;gCAGlC,WAAW,KAAK,QAAQ;sDACF,WAAW;;uDAEV,WAAW;;KAE7D,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;SAC9B,WAAW,CAAC,mCAAmC,CAAC;SAChD,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;SAC3C,QAAQ,CAAC,QAAQ,EAAE,oCAAoC,CAAC;SACxD,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEtC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAEtB,GAAG,CAAC,MAAM,CACR,KAAK,EAAE,OAAe,EAAE,OAA2B,EAAE,IAAqC,EAAE,EAAE;QAC5F,IAAI,IAAI,GAAY,EAAE,CAAC;QACvB,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7B,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,KAAK,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAChD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,MAAM,GAAiB,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAE/E,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,kBAAkB,OAAO,aAAa,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACxE,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;YAC1C,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
export declare const PATCH_SCRIPT = "(() => {\n if (window.__tauriDevToolsPatched) return 'already_patched';\n function getInvokeTarget() {\n if (window.__TAURI_INTERNALS__ && typeof window.__TAURI_INTERNALS__.invoke === 'function') {\n return { owner: window.__TAURI_INTERNALS__, invoke: window.__TAURI_INTERNALS__.invoke };\n }\n if (window.__TAURI__ && window.__TAURI__.core && typeof window.__TAURI__.core.invoke === 'function') {\n return { owner: window.__TAURI__.core, invoke: window.__TAURI__.core.invoke };\n }\n return null;\n }\n var target = getInvokeTarget();\n if (!target) {\n return 'no_tauri';\n }\n window.__tauriDevToolsOriginalInvoke = target.invoke;\n window.__tauriDevToolsInvokeOwner = target.owner;\n window.__tauriDevToolsIpcLog = [];\n target.owner.invoke = function(cmd, args, options) {\n var entry = { command: cmd, args: args || {}, timestamp: Date.now() };\n var start = performance.now();\n return window.__tauriDevToolsOriginalInvoke.call(this, cmd, args, options).then(function(result) {\n entry.duration = Math.round(performance.now() - start);\n entry.result = result;\n window.__tauriDevToolsIpcLog.push(entry);\n return result;\n }).catch(function(err) {\n entry.duration = Math.round(performance.now() - start);\n entry.error = err && err.message ? err.message : String(err);\n window.__tauriDevToolsIpcLog.push(entry);\n throw err;\n });\n };\n window.__tauriDevToolsPatched = true;\n return 'patched';\n})()";
|
|
3
|
+
export declare const DRAIN_SCRIPT = "(() => {\n var log = window.__tauriDevToolsIpcLog || [];\n window.__tauriDevToolsIpcLog = [];\n return JSON.stringify(log);\n})()";
|
|
4
|
+
export declare const CLEANUP_SCRIPT = "(() => {\n if (window.__tauriDevToolsOriginalInvoke && window.__tauriDevToolsInvokeOwner) {\n window.__tauriDevToolsInvokeOwner.invoke = window.__tauriDevToolsOriginalInvoke;\n delete window.__tauriDevToolsOriginalInvoke;\n delete window.__tauriDevToolsInvokeOwner;\n delete window.__tauriDevToolsIpcLog;\n delete window.__tauriDevToolsPatched;\n }\n return 'cleaned';\n})()";
|
|
2
5
|
export declare function registerIpcMonitor(program: Command): void;
|
|
@@ -2,17 +2,28 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { addBridgeOptions, resolveBridge } from './shared.js';
|
|
4
4
|
import { IpcEntrySchema } from '../schemas/commands.js';
|
|
5
|
-
const PATCH_SCRIPT = `(() => {
|
|
5
|
+
export const PATCH_SCRIPT = `(() => {
|
|
6
6
|
if (window.__tauriDevToolsPatched) return 'already_patched';
|
|
7
|
-
|
|
7
|
+
function getInvokeTarget() {
|
|
8
|
+
if (window.__TAURI_INTERNALS__ && typeof window.__TAURI_INTERNALS__.invoke === 'function') {
|
|
9
|
+
return { owner: window.__TAURI_INTERNALS__, invoke: window.__TAURI_INTERNALS__.invoke };
|
|
10
|
+
}
|
|
11
|
+
if (window.__TAURI__ && window.__TAURI__.core && typeof window.__TAURI__.core.invoke === 'function') {
|
|
12
|
+
return { owner: window.__TAURI__.core, invoke: window.__TAURI__.core.invoke };
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
var target = getInvokeTarget();
|
|
17
|
+
if (!target) {
|
|
8
18
|
return 'no_tauri';
|
|
9
19
|
}
|
|
10
|
-
window.__tauriDevToolsOriginalInvoke =
|
|
20
|
+
window.__tauriDevToolsOriginalInvoke = target.invoke;
|
|
21
|
+
window.__tauriDevToolsInvokeOwner = target.owner;
|
|
11
22
|
window.__tauriDevToolsIpcLog = [];
|
|
12
|
-
|
|
23
|
+
target.owner.invoke = function(cmd, args, options) {
|
|
13
24
|
var entry = { command: cmd, args: args || {}, timestamp: Date.now() };
|
|
14
25
|
var start = performance.now();
|
|
15
|
-
return window.__tauriDevToolsOriginalInvoke.call(this, cmd, args).then(function(result) {
|
|
26
|
+
return window.__tauriDevToolsOriginalInvoke.call(this, cmd, args, options).then(function(result) {
|
|
16
27
|
entry.duration = Math.round(performance.now() - start);
|
|
17
28
|
entry.result = result;
|
|
18
29
|
window.__tauriDevToolsIpcLog.push(entry);
|
|
@@ -27,15 +38,16 @@ const PATCH_SCRIPT = `(() => {
|
|
|
27
38
|
window.__tauriDevToolsPatched = true;
|
|
28
39
|
return 'patched';
|
|
29
40
|
})()`;
|
|
30
|
-
const DRAIN_SCRIPT = `(() => {
|
|
41
|
+
export const DRAIN_SCRIPT = `(() => {
|
|
31
42
|
var log = window.__tauriDevToolsIpcLog || [];
|
|
32
43
|
window.__tauriDevToolsIpcLog = [];
|
|
33
44
|
return JSON.stringify(log);
|
|
34
45
|
})()`;
|
|
35
|
-
const CLEANUP_SCRIPT = `(() => {
|
|
36
|
-
if (window.__tauriDevToolsOriginalInvoke) {
|
|
37
|
-
window.
|
|
46
|
+
export const CLEANUP_SCRIPT = `(() => {
|
|
47
|
+
if (window.__tauriDevToolsOriginalInvoke && window.__tauriDevToolsInvokeOwner) {
|
|
48
|
+
window.__tauriDevToolsInvokeOwner.invoke = window.__tauriDevToolsOriginalInvoke;
|
|
38
49
|
delete window.__tauriDevToolsOriginalInvoke;
|
|
50
|
+
delete window.__tauriDevToolsInvokeOwner;
|
|
39
51
|
delete window.__tauriDevToolsIpcLog;
|
|
40
52
|
delete window.__tauriDevToolsPatched;
|
|
41
53
|
}
|
|
@@ -78,7 +90,7 @@ export function registerIpcMonitor(program) {
|
|
|
78
90
|
// Inject the monkey-patch
|
|
79
91
|
const patchResult = await bridge.eval(PATCH_SCRIPT);
|
|
80
92
|
if (patchResult === 'no_tauri') {
|
|
81
|
-
throw new Error('
|
|
93
|
+
throw new Error('Tauri invoke API not found. Expected window.__TAURI_INTERNALS__.invoke or window.__TAURI__.core.invoke.');
|
|
82
94
|
}
|
|
83
95
|
let stopped = false;
|
|
84
96
|
const onSignal = () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ipcMonitor.js","sourceRoot":"","sources":["../../src/commands/ipcMonitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGxD,MAAM,YAAY,GAAG
|
|
1
|
+
{"version":3,"file":"ipcMonitor.js","sourceRoot":"","sources":["../../src/commands/ipcMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
+
export declare const PAGE_STATE_SCRIPT = "(() => {\n var state = {\n url: window.location.href,\n title: document.title,\n viewport: { width: window.innerWidth, height: window.innerHeight },\n scroll: { x: Math.round(window.scrollX), y: Math.round(window.scrollY) },\n document: { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight },\n hasTauri: !!(window.__TAURI_INTERNALS__ || window.__TAURI__)\n };\n return JSON.stringify(state);\n})()";
|
|
2
3
|
export declare function registerPageState(program: Command): void;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { addBridgeOptions, resolveBridge } from './shared.js';
|
|
3
3
|
import { PageStateSchema } from '../schemas/commands.js';
|
|
4
|
-
const PAGE_STATE_SCRIPT = `(() => {
|
|
4
|
+
export const PAGE_STATE_SCRIPT = `(() => {
|
|
5
5
|
var state = {
|
|
6
6
|
url: window.location.href,
|
|
7
7
|
title: document.title,
|
|
8
8
|
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
9
9
|
scroll: { x: Math.round(window.scrollX), y: Math.round(window.scrollY) },
|
|
10
10
|
document: { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight },
|
|
11
|
-
hasTauri: !!(window.__TAURI__)
|
|
11
|
+
hasTauri: !!(window.__TAURI_INTERNALS__ || window.__TAURI__)
|
|
12
12
|
};
|
|
13
13
|
return JSON.stringify(state);
|
|
14
14
|
})()`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pageState.js","sourceRoot":"","sources":["../../src/commands/pageState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,iBAAiB,GAAG;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"pageState.js","sourceRoot":"","sources":["../../src/commands/pageState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;KAU5B,CAAC;AAEN,SAAS,eAAe,CAAC,KAAgB;IACvC,MAAM,KAAK,GAAG;QACZ,oBAAoB,KAAK,CAAC,GAAG,EAAE;QAC/B,oBAAoB,KAAK,CAAC,KAAK,EAAE;QACjC,oBAAoB,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE;QACnE,oBAAoB,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE;QACvD,oBAAoB,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE;QACnE,oBAAoB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE;KACpD,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,OAAgB;IAChD,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC;SAClC,WAAW,CAAC,wEAAwE,CAAC;SACrF,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;IAEtC,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAEtB,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAuD,EAAE,EAAE;QAC3E,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACjD,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAE7D,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -12,7 +12,7 @@ const PAGE_STATE_SCRIPT = `(() => {
|
|
|
12
12
|
viewport: { width: window.innerWidth, height: window.innerHeight },
|
|
13
13
|
scroll: { x: Math.round(window.scrollX), y: Math.round(window.scrollY) },
|
|
14
14
|
document: { width: document.documentElement.scrollWidth, height: document.documentElement.scrollHeight },
|
|
15
|
-
hasTauri: !!(window.__TAURI__)
|
|
15
|
+
hasTauri: !!(window.__TAURI_INTERNALS__ || window.__TAURI__)
|
|
16
16
|
});
|
|
17
17
|
})()`;
|
|
18
18
|
const STORAGE_SCRIPT = `(() => {
|
|
@@ -430,6 +430,57 @@ pub fn __dev_bridge_result(
|
|
|
430
430
|
state.notify.notify_all();
|
|
431
431
|
}
|
|
432
432
|
|
|
433
|
+
const EVAL_TIMEOUT_MESSAGE: &str = "Eval timeout: no result callback received. Re-copy examples/tauri-bridge/src/dev_bridge.rs from tauri-agent-tools 0.7.0+ and verify Tauri IPC is available.";
|
|
434
|
+
|
|
435
|
+
fn build_eval_callback_js(js: &str, request_id: &str) -> String {
|
|
436
|
+
format!(
|
|
437
|
+
r#"
|
|
438
|
+
(async () => {{
|
|
439
|
+
const __getDevBridgeInvoke = () => {{
|
|
440
|
+
if (window.__TAURI_INTERNALS__ && typeof window.__TAURI_INTERNALS__.invoke === "function") {{
|
|
441
|
+
return window.__TAURI_INTERNALS__.invoke.bind(window.__TAURI_INTERNALS__);
|
|
442
|
+
}}
|
|
443
|
+
if (window.__TAURI__ && window.__TAURI__.core && typeof window.__TAURI__.core.invoke === "function") {{
|
|
444
|
+
return window.__TAURI__.core.invoke.bind(window.__TAURI__.core);
|
|
445
|
+
}}
|
|
446
|
+
return null;
|
|
447
|
+
}};
|
|
448
|
+
|
|
449
|
+
let __devBridgeInvoke = __getDevBridgeInvoke();
|
|
450
|
+
try {{
|
|
451
|
+
if (!__devBridgeInvoke) {{
|
|
452
|
+
throw new Error("Tauri invoke API not found: expected window.__TAURI_INTERNALS__.invoke or window.__TAURI__.core.invoke");
|
|
453
|
+
}}
|
|
454
|
+
let __result = await eval({js});
|
|
455
|
+
if (typeof __result === "undefined") {{
|
|
456
|
+
__result = null;
|
|
457
|
+
}} else if (typeof __result === "object" && __result !== null) {{
|
|
458
|
+
__result = JSON.stringify(__result);
|
|
459
|
+
}} else if (typeof __result !== "string") {{
|
|
460
|
+
__result = String(__result);
|
|
461
|
+
}}
|
|
462
|
+
await __devBridgeInvoke("__dev_bridge_result", {{
|
|
463
|
+
id: {id},
|
|
464
|
+
value: __result
|
|
465
|
+
}});
|
|
466
|
+
}} catch(e) {{
|
|
467
|
+
__devBridgeInvoke = __devBridgeInvoke || __getDevBridgeInvoke();
|
|
468
|
+
if (!__devBridgeInvoke) {{
|
|
469
|
+
throw e;
|
|
470
|
+
}}
|
|
471
|
+
const __message = e && e.message ? e.message : String(e);
|
|
472
|
+
await __devBridgeInvoke("__dev_bridge_result", {{
|
|
473
|
+
id: {id},
|
|
474
|
+
value: "ERROR: " + __message
|
|
475
|
+
}});
|
|
476
|
+
}}
|
|
477
|
+
}})();
|
|
478
|
+
"#,
|
|
479
|
+
js = serde_json::to_string(js).unwrap(),
|
|
480
|
+
id = serde_json::to_string(request_id).unwrap(),
|
|
481
|
+
)
|
|
482
|
+
}
|
|
483
|
+
|
|
433
484
|
/// Start the development bridge HTTP server.
|
|
434
485
|
///
|
|
435
486
|
/// Returns the bound port, a shared log buffer, and a sidecar registry. Both
|
|
@@ -747,36 +798,18 @@ pub fn start_bridge(
|
|
|
747
798
|
let window_label = eval_req.window.as_deref().unwrap_or("main");
|
|
748
799
|
if let Some(window) = app_handle.get_webview_window(window_label) {
|
|
749
800
|
// Build JS that evaluates the expression, then calls back into Rust
|
|
750
|
-
// via
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
}}
|
|
763
|
-
await window.__TAURI__.core.invoke("__dev_bridge_result", {{
|
|
764
|
-
id: {id},
|
|
765
|
-
value: __result
|
|
766
|
-
}});
|
|
767
|
-
}} catch(e) {{
|
|
768
|
-
await window.__TAURI__.core.invoke("__dev_bridge_result", {{
|
|
769
|
-
id: {id},
|
|
770
|
-
value: "ERROR: " + e.message
|
|
771
|
-
}});
|
|
772
|
-
}}
|
|
773
|
-
}})();
|
|
774
|
-
"#,
|
|
775
|
-
js = serde_json::to_string(&eval_req.js).unwrap(),
|
|
776
|
-
id = serde_json::to_string(&request_id).unwrap(),
|
|
777
|
-
);
|
|
778
|
-
|
|
779
|
-
let _ = window.eval(&callback_js);
|
|
801
|
+
// via Tauri's invoke API to deliver the result. Prefer the
|
|
802
|
+
// internal global because Tauri 2 does not expose __TAURI__
|
|
803
|
+
// unless app.withGlobalTauri is enabled.
|
|
804
|
+
let callback_js = build_eval_callback_js(&eval_req.js, &request_id);
|
|
805
|
+
|
|
806
|
+
if let Err(e) = window.eval(&callback_js) {
|
|
807
|
+
let _ = request.respond(
|
|
808
|
+
Response::from_string(format!("Eval injection failed: {e}"))
|
|
809
|
+
.with_status_code(500),
|
|
810
|
+
);
|
|
811
|
+
continue;
|
|
812
|
+
}
|
|
780
813
|
|
|
781
814
|
// Wait for the result with a 5-second timeout
|
|
782
815
|
let mut results = pending.results.lock().unwrap();
|
|
@@ -799,7 +832,7 @@ pub fn start_bridge(
|
|
|
799
832
|
// Timeout — clean up and respond with 504
|
|
800
833
|
results.remove(&request_id);
|
|
801
834
|
let _ = request.respond(
|
|
802
|
-
Response::from_string(
|
|
835
|
+
Response::from_string(EVAL_TIMEOUT_MESSAGE).with_status_code(504),
|
|
803
836
|
);
|
|
804
837
|
break;
|
|
805
838
|
}
|
|
@@ -812,7 +845,7 @@ pub fn start_bridge(
|
|
|
812
845
|
if timeout_result.timed_out() && !results.contains_key(&request_id) {
|
|
813
846
|
results.remove(&request_id);
|
|
814
847
|
let _ = request.respond(
|
|
815
|
-
Response::from_string(
|
|
848
|
+
Response::from_string(EVAL_TIMEOUT_MESSAGE).with_status_code(504),
|
|
816
849
|
);
|
|
817
850
|
break;
|
|
818
851
|
}
|
|
@@ -834,6 +867,53 @@ pub fn start_bridge(
|
|
|
834
867
|
Ok((port, log_buffer, sidecar_registry))
|
|
835
868
|
}
|
|
836
869
|
|
|
870
|
+
#[cfg(test)]
|
|
871
|
+
mod tests {
|
|
872
|
+
use super::*;
|
|
873
|
+
|
|
874
|
+
#[test]
|
|
875
|
+
fn eval_callback_prefers_tauri_internals() {
|
|
876
|
+
let script = build_eval_callback_js("document.title", "request-1");
|
|
877
|
+
let internals = script.find("window.__TAURI_INTERNALS__.invoke").unwrap();
|
|
878
|
+
let global = script.find("window.__TAURI__.core.invoke").unwrap();
|
|
879
|
+
|
|
880
|
+
assert!(internals < global);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
#[test]
|
|
884
|
+
fn eval_callback_keeps_global_tauri_fallback() {
|
|
885
|
+
let script = build_eval_callback_js("document.title", "request-1");
|
|
886
|
+
|
|
887
|
+
assert!(script.contains("window.__TAURI__.core.invoke"));
|
|
888
|
+
assert!(!script.contains("app.withGlobalTauri"));
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
#[test]
|
|
892
|
+
fn eval_callback_safely_embeds_js_and_request_id() {
|
|
893
|
+
let js = r#"document.querySelector("[data-name=\"x\"]").textContent"#;
|
|
894
|
+
let request_id = r#"request-"quoted""#;
|
|
895
|
+
let script = build_eval_callback_js(js, request_id);
|
|
896
|
+
|
|
897
|
+
assert!(script.contains(&serde_json::to_string(js).unwrap()));
|
|
898
|
+
assert!(script.contains(&serde_json::to_string(request_id).unwrap()));
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
#[test]
|
|
902
|
+
fn eval_callback_uses_dev_bridge_result_command() {
|
|
903
|
+
let script = build_eval_callback_js("1 + 1", "request-1");
|
|
904
|
+
|
|
905
|
+
assert!(script.contains("__dev_bridge_result"));
|
|
906
|
+
assert!(!script.contains("await window.__TAURI__.core.invoke"));
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
#[test]
|
|
910
|
+
fn eval_timeout_message_is_actionable() {
|
|
911
|
+
assert!(EVAL_TIMEOUT_MESSAGE.contains("no result callback received"));
|
|
912
|
+
assert!(EVAL_TIMEOUT_MESSAGE.contains("Re-copy"));
|
|
913
|
+
assert!(EVAL_TIMEOUT_MESSAGE.contains("dev_bridge.rs"));
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
837
917
|
/// Read declared capabilities from tauri.conf.json via `app.config()`. Returns
|
|
838
918
|
/// a flat list of capability entries. Tauri 2 lets capabilities be either bare
|
|
839
919
|
/// permission identifiers (strings) or full inline definitions; we surface
|
package/package.json
CHANGED
package/rust-bridge/README.md
CHANGED
|
@@ -16,6 +16,9 @@ rand = "0.8"
|
|
|
16
16
|
uuid = { version = "1", features = ["v4"] }
|
|
17
17
|
tracing = "0.1"
|
|
18
18
|
tracing-subscriber = "0.3"
|
|
19
|
+
|
|
20
|
+
[target.'cfg(unix)'.dependencies]
|
|
21
|
+
libc = "0.2"
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
### 2. Copy the bridge module
|
|
@@ -84,7 +87,7 @@ tauri-agent-tools eval "document.title"
|
|
|
84
87
|
3. `tauri-agent-tools` discovers the token file and authenticates via the token
|
|
85
88
|
4. The bridge exposes four endpoints: `POST /eval` (JS evaluation), `POST /logs` (Rust log retrieval), `POST /describe` (bridge metadata), and `GET /version` (unauthenticated health check)
|
|
86
89
|
5. `/eval` accepts an optional `window` field to target specific webview windows (defaults to `"main"`)
|
|
87
|
-
6. The injected JS evaluates the expression, then calls back into Rust via `window.
|
|
90
|
+
6. The injected JS evaluates the expression, then calls back into Rust via `window.__TAURI_INTERNALS__.invoke("__dev_bridge_result", { id, value })` to deliver the result, falling back to `window.__TAURI__.core.invoke()` for older/global-enabled apps
|
|
88
91
|
7. The HTTP handler thread waits for the result (up to 5 seconds) and returns it as JSON
|
|
89
92
|
8. `/logs` drains the ring buffer of captured `tracing` events and returns them as JSON
|
|
90
93
|
9. `/describe` returns PID, window labels, and capabilities
|
|
@@ -98,6 +101,12 @@ tauri-agent-tools eval "document.title"
|
|
|
98
101
|
- **Inspection is read-only** — inspection commands only read DOM state
|
|
99
102
|
- **Interaction is debug-only** — interaction commands use eval-based DOM dispatch, sandboxed to the webview
|
|
100
103
|
|
|
104
|
+
## Troubleshooting
|
|
105
|
+
|
|
106
|
+
### `Eval timeout: no result callback received`
|
|
107
|
+
|
|
108
|
+
Re-copy `examples/tauri-bridge/src/dev_bridge.rs` from the latest package. Current bridge code uses Tauri 2's always-present `window.__TAURI_INTERNALS__.invoke()` callback path and does **not** require `app.withGlobalTauri: true`. Older copied bridge files used `window.__TAURI__.core.invoke()` and can time out in apps that keep Tauri's global API disabled.
|
|
109
|
+
|
|
101
110
|
## Agent-Assisted Setup
|
|
102
111
|
|
|
103
112
|
If you're using an AI coding agent (Claude Code, Codex, Cursor, etc.), the `tauri-bridge-setup` skill can guide automated setup. See `.agents/skills/tauri-bridge-setup/SKILL.md` or run:
|