@mseep/clawdcursor 1.5.5

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 (354) hide show
  1. package/CHANGELOG.md +2264 -0
  2. package/LICENSE +21 -0
  3. package/README.md +385 -0
  4. package/SECURITY.md +44 -0
  5. package/SKILL.md +503 -0
  6. package/dist/core/agent-loop/agent.d.ts +42 -0
  7. package/dist/core/agent-loop/agent.js +1023 -0
  8. package/dist/core/agent-loop/agent.js.map +1 -0
  9. package/dist/core/agent-loop/batch-tool.d.ts +25 -0
  10. package/dist/core/agent-loop/batch-tool.js +218 -0
  11. package/dist/core/agent-loop/batch-tool.js.map +1 -0
  12. package/dist/core/agent-loop/coord-scale.d.ts +72 -0
  13. package/dist/core/agent-loop/coord-scale.js +89 -0
  14. package/dist/core/agent-loop/coord-scale.js.map +1 -0
  15. package/dist/core/agent-loop/focus-guard.d.ts +24 -0
  16. package/dist/core/agent-loop/focus-guard.js +29 -0
  17. package/dist/core/agent-loop/focus-guard.js.map +1 -0
  18. package/dist/core/agent-loop/project-mcp.d.ts +97 -0
  19. package/dist/core/agent-loop/project-mcp.js +253 -0
  20. package/dist/core/agent-loop/project-mcp.js.map +1 -0
  21. package/dist/core/agent-loop/prompt.d.ts +45 -0
  22. package/dist/core/agent-loop/prompt.js +426 -0
  23. package/dist/core/agent-loop/prompt.js.map +1 -0
  24. package/dist/core/agent-loop/tool-meta.d.ts +93 -0
  25. package/dist/core/agent-loop/tool-meta.js +651 -0
  26. package/dist/core/agent-loop/tool-meta.js.map +1 -0
  27. package/dist/core/agent-loop/tools.d.ts +38 -0
  28. package/dist/core/agent-loop/tools.js +2134 -0
  29. package/dist/core/agent-loop/tools.js.map +1 -0
  30. package/dist/core/agent-loop/types.d.ts +170 -0
  31. package/dist/core/agent-loop/types.js +12 -0
  32. package/dist/core/agent-loop/types.js.map +1 -0
  33. package/dist/core/agent.d.ts +51 -0
  34. package/dist/core/agent.js +245 -0
  35. package/dist/core/agent.js.map +1 -0
  36. package/dist/core/app-categories.d.ts +67 -0
  37. package/dist/core/app-categories.js +108 -0
  38. package/dist/core/app-categories.js.map +1 -0
  39. package/dist/core/banner.d.ts +70 -0
  40. package/dist/core/banner.js +245 -0
  41. package/dist/core/banner.js.map +1 -0
  42. package/dist/core/classify/capability.d.ts +45 -0
  43. package/dist/core/classify/capability.js +78 -0
  44. package/dist/core/classify/capability.js.map +1 -0
  45. package/dist/core/decompose/llm-decomposer.d.ts +35 -0
  46. package/dist/core/decompose/llm-decomposer.js +156 -0
  47. package/dist/core/decompose/llm-decomposer.js.map +1 -0
  48. package/dist/core/decompose/parser.d.ts +27 -0
  49. package/dist/core/decompose/parser.js +101 -0
  50. package/dist/core/decompose/parser.js.map +1 -0
  51. package/dist/core/observability/correlation.d.ts +19 -0
  52. package/dist/core/observability/correlation.js +36 -0
  53. package/dist/core/observability/correlation.js.map +1 -0
  54. package/dist/core/observability/cost-meter.d.ts +51 -0
  55. package/dist/core/observability/cost-meter.js +134 -0
  56. package/dist/core/observability/cost-meter.js.map +1 -0
  57. package/dist/core/observability/logger.d.ts +61 -0
  58. package/dist/core/observability/logger.js +550 -0
  59. package/dist/core/observability/logger.js.map +1 -0
  60. package/dist/core/router/aliases.d.ts +50 -0
  61. package/dist/core/router/aliases.js +104 -0
  62. package/dist/core/router/aliases.js.map +1 -0
  63. package/dist/core/router/normalize.d.ts +41 -0
  64. package/dist/core/router/normalize.js +80 -0
  65. package/dist/core/router/normalize.js.map +1 -0
  66. package/dist/core/safety.d.ts +126 -0
  67. package/dist/core/safety.js +568 -0
  68. package/dist/core/safety.js.map +1 -0
  69. package/dist/core/sense/a11y-resolver.d.ts +73 -0
  70. package/dist/core/sense/a11y-resolver.js +76 -0
  71. package/dist/core/sense/a11y-resolver.js.map +1 -0
  72. package/dist/core/sense/fingerprint.d.ts +41 -0
  73. package/dist/core/sense/fingerprint.js +123 -0
  74. package/dist/core/sense/fingerprint.js.map +1 -0
  75. package/dist/core/sense/rank.d.ts +70 -0
  76. package/dist/core/sense/rank.js +192 -0
  77. package/dist/core/sense/rank.js.map +1 -0
  78. package/dist/core/sense/reactive-check.d.ts +40 -0
  79. package/dist/core/sense/reactive-check.js +48 -0
  80. package/dist/core/sense/reactive-check.js.map +1 -0
  81. package/dist/core/sense/snapshot.d.ts +19 -0
  82. package/dist/core/sense/snapshot.js +100 -0
  83. package/dist/core/sense/snapshot.js.map +1 -0
  84. package/dist/core/sense/types.d.ts +66 -0
  85. package/dist/core/sense/types.js +9 -0
  86. package/dist/core/sense/types.js.map +1 -0
  87. package/dist/core/sense/ui-map-anchors.d.ts +7 -0
  88. package/dist/core/sense/ui-map-anchors.js +24 -0
  89. package/dist/core/sense/ui-map-anchors.js.map +1 -0
  90. package/dist/core/sense/ui-map-elements.d.ts +5 -0
  91. package/dist/core/sense/ui-map-elements.js +33 -0
  92. package/dist/core/sense/ui-map-elements.js.map +1 -0
  93. package/dist/core/sense/ui-map-find.d.ts +56 -0
  94. package/dist/core/sense/ui-map-find.js +153 -0
  95. package/dist/core/sense/ui-map-find.js.map +1 -0
  96. package/dist/core/sense/ui-map-fuse.d.ts +4 -0
  97. package/dist/core/sense/ui-map-fuse.js +44 -0
  98. package/dist/core/sense/ui-map-fuse.js.map +1 -0
  99. package/dist/core/sense/ui-map-geom.d.ts +3 -0
  100. package/dist/core/sense/ui-map-geom.js +16 -0
  101. package/dist/core/sense/ui-map-geom.js.map +1 -0
  102. package/dist/core/sense/ui-map-holder.d.ts +58 -0
  103. package/dist/core/sense/ui-map-holder.js +87 -0
  104. package/dist/core/sense/ui-map-holder.js.map +1 -0
  105. package/dist/core/sense/ui-map-normalize.d.ts +19 -0
  106. package/dist/core/sense/ui-map-normalize.js +65 -0
  107. package/dist/core/sense/ui-map-normalize.js.map +1 -0
  108. package/dist/core/sense/ui-map-render.d.ts +4 -0
  109. package/dist/core/sense/ui-map-render.js +34 -0
  110. package/dist/core/sense/ui-map-render.js.map +1 -0
  111. package/dist/core/sense/ui-map-resolve.d.ts +41 -0
  112. package/dist/core/sense/ui-map-resolve.js +59 -0
  113. package/dist/core/sense/ui-map-resolve.js.map +1 -0
  114. package/dist/core/sense/ui-map-types.d.ts +66 -0
  115. package/dist/core/sense/ui-map-types.js +11 -0
  116. package/dist/core/sense/ui-map-types.js.map +1 -0
  117. package/dist/core/sense/ui-map.d.ts +29 -0
  118. package/dist/core/sense/ui-map.js +113 -0
  119. package/dist/core/sense/ui-map.js.map +1 -0
  120. package/dist/core/verify/assertions.d.ts +132 -0
  121. package/dist/core/verify/assertions.js +284 -0
  122. package/dist/core/verify/assertions.js.map +1 -0
  123. package/dist/index.d.ts +21 -0
  124. package/dist/index.js +24 -0
  125. package/dist/index.js.map +1 -0
  126. package/dist/llm/browser-config.d.ts +36 -0
  127. package/dist/llm/browser-config.js +83 -0
  128. package/dist/llm/browser-config.js.map +1 -0
  129. package/dist/llm/client.d.ts +268 -0
  130. package/dist/llm/client.js +1094 -0
  131. package/dist/llm/client.js.map +1 -0
  132. package/dist/llm/config.d.ts +79 -0
  133. package/dist/llm/config.js +375 -0
  134. package/dist/llm/config.js.map +1 -0
  135. package/dist/llm/credentials.d.ts +35 -0
  136. package/dist/llm/credentials.js +491 -0
  137. package/dist/llm/credentials.js.map +1 -0
  138. package/dist/llm/external-creds.d.ts +42 -0
  139. package/dist/llm/external-creds.js +169 -0
  140. package/dist/llm/external-creds.js.map +1 -0
  141. package/dist/llm/providers.d.ts +123 -0
  142. package/dist/llm/providers.js +717 -0
  143. package/dist/llm/providers.js.map +1 -0
  144. package/dist/paths.d.ts +31 -0
  145. package/dist/paths.js +147 -0
  146. package/dist/paths.js.map +1 -0
  147. package/dist/platform/accessibility.d.ts +139 -0
  148. package/dist/platform/accessibility.js +670 -0
  149. package/dist/platform/accessibility.js.map +1 -0
  150. package/dist/platform/cdp-driver.d.ts +318 -0
  151. package/dist/platform/cdp-driver.js +1179 -0
  152. package/dist/platform/cdp-driver.js.map +1 -0
  153. package/dist/platform/index.d.ts +11 -0
  154. package/dist/platform/index.js +69 -0
  155. package/dist/platform/index.js.map +1 -0
  156. package/dist/platform/keys.d.ts +17 -0
  157. package/dist/platform/keys.js +129 -0
  158. package/dist/platform/keys.js.map +1 -0
  159. package/dist/platform/launch-poll.d.ts +101 -0
  160. package/dist/platform/launch-poll.js +177 -0
  161. package/dist/platform/launch-poll.js.map +1 -0
  162. package/dist/platform/linux.d.ts +173 -0
  163. package/dist/platform/linux.js +1253 -0
  164. package/dist/platform/linux.js.map +1 -0
  165. package/dist/platform/macos.d.ts +136 -0
  166. package/dist/platform/macos.js +976 -0
  167. package/dist/platform/macos.js.map +1 -0
  168. package/dist/platform/native-desktop.d.ts +145 -0
  169. package/dist/platform/native-desktop.js +936 -0
  170. package/dist/platform/native-desktop.js.map +1 -0
  171. package/dist/platform/native-helper.d.ts +130 -0
  172. package/dist/platform/native-helper.js +592 -0
  173. package/dist/platform/native-helper.js.map +1 -0
  174. package/dist/platform/ocr-engine.d.ts +78 -0
  175. package/dist/platform/ocr-engine.js +363 -0
  176. package/dist/platform/ocr-engine.js.map +1 -0
  177. package/dist/platform/ps-runner.d.ts +28 -0
  178. package/dist/platform/ps-runner.js +228 -0
  179. package/dist/platform/ps-runner.js.map +1 -0
  180. package/dist/platform/types.d.ts +397 -0
  181. package/dist/platform/types.js +15 -0
  182. package/dist/platform/types.js.map +1 -0
  183. package/dist/platform/uri-handler.d.ts +75 -0
  184. package/dist/platform/uri-handler.js +273 -0
  185. package/dist/platform/uri-handler.js.map +1 -0
  186. package/dist/platform/wayland-backend.d.ts +53 -0
  187. package/dist/platform/wayland-backend.js +348 -0
  188. package/dist/platform/wayland-backend.js.map +1 -0
  189. package/dist/platform/windows.d.ts +232 -0
  190. package/dist/platform/windows.js +1210 -0
  191. package/dist/platform/windows.js.map +1 -0
  192. package/dist/postbuild.d.ts +10 -0
  193. package/dist/postbuild.js +98 -0
  194. package/dist/postbuild.js.map +1 -0
  195. package/dist/schema/snapshot.d.ts +33 -0
  196. package/dist/schema/snapshot.js +90 -0
  197. package/dist/schema/snapshot.js.map +1 -0
  198. package/dist/shortcuts.d.ts +30 -0
  199. package/dist/shortcuts.js +261 -0
  200. package/dist/shortcuts.js.map +1 -0
  201. package/dist/surface/cli.d.ts +7 -0
  202. package/dist/surface/cli.js +1556 -0
  203. package/dist/surface/cli.js.map +1 -0
  204. package/dist/surface/dashboard.d.ts +8 -0
  205. package/dist/surface/dashboard.js +1193 -0
  206. package/dist/surface/dashboard.js.map +1 -0
  207. package/dist/surface/doctor.d.ts +29 -0
  208. package/dist/surface/doctor.js +1514 -0
  209. package/dist/surface/doctor.js.map +1 -0
  210. package/dist/surface/format.d.ts +10 -0
  211. package/dist/surface/format.js +37 -0
  212. package/dist/surface/format.js.map +1 -0
  213. package/dist/surface/http-utility.d.ts +65 -0
  214. package/dist/surface/http-utility.js +336 -0
  215. package/dist/surface/http-utility.js.map +1 -0
  216. package/dist/surface/mcp-server.d.ts +91 -0
  217. package/dist/surface/mcp-server.js +280 -0
  218. package/dist/surface/mcp-server.js.map +1 -0
  219. package/dist/surface/onboarding.d.ts +15 -0
  220. package/dist/surface/onboarding.js +184 -0
  221. package/dist/surface/onboarding.js.map +1 -0
  222. package/dist/surface/pidfile.d.ts +79 -0
  223. package/dist/surface/pidfile.js +263 -0
  224. package/dist/surface/pidfile.js.map +1 -0
  225. package/dist/surface/readiness.d.ts +45 -0
  226. package/dist/surface/readiness.js +230 -0
  227. package/dist/surface/readiness.js.map +1 -0
  228. package/dist/surface/report.d.ts +68 -0
  229. package/dist/surface/report.js +341 -0
  230. package/dist/surface/report.js.map +1 -0
  231. package/dist/surface/skill-register.d.ts +14 -0
  232. package/dist/surface/skill-register.js +150 -0
  233. package/dist/surface/skill-register.js.map +1 -0
  234. package/dist/surface/version.d.ts +6 -0
  235. package/dist/surface/version.js +27 -0
  236. package/dist/surface/version.js.map +1 -0
  237. package/dist/tools/a11y.d.ts +8 -0
  238. package/dist/tools/a11y.js +545 -0
  239. package/dist/tools/a11y.js.map +1 -0
  240. package/dist/tools/a11y_depth.d.ts +19 -0
  241. package/dist/tools/a11y_depth.js +455 -0
  242. package/dist/tools/a11y_depth.js.map +1 -0
  243. package/dist/tools/agent.d.ts +15 -0
  244. package/dist/tools/agent.js +248 -0
  245. package/dist/tools/agent.js.map +1 -0
  246. package/dist/tools/batch.d.ts +46 -0
  247. package/dist/tools/batch.js +230 -0
  248. package/dist/tools/batch.js.map +1 -0
  249. package/dist/tools/cdp.d.ts +8 -0
  250. package/dist/tools/cdp.js +233 -0
  251. package/dist/tools/cdp.js.map +1 -0
  252. package/dist/tools/compact.d.ts +63 -0
  253. package/dist/tools/compact.js +418 -0
  254. package/dist/tools/compact.js.map +1 -0
  255. package/dist/tools/cost-class.d.ts +38 -0
  256. package/dist/tools/cost-class.js +117 -0
  257. package/dist/tools/cost-class.js.map +1 -0
  258. package/dist/tools/desktop.d.ts +9 -0
  259. package/dist/tools/desktop.js +346 -0
  260. package/dist/tools/desktop.js.map +1 -0
  261. package/dist/tools/electron_bridge.d.ts +41 -0
  262. package/dist/tools/electron_bridge.js +261 -0
  263. package/dist/tools/electron_bridge.js.map +1 -0
  264. package/dist/tools/extras.d.ts +22 -0
  265. package/dist/tools/extras.js +942 -0
  266. package/dist/tools/extras.js.map +1 -0
  267. package/dist/tools/favorites.d.ts +13 -0
  268. package/dist/tools/favorites.js +137 -0
  269. package/dist/tools/favorites.js.map +1 -0
  270. package/dist/tools/introspection.d.ts +13 -0
  271. package/dist/tools/introspection.js +55 -0
  272. package/dist/tools/introspection.js.map +1 -0
  273. package/dist/tools/ocr.d.ts +8 -0
  274. package/dist/tools/ocr.js +66 -0
  275. package/dist/tools/ocr.js.map +1 -0
  276. package/dist/tools/orchestration.d.ts +7 -0
  277. package/dist/tools/orchestration.js +377 -0
  278. package/dist/tools/orchestration.js.map +1 -0
  279. package/dist/tools/playbooks/extract-compose.d.ts +22 -0
  280. package/dist/tools/playbooks/extract-compose.js +85 -0
  281. package/dist/tools/playbooks/extract-compose.js.map +1 -0
  282. package/dist/tools/playbooks/find-replace.d.ts +11 -0
  283. package/dist/tools/playbooks/find-replace.js +56 -0
  284. package/dist/tools/playbooks/find-replace.js.map +1 -0
  285. package/dist/tools/playbooks/index.d.ts +63 -0
  286. package/dist/tools/playbooks/index.js +70 -0
  287. package/dist/tools/playbooks/index.js.map +1 -0
  288. package/dist/tools/playbooks/keys-blocklist.d.ts +24 -0
  289. package/dist/tools/playbooks/keys-blocklist.js +89 -0
  290. package/dist/tools/playbooks/keys-blocklist.js.map +1 -0
  291. package/dist/tools/registry.d.ts +40 -0
  292. package/dist/tools/registry.js +560 -0
  293. package/dist/tools/registry.js.map +1 -0
  294. package/dist/tools/safety-gate.d.ts +16 -0
  295. package/dist/tools/safety-gate.js +70 -0
  296. package/dist/tools/safety-gate.js.map +1 -0
  297. package/dist/tools/scheduler.d.ts +76 -0
  298. package/dist/tools/scheduler.js +413 -0
  299. package/dist/tools/scheduler.js.map +1 -0
  300. package/dist/tools/shortcuts.d.ts +13 -0
  301. package/dist/tools/shortcuts.js +205 -0
  302. package/dist/tools/shortcuts.js.map +1 -0
  303. package/dist/tools/smart.d.ts +15 -0
  304. package/dist/tools/smart.js +785 -0
  305. package/dist/tools/smart.js.map +1 -0
  306. package/dist/tools/types.d.ts +174 -0
  307. package/dist/tools/types.js +67 -0
  308. package/dist/tools/types.js.map +1 -0
  309. package/dist/tools/window-text.d.ts +15 -0
  310. package/dist/tools/window-text.js +39 -0
  311. package/dist/tools/window-text.js.map +1 -0
  312. package/dist/types.d.ts +122 -0
  313. package/dist/types.js +41 -0
  314. package/dist/types.js.map +1 -0
  315. package/native/Package.swift +38 -0
  316. package/native/README.md +113 -0
  317. package/native/Sources/ClawdCursorHelper/main.swift +602 -0
  318. package/native/Sources/ClawdCursorHost/main.swift +182 -0
  319. package/native/Sources/PermissionCheck/main.swift +53 -0
  320. package/native/Sources/ScreenshotHelper/main.swift +219 -0
  321. package/native/build.sh +139 -0
  322. package/native/entitlements.plist +12 -0
  323. package/package.json +115 -0
  324. package/scripts/banner.ps1 +112 -0
  325. package/scripts/coord-accuracy.ps1 +140 -0
  326. package/scripts/coord-uwp.ps1 +80 -0
  327. package/scripts/edge-glow.ps1 +180 -0
  328. package/scripts/find-element.ps1 +198 -0
  329. package/scripts/get-foreground-window.ps1 +71 -0
  330. package/scripts/get-screen-context.ps1 +183 -0
  331. package/scripts/get-windows.ps1 +66 -0
  332. package/scripts/install-panic-hotkey.ps1 +46 -0
  333. package/scripts/interact-element.ps1 +431 -0
  334. package/scripts/invoke-element.ps1 +314 -0
  335. package/scripts/linux/atspi-bridge.py +356 -0
  336. package/scripts/linux/ocr-recognize.py +154 -0
  337. package/scripts/mac/_window-picker.jxa +163 -0
  338. package/scripts/mac/find-element.jxa +0 -0
  339. package/scripts/mac/find-element.sh +161 -0
  340. package/scripts/mac/focus-window.jxa +284 -0
  341. package/scripts/mac/get-focused-element.jxa +102 -0
  342. package/scripts/mac/get-foreground-window.jxa +173 -0
  343. package/scripts/mac/get-screen-context.jxa +197 -0
  344. package/scripts/mac/get-ui-tree.sh +141 -0
  345. package/scripts/mac/get-windows.jxa +117 -0
  346. package/scripts/mac/interact-element.sh +235 -0
  347. package/scripts/mac/invoke-element.jxa +408 -0
  348. package/scripts/mac/ocr-recognize.swift +124 -0
  349. package/scripts/ocr-recognize.ps1 +102 -0
  350. package/scripts/postinstall-native.js +48 -0
  351. package/scripts/ps-bridge.ps1 +830 -0
  352. package/scripts/smoke-mcp.ps1 +119 -0
  353. package/scripts/sync-version.ts +178 -0
  354. package/scripts/verify-install.js +81 -0
