tauri-agent-tools 0.5.1 → 0.6.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 +105 -12
- package/.agents/skills/tauri-bridge-setup/SKILL.md +42 -6
- package/AGENTS.md +9 -7
- package/README.md +51 -11
- package/dist/bridge/client.d.ts +5 -2
- package/dist/bridge/client.js +38 -3
- package/dist/bridge/client.js.map +1 -1
- package/dist/cli.js +22 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/capture.d.ts +3 -0
- package/dist/commands/capture.js +218 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/check.d.ts +5 -0
- package/dist/commands/check.js +174 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/eval.js +16 -3
- package/dist/commands/eval.js.map +1 -1
- package/dist/commands/interact/click.d.ts +6 -0
- package/dist/commands/interact/click.js +102 -0
- package/dist/commands/interact/click.js.map +1 -0
- package/dist/commands/interact/focus.d.ts +3 -0
- package/dist/commands/interact/focus.js +40 -0
- package/dist/commands/interact/focus.js.map +1 -0
- package/dist/commands/interact/navigate.d.ts +3 -0
- package/dist/commands/interact/navigate.js +49 -0
- package/dist/commands/interact/navigate.js.map +1 -0
- package/dist/commands/interact/scroll.d.ts +11 -0
- package/dist/commands/interact/scroll.js +110 -0
- package/dist/commands/interact/scroll.js.map +1 -0
- package/dist/commands/interact/select.d.ts +3 -0
- package/dist/commands/interact/select.js +59 -0
- package/dist/commands/interact/select.js.map +1 -0
- package/dist/commands/interact/shared.d.ts +23 -0
- package/dist/commands/interact/shared.js +62 -0
- package/dist/commands/interact/shared.js.map +1 -0
- package/dist/commands/interact/type.d.ts +6 -0
- package/dist/commands/interact/type.js +59 -0
- package/dist/commands/interact/type.js.map +1 -0
- package/dist/commands/invoke.d.ts +3 -0
- package/dist/commands/invoke.js +53 -0
- package/dist/commands/invoke.js.map +1 -0
- package/dist/commands/probe.d.ts +2 -0
- package/dist/commands/probe.js +117 -0
- package/dist/commands/probe.js.map +1 -0
- package/dist/commands/shared.d.ts +10 -4
- package/dist/commands/shared.js +23 -3
- package/dist/commands/shared.js.map +1 -1
- package/dist/commands/storeInspect.d.ts +13 -0
- package/dist/commands/storeInspect.js +156 -0
- package/dist/commands/storeInspect.js.map +1 -0
- package/dist/schemas/bridge.d.ts +34 -0
- package/dist/schemas/bridge.js +13 -0
- package/dist/schemas/bridge.js.map +1 -1
- package/dist/schemas/commands.d.ts +126 -0
- package/dist/schemas/commands.js +28 -0
- package/dist/schemas/commands.js.map +1 -1
- package/dist/schemas/index.d.ts +3 -2
- package/dist/schemas/index.js +3 -2
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/interact.d.ts +118 -0
- package/dist/schemas/interact.js +31 -0
- package/dist/schemas/interact.js.map +1 -0
- package/examples/tauri-bridge/src/dev_bridge.rs +88 -2
- package/package.json +1 -1
- package/rust-bridge/README.md +7 -5
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// === Interaction Results ===
|
|
3
|
+
export const InteractionResultSchema = z.object({
|
|
4
|
+
success: z.boolean(),
|
|
5
|
+
selector: z.string().optional(),
|
|
6
|
+
tagName: z.string().optional(),
|
|
7
|
+
error: z.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
export const ClickResultSchema = InteractionResultSchema.extend({
|
|
10
|
+
text: z.string().optional(),
|
|
11
|
+
});
|
|
12
|
+
export const TypeResultSchema = InteractionResultSchema.extend({
|
|
13
|
+
value: z.string().optional(),
|
|
14
|
+
});
|
|
15
|
+
export const ScrollResultSchema = z.object({
|
|
16
|
+
success: z.boolean(),
|
|
17
|
+
scrollX: z.number().optional(),
|
|
18
|
+
scrollY: z.number().optional(),
|
|
19
|
+
error: z.string().optional(),
|
|
20
|
+
});
|
|
21
|
+
export const SelectResultSchema = InteractionResultSchema.extend({
|
|
22
|
+
value: z.string().optional(),
|
|
23
|
+
checked: z.boolean().optional(),
|
|
24
|
+
});
|
|
25
|
+
export const InvokeResultSchema = z.object({
|
|
26
|
+
success: z.boolean(),
|
|
27
|
+
command: z.string(),
|
|
28
|
+
result: z.unknown().optional(),
|
|
29
|
+
error: z.string().optional(),
|
|
30
|
+
});
|
|
31
|
+
//# sourceMappingURL=interact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interact.js","sourceRoot":"","sources":["../../src/schemas/interact.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,8BAA8B;AAE9B,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,MAAM,CAAC;IAC9D,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC5B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,gBAAgB,GAAG,uBAAuB,CAAC,MAAM,CAAC;IAC7D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,uBAAuB,CAAC,MAAM,CAAC;IAC/D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IACzC,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE;IACnB,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;IAC9B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC7B,CAAC,CAAC"}
|
|
@@ -15,6 +15,8 @@ use tracing_subscriber::util::SubscriberInitExt;
|
|
|
15
15
|
struct EvalRequest {
|
|
16
16
|
js: String,
|
|
17
17
|
token: String,
|
|
18
|
+
#[serde(default)]
|
|
19
|
+
window: Option<String>,
|
|
18
20
|
}
|
|
19
21
|
|
|
20
22
|
#[derive(Deserialize)]
|
|
@@ -41,6 +43,32 @@ struct LogResponse {
|
|
|
41
43
|
entries: Vec<LogEntry>,
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
#[derive(Deserialize)]
|
|
47
|
+
struct DescribeRequest {
|
|
48
|
+
token: String,
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
#[derive(Serialize, Default)]
|
|
52
|
+
struct DescribeResponse {
|
|
53
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
54
|
+
app: Option<String>,
|
|
55
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
56
|
+
pid: Option<u32>,
|
|
57
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
58
|
+
windows: Option<Vec<String>>,
|
|
59
|
+
capabilities: Vec<String>,
|
|
60
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
61
|
+
surfaces: Option<HashMap<String, String>>,
|
|
62
|
+
#[serde(skip_serializing_if = "Option::is_none")]
|
|
63
|
+
exports: Option<HashMap<String, String>>,
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#[derive(Serialize)]
|
|
67
|
+
struct VersionResponse {
|
|
68
|
+
version: String,
|
|
69
|
+
endpoints: Vec<String>,
|
|
70
|
+
}
|
|
71
|
+
|
|
44
72
|
#[derive(Serialize)]
|
|
45
73
|
struct TokenFile {
|
|
46
74
|
port: u16,
|
|
@@ -295,7 +323,24 @@ pub fn start_bridge(app: &AppHandle) -> Result<(u16, Arc<LogBuffer>), String> {
|
|
|
295
323
|
let is_post = request.method().as_str() == "POST";
|
|
296
324
|
let url = request.url().to_string();
|
|
297
325
|
|
|
298
|
-
|
|
326
|
+
// Handle GET /version (no auth needed)
|
|
327
|
+
if url == "/version" && request.method().as_str() == "GET" {
|
|
328
|
+
let resp = VersionResponse {
|
|
329
|
+
version: "0.6.0".to_string(),
|
|
330
|
+
endpoints: vec![
|
|
331
|
+
"/eval".to_string(),
|
|
332
|
+
"/logs".to_string(),
|
|
333
|
+
"/describe".to_string(),
|
|
334
|
+
"/version".to_string(),
|
|
335
|
+
],
|
|
336
|
+
};
|
|
337
|
+
let json = serde_json::to_string(&resp).unwrap();
|
|
338
|
+
let header = Header::from_bytes("Content-Type", "application/json").unwrap();
|
|
339
|
+
let _ = request.respond(Response::from_string(json).with_header(header));
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if !is_post || (url != "/eval" && url != "/logs" && url != "/describe") {
|
|
299
344
|
let _ = request.respond(Response::from_string("Not found").with_status_code(404));
|
|
300
345
|
continue;
|
|
301
346
|
}
|
|
@@ -333,6 +378,46 @@ pub fn start_bridge(app: &AppHandle) -> Result<(u16, Arc<LogBuffer>), String> {
|
|
|
333
378
|
continue;
|
|
334
379
|
}
|
|
335
380
|
|
|
381
|
+
// Handle /describe endpoint
|
|
382
|
+
if url == "/describe" {
|
|
383
|
+
let desc_req: DescribeRequest = match serde_json::from_str(&body) {
|
|
384
|
+
Ok(r) => r,
|
|
385
|
+
Err(_) => {
|
|
386
|
+
let _ = request
|
|
387
|
+
.respond(Response::from_string("Invalid JSON").with_status_code(400));
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
if desc_req.token != expected_token {
|
|
393
|
+
let _ = request
|
|
394
|
+
.respond(Response::from_string("Unauthorized").with_status_code(401));
|
|
395
|
+
continue;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
let windows: Vec<String> = app_handle
|
|
399
|
+
.webview_windows()
|
|
400
|
+
.keys()
|
|
401
|
+
.cloned()
|
|
402
|
+
.collect();
|
|
403
|
+
|
|
404
|
+
let resp = DescribeResponse {
|
|
405
|
+
pid: Some(std::process::id()),
|
|
406
|
+
windows: Some(windows),
|
|
407
|
+
capabilities: vec![
|
|
408
|
+
"eval".to_string(),
|
|
409
|
+
"logs".to_string(),
|
|
410
|
+
"describe".to_string(),
|
|
411
|
+
],
|
|
412
|
+
..Default::default()
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
let json = serde_json::to_string(&resp).unwrap();
|
|
416
|
+
let header = Header::from_bytes("Content-Type", "application/json").unwrap();
|
|
417
|
+
let _ = request.respond(Response::from_string(json).with_header(header));
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
|
|
336
421
|
// Handle /eval endpoint
|
|
337
422
|
let eval_req: EvalRequest = match serde_json::from_str(&body) {
|
|
338
423
|
Ok(r) => r,
|
|
@@ -353,7 +438,8 @@ pub fn start_bridge(app: &AppHandle) -> Result<(u16, Arc<LogBuffer>), String> {
|
|
|
353
438
|
// Evaluate JS in webview via callback pattern
|
|
354
439
|
let request_id = uuid::Uuid::new_v4().to_string();
|
|
355
440
|
|
|
356
|
-
|
|
441
|
+
let window_label = eval_req.window.as_deref().unwrap_or("main");
|
|
442
|
+
if let Some(window) = app_handle.get_webview_window(window_label) {
|
|
357
443
|
// Build JS that evaluates the expression, then calls back into Rust
|
|
358
444
|
// via __TAURI__.core.invoke() to deliver the result.
|
|
359
445
|
let callback_js = format!(
|
package/package.json
CHANGED
package/rust-bridge/README.md
CHANGED
|
@@ -82,19 +82,21 @@ tauri-agent-tools eval "document.title"
|
|
|
82
82
|
1. Bridge starts an HTTP server on a random localhost port
|
|
83
83
|
2. A token file with `{ port, token, pid }` is written to `/tmp/`
|
|
84
84
|
3. `tauri-agent-tools` discovers the token file and authenticates via the token
|
|
85
|
-
4.
|
|
86
|
-
5.
|
|
85
|
+
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
|
+
5. `/eval` accepts an optional `window` field to target specific webview windows (defaults to `"main"`)
|
|
87
87
|
6. The injected JS evaluates the expression, then calls back into Rust via `window.__TAURI__.core.invoke("__dev_bridge_result", { id, value })` to deliver the result
|
|
88
88
|
7. The HTTP handler thread waits for the result (up to 5 seconds) and returns it as JSON
|
|
89
|
-
8.
|
|
90
|
-
9.
|
|
89
|
+
8. `/logs` drains the ring buffer of captured `tracing` events and returns them as JSON
|
|
90
|
+
9. `/describe` returns PID, window labels, and capabilities
|
|
91
|
+
10. The token file is cleaned up when the app exits
|
|
91
92
|
|
|
92
93
|
## Security
|
|
93
94
|
|
|
94
95
|
- **Localhost only** — the bridge binds to `127.0.0.1`
|
|
95
96
|
- **Token authenticated** — every request requires a random 32-char token
|
|
96
97
|
- **Development only** — wrapped in `cfg!(debug_assertions)`, stripped in release builds
|
|
97
|
-
- **
|
|
98
|
+
- **Inspection is read-only** — inspection commands only read DOM state
|
|
99
|
+
- **Interaction is debug-only** — interaction commands use eval-based DOM dispatch, sandboxed to the webview
|
|
98
100
|
|
|
99
101
|
## Agent-Assisted Setup
|
|
100
102
|
|