tauri-agent-tools 0.9.1 → 0.9.3

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 (122) hide show
  1. package/.agents/skills/tauri-agent-tools/SKILL.md +32 -13
  2. package/.agents/skills/tauri-bridge-setup/SKILL.md +4 -3
  3. package/.agents/skills/tauri-debug-quickstart/SKILL.md +3 -1
  4. package/AGENTS.md +7 -3
  5. package/README.md +35 -14
  6. package/dist/bridge/client.d.ts +1 -0
  7. package/dist/bridge/client.js +2 -0
  8. package/dist/bridge/client.js.map +1 -1
  9. package/dist/bridge/evaluate.d.ts +11 -0
  10. package/dist/bridge/evaluate.js +33 -0
  11. package/dist/bridge/evaluate.js.map +1 -0
  12. package/dist/bridge/logReader.d.ts +27 -0
  13. package/dist/bridge/logReader.js +26 -0
  14. package/dist/bridge/logReader.js.map +1 -0
  15. package/dist/bridge/observers.d.ts +11 -0
  16. package/dist/bridge/observers.js +195 -0
  17. package/dist/bridge/observers.js.map +1 -0
  18. package/dist/cli.js +28 -8
  19. package/dist/cli.js.map +1 -1
  20. package/dist/commands/bundle.js +122 -101
  21. package/dist/commands/bundle.js.map +1 -1
  22. package/dist/commands/capture.d.ts +3 -3
  23. package/dist/commands/capture.js +167 -141
  24. package/dist/commands/capture.js.map +1 -1
  25. package/dist/commands/check.js +44 -59
  26. package/dist/commands/check.js.map +1 -1
  27. package/dist/commands/consoleMonitor.js +18 -85
  28. package/dist/commands/consoleMonitor.js.map +1 -1
  29. package/dist/commands/diagnose.js +4 -32
  30. package/dist/commands/diagnose.js.map +1 -1
  31. package/dist/commands/diff.js +28 -38
  32. package/dist/commands/diff.js.map +1 -1
  33. package/dist/commands/dom.js +2 -2
  34. package/dist/commands/dom.js.map +1 -1
  35. package/dist/commands/eval.js +11 -1
  36. package/dist/commands/eval.js.map +1 -1
  37. package/dist/commands/forensics.js +1 -7
  38. package/dist/commands/forensics.js.map +1 -1
  39. package/dist/commands/info.d.ts +2 -2
  40. package/dist/commands/info.js +3 -1
  41. package/dist/commands/info.js.map +1 -1
  42. package/dist/commands/interact/click.js +14 -44
  43. package/dist/commands/interact/click.js.map +1 -1
  44. package/dist/commands/interact/scroll.js +6 -0
  45. package/dist/commands/interact/scroll.js.map +1 -1
  46. package/dist/commands/interact/select.d.ts +6 -1
  47. package/dist/commands/interact/select.js +87 -29
  48. package/dist/commands/interact/select.js.map +1 -1
  49. package/dist/commands/interact/shared.d.ts +96 -0
  50. package/dist/commands/interact/shared.js +266 -1
  51. package/dist/commands/interact/shared.js.map +1 -1
  52. package/dist/commands/interact/type.d.ts +10 -2
  53. package/dist/commands/interact/type.js +44 -29
  54. package/dist/commands/interact/type.js.map +1 -1
  55. package/dist/commands/ipcMonitor.d.ts +3 -3
  56. package/dist/commands/ipcMonitor.js +26 -96
  57. package/dist/commands/ipcMonitor.js.map +1 -1
  58. package/dist/commands/listWindows.d.ts +2 -2
  59. package/dist/commands/listWindows.js.map +1 -1
  60. package/dist/commands/logs.d.ts +4 -27
  61. package/dist/commands/logs.js +12 -41
  62. package/dist/commands/logs.js.map +1 -1
  63. package/dist/commands/mutations.js +20 -101
  64. package/dist/commands/mutations.js.map +1 -1
  65. package/dist/commands/osLogs.js +2 -5
  66. package/dist/commands/osLogs.js.map +1 -1
  67. package/dist/commands/probe.js +18 -16
  68. package/dist/commands/probe.js.map +1 -1
  69. package/dist/commands/rustLogs.js +23 -43
  70. package/dist/commands/rustLogs.js.map +1 -1
  71. package/dist/commands/screenshot.d.ts +2 -2
  72. package/dist/commands/screenshot.js +7 -4
  73. package/dist/commands/screenshot.js.map +1 -1
  74. package/dist/commands/shared.d.ts +4 -1
  75. package/dist/commands/shared.js +34 -4
  76. package/dist/commands/shared.js.map +1 -1
  77. package/dist/commands/sidecarReplay.js +4 -0
  78. package/dist/commands/sidecarReplay.js.map +1 -1
  79. package/dist/commands/snapshot.d.ts +2 -2
  80. package/dist/commands/snapshot.js +4 -4
  81. package/dist/commands/snapshot.js.map +1 -1
  82. package/dist/commands/storeInspect.js +2 -2
  83. package/dist/commands/storeInspect.js.map +1 -1
  84. package/dist/commands/wait.d.ts +2 -2
  85. package/dist/commands/wait.js +42 -57
  86. package/dist/commands/wait.js.map +1 -1
  87. package/dist/errors.d.ts +10 -0
  88. package/dist/errors.js +26 -0
  89. package/dist/errors.js.map +1 -0
  90. package/dist/platform/detect.d.ts +2 -2
  91. package/dist/platform/detect.js +11 -2
  92. package/dist/platform/detect.js.map +1 -1
  93. package/dist/platform/x11.d.ts +1 -0
  94. package/dist/platform/x11.js +16 -5
  95. package/dist/platform/x11.js.map +1 -1
  96. package/dist/schemas/commands.d.ts +6 -0
  97. package/dist/schemas/commands.js +2 -0
  98. package/dist/schemas/commands.js.map +1 -1
  99. package/dist/schemas/interact.d.ts +58 -0
  100. package/dist/schemas/interact.js +25 -0
  101. package/dist/schemas/interact.js.map +1 -1
  102. package/dist/types.d.ts +2 -0
  103. package/dist/util/exec.d.ts +6 -0
  104. package/dist/util/exec.js +13 -1
  105. package/dist/util/exec.js.map +1 -1
  106. package/dist/util/incidentFiles.d.ts +5 -0
  107. package/dist/util/incidentFiles.js +61 -0
  108. package/dist/util/incidentFiles.js.map +1 -0
  109. package/dist/util/monitor.d.ts +11 -0
  110. package/dist/util/monitor.js +42 -0
  111. package/dist/util/monitor.js.map +1 -0
  112. package/dist/util/poll.d.ts +2 -0
  113. package/dist/util/poll.js +28 -0
  114. package/dist/util/poll.js.map +1 -0
  115. package/dist/util/redactText.d.ts +5 -2
  116. package/dist/util/redactText.js +44 -11
  117. package/dist/util/redactText.js.map +1 -1
  118. package/dist/util/tauriConfig.js +15 -18
  119. package/dist/util/tauriConfig.js.map +1 -1
  120. package/examples/tauri-bridge/Cargo.lock +4742 -0
  121. package/package.json +10 -3
  122. package/rust-bridge/README.md +7 -1
