@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,228 @@
1
+ "use strict";
2
+ /**
3
+ * PSRunner — Persistent PowerShell UIA bridge.
4
+ *
5
+ * Keeps one powershell.exe alive for the entire session.
6
+ * UI Automation assemblies are loaded once at startup (~800ms).
7
+ * Each subsequent command costs only the actual work — no 200-500ms spawn overhead.
8
+ *
9
+ * Protocol: newline-delimited JSON on stdin/stdout.
10
+ * Send: {"cmd":"invoke-element","processId":123,...}\n
11
+ * Recv: {"success":true,...}\n
12
+ *
13
+ * Commands are serialized (one at a time), queued if a call is in-flight.
14
+ */
15
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ var desc = Object.getOwnPropertyDescriptor(m, k);
18
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
19
+ desc = { enumerable: true, get: function() { return m[k]; } };
20
+ }
21
+ Object.defineProperty(o, k2, desc);
22
+ }) : (function(o, m, k, k2) {
23
+ if (k2 === undefined) k2 = k;
24
+ o[k2] = m[k];
25
+ }));
26
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
27
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
28
+ }) : function(o, v) {
29
+ o["default"] = v;
30
+ });
31
+ var __importStar = (this && this.__importStar) || (function () {
32
+ var ownKeys = function(o) {
33
+ ownKeys = Object.getOwnPropertyNames || function (o) {
34
+ var ar = [];
35
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
36
+ return ar;
37
+ };
38
+ return ownKeys(o);
39
+ };
40
+ return function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
44
+ __setModuleDefault(result, mod);
45
+ return result;
46
+ };
47
+ })();
48
+ Object.defineProperty(exports, "__esModule", { value: true });
49
+ exports.psRunner = exports.PSRunner = void 0;
50
+ const child_process_1 = require("child_process");
51
+ const readline = __importStar(require("readline"));
52
+ const path = __importStar(require("path"));
53
+ const paths_1 = require("../paths");
54
+ const BRIDGE_SCRIPT = path.join((0, paths_1.getPackageRoot)(), 'scripts', 'ps-bridge.ps1');
55
+ const READY_TIMEOUT = 12000; // initial PS startup + assembly load
56
+ const CALL_TIMEOUT = 20000; // per command (reduced from 45s — PSRunner is fast enough)
57
+ const MAX_QUEUE_SIZE = 100; // backpressure — reject if queue exceeds this
58
+ class PSRunner {
59
+ proc = null;
60
+ rl = null;
61
+ ready = false;
62
+ dead = false;
63
+ queue = [];
64
+ current = null;
65
+ startPromise = null;
66
+ async start() {
67
+ if (this.startPromise)
68
+ return this.startPromise;
69
+ this.startPromise = this._start().catch(err => {
70
+ this.startPromise = null;
71
+ throw err;
72
+ });
73
+ return this.startPromise;
74
+ }
75
+ _start() {
76
+ // Capture reject so the exit handler can settle the startup promise even
77
+ // when the PS bridge exits before it outputs {"ready":true}. Without
78
+ // this, clearTimeout(readyTimer) in the exit handler would leave
79
+ // startPromise as a zombie — never resolved, never rejected — causing
80
+ // every subsequent `await this.startPromise` to hang forever.
81
+ let startReject;
82
+ return new Promise((resolve, reject) => {
83
+ startReject = reject;
84
+ this.dead = false;
85
+ this.ready = false;
86
+ this.proc = (0, child_process_1.spawn)('powershell.exe', [
87
+ '-NoProfile',
88
+ '-NonInteractive',
89
+ '-ExecutionPolicy', 'Bypass',
90
+ '-File', BRIDGE_SCRIPT,
91
+ ], { stdio: ['pipe', 'pipe', 'pipe'] });
92
+ this.rl = readline.createInterface({ input: this.proc.stdout });
93
+ const readyTimer = setTimeout(() => {
94
+ reject(new Error('PSRunner: timed out waiting for bridge ready'));
95
+ }, READY_TIMEOUT);
96
+ this.rl.on('line', (line) => {
97
+ line = line.trim();
98
+ if (!line)
99
+ return;
100
+ let data;
101
+ try {
102
+ data = JSON.parse(line);
103
+ }
104
+ catch {
105
+ return;
106
+ }
107
+ if (!this.ready) {
108
+ if (data.ready) {
109
+ this.ready = true;
110
+ clearTimeout(readyTimer);
111
+ console.log('[PSBridge] Ready — UIA assemblies loaded');
112
+ resolve();
113
+ }
114
+ else if (data.error) {
115
+ clearTimeout(readyTimer);
116
+ reject(new Error(`PSRunner startup: ${data.error}`));
117
+ }
118
+ return;
119
+ }
120
+ // Deliver to in-flight call
121
+ const call = this.current;
122
+ this.current = null;
123
+ if (call) {
124
+ clearTimeout(call.timer);
125
+ if (data.error)
126
+ call.reject(new Error(data.error));
127
+ else
128
+ call.resolve(data);
129
+ }
130
+ this._drain();
131
+ });
132
+ this.proc.stderr.on('data', (chunk) => {
133
+ const msg = chunk.toString().trim();
134
+ if (msg)
135
+ console.error(`[PSBridge] ${msg}`);
136
+ });
137
+ this.proc.on('exit', (code) => {
138
+ const pending = this.current ? [this.current, ...this.queue] : [...this.queue];
139
+ this.dead = true;
140
+ this.ready = false;
141
+ this.startPromise = null;
142
+ clearTimeout(readyTimer);
143
+ if (pending.length > 0) {
144
+ console.error(`[PSBridge] Process exited (code ${code}) with ${pending.length} pending command(s) — will restart on next call`);
145
+ }
146
+ this.current = null;
147
+ this.queue = [];
148
+ const err = new Error(`PSRunner exited (code ${code})`);
149
+ // Reject the startup promise if the bridge never signalled ready.
150
+ // Previously this was omitted: clearTimeout(readyTimer) disabled the
151
+ // 12-second safety net but no rejection was issued, leaving
152
+ // startPromise as an unsettled zombie. Any awaiter (e.g.
153
+ // getActiveWindow inside key_press) would then hang forever.
154
+ startReject(err);
155
+ for (const c of pending) {
156
+ clearTimeout(c.timer);
157
+ c.reject(err);
158
+ }
159
+ });
160
+ });
161
+ }
162
+ async run(command) {
163
+ // Auto-start or auto-restart
164
+ if (!this.startPromise || this.dead) {
165
+ if (this.dead)
166
+ console.log('[PSBridge] Restarting crashed bridge process...');
167
+ this.dead = false;
168
+ await this.start();
169
+ }
170
+ else {
171
+ await this.startPromise;
172
+ }
173
+ return new Promise((resolve, reject) => {
174
+ if (this.queue.length >= MAX_QUEUE_SIZE) {
175
+ reject(new Error(`PSRunner queue full (${MAX_QUEUE_SIZE}) — backpressure. Try again later.`));
176
+ return;
177
+ }
178
+ const call = {
179
+ command,
180
+ resolve,
181
+ reject,
182
+ timer: setTimeout(() => {
183
+ if (this.current === call)
184
+ this.current = null;
185
+ console.error(`[PSBridge] Command timeout after ${CALL_TIMEOUT}ms: ${String(command.cmd)}`);
186
+ reject(new Error(`PSRunner timeout: ${String(command.cmd)}`));
187
+ this._drain();
188
+ }, CALL_TIMEOUT),
189
+ };
190
+ this.queue.push(call);
191
+ this._drain();
192
+ });
193
+ }
194
+ _drain() {
195
+ if (this.current || this.queue.length === 0 || !this.proc || this.dead)
196
+ return;
197
+ this.current = this.queue.shift();
198
+ try {
199
+ const line = JSON.stringify(this.current.command) + '\n';
200
+ this.proc.stdin.write(line);
201
+ }
202
+ catch (err) {
203
+ const call = this.current;
204
+ this.current = null;
205
+ clearTimeout(call.timer);
206
+ call.reject(err);
207
+ this._drain();
208
+ }
209
+ }
210
+ stop() {
211
+ if (this.proc) {
212
+ try {
213
+ this.proc.stdin.write('EXIT\n');
214
+ }
215
+ catch { }
216
+ setTimeout(() => { try {
217
+ this.proc?.kill();
218
+ }
219
+ catch { } }, 500);
220
+ }
221
+ this.ready = false;
222
+ this.dead = true;
223
+ }
224
+ }
225
+ exports.PSRunner = PSRunner;
226
+ // Singleton — shared across all AccessibilityBridge instances
227
+ exports.psRunner = new PSRunner();
228
+ //# sourceMappingURL=ps-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ps-runner.js","sourceRoot":"","sources":["../../src/platform/ps-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,397 @@
1
+ /**
2
+ * PlatformAdapter — single contract for all platform-specific operations.
3
+ *
4
+ * Replaces scattered `if (IS_MAC) ... else ...` branching across 34 files.
5
+ * Each platform implements this interface; business logic stays platform-free.
6
+ *
7
+ * Tranche 1A (v0.8.1-alpha): adds the primitives needed to unblock the
8
+ * Tranche 1B / 2 MCP tools (mouseDown/mouseUp, keyDown/keyUp, middle click,
9
+ * horizontal scroll, window-state / bounds control, display enumeration,
10
+ * waitForElement, widened invokeElement actions, UI-element state flags).
11
+ * Every change is ADDITIVE — existing signatures kept so no caller breaks.
12
+ */
13
+ export interface ScreenSize {
14
+ /** Physical pixels (what screenshots are captured at). */
15
+ physicalWidth: number;
16
+ physicalHeight: number;
17
+ /** Logical pixels (what mouse coordinates use). */
18
+ logicalWidth: number;
19
+ logicalHeight: number;
20
+ /** Physical / logical (e.g. 2.0 on Retina, 1.0 on standard). */
21
+ dpiRatio: number;
22
+ }
23
+ /**
24
+ * A physical display. `getScreenSize()` returns the primary display only —
25
+ * `listDisplays()` returns every connected display so callers can target a
26
+ * specific one for screenshots or mouse coordinates.
27
+ */
28
+ export interface Display {
29
+ /** Index (0 = primary). Stable per boot. */
30
+ index: number;
31
+ /** Human label (e.g. "Display 1", "Built-in Retina Display"). */
32
+ label: string;
33
+ /** Whether this is the primary / main display. */
34
+ primary: boolean;
35
+ /** Logical bounds — mouse-coordinate space. Can be negative for left-of-primary. */
36
+ bounds: {
37
+ x: number;
38
+ y: number;
39
+ width: number;
40
+ height: number;
41
+ };
42
+ /** Physical (pixel) dimensions. */
43
+ physicalSize: {
44
+ width: number;
45
+ height: number;
46
+ };
47
+ /** Physical / logical scale. */
48
+ dpiRatio: number;
49
+ }
50
+ export interface ScreenshotResult {
51
+ /** PNG image buffer. */
52
+ buffer: Buffer;
53
+ /** Image dimensions (may differ from screen size if resized). */
54
+ width: number;
55
+ height: number;
56
+ /** Multiplier to convert image coords back to physical screen coords. */
57
+ scaleFactor: number;
58
+ }
59
+ export interface WindowInfo {
60
+ title: string;
61
+ processName: string;
62
+ processId: number;
63
+ bounds: {
64
+ x: number;
65
+ y: number;
66
+ width: number;
67
+ height: number;
68
+ };
69
+ isMinimized: boolean;
70
+ /** Platform-opaque handle for re-targeting. */
71
+ handle?: number | string;
72
+ }
73
+ export interface UiElement {
74
+ name: string;
75
+ controlType: string;
76
+ /** Platform subrole when present (macOS AX exposes e.g. "AXSecureTextField",
77
+ * "AXSearchField"); used to detect secureness and refine the role. */
78
+ subrole?: string;
79
+ /** Whether this is a password/secure field — its `value` is withheld. */
80
+ secure?: boolean;
81
+ bounds: {
82
+ x: number;
83
+ y: number;
84
+ width: number;
85
+ height: number;
86
+ };
87
+ /** Optional structured value (e.g. text field contents). */
88
+ value?: string;
89
+ /** Whether the element is enabled and interactable. */
90
+ enabled?: boolean;
91
+ /** Whether the element currently has keyboard focus. */
92
+ focused?: boolean;
93
+ /** Whether the element is currently selected (list items, tabs, radios). */
94
+ selected?: boolean;
95
+ /** Element is in a disabled (grayed-out) state. Opposite of `enabled`. */
96
+ disabled?: boolean;
97
+ /** Element is marked busy (e.g. progress in-flight). */
98
+ busy?: boolean;
99
+ /** Element is off-screen / scrolled out of view. */
100
+ offscreen?: boolean;
101
+ /** Element supports expand/collapse (has an ExpandCollapse a11y pattern). */
102
+ expandable?: boolean;
103
+ /** Current expand state when `expandable` is true. */
104
+ expanded?: boolean;
105
+ /** Platform-opaque automation identifier (UIA AutomationId, AX identifier, AT-SPI name). */
106
+ automationId?: string;
107
+ /** Owning-process id when known. */
108
+ processId?: number;
109
+ /**
110
+ * Human-readable description of the element when its primary `name` is
111
+ * empty. UIA exposes this via `LocalizedControlType` / `HelpText`; AX
112
+ * exposes it via `AXDescription` / `AXRoleDescription`; AT-SPI exposes
113
+ * it via the `description` attribute. Many third-party macOS apps (Xcode
114
+ * in particular) put their visible text in `AXDescription` rather than
115
+ * `AXTitle`, so `name` arrives empty and the element looks anonymous to
116
+ * the agent. Consumers should fall back through `name → description →
117
+ * value → controlType` when rendering. Adapters populate when available;
118
+ * undefined is acceptable (back-compat).
119
+ *
120
+ * Added 0.9.4 for issue #101 bug 5.
121
+ */
122
+ description?: string;
123
+ }
124
+ export interface PermissionStatus {
125
+ /** Can we send keyboard/mouse events to other apps? */
126
+ input: boolean;
127
+ /** Can we read window contents / accessibility tree? */
128
+ accessibility: boolean;
129
+ /** Can we capture the screen? */
130
+ screenRecording: boolean;
131
+ }
132
+ /** Pointer button — extended in Tranche 1A to include middle click. */
133
+ export type MouseButton = 'left' | 'right' | 'middle';
134
+ /**
135
+ * Result of the pre-click foreground promotion (Win32 WindowFromPoint +
136
+ * SetForegroundWindow). `activated:false` means the OS refused to bring the
137
+ * window at the click point to the foreground (foreground-lock) — the click
138
+ * likely landed on a DIFFERENT window than intended, so the caller must warn
139
+ * and not blindly send keystrokes next. `title`/`processName` identify the
140
+ * window that was actually promoted/clicked.
141
+ */
142
+ export interface FocusActivation {
143
+ activated: boolean;
144
+ title?: string;
145
+ processName?: string;
146
+ reason?: string;
147
+ }
148
+ /**
149
+ * Scroll direction — extended in Tranche 1A to include horizontal. Windows
150
+ * and macOS native wheel APIs support both axes; Linux X11 uses xdotool
151
+ * buttons 6/7 or nut-js's `scrollLeft/scrollRight`; Wayland is iffy on
152
+ * horizontal and degrades gracefully.
153
+ */
154
+ export type ScrollDirection = 'up' | 'down' | 'left' | 'right';
155
+ /**
156
+ * Canonical window state verbs. `setWindowState('close')` is a polite
157
+ * close request (WM_CLOSE / AXCloseAction / wmctrl -c) — the app MAY
158
+ * prompt the user (e.g. "Save changes?") and refuse. Callers must not
159
+ * assume the window was actually closed.
160
+ */
161
+ export type WindowState = 'maximize' | 'minimize' | 'normal' | 'close';
162
+ /**
163
+ * Invoke-element action union. Expanded in Tranche 1A to cover the UIA
164
+ * ExpandCollapse / Toggle / Selection patterns that `ps-bridge.ps1`
165
+ * already implements on Windows and that `invoke-element.jxa` now
166
+ * implements on macOS. Linux returns `{success:false}` until the
167
+ * AT-SPI bridge lands.
168
+ */
169
+ export type InvokeAction = 'click' | 'focus' | 'set-value' | 'get-value' | 'expand' | 'collapse' | 'toggle' | 'select';
170
+ export interface WaitForElementQuery {
171
+ name?: string;
172
+ controlType?: string;
173
+ processId?: number;
174
+ /** Poll interval in ms (default 250). */
175
+ intervalMs?: number;
176
+ }
177
+ /**
178
+ * Platform-agnostic interface every supported OS implements.
179
+ *
180
+ * Business logic uses this interface and never touches `process.platform`.
181
+ */
182
+ export interface PlatformAdapter {
183
+ /** OS family this adapter handles. */
184
+ readonly platform: 'darwin' | 'win32' | 'linux';
185
+ /**
186
+ * Optional environment hint — Linux sets this to 'wayland' or 'x11' so
187
+ * callers can surface graceful "not supported on Wayland" errors for
188
+ * known-broken primitives (cursor queries, some global hotkeys).
189
+ * Undefined on Windows and macOS.
190
+ */
191
+ readonly environment?: 'wayland' | 'x11';
192
+ /** One-time setup (warm caches, start helpers). */
193
+ init(): Promise<void>;
194
+ /** Cleanup on shutdown. */
195
+ shutdown(): Promise<void>;
196
+ checkPermissions(): Promise<PermissionStatus>;
197
+ requestPermissions(): Promise<PermissionStatus>;
198
+ /** Get the primary display geometry. */
199
+ getScreenSize(): Promise<ScreenSize>;
200
+ /**
201
+ * List ALL connected displays. Tranche 1A primitive — unblocks
202
+ * multi-monitor-aware screenshot and mouse targeting. Primary display
203
+ * is always at index 0.
204
+ */
205
+ listDisplays(): Promise<Display[]>;
206
+ /**
207
+ * Capture the full screen as PNG. Optionally resize to maxWidth.
208
+ * `displayIndex` (Tranche 1A) selects a specific display — 0 (default)
209
+ * is primary. Passing an out-of-range index falls back to primary.
210
+ */
211
+ screenshot(opts?: {
212
+ maxWidth?: number;
213
+ displayIndex?: number;
214
+ }): Promise<ScreenshotResult>;
215
+ /** Capture a region of the screen. */
216
+ screenshotRegion(x: number, y: number, w: number, h: number): Promise<ScreenshotResult>;
217
+ listWindows(): Promise<WindowInfo[]>;
218
+ getActiveWindow(): Promise<WindowInfo | null>;
219
+ focusWindow(query: {
220
+ processName?: string;
221
+ processId?: number;
222
+ title?: string;
223
+ }): Promise<boolean>;
224
+ /**
225
+ * Legacy shim — preserved for back-compat. New code should call
226
+ * `setWindowState('maximize')`. Default behavior unchanged.
227
+ */
228
+ maximizeWindow(): Promise<void>;
229
+ /**
230
+ * Canonical window-state control. Semantics (Tranche 1A):
231
+ * - 'maximize' — full-working-area size
232
+ * - 'minimize' — hide to taskbar/Dock
233
+ * - 'normal' — restore from minimized/maximized to previous bounds
234
+ * - 'close' — polite close request; app may prompt / refuse
235
+ *
236
+ * Target: the currently-focused window unless `query` is supplied.
237
+ * Returns true when the request was accepted, NOT when the state
238
+ * transition completed.
239
+ */
240
+ setWindowState(state: WindowState, query?: {
241
+ processName?: string;
242
+ processId?: number;
243
+ title?: string;
244
+ }): Promise<boolean>;
245
+ /**
246
+ * Set the foreground (or matched) window's logical-pixel bounds.
247
+ * Returns true when the request was accepted. No-op where the WM
248
+ * refuses programmatic move/resize (some tiling Linux WMs).
249
+ */
250
+ setWindowBounds(bounds: {
251
+ x?: number;
252
+ y?: number;
253
+ width?: number;
254
+ height?: number;
255
+ }, query?: {
256
+ processName?: string;
257
+ processId?: number;
258
+ title?: string;
259
+ }): Promise<boolean>;
260
+ getUiTree(processId?: number): Promise<UiElement[]>;
261
+ findElements(query: {
262
+ name?: string;
263
+ controlType?: string;
264
+ processId?: number;
265
+ }): Promise<UiElement[]>;
266
+ getFocusedElement(): Promise<UiElement | null>;
267
+ /**
268
+ * Invoke an accessibility action on a named element. Action union
269
+ * widened in Tranche 1A. Platforms that don't support a given action
270
+ * return `{ success:false }` — no throw.
271
+ */
272
+ invokeElement(query: {
273
+ name?: string;
274
+ controlType?: string;
275
+ processId?: number;
276
+ action?: InvokeAction;
277
+ value?: string;
278
+ }): Promise<{
279
+ success: boolean;
280
+ bounds?: {
281
+ x: number;
282
+ y: number;
283
+ width: number;
284
+ height: number;
285
+ };
286
+ /** Action-specific payload, e.g. `{ value }` for get-value, `{ toggleState }` for toggle. */
287
+ data?: Record<string, unknown>;
288
+ }>;
289
+ /**
290
+ * Poll for an element to appear. Returns the first matching element or
291
+ * null when `timeoutMs` elapses. Useful for waiting out transient UI
292
+ * (dialogs, spinners). Tranche 1A primitive — lifted from
293
+ * `action-router.ts`'s internal `waitForElement` helper.
294
+ */
295
+ waitForElement(query: WaitForElementQuery, timeoutMs: number): Promise<UiElement | null>;
296
+ /** All coords are in LOGICAL pixels (mouse coordinate space).
297
+ * Returns a FocusActivation describing the window brought to the foreground
298
+ * at the click point (when the platform verifies it) so callers can WARN on
299
+ * a failed/ wrong-window activation; void/undefined when not verifiable. */
300
+ mouseClick(x: number, y: number, opts?: {
301
+ button?: MouseButton;
302
+ count?: number;
303
+ }): Promise<FocusActivation | void>;
304
+ mouseMove(x: number, y: number): Promise<void>;
305
+ /**
306
+ * Move relative to the current cursor position. On Wayland where
307
+ * cursor-position queries are blocked, implementations SHOULD cache
308
+ * the last target from `mouseMove`/`mouseClick` and offset from there;
309
+ * if no cache is available, they return without error and log a
310
+ * graceful-degradation warning.
311
+ */
312
+ mouseMoveRelative(dx: number, dy: number): Promise<void>;
313
+ mouseDrag(x1: number, y1: number, x2: number, y2: number): Promise<void>;
314
+ mouseScroll(x: number, y: number, direction: ScrollDirection, amount?: number): Promise<void>;
315
+ /**
316
+ * Press a button without releasing. Pairs with `mouseUp`. Enables:
317
+ * - Hold modifier + click (Ctrl+click, Shift+click selection)
318
+ * - Multi-point drags (mouseDown at A, mouseMove through path, mouseUp at B)
319
+ * - Press-and-hold gestures
320
+ */
321
+ mouseDown(button?: MouseButton): Promise<void>;
322
+ /** Release a previously-pressed button. No-op if nothing pressed. */
323
+ mouseUp(button?: MouseButton): Promise<void>;
324
+ typeText(text: string): Promise<void>;
325
+ keyPress(combo: PortableKeyCombo): Promise<void>;
326
+ /**
327
+ * Press a key without releasing. Pairs with `keyUp`. Enables:
328
+ * - Hold shift while clicking
329
+ * - Gaming-style chord input
330
+ * - OS shortcuts that require precise down/up timing
331
+ *
332
+ * `key` accepts the same tokens as `keyPress` (e.g. "shift", "Return",
333
+ * "F5", "a"). macOS implementation uses `System Events` "key down"; Win
334
+ * and Linux use nut-js `keyboard.pressKey`.
335
+ */
336
+ keyDown(key: PortableKeyCombo): Promise<void>;
337
+ /** Release a previously-pressed key. No-op if not currently down. */
338
+ keyUp(key: PortableKeyCombo): Promise<void>;
339
+ readClipboard(): Promise<string>;
340
+ writeClipboard(text: string): Promise<void>;
341
+ /**
342
+ * Convenience wrapper around `launchApp`. Platform adapters keep this
343
+ * alias-data-agnostic — they DO NOT consult `APP_ALIASES`. Cross-OS
344
+ * name mapping (e.g. Windows "Notepad" → mac "TextEdit") and UWP /
345
+ * executable / searchTerm hints belong in the caller (the agent's
346
+ * `open_app` tool, the router's `handleOpenApp`), which resolves the
347
+ * alias and forwards the data through `launchApp` opts.
348
+ */
349
+ openApp(name: string, opts?: {
350
+ alwaysNewInstance?: boolean;
351
+ }): Promise<{
352
+ pid?: number;
353
+ title?: string;
354
+ }>;
355
+ launchApp(name: string, opts?: {
356
+ alwaysNewInstance?: boolean;
357
+ url?: string;
358
+ cwd?: string;
359
+ /** Windows UWP AppsFolder ID. Ignored on macOS and Linux. */
360
+ uwpAppId?: string;
361
+ /**
362
+ * Human-friendly term used when the platform falls back to its native
363
+ * search launcher (Windows Start Menu, macOS Spotlight). When omitted,
364
+ * the launcher uses `name` with the `.exe` / `.app` suffix stripped —
365
+ * which works for most apps but fails for cases like `msedge.exe`
366
+ * where the binary name isn't indexed (Windows Search would surface
367
+ * Microsoft Store as the closest match instead of Microsoft Edge).
368
+ * `APP_ALIASES` provides a curated `searchTerm` per app for this.
369
+ */
370
+ searchTerm?: string;
371
+ /**
372
+ * Skip the Start-Menu / search-launcher fallback (Windows). When the
373
+ * direct launch doesn't surface a window, return `{}` instead of typing
374
+ * the name into the OS search box. Used by `open_file` for a path, where
375
+ * the fallback would type "explorer" and open File Explorer at **Home**
376
+ * instead of the requested folder — a false "Opened" with a side effect.
377
+ */
378
+ noStartMenuFallback?: boolean;
379
+ }): Promise<{
380
+ pid?: number;
381
+ title?: string;
382
+ handle?: number | string;
383
+ }>;
384
+ }
385
+ /**
386
+ * Portable key combo spec — uses semantic modifiers, not platform names.
387
+ *
388
+ * "mod" resolves to Cmd on macOS, Ctrl on Windows/Linux.
389
+ * "alt" stays "alt" on Windows/Linux, becomes "option" on macOS at the OS level.
390
+ *
391
+ * Examples:
392
+ * "mod+s" — save (Cmd+S on mac, Ctrl+S elsewhere)
393
+ * "mod+shift+t" — reopen tab
394
+ * "Return" — single key
395
+ * "shift+Tab" — modifier + key
396
+ */
397
+ export type PortableKeyCombo = string;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ /**
3
+ * PlatformAdapter — single contract for all platform-specific operations.
4
+ *
5
+ * Replaces scattered `if (IS_MAC) ... else ...` branching across 34 files.
6
+ * Each platform implements this interface; business logic stays platform-free.
7
+ *
8
+ * Tranche 1A (v0.8.1-alpha): adds the primitives needed to unblock the
9
+ * Tranche 1B / 2 MCP tools (mouseDown/mouseUp, keyDown/keyUp, middle click,
10
+ * horizontal scroll, window-state / bounds control, display enumeration,
11
+ * waitForElement, widened invokeElement actions, UI-element state flags).
12
+ * Every change is ADDITIVE — existing signatures kept so no caller breaks.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/platform/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG"}