@@ -0,0 +1,431 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Enhanced UI element interaction script with additional patterns.
4
+ Extends invoke-element.ps1 with SendKeys, ScrollPattern, and partial name matching.
5
+
6
+ .DESCRIPTION
7
+ This script provides advanced UI Automation interactions that go beyond
8
+ what invoke-element.ps1 handles:
9
+
10
+ - sendkeys: Focus element and send keystrokes (for elements without ValuePattern)
11
+ - scroll: Scroll an element using ScrollPattern
12
+ - get-patterns: List all supported patterns on an element (for debugging)
13
+ - click-at: Click at the element's center using Win32 mouse_event
14
+ - wait-enabled: Poll until an element becomes enabled
15
+
16
+ Uses .NET System.Windows.Automation namespace for reliable element interaction.
17
+
18
+ .PARAMETER Name
19
+ Find element by Name (exact match).
20
+
21
+ .PARAMETER AutomationId
22
+ Find element by AutomationId (exact match).
23
+
24
+ .PARAMETER ControlType
25
+ Filter by ControlType (e.g. "Button", "Edit", "MenuItem").
26
+
27
+ .PARAMETER ProcessId
28
+ Required. Process ID of the target window.
29
+
30
+ .PARAMETER Action
31
+ Action to perform: sendkeys, scroll, get-patterns, click-at, wait-enabled
32
+
33
+ .PARAMETER Value
34
+ The text/keys to send (for sendkeys), or scroll amount (for scroll).
35
+
36
+ .PARAMETER Direction
37
+ Scroll direction: "up", "down", "left", "right" (for scroll action).
38
+
39
+ .PARAMETER PartialMatch
40
+ If specified, match Name using substring/contains instead of exact match.
41
+
42
+ .EXAMPLE
43
+ # Send keys to a text field that doesn't support ValuePattern
44
+ .\interact-element.ps1 -Name "Search" -Action sendkeys -Value "hello" -ProcessId 1234
45
+
46
+ # Scroll a list down
47
+ .\interact-element.ps1 -Name "ListView" -Action scroll -Direction down -Value "3" -ProcessId 1234
48
+
49
+ # Get all supported patterns for debugging
50
+ .\interact-element.ps1 -Name "Submit" -Action get-patterns -ProcessId 1234
51
+
52
+ # Find by partial name match
53
+ .\interact-element.ps1 -Name "Save" -Action click-at -ProcessId 1234 -PartialMatch
54
+ #>
55
+ param(
56
+ [string]$Name = "",
57
+ [string]$AutomationId = "",
58
+ [string]$ControlType = "",
59
+ [Parameter(Mandatory=$true)]
60
+ [int]$ProcessId,
61
+ [Parameter(Mandatory=$true)]
62
+ [ValidateSet("sendkeys", "scroll", "get-patterns", "click-at", "wait-enabled")]
63
+ [string]$Action,
64
+ [string]$Value = "",
65
+ [string]$Direction = "down",
66
+ [switch]$PartialMatch
67
+ )
68
+
69
+ # ── Load UI Automation assemblies ──
70
+ try {
71
+ Add-Type -AssemblyName UIAutomationClient
72
+ Add-Type -AssemblyName UIAutomationTypes
73
+ Add-Type -AssemblyName System.Windows.Forms
74
+ } catch {
75
+ [Console]::Out.Write((@{ success = $false; error = "Failed to load assemblies: $($_.Exception.Message)" } | ConvertTo-Json -Compress))
76
+ exit 1
77
+ }
78
+
79
+ # ── Win32 mouse_event for coordinate clicking ──
80
+ Add-Type @"
81
+ using System;
82
+ using System.Runtime.InteropServices;
83
+ public class Win32Mouse {
84
+ [DllImport("user32.dll")]
85
+ public static extern bool SetCursorPos(int X, int Y);
86
+
87
+ [DllImport("user32.dll")]
88
+ public static extern void mouse_event(uint dwFlags, int dx, int dy, uint dwData, IntPtr dwExtraInfo);
89
+
90
+ public const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
91
+ public const uint MOUSEEVENTF_LEFTUP = 0x0004;
92
+
93
+ public static void ClickAt(int x, int y) {
94
+ SetCursorPos(x, y);
95
+ System.Threading.Thread.Sleep(50);
96
+ mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, IntPtr.Zero);
97
+ System.Threading.Thread.Sleep(30);
98
+ mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, IntPtr.Zero);
99
+ }
100
+ }
101
+ "@ -ErrorAction SilentlyContinue
102
+
103
+ $ErrorActionPreference = 'Stop'
104
+
105
+ # ── Control type mapping ──
106
+ $ctMap = @{
107
+ "Button" = [System.Windows.Automation.ControlType]::Button
108
+ "CheckBox" = [System.Windows.Automation.ControlType]::CheckBox
109
+ "ComboBox" = [System.Windows.Automation.ControlType]::ComboBox
110
+ "Custom" = [System.Windows.Automation.ControlType]::Custom
111
+ "DataItem" = [System.Windows.Automation.ControlType]::DataItem
112
+ "Document" = [System.Windows.Automation.ControlType]::Document
113
+ "Edit" = [System.Windows.Automation.ControlType]::Edit
114
+ "Group" = [System.Windows.Automation.ControlType]::Group
115
+ "Hyperlink" = [System.Windows.Automation.ControlType]::Hyperlink
116
+ "List" = [System.Windows.Automation.ControlType]::List
117
+ "ListItem" = [System.Windows.Automation.ControlType]::ListItem
118
+ "Menu" = [System.Windows.Automation.ControlType]::Menu
119
+ "MenuBar" = [System.Windows.Automation.ControlType]::MenuBar
120
+ "MenuItem" = [System.Windows.Automation.ControlType]::MenuItem
121
+ "Pane" = [System.Windows.Automation.ControlType]::Pane
122
+ "RadioButton" = [System.Windows.Automation.ControlType]::RadioButton
123
+ "ScrollBar" = [System.Windows.Automation.ControlType]::ScrollBar
124
+ "Slider" = [System.Windows.Automation.ControlType]::Slider
125
+ "Spinner" = [System.Windows.Automation.ControlType]::Spinner
126
+ "SplitButton" = [System.Windows.Automation.ControlType]::SplitButton
127
+ "Tab" = [System.Windows.Automation.ControlType]::Tab
128
+ "TabItem" = [System.Windows.Automation.ControlType]::TabItem
129
+ "Text" = [System.Windows.Automation.ControlType]::Text
130
+ "ToolBar" = [System.Windows.Automation.ControlType]::ToolBar
131
+ "Tree" = [System.Windows.Automation.ControlType]::Tree
132
+ "TreeItem" = [System.Windows.Automation.ControlType]::TreeItem
133
+ "Window" = [System.Windows.Automation.ControlType]::Window
134
+ }
135
+
136
+ # ── Helper: Find element with optional partial match ──
137
+ function Find-UIElement {
138
+ param(
139
+ [System.Windows.Automation.AutomationElement]$SearchRoot,
140
+ [string]$Name,
141
+ [string]$AutomationId,
142
+ [string]$ControlType,
143
+ [switch]$PartialMatch
144
+ )
145
+
146
+ if ($PartialMatch -and $Name -ne "") {
147
+ # For partial match, we can't use PropertyCondition — walk the tree
148
+ $conditions = @()
149
+
150
+ if ($ControlType -ne "" -and $ctMap.ContainsKey($ControlType)) {
151
+ $conditions += New-Object System.Windows.Automation.PropertyCondition(
152
+ [System.Windows.Automation.AutomationElement]::ControlTypeProperty,
153
+ $ctMap[$ControlType]
154
+ )
155
+ }
156
+
157
+ if ($conditions.Count -eq 0) {
158
+ $searchCondition = [System.Windows.Automation.Condition]::TrueCondition
159
+ } elseif ($conditions.Count -eq 1) {
160
+ $searchCondition = $conditions[0]
161
+ } else {
162
+ $searchCondition = New-Object System.Windows.Automation.AndCondition(
163
+ [System.Windows.Automation.Condition[]]$conditions
164
+ )
165
+ }
166
+
167
+ $elements = $SearchRoot.FindAll(
168
+ [System.Windows.Automation.TreeScope]::Descendants,
169
+ $searchCondition
170
+ )
171
+
172
+ $lowerName = $Name.ToLower()
173
+ foreach ($el in $elements) {
174
+ try {
175
+ $elName = $el.Current.Name
176
+ if ($elName -and $elName.ToLower().Contains($lowerName)) {
177
+ return $el
178
+ }
179
+ } catch {
180
+ continue
181
+ }
182
+ }
183
+ return $null
184
+ }
185
+
186
+ # Exact match (standard approach)
187
+ $conditions = @()
188
+
189
+ if ($AutomationId -ne "") {
190
+ $conditions += New-Object System.Windows.Automation.PropertyCondition(
191
+ [System.Windows.Automation.AutomationElement]::AutomationIdProperty,
192
+ $AutomationId
193
+ )
194
+ }
195
+
196
+ if ($Name -ne "") {
197
+ $conditions += New-Object System.Windows.Automation.PropertyCondition(
198
+ [System.Windows.Automation.AutomationElement]::NameProperty,
199
+ $Name
200
+ )
201
+ }
202
+
203
+ if ($ControlType -ne "" -and $ctMap.ContainsKey($ControlType)) {
204
+ $conditions += New-Object System.Windows.Automation.PropertyCondition(
205
+ [System.Windows.Automation.AutomationElement]::ControlTypeProperty,
206
+ $ctMap[$ControlType]
207
+ )
208
+ }
209
+
210
+ if ($conditions.Count -eq 0) {
211
+ return $null
212
+ }
213
+
214
+ if ($conditions.Count -eq 1) {
215
+ $searchCondition = $conditions[0]
216
+ } else {
217
+ $searchCondition = New-Object System.Windows.Automation.AndCondition(
218
+ [System.Windows.Automation.Condition[]]$conditions
219
+ )
220
+ }
221
+
222
+ return $SearchRoot.FindFirst(
223
+ [System.Windows.Automation.TreeScope]::Descendants,
224
+ $searchCondition
225
+ )
226
+ }
227
+
228
+ # ══════════════════════════════════════════════════════════════
229
+ # MAIN LOGIC
230
+ # ══════════════════════════════════════════════════════════════
231
+
232
+ try {
233
+ $root = [System.Windows.Automation.AutomationElement]::RootElement
234
+
235
+ # Find the target window by ProcessId
236
+ $procCondition = New-Object System.Windows.Automation.PropertyCondition(
237
+ [System.Windows.Automation.AutomationElement]::ProcessIdProperty,
238
+ $ProcessId
239
+ )
240
+ $window = $root.FindFirst(
241
+ [System.Windows.Automation.TreeScope]::Children,
242
+ $procCondition
243
+ )
244
+
245
+ if ($null -eq $window) {
246
+ [Console]::Out.Write((@{ success = $false; error = "No window found for ProcessId $ProcessId" } | ConvertTo-Json -Compress))
247
+ exit 0
248
+ }
249
+
250
+ # Find the target element
251
+ $element = Find-UIElement -SearchRoot $window -Name $Name -AutomationId $AutomationId -ControlType $ControlType -PartialMatch:$PartialMatch
252
+
253
+ if ($null -eq $element) {
254
+ $searchDesc = ""
255
+ if ($AutomationId -ne "") { $searchDesc += "AutomationId='$AutomationId' " }
256
+ if ($Name -ne "") { $searchDesc += "Name='$Name' " }
257
+ if ($ControlType -ne "") { $searchDesc += "ControlType='$ControlType' " }
258
+ if ($PartialMatch) { $searchDesc += "(partial match) " }
259
+ [Console]::Out.Write((@{ success = $false; error = "Element not found: $($searchDesc.Trim())" } | ConvertTo-Json -Compress))
260
+ exit 0
261
+ }
262
+
263
+ # Execute the action
264
+ switch ($Action) {
265
+ "sendkeys" {
266
+ # Focus the element, then send keystrokes via SendKeys
267
+ # This works for elements that don't support ValuePattern (e.g., web content, rich text)
268
+ if ($Value -eq "") {
269
+ [Console]::Out.Write((@{ success = $false; error = "Value parameter required for sendkeys action" } | ConvertTo-Json -Compress))
270
+ exit 0
271
+ }
272
+
273
+ try {
274
+ $element.SetFocus()
275
+ Start-Sleep -Milliseconds 100
276
+
277
+ # Use System.Windows.Forms.SendKeys for reliable text input
278
+ # Escape special SendKeys characters: +, ^, %, ~, {, }, (, )
279
+ $escaped = $Value -replace '([+^%~{}()\[\]])', '{$1}'
280
+ [System.Windows.Forms.SendKeys]::SendWait($escaped)
281
+
282
+ [Console]::Out.Write((@{
283
+ success = $true
284
+ action = "sendkeys"
285
+ method = "SendKeys"
286
+ value = $Value
287
+ } | ConvertTo-Json -Compress))
288
+ } catch {
289
+ [Console]::Out.Write((@{
290
+ success = $false
291
+ error = "SendKeys failed: $($_.Exception.Message)"
292
+ } | ConvertTo-Json -Compress))
293
+ }
294
+ }
295
+
296
+ "scroll" {
297
+ # Scroll using ScrollPattern
298
+ try {
299
+ $scrollPattern = $element.GetCurrentPattern([System.Windows.Automation.ScrollPattern]::Pattern)
300
+
301
+ $amount = 3 # Default scroll amount (lines)
302
+ if ($Value -ne "") {
303
+ $amount = [int]$Value
304
+ }
305
+
306
+ # ScrollPattern.Scroll uses ScrollAmount enum
307
+ $scrollAmount = switch ($amount) {
308
+ 1 { [System.Windows.Automation.ScrollAmount]::SmallIncrement }
309
+ default { [System.Windows.Automation.ScrollAmount]::LargeIncrement }
310
+ }
311
+ $noScroll = [System.Windows.Automation.ScrollAmount]::NoAmount
312
+
313
+ switch ($Direction) {
314
+ "down" { $scrollPattern.Scroll($noScroll, $scrollAmount) }
315
+ "up" { $scrollPattern.Scroll($noScroll, [System.Windows.Automation.ScrollAmount]::SmallDecrement) }
316
+ "right" { $scrollPattern.Scroll($scrollAmount, $noScroll) }
317
+ "left" { $scrollPattern.Scroll([System.Windows.Automation.ScrollAmount]::SmallDecrement, $noScroll) }
318
+ }
319
+
320
+ [Console]::Out.Write((@{
321
+ success = $true
322
+ action = "scroll"
323
+ direction = $Direction
324
+ amount = $amount
325
+ } | ConvertTo-Json -Compress))
326
+ } catch {
327
+ [Console]::Out.Write((@{
328
+ success = $false
329
+ error = "ScrollPattern not supported or scroll failed: $($_.Exception.Message)"
330
+ } | ConvertTo-Json -Compress))
331
+ }
332
+ }
333
+
334
+ "get-patterns" {
335
+ # List all supported UIA patterns on the element — useful for debugging
336
+ $supported = @()
337
+ $patternIds = $element.GetSupportedPatterns()
338
+
339
+ foreach ($pid in $patternIds) {
340
+ $supported += $pid.ProgrammaticName
341
+ }
342
+
343
+ $rect = $element.Current.BoundingRectangle
344
+ $bounds = @{
345
+ x = [int]$rect.X
346
+ y = [int]$rect.Y
347
+ width = [int]$rect.Width
348
+ height = [int]$rect.Height
349
+ }
350
+
351
+ [Console]::Out.Write((@{
352
+ success = $true
353
+ action = "get-patterns"
354
+ name = $element.Current.Name
355
+ automationId = $element.Current.AutomationId
356
+ controlType = $element.Current.ControlType.ProgrammaticName
357
+ className = $element.Current.ClassName
358
+ isEnabled = $element.Current.IsEnabled
359
+ patterns = $supported
360
+ bounds = $bounds
361
+ } | ConvertTo-Json -Depth 5 -Compress))
362
+ }
363
+
364
+ "click-at" {
365
+ # Click at the element's center using Win32 mouse_event
366
+ # More reliable than InvokePattern for some elements (e.g., custom controls)
367
+ $rect = $element.Current.BoundingRectangle
368
+ if ([double]::IsInfinity($rect.X) -or [double]::IsInfinity($rect.Y) -or $rect.Width -le 0 -or $rect.Height -le 0) {
369
+ [Console]::Out.Write((@{
370
+ success = $false
371
+ error = "Element has no valid bounds for coordinate click"
372
+ } | ConvertTo-Json -Compress))
373
+ exit 0
374
+ }
375
+
376
+ $clickX = [int]($rect.X + $rect.Width / 2)
377
+ $clickY = [int]($rect.Y + $rect.Height / 2)
378
+
379
+ try {
380
+ [Win32Mouse]::ClickAt($clickX, $clickY)
381
+ [Console]::Out.Write((@{
382
+ success = $true
383
+ action = "click-at"
384
+ method = "Win32Mouse"
385
+ clickPoint = @{ x = $clickX; y = $clickY }
386
+ } | ConvertTo-Json -Depth 5 -Compress))
387
+ } catch {
388
+ [Console]::Out.Write((@{
389
+ success = $false
390
+ error = "Win32 click failed: $($_.Exception.Message)"
391
+ clickPoint = @{ x = $clickX; y = $clickY }
392
+ } | ConvertTo-Json -Depth 5 -Compress))
393
+ }
394
+ }
395
+
396
+ "wait-enabled" {
397
+ # Poll until the element is enabled (or timeout after Value seconds)
398
+ $timeout = 10
399
+ if ($Value -ne "") { $timeout = [int]$Value }
400
+
401
+ $deadline = (Get-Date).AddSeconds($timeout)
402
+ $found = $false
403
+
404
+ while ((Get-Date) -lt $deadline) {
405
+ if ($element.Current.IsEnabled) {
406
+ $found = $true
407
+ break
408
+ }
409
+ Start-Sleep -Milliseconds 500
410
+ }
411
+
412
+ if ($found) {
413
+ [Console]::Out.Write((@{
414
+ success = $true
415
+ action = "wait-enabled"
416
+ enabled = $true
417
+ } | ConvertTo-Json -Compress))
418
+ } else {
419
+ [Console]::Out.Write((@{
420
+ success = $false
421
+ action = "wait-enabled"
422
+ enabled = $false
423
+ error = "Element still disabled after ${timeout}s"
424
+ } | ConvertTo-Json -Compress))
425
+ }
426
+ }
427
+ }
428
+ } catch {
429
+ [Console]::Out.Write((@{ success = $false; error = $_.Exception.Message } | ConvertTo-Json -Compress))
430
+ exit 1
431
+ }