@@ -1 +1 @@
1
- {"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,UAAU,YAAY,CAC1B,OAAgB,EAChB,UAA4D;IAE5D,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;SAC5B,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,qBAAqB,EAAE,yDAAyD,CAAC;SACxF,MAAM,CAAC,sBAAsB,EAAE,4DAA4D,CAAC;SAC5F,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAA2D,EAAE,EAAE;QAC5E,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;QACnC,IAAI,QAAgB,CAAC;QACrB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC3B,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,QAAQ,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;QAE5C,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAE9C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"info.js","sourceRoot":"","sources":["../../src/commands/info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,UAAU,YAAY,CAC1B,OAAgB,EAChB,UAA0B;IAE1B,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC;SAC5B,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,uBAAuB,EAAE,+EAA+E,CAAC;SAChH,MAAM,CAAC,sBAAsB,EAAE,4DAA4D,CAAC;SAC5F,MAAM,CAAC,QAAQ,EAAE,gBAAgB,CAAC;SAClC,MAAM,CAAC,KAAK,EAAE,IAA2D,EAAE,EAAE;QAC5E,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAChG,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;QACnC,IAAI,QAAgB,CAAC;QACrB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC3B,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,QAAQ,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnD,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;QAE5C,MAAM,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAE9C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC;YACpD,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACvD,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -1,6 +1,9 @@
1
1
  import { Command } from 'commander';
2
- import { resolveBridge, parseIntArg } from '../shared.js';
2
+ import { resolveBridge, parseNonNegativeInt } from '../shared.js';
3
3
  import { addInteractOptions, escapeSelector } from './shared.js';
4
+ import { evaluateExpression } from '../../bridge/evaluate.js';
5
+ import { pollUntil } from '../../util/poll.js';
6
+ import { CliError } from '../../errors.js';
4
7
  import { ClickResultSchema } from '../../schemas/interact.js';
5
8
  export function buildClickScript(selector, opts) {
6
9
  const escaped = escapeSelector(selector);
@@ -24,52 +27,13 @@ export function buildClickScript(selector, opts) {
24
27
  return JSON.stringify({ success: true, selector: '${escaped}', tagName: el.tagName.toLowerCase(), text: text });
25
28
  })()`;
26
29
  }
27
- function buildWaitAndClickScript(selector, opts, waitMs) {
28
- const escaped = escapeSelector(selector);
29
- const button = opts.right ? 2 : 0;
30
- const clickEvents = opts.right
31
- ? `el.dispatchEvent(new MouseEvent('contextmenu', eventOpts));`
32
- : opts.double
33
- ? `el.dispatchEvent(new MouseEvent('click', eventOpts));
34
- el.dispatchEvent(new MouseEvent('dblclick', eventOpts));`
35
- : `el.dispatchEvent(new MouseEvent('click', eventOpts));`;
36
- return `(() => {
37
- var deadline = Date.now() + ${waitMs};
38
- function attempt() {
39
- var el = document.querySelector('${escaped}');
40
- if (el) {
41
- var r = el.getBoundingClientRect();
42
- var clientX = r.left + r.width / 2;
43
- var clientY = r.top + r.height / 2;
44
- var eventOpts = { bubbles: true, cancelable: true, clientX: clientX, clientY: clientY, button: ${button} };
45
- el.dispatchEvent(new MouseEvent('mousedown', eventOpts));
46
- el.dispatchEvent(new MouseEvent('mouseup', eventOpts));
47
- ${clickEvents}
48
- var text = (el.textContent || '').trim().slice(0, 100);
49
- return JSON.stringify({ success: true, selector: '${escaped}', tagName: el.tagName.toLowerCase(), text: text });
50
- }
51
- if (Date.now() >= deadline) {
52
- return JSON.stringify({ success: false, selector: '${escaped}', error: 'Element not found' });
53
- }
54
- return null;
55
- }
56
- return new Promise(function(resolve) {
57
- function poll() {
58
- var result = attempt();
59
- if (result !== null) { resolve(result); return; }
60
- setTimeout(poll, 100);
61
- }
62
- poll();
63
- });
64
- })()`;
65
- }
66
30
  export function registerClick(program) {
67
31
  const cmd = new Command('click')
68
32
  .description('Dispatch mouse click events on a DOM element')
69
33
  .argument('<selector>', 'CSS selector of the element to click')
70
34
  .option('--double', 'Dispatch a double-click (dblclick) instead of a single click')
71
35
  .option('--right', 'Dispatch a right-click (contextmenu) instead of a left click')
72
- .option('--wait <ms>', 'Wait up to <ms> milliseconds for element to appear', parseIntArg, 0)
36
+ .option('--wait <ms>', 'Wait up to <ms> milliseconds for element to appear', parseNonNegativeInt, 0)
73
37
  .addHelpText('after', `
74
38
  Examples:
75
39
  $ tauri-agent-tools click "button.submit"
@@ -78,11 +42,17 @@ Examples:
78
42
  $ tauri-agent-tools click ".lazy-item" --wait 3000 --json`);
79
43
  addInteractOptions(cmd);
80
44
  cmd.action(async (selector, opts) => {
45
+ if (opts.double && opts.right)
46
+ throw new CliError('INVALID_ARGUMENT', '--double and --right cannot be combined', 'Choose one click type.');
81
47
  const bridge = await resolveBridge(opts);
82
48
  const clickOpts = { double: !!opts.double, right: !!opts.right };
83
- const script = opts.wait > 0
84
- ? buildWaitAndClickScript(selector, clickOpts, opts.wait)
85
- : buildClickScript(selector, clickOpts);
49
+ if (opts.wait > 0) {
50
+ await pollUntil(async (remaining) => {
51
+ const result = await evaluateExpression(bridge, `document.querySelector(${JSON.stringify(selector)}) !== null`, Math.min(5000, remaining));
52
+ return result.truthy ? true : null;
53
+ }, opts.wait, 100, `Timed out waiting for element: ${selector}`);
54
+ }
55
+ const script = buildClickScript(selector, clickOpts);
86
56
  const raw = await bridge.eval(script);
87
57
  const result = ClickResultSchema.parse(JSON.parse(String(raw)));
88
58
  if (!result.success) {
@@ -1 +1 @@
1
- {"version":3,"file":"click.js","sourceRoot":"","sources":["../../../src/commands/interact/click.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"click.js","sourceRoot":"","sources":["../../../src/commands/interact/click.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,UAAU,gBAAgB,CAC9B,QAAgB,EAChB,IAAyC;IAEzC,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAElC,OAAO;qCAC4B,OAAO;gEACoB,OAAO;;;;mGAI4B,MAAM;;;IAGrG,IAAI,CAAC,KAAK;QACV,CAAC,CAAC,6DAA6D;QAC/D,CAAC,CAAC,IAAI,CAAC,MAAM;YACX,CAAC,CAAC;2DACmD;YACrD,CAAC,CAAC,uDAAuD;;sDAET,OAAO;KACxD,CAAC;AACN,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAgB;IAC5C,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,OAAO,CAAC;SAC7B,WAAW,CAAC,8CAA8C,CAAC;SAC3D,QAAQ,CAAC,YAAY,EAAE,sCAAsC,CAAC;SAC9D,MAAM,CAAC,UAAU,EAAE,8DAA8D,CAAC;SAClF,MAAM,CAAC,SAAS,EAAE,8DAA8D,CAAC;SACjF,MAAM,CAAC,aAAa,EAAE,oDAAoD,EAAE,mBAAmB,EAAE,CAAC,CAAC;SACnG,WAAW,CAAC,OAAO,EAAE;;;;;4DAKkC,CAAC,CAAC;IAE5D,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAExB,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,IAOnC,EAAE,EAAE;QACH,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,QAAQ,CAAC,kBAAkB,EAAE,yCAAyC,EAAE,wBAAwB,CAAC,CAAC;QAC3I,MAAM,MAAM,GAAiB,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QAEvD,MAAM,SAAS,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACjE,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,SAAS,CAAC,KAAK,EAAC,SAAS,EAAC,EAAE;gBAChC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,MAAM,EAC5C,0BAA0B,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC;gBAC7F,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;YACrC,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,kCAAkC,QAAQ,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAErD,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAEhE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,iBAAiB,MAAM,CAAC,KAAK,eAAe,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClF,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,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CAAC;YAC9F,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,KAAK,MAAM,CAAC,OAAO,GAAG,QAAQ,MAAM,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC;QACpF,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -2,6 +2,7 @@ import { Command } from 'commander';
2
2
  import { resolveBridge, parseIntArg } from '../shared.js';
3
3
  import { addInteractOptions, escapeSelector } from './shared.js';
4
4
  import { ScrollResultSchema } from '../../schemas/interact.js';
5
+ import { CliError } from '../../errors.js';
5
6
  export function buildScrollScript(opts) {
6
7
  const { selector, by, to, toTop, toBottom, intoView } = opts;
7
8
  if (selector && intoView) {
@@ -89,6 +90,11 @@ Examples:
89
90
  $ tauri-agent-tools scroll --selector ".panel" --by 100`);
90
91
  addInteractOptions(cmd);
91
92
  cmd.action(async (opts) => {
93
+ const modes = [opts.by !== undefined, opts.to !== undefined, opts.toTop, opts.toBottom, opts.intoView].filter(Boolean);
94
+ if (modes.length > 1)
95
+ throw new CliError('INVALID_ARGUMENT', 'Choose only one scroll action', 'Use --by, --to, --to-top, --to-bottom, or --into-view.');
96
+ if (opts.intoView && !opts.selector)
97
+ throw new CliError('INVALID_ARGUMENT', '--into-view requires --selector', 'Select the element to scroll into view.');
92
98
  const bridge = await resolveBridge(opts);
93
99
  const script = buildScrollScript({
94
100
  selector: opts.selector,
@@ -1 +1 @@
1
- {"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../../src/commands/interact/scroll.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scroll.js","sourceRoot":"","sources":["../../../src/commands/interact/scroll.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,8 @@
1
1
  import { Command } from 'commander';
2
- export declare function buildSelectScript(selector: string, value?: string, toggle?: boolean): string;
2
+ import type { VerifyOptions } from './shared.js';
3
+ /**
4
+ * Value mode writes through the native prototype value setter and verifies the
5
+ * write (see buildSetValueScript); toggle mode performs a native click().
6
+ */
7
+ export declare function buildSelectScript(selector: string, value?: string, toggle?: boolean, options?: VerifyOptions): string;
3
8
  export declare function registerSelect(program: Command): void;
@@ -1,37 +1,83 @@
1
1
  import { Command } from 'commander';
2
2
  import { resolveBridge } from '../shared.js';
3
- import { addInteractOptions, escapeSelector } from './shared.js';
3
+ import { addInteractOptions, addVerifyOptions, buildSetValueScript, escapeSelector, parseInteractResult, resolveVerifyTimeout, VERIFY_INTERVAL_MS, VERIFY_POLL_SNIPPET, } from './shared.js';
4
4
  import { SelectResultSchema } from '../../schemas/interact.js';
5
- export function buildSelectScript(selector, value, toggle = false) {
5
+ /**
6
+ * --toggle: a native click(). The browser flips checkedness internally (not
7
+ * through the JS `checked` setter React wraps), fires input + change, honours
8
+ * preventDefault(), and is the only event React's ChangeEventPlugin observes
9
+ * for checkbox/radio. click() is a no-op on disabled controls (including
10
+ * descendants of <fieldset disabled>) and cannot uncheck a radio, so those
11
+ * are refused up front instead of reporting a state that did not change.
12
+ */
13
+ function buildToggleScript(selector, verifyTimeoutMs) {
6
14
  const escaped = escapeSelector(selector);
7
- if (toggle) {
8
- return `(function() {
9
- try {
10
- var el = document.querySelector('${escaped}');
11
- if (!el) return JSON.stringify({ success: false, error: 'Element not found: ${escaped}' });
12
- el.checked = !el.checked;
13
- el.dispatchEvent(new Event('change', { bubbles: true }));
14
- el.dispatchEvent(new Event('input', { bubbles: true }));
15
- return JSON.stringify({ success: true, selector: '${escaped}', tagName: el.tagName.toLowerCase(), checked: el.checked });
16
- } catch (e) {
17
- return JSON.stringify({ success: false, error: String(e) });
15
+ return `(() => {${VERIFY_POLL_SNIPPET}
16
+ var selector = '${escaped}';
17
+ var fail = function (extra) { return JSON.stringify(Object.assign({ success: false, selector: selector }, extra)); };
18
+ function isDisabled(node) {
19
+ try { if (node.matches(':disabled')) return true; } catch (e) { /* selector unsupported */ }
20
+ if (node.disabled) return true;
21
+ return !!(typeof node.closest === 'function' && node.closest('fieldset[disabled]'));
18
22
  }
19
- })()`;
20
- }
21
- const escapedValue = value !== undefined ? escapeSelector(value) : '';
22
- return `(function() {
23
23
  try {
24
- var el = document.querySelector('${escaped}');
25
- if (!el) return JSON.stringify({ success: false, error: 'Element not found: ${escaped}' });
26
- el.value = '${escapedValue}';
27
- el.dispatchEvent(new Event('change', { bubbles: true }));
28
- el.dispatchEvent(new Event('input', { bubbles: true }));
29
- return JSON.stringify({ success: true, selector: '${escaped}', tagName: el.tagName.toLowerCase(), value: el.value });
24
+ var el = document.querySelector(selector);
25
+ if (!el) return fail({ error: 'Element not found: ' + selector });
26
+ var tagName = el.tagName.toLowerCase();
27
+ var inputType = tagName === 'input' ? String(el.type || 'text').toLowerCase() : '';
28
+ if (inputType !== 'checkbox' && inputType !== 'radio') {
29
+ return fail({ tagName: tagName, error: 'Element <' + tagName + (inputType ? ' type=' + inputType : '') + '> is not a checkbox or radio', hint: '--toggle supports <input type=checkbox|radio>; use \`select <selector> <value>\` for other elements.' });
30
+ }
31
+ var before = !!el.checked;
32
+ if (isDisabled(el)) {
33
+ return fail({ tagName: tagName, checked: before, error: 'Element is disabled (or inside a disabled <fieldset>); click() has no effect' });
34
+ }
35
+ if (inputType === 'radio' && before) {
36
+ return fail({ tagName: tagName, checked: true, error: 'Radio input is already checked; a radio cannot be unchecked by clicking it', hint: 'Toggle the sibling radio you want selected instead.' });
37
+ }
38
+ var expected = !before;
39
+ el.click();
40
+ return __verify(function () {
41
+ var cur = document.querySelector(selector) || (el.isConnected ? el : null);
42
+ return cur ? !!cur.checked : null;
43
+ }, expected, ${verifyTimeoutMs}, ${VERIFY_INTERVAL_MS}).then(function (v) {
44
+ if (v.ok) {
45
+ return JSON.stringify({ success: true, selector: selector, tagName: tagName, checked: v.observed, previousChecked: before, verified: true, verification: 'matched' });
46
+ }
47
+ if (v.observed === null) {
48
+ return fail({
49
+ tagName: tagName, previousChecked: before, verified: false,
50
+ error: 'Element left the document after click(); the checked state could not be verified',
51
+ hint: 'The app removed or re-rendered the element without a matching selector after the click (navigation, a remount, or the click consumed the item). Re-query the DOM to confirm the app state.'
52
+ });
53
+ }
54
+ return fail({
55
+ tagName: tagName, checked: !!v.observed, previousChecked: before, verified: false, verification: 'reverted',
56
+ error: 'Checked state reverted: click() set checked=' + expected + ' but the element reads ' + String(!!v.observed) + ' after ${verifyTimeoutMs}ms',
57
+ hint: 'A controlled checkbox whose change handler did not accept the change, or a click listener that called preventDefault().'
58
+ });
59
+ });
30
60
  } catch (e) {
31
- return JSON.stringify({ success: false, error: String(e) });
61
+ return fail({ error: 'Script error: ' + (e && e.message ? e.message : String(e)) });
32
62
  }
33
63
  })()`;
34
64
  }
65
+ /**
66
+ * Value mode writes through the native prototype value setter and verifies the
67
+ * write (see buildSetValueScript); toggle mode performs a native click().
68
+ */
69
+ export function buildSelectScript(selector, value, toggle = false, options) {
70
+ const verifyTimeoutMs = resolveVerifyTimeout(options);
71
+ if (toggle)
72
+ return buildToggleScript(selector, verifyTimeoutMs);
73
+ return buildSetValueScript(selector, value ?? '', {
74
+ focus: false,
75
+ clear: false,
76
+ lowerCaseTagName: true,
77
+ notFoundErrorExpr: `'Element not found: ' + selector`,
78
+ verifyTimeoutMs,
79
+ });
80
+ }
35
81
  export function registerSelect(program) {
36
82
  const cmd = new Command('select')
37
83
  .description('Set the value of a form element or toggle a checkbox')
@@ -42,17 +88,29 @@ export function registerSelect(program) {
42
88
  Examples:
43
89
  $ tauri-agent-tools select "select#country" "US"
44
90
  $ tauri-agent-tools select "input[name='agree']" --toggle
45
- $ tauri-agent-tools select "input#search" "hello world"`);
91
+ $ tauri-agent-tools select "input#search" "hello world"
92
+
93
+ Values are written through the native prototype setter and followed by bubbling
94
+ input + change events; <select> values must match an <option> value attribute.
95
+ --toggle performs a native click() so React and other frameworks that listen to
96
+ click for checkboxes update their state. The element is re-read afterwards and
97
+ the command fails when the app reverted the change.`);
46
98
  addInteractOptions(cmd);
99
+ addVerifyOptions(cmd);
47
100
  cmd.action(async (selector, value, opts) => {
101
+ // Build first: an invalid --verify-timeout fails before any bridge call.
102
+ const script = buildSelectScript(selector, value, opts.toggle ?? false, { verifyTimeoutMs: opts.verifyTimeout });
48
103
  const bridge = await resolveBridge(opts);
49
- const script = buildSelectScript(selector, value, opts.toggle ?? false);
50
104
  const raw = await bridge.eval(script);
51
- const result = SelectResultSchema.parse(JSON.parse(String(raw)));
105
+ const result = parseInteractResult(raw, SelectResultSchema, 'Select');
106
+ // select always prints its JSON result; on failure the object (verification,
107
+ // hint, options, …) still goes to stdout, and the thrown error reaches
108
+ // stderr and sets exit code 1.
109
+ console.log(JSON.stringify(result, null, 2));
52
110
  if (!result.success) {
53
- throw new Error(result.error ?? 'Select failed');
111
+ const hint = result.hint ? `\n hint: ${result.hint}` : '';
112
+ throw new Error(`${result.error ?? 'Select failed'}${hint}`);
54
113
  }
55
- console.log(JSON.stringify(result, null, 2));
56
114
  });
57
115
  program.addCommand(cmd);
58
116
  }
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/commands/interact/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,KAAc,EAAE,SAAkB,KAAK;IACzF,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IAEzC,IAAI,MAAM,EAAE,CAAC;QACX,OAAO;;uCAE4B,OAAO;kFACoC,OAAO;;;;wDAIjC,OAAO;;;;KAI1D,CAAC;IACJ,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,OAAO;;uCAE8B,OAAO;kFACoC,OAAO;kBACvE,YAAY;;;wDAG0B,OAAO;;;;KAI1D,CAAC;AACN,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;SAC9B,WAAW,CAAC,sDAAsD,CAAC;SACnE,QAAQ,CAAC,YAAY,EAAE,6BAA6B,CAAC;SACrD,QAAQ,CAAC,SAAS,EAAE,oCAAoC,CAAC;SACzD,MAAM,CAAC,UAAU,EAAE,iDAAiD,CAAC;SACrE,WAAW,CAAC,OAAO,EAAE;;;;0DAIgC,CAAC,CAAC;IAE1D,kBAAkB,CAAC,GAAG,CAAC,CAAC;IAExB,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,QAAgB,EAAE,KAAyB,EAAE,IAAuC,EAAE,EAAE;QACxG,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;QACxE,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,IAAI,eAAe,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
1
+ {"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/commands/interact/select.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D;;;;;;;GAOG;AACH,SAAS,iBAAiB,CAAC,QAAgB,EAAE,eAAuB;IAClE,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACzC,OAAO,WAAW,mBAAmB;oBACnB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA2BR,eAAe,KAAK,kBAAkB;;;;;;;;;;;;;wIAa+E,eAAe;;;;;;;KAOlJ,CAAC;AACN,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,QAAgB,EAChB,KAAc,EACd,SAAkB,KAAK,EACvB,OAAuB;IAEvB,MAAM,eAAe,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACtD,IAAI,MAAM;QAAE,OAAO,iBAAiB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAChE,OAAO,mBAAmB,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE,EAAE;QAChD,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,KAAK;QACZ,gBAAgB,EAAE,IAAI;QACtB,iBAAiB,EAAE,kCAAkC;QACrD,eAAe;KAChB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,QAAQ,CAAC;SAC9B,WAAW,CAAC,sDAAsD,CAAC;SACnE,QAAQ,CAAC,YAAY,EAAE,6BAA6B,CAAC;SACrD,QAAQ,CAAC,SAAS,EAAE,oCAAoC,CAAC;SACzD,MAAM,CAAC,UAAU,EAAE,iDAAiD,CAAC;SACrE,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;oDAU0B,CAAC,CAAC;IAEpD,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACxB,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAEtB,GAAG,CAAC,MAAM,CACR,KAAK,EACH,QAAgB,EAChB,KAAyB,EACzB,IAA8D,EAC9D,EAAE;QACF,yEAAyE;QACzE,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,IAAI,KAAK,EAAE,EAAE,eAAe,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QACjH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QACtE,6EAA6E;QAC7E,uEAAuE;QACvE,+BAA+B;QAC/B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,IAAI,eAAe,GAAG,IAAI,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC1B,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import type { Command } from 'commander';
2
+ import type { z } from 'zod';
2
3
  /**
3
4
  * Escapes backslashes and single quotes in CSS selectors for safe
4
5
  * embedding inside JS string literals wrapped in single quotes.
@@ -21,3 +22,98 @@ export declare function buildWaitAndFindScript(selector: string, waitMs: number)
21
22
  * plus --json for machine-readable output. Returns the command for chaining.
22
23
  */
23
24
  export declare function addInteractOptions(cmd: Command): Command;
25
+ /**
26
+ * Default deadline for the post-write re-read. An accepted write resolves on
27
+ * the first (synchronous) check, so it costs nothing; only a rejected write
28
+ * waits out the whole deadline.
29
+ */
30
+ export declare const DEFAULT_VERIFY_TIMEOUT_MS = 500;
31
+ /**
32
+ * dev_bridge.rs answers 504 after 5 s and BridgeClient.eval aborts at 5 s;
33
+ * keep at least 1 s of slack for dispatch + IPC + HTTP.
34
+ */
35
+ export declare const MAX_VERIFY_TIMEOUT_MS = 4000;
36
+ /**
37
+ * Poll cadence after the synchronous first check. React commits
38
+ * transition-lane updates on a Scheduler macrotask, so a microtask/rAF
39
+ * re-read would be too early.
40
+ */
41
+ export declare const VERIFY_INTERVAL_MS = 50;
42
+ export interface VerifyOptions {
43
+ /** 0..MAX_VERIFY_TIMEOUT_MS; 0 = single synchronous check. Default DEFAULT_VERIFY_TIMEOUT_MS. */
44
+ verifyTimeoutMs?: number;
45
+ }
46
+ export declare function resolveVerifyTimeout(opts?: VerifyOptions): number;
47
+ /** Adds --verify-timeout to a value-writing interaction command. */
48
+ export declare function addVerifyOptions(cmd: Command): Command;
49
+ /**
50
+ * JS snippet defining `__resolveValueWriter(node)`.
51
+ *
52
+ * React (react-dom's inputValueTracking) redefines `value` as an own accessor
53
+ * on every mounted <input>/<textarea> instance to remember what it wrote;
54
+ * assigning through that accessor makes the following input/change event a
55
+ * no-op for React (#10). Built-in form elements are therefore written through
56
+ * the prototype setter React itself captured. Custom elements are searched up
57
+ * their prototype chain (Lit/Stencil define accessors on the class prototype)
58
+ * and fall back to plain assignment for instance-defined or class-field
59
+ * `value`s. Anything else has no value setter and is refused instead of being
60
+ * silently given an expando property.
61
+ *
62
+ * The parameter is deliberately named `node` so generated scripts never
63
+ * contain the text `el.value =`.
64
+ */
65
+ export declare const NATIVE_VALUE_WRITER_SNIPPET = "\n function __resolveValueWriter(node) {\n var tag = node.tagName;\n var proto = tag === 'INPUT' ? HTMLInputElement.prototype\n : tag === 'TEXTAREA' ? HTMLTextAreaElement.prototype\n : tag === 'SELECT' ? HTMLSelectElement.prototype\n : null;\n if (proto) {\n var d = Object.getOwnPropertyDescriptor(proto, 'value');\n if (d && typeof d.set === 'function') return { kind: 'native', set: function (v) { d.set.call(node, v); } };\n return { kind: 'assign', set: function (v) { node.value = v; } };\n }\n if (String(node.localName || '').indexOf('-') !== -1) {\n var p = Object.getPrototypeOf(node);\n while (p && p !== Object.prototype) {\n var cd = Object.getOwnPropertyDescriptor(p, 'value');\n if (cd && typeof cd.set === 'function') return { kind: 'custom', set: function (v) { cd.set.call(node, v); } };\n p = Object.getPrototypeOf(p);\n }\n if ('value' in node) return { kind: 'assign', set: function (v) { node.value = v; } };\n }\n return null;\n }";
66
+ /**
67
+ * JS snippet defining `__verify(read, expected, timeoutMs, intervalMs)`.
68
+ *
69
+ * The first read is synchronous: React restores a rejected controlled value
70
+ * inside dispatchEvent, so it is already visible. Later reads catch
71
+ * transition-lane commits and frameworks that apply values asynchronously.
72
+ * Resolves `{ ok, observed }` and never rejects. `read` is re-invoked on every
73
+ * tick so a re-mounted node is read instead of a stale reference.
74
+ */
75
+ export declare const VERIFY_POLL_SNIPPET = "\n function __verify(read, expected, timeoutMs, intervalMs) {\n return new Promise(function (resolve) {\n var deadline = Date.now() + timeoutMs;\n function check() {\n var observed;\n try { observed = read(); } catch (e) { observed = undefined; }\n if (observed === expected) { resolve({ ok: true, observed: observed }); return; }\n if (Date.now() >= deadline) { resolve({ ok: false, observed: observed }); return; }\n setTimeout(check, intervalMs);\n }\n check();\n });\n }";
76
+ /**
77
+ * JS snippet defining `__settle()` — resolves after two macrotasks. Used after
78
+ * focus()/--clear so that state the app changed in response (React flushes an
79
+ * onFocus setState on a microtask, an accepted clear commits synchronously, and
80
+ * a commit scheduled from the app's own zero-delay timer lands on a Scheduler
81
+ * task after the first macrotask) is visible before the pre-write baseline is
82
+ * read and the target node is re-resolved.
83
+ */
84
+ export declare const SETTLE_SNIPPET = "\n function __settle() {\n return new Promise(function (resolve) {\n setTimeout(function () { setTimeout(resolve, 0); }, 0);\n });\n }";
85
+ /** JS snippet defining `__selectOptionValues(node)` — option values of a <select>, [] otherwise. */
86
+ export declare const SELECT_OPTIONS_SNIPPET = "\n function __selectOptionValues(node) {\n if (!node.options || typeof node.options.length !== 'number') return [];\n return Array.prototype.map.call(node.options, function (o) { return String(o.value); });\n }";
87
+ export interface SetValueScriptOptions {
88
+ /** `type` focuses the element first; `select` does not. */
89
+ focus: boolean;
90
+ /** `type --clear`: select() + write '' + input event before the real write. */
91
+ clear: boolean;
92
+ /** Existing contracts differ: `type` reports el.tagName as-is, `select` lower-cases it. */
93
+ lowerCaseTagName: boolean;
94
+ /** JS expression for the not-found error; `selector` is in scope. */
95
+ notFoundErrorExpr: string;
96
+ verifyTimeoutMs: number;
97
+ }
98
+ /**
99
+ * Shared script body for `type` and `select` value mode. Returns an arrow IIFE
100
+ * that resolves (via a Promise — the bridge awaits it) to a JSON string and
101
+ * never throws into the bridge.
102
+ *
103
+ * Sequence: snapshot `previousValue` → [focus] → [clear + input] → settle →
104
+ * re-resolve the target (the app may have re-mounted it) → snapshot `baseline`
105
+ * → native write → `applied` → refuse values the browser discarded or clamped
106
+ * back → input, change → verify. `reverted` means the re-read equals
107
+ * `baseline` or `previousValue`; comparing only against the pre-command value
108
+ * would let an app that accepted the clear (or changed the value on focus) but
109
+ * rejected the real write pass as `transformed`. A field the app empties after
110
+ * a non-empty write is a failure too ("cleared"): the intended value did not
111
+ * land whether the app rejected or consumed it.
112
+ */
113
+ export declare function buildSetValueScript(selector: string, value: string, o: SetValueScriptOptions): string;
114
+ /**
115
+ * Parses an interaction result from the bridge. dev_bridge.rs turns a thrown
116
+ * script into the string "ERROR: <message>", which JSON.parse would reject
117
+ * with an opaque SyntaxError — surface it as an actionable error instead.
118
+ */
119
+ export declare function parseInteractResult<S extends z.ZodTypeAny>(raw: unknown, schema: S, command: string): z.infer<S>;