@ashx-j/lunr-dev 0.2.16-dev.9.1 → 0.2.19-dev.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/README.md +7 -1
  3. package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -0
  4. package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
  5. package/dist/builtin-extensions/ashxj-thinking.js +44 -19
  6. package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
  7. package/dist/builtin-extensions/index.d.ts.map +1 -1
  8. package/dist/builtin-extensions/index.js +1 -0
  9. package/dist/builtin-extensions/index.js.map +1 -1
  10. package/dist/builtin-extensions/lunr-computer-use.d.ts +3 -0
  11. package/dist/builtin-extensions/lunr-computer-use.d.ts.map +1 -0
  12. package/dist/builtin-extensions/lunr-computer-use.js +157 -0
  13. package/dist/builtin-extensions/lunr-computer-use.js.map +1 -0
  14. package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
  15. package/dist/builtin-extensions/pi-lsp-extension/src/index.js +10 -3
  16. package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
  17. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts +5 -1
  18. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js +26 -4
  20. package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js.map +1 -1
  21. package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-mcp-adapter/index.js +37 -27
  23. package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
  24. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts +6 -1
  25. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +33 -8
  27. package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
  28. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  29. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +52 -23
  30. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  31. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
  32. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +6 -2
  33. package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
  34. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts +1 -1
  35. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
  36. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +5 -2
  37. package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
  38. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.d.ts +10 -0
  39. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.d.ts.map +1 -0
  40. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.js +38 -0
  41. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.js.map +1 -0
  42. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
  43. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +3 -16
  44. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
  45. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts +1 -1
  46. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.d.ts.map +1 -1
  47. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js +2 -0
  48. package/dist/builtin-extensions/pi-subagents/src/runs/shared/child-tools.js.map +1 -1
  49. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +1 -0
  50. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  51. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +70 -30
  52. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  53. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  54. package/dist/builtin-extensions/pi-web-access/index.js +103 -102
  55. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  56. package/dist/core/agent-session-services.d.ts.map +1 -1
  57. package/dist/core/agent-session-services.js +1 -1
  58. package/dist/core/agent-session-services.js.map +1 -1
  59. package/dist/core/computer-use/adapter.d.ts +23 -0
  60. package/dist/core/computer-use/adapter.d.ts.map +1 -0
  61. package/dist/core/computer-use/adapter.js +116 -0
  62. package/dist/core/computer-use/adapter.js.map +1 -0
  63. package/dist/core/computer-use/lease.d.ts +18 -0
  64. package/dist/core/computer-use/lease.d.ts.map +1 -0
  65. package/dist/core/computer-use/lease.js +129 -0
  66. package/dist/core/computer-use/lease.js.map +1 -0
  67. package/dist/core/computer-use/macos-runtime.d.ts +14 -0
  68. package/dist/core/computer-use/macos-runtime.d.ts.map +1 -0
  69. package/dist/core/computer-use/macos-runtime.js +148 -0
  70. package/dist/core/computer-use/macos-runtime.js.map +1 -0
  71. package/dist/core/computer-use/policy.d.ts +19 -0
  72. package/dist/core/computer-use/policy.d.ts.map +1 -0
  73. package/dist/core/computer-use/policy.js +66 -0
  74. package/dist/core/computer-use/policy.js.map +1 -0
  75. package/dist/core/computer-use/release.generated.d.ts +31 -0
  76. package/dist/core/computer-use/release.generated.d.ts.map +1 -0
  77. package/dist/core/computer-use/release.generated.js +36 -0
  78. package/dist/core/computer-use/release.generated.js.map +1 -0
  79. package/dist/core/computer-use/runtime.d.ts +13 -0
  80. package/dist/core/computer-use/runtime.d.ts.map +1 -0
  81. package/dist/core/computer-use/runtime.js +158 -0
  82. package/dist/core/computer-use/runtime.js.map +1 -0
  83. package/dist/core/computer-use/schemas.d.ts +88 -0
  84. package/dist/core/computer-use/schemas.d.ts.map +1 -0
  85. package/dist/core/computer-use/schemas.js +80 -0
  86. package/dist/core/computer-use/schemas.js.map +1 -0
  87. package/dist/core/computer-use/windows-desktop.d.ts +3 -0
  88. package/dist/core/computer-use/windows-desktop.d.ts.map +1 -0
  89. package/dist/core/computer-use/windows-desktop.js +48 -0
  90. package/dist/core/computer-use/windows-desktop.js.map +1 -0
  91. package/dist/core/computer-use/workflow.d.ts +24 -0
  92. package/dist/core/computer-use/workflow.d.ts.map +1 -0
  93. package/dist/core/computer-use/workflow.js +330 -0
  94. package/dist/core/computer-use/workflow.js.map +1 -0
  95. package/dist/core/keybindings.d.ts +2 -2
  96. package/dist/core/keybindings.d.ts.map +1 -1
  97. package/dist/core/keybindings.js +2 -2
  98. package/dist/core/keybindings.js.map +1 -1
  99. package/dist/core/model-runtime.d.ts +0 -3
  100. package/dist/core/model-runtime.d.ts.map +1 -1
  101. package/dist/core/model-runtime.js +1 -10
  102. package/dist/core/model-runtime.js.map +1 -1
  103. package/dist/core/package-manager.d.ts.map +1 -1
  104. package/dist/core/package-manager.js +1 -1
  105. package/dist/core/package-manager.js.map +1 -1
  106. package/dist/core/permissions.d.ts +1 -1
  107. package/dist/core/permissions.d.ts.map +1 -1
  108. package/dist/core/permissions.js +23 -7
  109. package/dist/core/permissions.js.map +1 -1
  110. package/dist/core/plan-mode.d.ts.map +1 -1
  111. package/dist/core/plan-mode.js +9 -0
  112. package/dist/core/plan-mode.js.map +1 -1
  113. package/dist/core/rollback.d.ts.map +1 -1
  114. package/dist/core/rollback.js +13 -90
  115. package/dist/core/rollback.js.map +1 -1
  116. package/dist/core/session-manager.d.ts +0 -1
  117. package/dist/core/session-manager.d.ts.map +1 -1
  118. package/dist/core/session-manager.js +21 -79
  119. package/dist/core/session-manager.js.map +1 -1
  120. package/dist/core/settings-manager.d.ts +6 -0
  121. package/dist/core/settings-manager.d.ts.map +1 -1
  122. package/dist/core/settings-manager.js +19 -0
  123. package/dist/core/settings-manager.js.map +1 -1
  124. package/dist/dev-cli.js +0 -0
  125. package/dist/gateway/agent-bridge.d.ts +6 -1
  126. package/dist/gateway/agent-bridge.d.ts.map +1 -1
  127. package/dist/gateway/agent-bridge.js +23 -6
  128. package/dist/gateway/agent-bridge.js.map +1 -1
  129. package/dist/gateway/cron.d.ts +1 -1
  130. package/dist/gateway/cron.d.ts.map +1 -1
  131. package/dist/gateway/cron.js +23 -7
  132. package/dist/gateway/cron.js.map +1 -1
  133. package/dist/modes/interactive/components/footer.d.ts +4 -2
  134. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  135. package/dist/modes/interactive/components/footer.js +23 -32
  136. package/dist/modes/interactive/components/footer.js.map +1 -1
  137. package/dist/modes/interactive/components/processes-selector.d.ts +2 -3
  138. package/dist/modes/interactive/components/processes-selector.d.ts.map +1 -1
  139. package/dist/modes/interactive/components/processes-selector.js +5 -10
  140. package/dist/modes/interactive/components/processes-selector.js.map +1 -1
  141. package/dist/modes/interactive/components/settings-selector.d.ts +4 -0
  142. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  143. package/dist/modes/interactive/components/settings-selector.js +20 -0
  144. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  145. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  146. package/dist/modes/interactive/interactive-mode.js +18 -8
  147. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  148. package/dist/modes/interactive/thinking-level-slash.d.ts +4 -0
  149. package/dist/modes/interactive/thinking-level-slash.d.ts.map +1 -0
  150. package/dist/modes/interactive/thinking-level-slash.js +23 -0
  151. package/dist/modes/interactive/thinking-level-slash.js.map +1 -0
  152. package/dist/node-runtime/adapter-AZMY335J.js +279 -0
  153. package/dist/node-runtime/{agent-session-services-IFJMSX7Z.js → agent-session-services-RSGP5GDN.js} +15 -12
  154. package/dist/node-runtime/{builtin-extensions-LYZ3BFWQ.js → builtin-extensions-7STLFW3A.js} +4 -3
  155. package/dist/node-runtime/chunk-2IDTZAG5.js +1415 -0
  156. package/dist/node-runtime/{chunk-7NBZ5P7I.js → chunk-4SJWFTUP.js} +1 -1
  157. package/dist/node-runtime/{chunk-AJX357CL.js → chunk-5NWQCSKR.js} +20 -1013
  158. package/dist/node-runtime/chunk-5OLJGVCB.js +68 -0
  159. package/dist/node-runtime/chunk-5Q45AVQG.js +108 -0
  160. package/dist/node-runtime/{chunk-TQNSPERU.js → chunk-5SQDLSZJ.js} +1 -1
  161. package/dist/node-runtime/{chunk-F4VQFJI2.js → chunk-6SPPH4FY.js} +4 -4
  162. package/dist/node-runtime/{chunk-PBC2Y6GS.js → chunk-6UB6NKA3.js} +29 -72
  163. package/dist/node-runtime/{chunk-A2KQXUJD.js → chunk-7AFOFSDY.js} +1 -1
  164. package/dist/node-runtime/chunk-BKAZ6BKX.js +2185 -0
  165. package/dist/node-runtime/{chunk-AHSTJBIB.js → chunk-EH2LJQPM.js} +4 -4
  166. package/dist/node-runtime/{chunk-N77MY65L.js → chunk-FLYMHKCS.js} +25 -25
  167. package/dist/node-runtime/{chunk-5P7PZMRU.js → chunk-HRS4HMDX.js} +1 -1
  168. package/dist/node-runtime/{chunk-IPA627GP.js → chunk-ISQDQIZN.js} +4 -4
  169. package/dist/node-runtime/{chunk-WJVFOIB5.js → chunk-J7QGQD45.js} +1 -1
  170. package/dist/node-runtime/{chunk-WOVTOV5P.js → chunk-JT6YCS5B.js} +29 -34
  171. package/dist/node-runtime/chunk-JZHEUQRL.js +180 -0
  172. package/dist/node-runtime/{chunk-ZKMFUD3Q.js → chunk-K72NVGUB.js} +3 -3
  173. package/dist/node-runtime/{chunk-ECD5L7YI.js → chunk-LCACDWHJ.js} +389 -15
  174. package/dist/node-runtime/{chunk-2QKLKMKC.js → chunk-LTXUQJI4.js} +1 -1
  175. package/dist/node-runtime/{chunk-MKKH27PH.js → chunk-LWJXTA6Z.js} +274 -2416
  176. package/dist/node-runtime/{chunk-EDBJNRSM.js → chunk-MGSB2C3M.js} +1 -1
  177. package/dist/node-runtime/{chunk-CDFZEWPU.js → chunk-MUMMMTW4.js} +6 -2
  178. package/dist/node-runtime/{chunk-YF63P5ZT.js → chunk-OTT6JMPU.js} +10 -67
  179. package/dist/node-runtime/{chunk-PGAJ5MO5.js → chunk-T5GM5BFH.js} +1 -1
  180. package/dist/node-runtime/{chunk-PCGNAY2O.js → chunk-TAP7QTUT.js} +38 -16
  181. package/dist/node-runtime/{chunk-4TLO4PO2.js → chunk-U6C7VTR5.js} +7 -1401
  182. package/dist/node-runtime/chunk-URD2SLIT.js +1019 -0
  183. package/dist/node-runtime/{chunk-QH42CDX3.js → chunk-W7S2REEG.js} +111 -84
  184. package/dist/node-runtime/{chunk-LZAW4ZX3.js → chunk-ZRDIMBEQ.js} +27 -9
  185. package/dist/node-runtime/{chunk-AD6VXAO7.js → chunk-ZSEZY3II.js} +5 -100
  186. package/dist/node-runtime/cli-runtime.js +1 -1
  187. package/dist/node-runtime/{command-L3LAHDIH.js → command-6UXQ6XZN.js} +1 -1
  188. package/dist/node-runtime/{commands-RL5YBW5I.js → commands-LGR5VT5X.js} +6 -4
  189. package/dist/node-runtime/{direct-tool-executor-JVDXTO7A.js → direct-tool-executor-TDJS7TBD.js} +9 -6
  190. package/dist/node-runtime/{export-html-KR26FOUZ.js → export-html-E4DT6ZJQ.js} +1 -1
  191. package/dist/node-runtime/{extract-XLQSJN4V.js → extract-IUCVZCWC.js} +2 -2
  192. package/dist/node-runtime/{gateway-X2TI5X7F.js → gateway-3OLC4GQN.js} +22 -367
  193. package/dist/node-runtime/{gemini-search-U7SUMPQA.js → gemini-search-NCIDF7NE.js} +1 -1
  194. package/dist/node-runtime/{gemini-url-context-PXWCBQHK.js → gemini-url-context-OKIN7AIP.js} +2 -2
  195. package/dist/node-runtime/image-resize-6ZPBFMWW.js +11 -0
  196. package/dist/node-runtime/index.js +53 -49
  197. package/dist/node-runtime/{init-NJV2T55N.js → init-EKE277AG.js} +6 -4
  198. package/dist/node-runtime/{interactive-mode-KOM35YF2.js → interactive-mode-S5M26CQ7.js} +20 -17
  199. package/dist/node-runtime/{interactive-view-U6OILKF3.js → interactive-view-N6F4KUIT.js} +3 -5
  200. package/dist/node-runtime/lunr-computer-use-4X3KUNF4.js +206 -0
  201. package/dist/node-runtime/{lunr-cron-YJ5UHYRD.js → lunr-cron-KKBOGAEF.js} +7 -1
  202. package/dist/node-runtime/main.js +24 -21
  203. package/dist/node-runtime/{mcp-auth-flow-QIXHW6QN.js → mcp-auth-flow-YL6RWPYG.js} +2 -1
  204. package/dist/node-runtime/{package-manager-cli-TZZHJCVI.js → package-manager-cli-C4EJOO5Q.js} +8 -6
  205. package/dist/node-runtime/{pi-mcp-adapter-QFB37AVN.js → pi-mcp-adapter-DPTJGAAL.js} +33 -27
  206. package/dist/node-runtime/{pi-subagents-7XJ4H53P.js → pi-subagents-VKCLYIBY.js} +103 -76
  207. package/dist/node-runtime/{pi-web-access-DPGAVKOA.js → pi-web-access-BV6DSZOP.js} +72 -69
  208. package/dist/node-runtime/{proxy-modes-HEEFK4KC.js → proxy-modes-R64LU6WZ.js} +12 -9
  209. package/dist/node-runtime/rpc-entry.js +24 -21
  210. package/dist/node-runtime/runtime-3SB5ATHQ.js +21 -0
  211. package/dist/node-runtime/{runtime-bridges-PPHNBFWL.js → runtime-bridges-UJ5WJJLN.js} +3 -3
  212. package/dist/node-runtime/{session-manager-MQNBYACL.js → session-manager-QEMZBMTM.js} +3 -5
  213. package/dist/node-runtime/{session-selector-5AZLJS6U.js → session-selector-URVJLOTK.js} +2 -2
  214. package/dist/node-runtime/{settings-manager-5LF2VQWC.js → settings-manager-K6IPIQTI.js} +3 -1
  215. package/dist/node-runtime/{src-Y7JSCK64.js → src-GPFAU3N6.js} +30 -10
  216. package/dist/node-runtime/{subagent-executor-5RNDEPIJ.js → subagent-executor-EFLTO32A.js} +39 -21
  217. package/dist/node-runtime/{update-cli-A253SZ7P.js → update-cli-I6OVDRPL.js} +3 -1
  218. package/dist/node-runtime/{video-extract-OYT5WKS5.js → video-extract-ETA5RA7U.js} +2 -2
  219. package/dist/node-runtime/workflow-SA34S4VX.js +325 -0
  220. package/dist/node-runtime/{youtube-extract-TQYKGFGS.js → youtube-extract-SRVGNN26.js} +2 -2
  221. package/dist/rpc.d.ts +3 -0
  222. package/dist/rpc.d.ts.map +1 -0
  223. package/dist/rpc.js +18 -0
  224. package/dist/rpc.js.map +1 -0
  225. package/dist/startup/interactive-view.d.ts.map +1 -1
  226. package/dist/startup/interactive-view.js +1 -2
  227. package/dist/startup/interactive-view.js.map +1 -1
  228. package/docs/computer-use.md +277 -0
  229. package/docs/development.md +0 -32
  230. package/docs/features.md +2 -2
  231. package/docs/interactive-startup.md +10 -3
  232. package/docs/keybindings.md +2 -2
  233. package/docs/terminal-setup.md +1 -1
  234. package/docs/usage.md +1 -1
  235. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  236. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  237. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  238. package/examples/extensions/gondolin/package-lock.json +2 -2
  239. package/examples/extensions/gondolin/package.json +1 -1
  240. package/examples/extensions/hidden-thinking-label.ts +1 -1
  241. package/examples/extensions/sandbox/package-lock.json +2 -2
  242. package/examples/extensions/sandbox/package.json +1 -1
  243. package/examples/extensions/with-deps/package-lock.json +2 -2
  244. package/examples/extensions/with-deps/package.json +1 -1
  245. package/install-lock/package-lock.json +3827 -0
  246. package/install-lock/package.json +18 -0
  247. package/native/computer-use/LICENSE.md +21 -0
  248. package/npm-shrinkwrap.json +3808 -0
  249. package/package.json +16 -10
  250. package/dist/startup/interactive-shell.d.ts +0 -55
  251. package/dist/startup/interactive-shell.d.ts.map +0 -1
  252. package/dist/startup/interactive-shell.js +0 -264
  253. package/dist/startup/interactive-shell.js.map +0 -1
  254. package/dist/node-runtime/{chunk-YSKSB3BJ.js → chunk-CH6OL6P2.js} +2 -2
  255. package/dist/node-runtime/{chunk-VSELYKWU.js → chunk-EHMBW7FA.js} +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-services.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAEN,KAAK,4BAA4B,EACjC,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,yBAAyB,EAAE,KAAK,wBAAwB,EAAsB,MAAM,UAAU,CAAC;AAC7G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD;;;;;;GAMG;AACH,MAAM,WAAW,6BAA6B;IAC7C,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iCAAiC;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IACpD,qBAAqB,CAAC,EAAE,IAAI,CAAC,4BAA4B,EAAE,KAAK,GAAG,UAAU,GAAG,iBAAiB,CAAC,CAAC;IACnG,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;CAC1D;AAED;;;;;GAKG;AACH,MAAM,WAAW,qCAAqC;IACrD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,aAAa,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAC3E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,yBAAyB,CAAC,cAAc,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC/C,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,6BAA6B,EAAE,CAAC;CAC7C;AAoDD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,iCAAiC,GACxC,OAAO,CAAC,oBAAoB,CAAC,CA8C/B;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CACnD,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,wBAAwB,CAAC,CAiBnC","sourcesContent":["import { join } from \"node:path\";\nimport type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport type { Model } from \"@ashx-j/lunr-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport {\n\tDefaultResourceLoader,\n\ttype DefaultResourceLoaderOptions,\n\ttype ResourceLoader,\n\ttype ResourceLoaderReloadOptions,\n} from \"./resource-loader.ts\";\nimport { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession } from \"./sdk.ts\";\nimport type { SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tsettingsManager?: SettingsManager;\n\tmodelRuntime?: ModelRuntime;\n\textensionFlagValues?: Map<string, boolean | string>;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n\tresourceLoaderReloadOptions?: ResourceLoaderReloadOptions;\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tmodel?: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: string[];\n\texcludeTools?: CreateAgentSessionOptions[\"excludeTools\"];\n\tnoTools?: CreateAgentSessionOptions[\"noTools\"];\n\tcustomTools?: ToolDefinition[];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\tagentDir: string;\n\tmodelRuntime: ModelRuntime;\n\tsettingsManager: SettingsManager;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\nfunction applyExtensionFlagValues(\n\tresourceLoader: ResourceLoader,\n\textensionFlagValues: Map<string, boolean | string> | undefined,\n): AgentSessionRuntimeDiagnostic[] {\n\tif (!extensionFlagValues) {\n\t\treturn [];\n\t}\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tconst registeredFlags = new Map<string, { type: \"boolean\" | \"string\" }>();\n\tfor (const extension of extensionsResult.extensions) {\n\t\tfor (const [name, flag] of extension.flags) {\n\t\t\tregisteredFlags.set(name, { type: flag.type });\n\t\t}\n\t}\n\n\tconst unknownFlags: string[] = [];\n\tconst deferredFlags = new Set([\"mcp-config\"]);\n\tfor (const [name, value] of extensionFlagValues) {\n\t\tconst flag = registeredFlags.get(name);\n\t\tif (!flag) {\n\t\t\tif (deferredFlags.has(name)) continue;\n\t\t\tunknownFlags.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (flag.type === \"boolean\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, true);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t\tcontinue;\n\t\t}\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Extension flag \"--${name}\" requires a value`,\n\t\t});\n\t}\n\n\tif (unknownFlags.length > 0) {\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Unknown option${unknownFlags.length === 1 ? \"\" : \"s\"}: ${unknownFlags.map((name) => `--${name}`).join(\", \")}`,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = resolvePath(options.cwd);\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();\n\tconst modelRuntime =\n\t\toptions.modelRuntime ??\n\t\t(await ModelRuntime.createForAgentSession({\n\t\t\tauthPath: join(agentDir, \"auth.json\"),\n\t\t\tmodelsPath: join(agentDir, \"models.json\"),\n\t\t}));\n\ttime(\"ModelRuntime.create\");\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload(options.resourceLoaderReloadOptions);\n\ttime(\"resourceLoader.reload\");\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tfor (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {\n\t\ttry {\n\t\t\tmodelRuntime.registerProvider(name, config);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `Extension \"${extensionPath}\" error: ${message}`,\n\t\t\t});\n\t\t}\n\t}\n\textensionsResult.runtime.pendingProviderRegistrations = [];\n\tawait modelRuntime.refresh({ allowNetwork: false });\n\ttime(\"modelRuntime.refresh(cache-only)\");\n\tdiagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tmodelRuntime,\n\t\tsettingsManager,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tmodelRuntime: options.services.modelRuntime,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tresourceLoader: options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\texcludeTools: options.excludeTools,\n\t\tnoTools: options.noTools,\n\t\tcustomTools: options.customTools,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n}\n"]}
1
+ {"version":3,"file":"agent-session-services.d.ts","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAGnD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAEN,KAAK,4BAA4B,EACjC,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,KAAK,yBAAyB,EAAE,KAAK,wBAAwB,EAAsB,MAAM,UAAU,CAAC;AAC7G,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD;;;;;;GAMG;AACH,MAAM,WAAW,6BAA6B;IAC7C,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iCAAiC;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC;IACpD,qBAAqB,CAAC,EAAE,IAAI,CAAC,4BAA4B,EAAE,KAAK,GAAG,UAAU,GAAG,iBAAiB,CAAC,CAAC;IACnG,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;CAC1D;AAED;;;;;GAKG;AACH,MAAM,WAAW,qCAAqC;IACrD,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,cAAc,EAAE,cAAc,CAAC;IAC/B,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAAC,aAAa,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAC3E,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,YAAY,CAAC,EAAE,yBAAyB,CAAC,cAAc,CAAC,CAAC;IACzD,OAAO,CAAC,EAAE,yBAAyB,CAAC,SAAS,CAAC,CAAC;IAC/C,WAAW,CAAC,EAAE,cAAc,EAAE,CAAC;CAC/B;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,CAAC;IAC3B,eAAe,EAAE,eAAe,CAAC;IACjC,cAAc,EAAE,cAAc,CAAC;IAC/B,WAAW,EAAE,6BAA6B,EAAE,CAAC;CAC7C;AAoDD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAC/C,OAAO,EAAE,iCAAiC,GACxC,OAAO,CAAC,oBAAoB,CAAC,CA8C/B;AAED;;;;;;GAMG;AACH,wBAAsB,8BAA8B,CACnD,OAAO,EAAE,qCAAqC,GAC5C,OAAO,CAAC,wBAAwB,CAAC,CAiBnC","sourcesContent":["import { join } from \"node:path\";\nimport type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport type { Model } from \"@ashx-j/lunr-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport {\n\tDefaultResourceLoader,\n\ttype DefaultResourceLoaderOptions,\n\ttype ResourceLoader,\n\ttype ResourceLoaderReloadOptions,\n} from \"./resource-loader.ts\";\nimport { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession } from \"./sdk.ts\";\nimport type { SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tsettingsManager?: SettingsManager;\n\tmodelRuntime?: ModelRuntime;\n\textensionFlagValues?: Map<string, boolean | string>;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n\tresourceLoaderReloadOptions?: ResourceLoaderReloadOptions;\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tmodel?: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: string[];\n\texcludeTools?: CreateAgentSessionOptions[\"excludeTools\"];\n\tnoTools?: CreateAgentSessionOptions[\"noTools\"];\n\tcustomTools?: ToolDefinition[];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\tagentDir: string;\n\tmodelRuntime: ModelRuntime;\n\tsettingsManager: SettingsManager;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\nfunction applyExtensionFlagValues(\n\tresourceLoader: ResourceLoader,\n\textensionFlagValues: Map<string, boolean | string> | undefined,\n): AgentSessionRuntimeDiagnostic[] {\n\tif (!extensionFlagValues) {\n\t\treturn [];\n\t}\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tconst registeredFlags = new Map<string, { type: \"boolean\" | \"string\" }>();\n\tfor (const extension of extensionsResult.extensions) {\n\t\tfor (const [name, flag] of extension.flags) {\n\t\t\tregisteredFlags.set(name, { type: flag.type });\n\t\t}\n\t}\n\n\tconst unknownFlags: string[] = [];\n\tconst deferredFlags = new Set([\"mcp-config\"]);\n\tfor (const [name, value] of extensionFlagValues) {\n\t\tconst flag = registeredFlags.get(name);\n\t\tif (!flag) {\n\t\t\tif (deferredFlags.has(name)) continue;\n\t\t\tunknownFlags.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (flag.type === \"boolean\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, true);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t\tcontinue;\n\t\t}\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Extension flag \"--${name}\" requires a value`,\n\t\t});\n\t}\n\n\tif (unknownFlags.length > 0) {\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Unknown option${unknownFlags.length === 1 ? \"\" : \"s\"}: ${unknownFlags.map((name) => `--${name}`).join(\", \")}`,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = resolvePath(options.cwd);\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();\n\tconst modelRuntime =\n\t\toptions.modelRuntime ??\n\t\t(await ModelRuntime.create({\n\t\t\tauthPath: join(agentDir, \"auth.json\"),\n\t\t\tmodelsPath: join(agentDir, \"models.json\"),\n\t\t}));\n\ttime(\"ModelRuntime.create\");\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload(options.resourceLoaderReloadOptions);\n\ttime(\"resourceLoader.reload\");\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tfor (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {\n\t\ttry {\n\t\t\tmodelRuntime.registerProvider(name, config);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `Extension \"${extensionPath}\" error: ${message}`,\n\t\t\t});\n\t\t}\n\t}\n\textensionsResult.runtime.pendingProviderRegistrations = [];\n\tawait modelRuntime.refresh({ allowNetwork: false });\n\ttime(\"modelRuntime.refresh(cache-only)\");\n\tdiagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tmodelRuntime,\n\t\tsettingsManager,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tmodelRuntime: options.services.modelRuntime,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tresourceLoader: options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\texcludeTools: options.excludeTools,\n\t\tnoTools: options.noTools,\n\t\tcustomTools: options.customTools,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n}\n"]}
@@ -58,7 +58,7 @@ export async function createAgentSessionServices(options) {
58
58
  const cwd = resolvePath(options.cwd);
59
59
  const agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();
60
60
  const modelRuntime = options.modelRuntime ??
61
- (await ModelRuntime.createForAgentSession({
61
+ (await ModelRuntime.create({
62
62
  authPath: join(agentDir, "auth.json"),
63
63
  modelsPath: join(agentDir, "models.json"),
64
64
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"agent-session-services.js","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport type { Model } from \"@ashx-j/lunr-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport {\n\tDefaultResourceLoader,\n\ttype DefaultResourceLoaderOptions,\n\ttype ResourceLoader,\n\ttype ResourceLoaderReloadOptions,\n} from \"./resource-loader.ts\";\nimport { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession } from \"./sdk.ts\";\nimport type { SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tsettingsManager?: SettingsManager;\n\tmodelRuntime?: ModelRuntime;\n\textensionFlagValues?: Map<string, boolean | string>;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n\tresourceLoaderReloadOptions?: ResourceLoaderReloadOptions;\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tmodel?: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: string[];\n\texcludeTools?: CreateAgentSessionOptions[\"excludeTools\"];\n\tnoTools?: CreateAgentSessionOptions[\"noTools\"];\n\tcustomTools?: ToolDefinition[];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\tagentDir: string;\n\tmodelRuntime: ModelRuntime;\n\tsettingsManager: SettingsManager;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\nfunction applyExtensionFlagValues(\n\tresourceLoader: ResourceLoader,\n\textensionFlagValues: Map<string, boolean | string> | undefined,\n): AgentSessionRuntimeDiagnostic[] {\n\tif (!extensionFlagValues) {\n\t\treturn [];\n\t}\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tconst registeredFlags = new Map<string, { type: \"boolean\" | \"string\" }>();\n\tfor (const extension of extensionsResult.extensions) {\n\t\tfor (const [name, flag] of extension.flags) {\n\t\t\tregisteredFlags.set(name, { type: flag.type });\n\t\t}\n\t}\n\n\tconst unknownFlags: string[] = [];\n\tconst deferredFlags = new Set([\"mcp-config\"]);\n\tfor (const [name, value] of extensionFlagValues) {\n\t\tconst flag = registeredFlags.get(name);\n\t\tif (!flag) {\n\t\t\tif (deferredFlags.has(name)) continue;\n\t\t\tunknownFlags.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (flag.type === \"boolean\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, true);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t\tcontinue;\n\t\t}\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Extension flag \"--${name}\" requires a value`,\n\t\t});\n\t}\n\n\tif (unknownFlags.length > 0) {\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Unknown option${unknownFlags.length === 1 ? \"\" : \"s\"}: ${unknownFlags.map((name) => `--${name}`).join(\", \")}`,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = resolvePath(options.cwd);\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();\n\tconst modelRuntime =\n\t\toptions.modelRuntime ??\n\t\t(await ModelRuntime.createForAgentSession({\n\t\t\tauthPath: join(agentDir, \"auth.json\"),\n\t\t\tmodelsPath: join(agentDir, \"models.json\"),\n\t\t}));\n\ttime(\"ModelRuntime.create\");\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload(options.resourceLoaderReloadOptions);\n\ttime(\"resourceLoader.reload\");\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tfor (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {\n\t\ttry {\n\t\t\tmodelRuntime.registerProvider(name, config);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `Extension \"${extensionPath}\" error: ${message}`,\n\t\t\t});\n\t\t}\n\t}\n\textensionsResult.runtime.pendingProviderRegistrations = [];\n\tawait modelRuntime.refresh({ allowNetwork: false });\n\ttime(\"modelRuntime.refresh(cache-only)\");\n\tdiagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tmodelRuntime,\n\t\tsettingsManager,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tmodelRuntime: options.services.modelRuntime,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tresourceLoader: options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\texcludeTools: options.excludeTools,\n\t\tnoTools: options.noTools,\n\t\tcustomTools: options.customTools,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n}\n"]}
1
+ {"version":3,"file":"agent-session-services.js","sourceRoot":"","sources":["../../src/core/agent-session-services.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport type { Model } from \"@ashx-j/lunr-ai\";\nimport { getAgentDir } from \"../config.ts\";\nimport { resolvePath } from \"../utils/paths.ts\";\nimport type { SessionStartEvent, ToolDefinition } from \"./extensions/index.ts\";\nimport { ModelRuntime } from \"./model-runtime.ts\";\nimport {\n\tDefaultResourceLoader,\n\ttype DefaultResourceLoaderOptions,\n\ttype ResourceLoader,\n\ttype ResourceLoaderReloadOptions,\n} from \"./resource-loader.ts\";\nimport { type CreateAgentSessionOptions, type CreateAgentSessionResult, createAgentSession } from \"./sdk.ts\";\nimport type { SessionManager } from \"./session-manager.ts\";\nimport { SettingsManager } from \"./settings-manager.ts\";\nimport { time } from \"./timings.ts\";\n\n/**\n * Non-fatal issues collected while creating services or sessions.\n *\n * Runtime creation returns diagnostics to the caller instead of printing or\n * exiting. The app layer decides whether warnings should be shown and whether\n * errors should abort startup.\n */\nexport interface AgentSessionRuntimeDiagnostic {\n\ttype: \"info\" | \"warning\" | \"error\";\n\tmessage: string;\n}\n\n/**\n * Inputs for creating cwd-bound runtime services.\n *\n * These services are recreated whenever the effective session cwd changes.\n * CLI-provided resource paths should be resolved to absolute paths before they\n * reach this function, so later cwd switches do not reinterpret them.\n */\nexport interface CreateAgentSessionServicesOptions {\n\tcwd: string;\n\tagentDir?: string;\n\tsettingsManager?: SettingsManager;\n\tmodelRuntime?: ModelRuntime;\n\textensionFlagValues?: Map<string, boolean | string>;\n\tresourceLoaderOptions?: Omit<DefaultResourceLoaderOptions, \"cwd\" | \"agentDir\" | \"settingsManager\">;\n\tresourceLoaderReloadOptions?: ResourceLoaderReloadOptions;\n}\n\n/**\n * Inputs for creating an AgentSession from already-created services.\n *\n * Use this after services exist and any cwd-bound model/tool/session options\n * have been resolved against those services.\n */\nexport interface CreateAgentSessionFromServicesOptions {\n\tservices: AgentSessionServices;\n\tsessionManager: SessionManager;\n\tsessionStartEvent?: SessionStartEvent;\n\tmodel?: Model<any>;\n\tthinkingLevel?: ThinkingLevel;\n\tscopedModels?: Array<{ model: Model<any>; thinkingLevel?: ThinkingLevel }>;\n\ttools?: string[];\n\texcludeTools?: CreateAgentSessionOptions[\"excludeTools\"];\n\tnoTools?: CreateAgentSessionOptions[\"noTools\"];\n\tcustomTools?: ToolDefinition[];\n}\n\n/**\n * Coherent cwd-bound runtime services for one effective session cwd.\n *\n * This is infrastructure only. The AgentSession itself is created separately so\n * session options can be resolved against these services first.\n */\nexport interface AgentSessionServices {\n\tcwd: string;\n\tagentDir: string;\n\tmodelRuntime: ModelRuntime;\n\tsettingsManager: SettingsManager;\n\tresourceLoader: ResourceLoader;\n\tdiagnostics: AgentSessionRuntimeDiagnostic[];\n}\n\nfunction applyExtensionFlagValues(\n\tresourceLoader: ResourceLoader,\n\textensionFlagValues: Map<string, boolean | string> | undefined,\n): AgentSessionRuntimeDiagnostic[] {\n\tif (!extensionFlagValues) {\n\t\treturn [];\n\t}\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tconst registeredFlags = new Map<string, { type: \"boolean\" | \"string\" }>();\n\tfor (const extension of extensionsResult.extensions) {\n\t\tfor (const [name, flag] of extension.flags) {\n\t\t\tregisteredFlags.set(name, { type: flag.type });\n\t\t}\n\t}\n\n\tconst unknownFlags: string[] = [];\n\tconst deferredFlags = new Set([\"mcp-config\"]);\n\tfor (const [name, value] of extensionFlagValues) {\n\t\tconst flag = registeredFlags.get(name);\n\t\tif (!flag) {\n\t\t\tif (deferredFlags.has(name)) continue;\n\t\t\tunknownFlags.push(name);\n\t\t\tcontinue;\n\t\t}\n\t\tif (flag.type === \"boolean\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, true);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof value === \"string\") {\n\t\t\textensionsResult.runtime.flagValues.set(name, value);\n\t\t\tcontinue;\n\t\t}\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Extension flag \"--${name}\" requires a value`,\n\t\t});\n\t}\n\n\tif (unknownFlags.length > 0) {\n\t\tdiagnostics.push({\n\t\t\ttype: \"error\",\n\t\t\tmessage: `Unknown option${unknownFlags.length === 1 ? \"\" : \"s\"}: ${unknownFlags.map((name) => `--${name}`).join(\", \")}`,\n\t\t});\n\t}\n\n\treturn diagnostics;\n}\n\n/**\n * Create cwd-bound runtime services.\n *\n * Returns services plus diagnostics. It does not create an AgentSession.\n */\nexport async function createAgentSessionServices(\n\toptions: CreateAgentSessionServicesOptions,\n): Promise<AgentSessionServices> {\n\tconst cwd = resolvePath(options.cwd);\n\tconst agentDir = options.agentDir ? resolvePath(options.agentDir) : getAgentDir();\n\tconst modelRuntime =\n\t\toptions.modelRuntime ??\n\t\t(await ModelRuntime.create({\n\t\t\tauthPath: join(agentDir, \"auth.json\"),\n\t\t\tmodelsPath: join(agentDir, \"models.json\"),\n\t\t}));\n\ttime(\"ModelRuntime.create\");\n\tconst settingsManager = options.settingsManager ?? SettingsManager.create(cwd, agentDir);\n\tconst resourceLoader = new DefaultResourceLoader({\n\t\t...(options.resourceLoaderOptions ?? {}),\n\t\tcwd,\n\t\tagentDir,\n\t\tsettingsManager,\n\t});\n\tawait resourceLoader.reload(options.resourceLoaderReloadOptions);\n\ttime(\"resourceLoader.reload\");\n\n\tconst diagnostics: AgentSessionRuntimeDiagnostic[] = [];\n\tconst extensionsResult = resourceLoader.getExtensions();\n\tfor (const { name, config, extensionPath } of extensionsResult.runtime.pendingProviderRegistrations) {\n\t\ttry {\n\t\t\tmodelRuntime.registerProvider(name, config);\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"error\",\n\t\t\t\tmessage: `Extension \"${extensionPath}\" error: ${message}`,\n\t\t\t});\n\t\t}\n\t}\n\textensionsResult.runtime.pendingProviderRegistrations = [];\n\tawait modelRuntime.refresh({ allowNetwork: false });\n\ttime(\"modelRuntime.refresh(cache-only)\");\n\tdiagnostics.push(...applyExtensionFlagValues(resourceLoader, options.extensionFlagValues));\n\n\treturn {\n\t\tcwd,\n\t\tagentDir,\n\t\tmodelRuntime,\n\t\tsettingsManager,\n\t\tresourceLoader,\n\t\tdiagnostics,\n\t};\n}\n\n/**\n * Create an AgentSession from previously created services.\n *\n * This keeps session creation separate from service creation so callers can\n * resolve model, thinking, tools, and other session inputs against the target\n * cwd before constructing the session.\n */\nexport async function createAgentSessionFromServices(\n\toptions: CreateAgentSessionFromServicesOptions,\n): Promise<CreateAgentSessionResult> {\n\treturn createAgentSession({\n\t\tcwd: options.services.cwd,\n\t\tagentDir: options.services.agentDir,\n\t\tmodelRuntime: options.services.modelRuntime,\n\t\tsettingsManager: options.services.settingsManager,\n\t\tresourceLoader: options.services.resourceLoader,\n\t\tsessionManager: options.sessionManager,\n\t\tmodel: options.model,\n\t\tthinkingLevel: options.thinkingLevel,\n\t\tscopedModels: options.scopedModels,\n\t\ttools: options.tools,\n\t\texcludeTools: options.excludeTools,\n\t\tnoTools: options.noTools,\n\t\tcustomTools: options.customTools,\n\t\tsessionStartEvent: options.sessionStartEvent,\n\t});\n}\n"]}
@@ -0,0 +1,23 @@
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ export type DriverReply = Awaited<ReturnType<Client["callTool"]>>;
3
+ export interface ComputerDriver {
4
+ call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;
5
+ close(): Promise<void>;
6
+ setProcessObserver?(observer: (pid: number) => Promise<void>): void;
7
+ }
8
+ export declare class CuaAdapter implements ComputerDriver {
9
+ private client?;
10
+ private transport?;
11
+ private mac?;
12
+ private stateDirectory?;
13
+ private connecting?;
14
+ private closing?;
15
+ private readonly abort;
16
+ private processObserver?;
17
+ setProcessObserver(observer: (pid: number) => Promise<void>): void;
18
+ private connect;
19
+ call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;
20
+ close(): Promise<void>;
21
+ private stop;
22
+ }
23
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/core/computer-use/adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAMnE,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAClE,MAAM,WAAW,cAAc;IAC9B,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC9F,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,kBAAkB,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CACpE;AAED,qBAAa,UAAW,YAAW,cAAc;IAChD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,SAAS,CAAC,CAAuB;IACzC,OAAO,CAAC,GAAG,CAAC,CAAa;IACzB,OAAO,CAAC,cAAc,CAAC,CAAS;IAChC,OAAO,CAAC,UAAU,CAAC,CAAgB;IACnC,OAAO,CAAC,OAAO,CAAC,CAAgB;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAyB;IAC/C,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,kBAAkB,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEjE;YAEa,OAAO;IA4Cf,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,CAelG;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAIrB;YAEa,IAAI;CAwBlB","sourcesContent":["import { mkdir, mkdtemp, realpath, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { MacRuntime } from \"./macos-runtime.ts\";\nimport { CUA_VERSION, installRuntime, runtimeEnvironment } from \"./runtime.ts\";\nimport { assertInteractiveDesktop } from \"./windows-desktop.ts\";\n\nexport type DriverReply = Awaited<ReturnType<Client[\"callTool\"]>>;\nexport interface ComputerDriver {\n\tcall(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;\n\tclose(): Promise<void>;\n\tsetProcessObserver?(observer: (pid: number) => Promise<void>): void;\n}\n\nexport class CuaAdapter implements ComputerDriver {\n\tprivate client?: Client;\n\tprivate transport?: StdioClientTransport;\n\tprivate mac?: MacRuntime;\n\tprivate stateDirectory?: string;\n\tprivate connecting?: Promise<void>;\n\tprivate closing?: Promise<void>;\n\tprivate readonly abort = new AbortController();\n\tprivate processObserver?: (pid: number) => Promise<void>;\n\tsetProcessObserver(observer: (pid: number) => Promise<void>): void {\n\t\tthis.processObserver = observer;\n\t}\n\n\tprivate async connect(signal: AbortSignal): Promise<void> {\n\t\tconst { command, app } = await installRuntime(signal);\n\t\tsignal.throwIfAborted();\n\t\tlet args = [\"mcp\", \"--direct\", \"--embedded\", \"--no-overlay\"];\n\t\tif (app) {\n\t\t\tthis.mac = new MacRuntime();\n\t\t\tconst socket = await this.mac.start(app, signal);\n\t\t\targs = [\"mcp\", \"--embedded\", \"--socket\", socket, \"--no-overlay\"];\n\t\t}\n\t\tsignal.throwIfAborted();\n\t\tconst state = await mkdtemp(join(await realpath(tmpdir()), \"lunr-cua-client-\"));\n\t\tthis.stateDirectory = state;\n\t\tconst appData = join(state, \"AppData\");\n\t\tawait mkdir(appData);\n\t\tsignal.throwIfAborted();\n\t\tthis.transport = new StdioClientTransport({\n\t\t\tcommand,\n\t\t\targs,\n\t\t\tstderr: \"pipe\",\n\t\t\tenv: {\n\t\t\t\t...runtimeEnvironment(),\n\t\t\t\tHOME: state,\n\t\t\t\tUSERPROFILE: state,\n\t\t\t\tAPPDATA: appData,\n\t\t\t\tLOCALAPPDATA: appData,\n\t\t\t\tXDG_CONFIG_HOME: appData,\n\t\t\t\tXDG_STATE_HOME: appData,\n\t\t\t},\n\t\t});\n\t\t// Drain diagnostics without retaining desktop or runtime data in session history.\n\t\tthis.transport.stderr?.on(\"data\", () => {});\n\t\tthis.client = new Client({ name: \"lunr-computer-use\", version: CUA_VERSION });\n\t\tawait this.client.connect(this.transport, { timeout: 15000, signal });\n\t\tsignal.throwIfAborted();\n\t\tif (this.client.getServerVersion()?.version !== CUA_VERSION)\n\t\t\tthrow new Error(\"Computer runtime version mismatch.\");\n\t\tconst pids = [this.transport.pid, ...(this.mac ? [this.mac.processId] : [])];\n\t\tfor (const pid of pids) {\n\t\t\tif (typeof pid !== \"number\" || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Computer runtime process identity is missing. Input refused.\");\n\t\t\tawait this.processObserver?.(pid);\n\t\t}\n\t}\n\n\tasync call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply> {\n\t\tconst combined = AbortSignal.any([this.abort.signal, ...(signal ? [signal] : [])]);\n\t\tcombined.throwIfAborted();\n\t\ttry {\n\t\t\tawait assertInteractiveDesktop(combined);\n\t\t\tcombined.throwIfAborted();\n\t\t\tthis.connecting ??= this.connect(AbortSignal.any([combined, AbortSignal.timeout(60000)]));\n\t\t\tawait this.connecting;\n\t\t\tcombined.throwIfAborted();\n\t\t\tif (!this.client) throw new Error(\"Computer connection closed.\");\n\t\t\treturn await this.client.callTool({ name, arguments: args }, undefined, { timeout: 15000, signal: combined });\n\t\t} catch (error) {\n\t\t\tawait this.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.abort.abort();\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.connecting?.catch(() => undefined);\n\t\tconst pid = this.transport?.pid;\n\t\tawait this.client?.close();\n\t\tawait this.transport?.close();\n\t\tif (pid) {\n\t\t\tconst deadline = Date.now() + 5000;\n\t\t\tfor (;;) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ESRCH\") break;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (Date.now() >= deadline)\n\t\t\t\t\tthrow new Error(\"Owned computer process shutdown is unconfirmed. Desktop lease retained.\");\n\t\t\t\tawait delay(50);\n\t\t\t}\n\t\t}\n\t\tawait this.mac?.close();\n\t\tif (this.stateDirectory) await rm(this.stateDirectory, { recursive: true, force: true });\n\t\tthis.client = undefined;\n\t\tthis.transport = undefined;\n\t}\n}\n"]}
@@ -0,0 +1,116 @@
1
+ import { mkdir, mkdtemp, realpath, rm } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { setTimeout as delay } from "node:timers/promises";
5
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
6
+ import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
7
+ import { MacRuntime } from "./macos-runtime.js";
8
+ import { CUA_VERSION, installRuntime, runtimeEnvironment } from "./runtime.js";
9
+ import { assertInteractiveDesktop } from "./windows-desktop.js";
10
+ export class CuaAdapter {
11
+ client;
12
+ transport;
13
+ mac;
14
+ stateDirectory;
15
+ connecting;
16
+ closing;
17
+ abort = new AbortController();
18
+ processObserver;
19
+ setProcessObserver(observer) {
20
+ this.processObserver = observer;
21
+ }
22
+ async connect(signal) {
23
+ const { command, app } = await installRuntime(signal);
24
+ signal.throwIfAborted();
25
+ let args = ["mcp", "--direct", "--embedded", "--no-overlay"];
26
+ if (app) {
27
+ this.mac = new MacRuntime();
28
+ const socket = await this.mac.start(app, signal);
29
+ args = ["mcp", "--embedded", "--socket", socket, "--no-overlay"];
30
+ }
31
+ signal.throwIfAborted();
32
+ const state = await mkdtemp(join(await realpath(tmpdir()), "lunr-cua-client-"));
33
+ this.stateDirectory = state;
34
+ const appData = join(state, "AppData");
35
+ await mkdir(appData);
36
+ signal.throwIfAborted();
37
+ this.transport = new StdioClientTransport({
38
+ command,
39
+ args,
40
+ stderr: "pipe",
41
+ env: {
42
+ ...runtimeEnvironment(),
43
+ HOME: state,
44
+ USERPROFILE: state,
45
+ APPDATA: appData,
46
+ LOCALAPPDATA: appData,
47
+ XDG_CONFIG_HOME: appData,
48
+ XDG_STATE_HOME: appData,
49
+ },
50
+ });
51
+ // Drain diagnostics without retaining desktop or runtime data in session history.
52
+ this.transport.stderr?.on("data", () => { });
53
+ this.client = new Client({ name: "lunr-computer-use", version: CUA_VERSION });
54
+ await this.client.connect(this.transport, { timeout: 15000, signal });
55
+ signal.throwIfAborted();
56
+ if (this.client.getServerVersion()?.version !== CUA_VERSION)
57
+ throw new Error("Computer runtime version mismatch.");
58
+ const pids = [this.transport.pid, ...(this.mac ? [this.mac.processId] : [])];
59
+ for (const pid of pids) {
60
+ if (typeof pid !== "number" || !Number.isInteger(pid) || pid < 1)
61
+ throw new Error("Computer runtime process identity is missing. Input refused.");
62
+ await this.processObserver?.(pid);
63
+ }
64
+ }
65
+ async call(name, args, signal) {
66
+ const combined = AbortSignal.any([this.abort.signal, ...(signal ? [signal] : [])]);
67
+ combined.throwIfAborted();
68
+ try {
69
+ await assertInteractiveDesktop(combined);
70
+ combined.throwIfAborted();
71
+ this.connecting ??= this.connect(AbortSignal.any([combined, AbortSignal.timeout(60000)]));
72
+ await this.connecting;
73
+ combined.throwIfAborted();
74
+ if (!this.client)
75
+ throw new Error("Computer connection closed.");
76
+ return await this.client.callTool({ name, arguments: args }, undefined, { timeout: 15000, signal: combined });
77
+ }
78
+ catch (error) {
79
+ await this.close();
80
+ throw error;
81
+ }
82
+ }
83
+ close() {
84
+ this.abort.abort();
85
+ this.closing ??= this.stop();
86
+ return this.closing;
87
+ }
88
+ async stop() {
89
+ await this.connecting?.catch(() => undefined);
90
+ const pid = this.transport?.pid;
91
+ await this.client?.close();
92
+ await this.transport?.close();
93
+ if (pid) {
94
+ const deadline = Date.now() + 5000;
95
+ for (;;) {
96
+ try {
97
+ process.kill(pid, 0);
98
+ }
99
+ catch (error) {
100
+ if (error instanceof Error && "code" in error && error.code === "ESRCH")
101
+ break;
102
+ throw error;
103
+ }
104
+ if (Date.now() >= deadline)
105
+ throw new Error("Owned computer process shutdown is unconfirmed. Desktop lease retained.");
106
+ await delay(50);
107
+ }
108
+ }
109
+ await this.mac?.close();
110
+ if (this.stateDirectory)
111
+ await rm(this.stateDirectory, { recursive: true, force: true });
112
+ this.client = undefined;
113
+ this.transport = undefined;
114
+ }
115
+ }
116
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../src/core/computer-use/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAShE,MAAM,OAAO,UAAU;IACd,MAAM,CAAU;IAChB,SAAS,CAAwB;IACjC,GAAG,CAAc;IACjB,cAAc,CAAU;IACxB,UAAU,CAAiB;IAC3B,OAAO,CAAiB;IACf,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACvC,eAAe,CAAkC;IACzD,kBAAkB,CAAC,QAAwC,EAAQ;QAClE,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC;IAAA,CAChC;IAEO,KAAK,CAAC,OAAO,CAAC,MAAmB,EAAiB;QACzD,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;QACtD,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,IAAI,IAAI,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;QAC7D,IAAI,GAAG,EAAE,CAAC;YACT,IAAI,CAAC,GAAG,GAAG,IAAI,UAAU,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YACjD,IAAI,GAAG,CAAC,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;QAClE,CAAC;QACD,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC;QAChF,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QACvC,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QACrB,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,IAAI,oBAAoB,CAAC;YACzC,OAAO;YACP,IAAI;YACJ,MAAM,EAAE,MAAM;YACd,GAAG,EAAE;gBACJ,GAAG,kBAAkB,EAAE;gBACvB,IAAI,EAAE,KAAK;gBACX,WAAW,EAAE,KAAK;gBAClB,OAAO,EAAE,OAAO;gBAChB,YAAY,EAAE,OAAO;gBACrB,eAAe,EAAE,OAAO;gBACxB,cAAc,EAAE,OAAO;aACvB;SACD,CAAC,CAAC;QACH,kFAAkF;QAClF,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QAC9E,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,cAAc,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,EAAE,OAAO,KAAK,WAAW;YAC1D,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7E,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;gBAC/D,MAAM,IAAI,KAAK,CAAC,8DAA8D,CAAC,CAAC;YACjF,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC;QACnC,CAAC;IAAA,CACD;IAED,KAAK,CAAC,IAAI,CAAC,IAAY,EAAE,IAA6B,EAAE,MAAoB,EAAwB;QACnG,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACnF,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC1B,IAAI,CAAC;YACJ,MAAM,wBAAwB,CAAC,QAAQ,CAAC,CAAC;YACzC,QAAQ,CAAC,cAAc,EAAE,CAAC;YAC1B,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1F,MAAM,IAAI,CAAC,UAAU,CAAC;YACtB,QAAQ,CAAC,cAAc,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,MAAM;gBAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACjE,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC/G,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,KAAK,CAAC;QACb,CAAC;IAAA,CACD;IAED,KAAK,GAAkB;QACtB,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,OAAO,CAAC;IAAA,CACpB;IAEO,KAAK,CAAC,IAAI,GAAkB;QACnC,MAAM,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,CAAC;QAChC,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;QAC3B,MAAM,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,CAAC;QAC9B,IAAI,GAAG,EAAE,CAAC;YACT,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACnC,SAAS,CAAC;gBACT,IAAI,CAAC;oBACJ,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBACtB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBAChB,IAAI,KAAK,YAAY,KAAK,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO;wBAAE,MAAM;oBAC/E,MAAM,KAAK,CAAC;gBACb,CAAC;gBACD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ;oBACzB,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;gBAC5F,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;QACF,CAAC;QACD,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,cAAc;YAAE,MAAM,EAAE,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACzF,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QACxB,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAAA,CAC3B;CACD","sourcesContent":["import { mkdir, mkdtemp, realpath, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport { MacRuntime } from \"./macos-runtime.ts\";\nimport { CUA_VERSION, installRuntime, runtimeEnvironment } from \"./runtime.ts\";\nimport { assertInteractiveDesktop } from \"./windows-desktop.ts\";\n\nexport type DriverReply = Awaited<ReturnType<Client[\"callTool\"]>>;\nexport interface ComputerDriver {\n\tcall(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply>;\n\tclose(): Promise<void>;\n\tsetProcessObserver?(observer: (pid: number) => Promise<void>): void;\n}\n\nexport class CuaAdapter implements ComputerDriver {\n\tprivate client?: Client;\n\tprivate transport?: StdioClientTransport;\n\tprivate mac?: MacRuntime;\n\tprivate stateDirectory?: string;\n\tprivate connecting?: Promise<void>;\n\tprivate closing?: Promise<void>;\n\tprivate readonly abort = new AbortController();\n\tprivate processObserver?: (pid: number) => Promise<void>;\n\tsetProcessObserver(observer: (pid: number) => Promise<void>): void {\n\t\tthis.processObserver = observer;\n\t}\n\n\tprivate async connect(signal: AbortSignal): Promise<void> {\n\t\tconst { command, app } = await installRuntime(signal);\n\t\tsignal.throwIfAborted();\n\t\tlet args = [\"mcp\", \"--direct\", \"--embedded\", \"--no-overlay\"];\n\t\tif (app) {\n\t\t\tthis.mac = new MacRuntime();\n\t\t\tconst socket = await this.mac.start(app, signal);\n\t\t\targs = [\"mcp\", \"--embedded\", \"--socket\", socket, \"--no-overlay\"];\n\t\t}\n\t\tsignal.throwIfAborted();\n\t\tconst state = await mkdtemp(join(await realpath(tmpdir()), \"lunr-cua-client-\"));\n\t\tthis.stateDirectory = state;\n\t\tconst appData = join(state, \"AppData\");\n\t\tawait mkdir(appData);\n\t\tsignal.throwIfAborted();\n\t\tthis.transport = new StdioClientTransport({\n\t\t\tcommand,\n\t\t\targs,\n\t\t\tstderr: \"pipe\",\n\t\t\tenv: {\n\t\t\t\t...runtimeEnvironment(),\n\t\t\t\tHOME: state,\n\t\t\t\tUSERPROFILE: state,\n\t\t\t\tAPPDATA: appData,\n\t\t\t\tLOCALAPPDATA: appData,\n\t\t\t\tXDG_CONFIG_HOME: appData,\n\t\t\t\tXDG_STATE_HOME: appData,\n\t\t\t},\n\t\t});\n\t\t// Drain diagnostics without retaining desktop or runtime data in session history.\n\t\tthis.transport.stderr?.on(\"data\", () => {});\n\t\tthis.client = new Client({ name: \"lunr-computer-use\", version: CUA_VERSION });\n\t\tawait this.client.connect(this.transport, { timeout: 15000, signal });\n\t\tsignal.throwIfAborted();\n\t\tif (this.client.getServerVersion()?.version !== CUA_VERSION)\n\t\t\tthrow new Error(\"Computer runtime version mismatch.\");\n\t\tconst pids = [this.transport.pid, ...(this.mac ? [this.mac.processId] : [])];\n\t\tfor (const pid of pids) {\n\t\t\tif (typeof pid !== \"number\" || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Computer runtime process identity is missing. Input refused.\");\n\t\t\tawait this.processObserver?.(pid);\n\t\t}\n\t}\n\n\tasync call(name: string, args: Record<string, unknown>, signal?: AbortSignal): Promise<DriverReply> {\n\t\tconst combined = AbortSignal.any([this.abort.signal, ...(signal ? [signal] : [])]);\n\t\tcombined.throwIfAborted();\n\t\ttry {\n\t\t\tawait assertInteractiveDesktop(combined);\n\t\t\tcombined.throwIfAborted();\n\t\t\tthis.connecting ??= this.connect(AbortSignal.any([combined, AbortSignal.timeout(60000)]));\n\t\t\tawait this.connecting;\n\t\t\tcombined.throwIfAborted();\n\t\t\tif (!this.client) throw new Error(\"Computer connection closed.\");\n\t\t\treturn await this.client.callTool({ name, arguments: args }, undefined, { timeout: 15000, signal: combined });\n\t\t} catch (error) {\n\t\t\tawait this.close();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.abort.abort();\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.connecting?.catch(() => undefined);\n\t\tconst pid = this.transport?.pid;\n\t\tawait this.client?.close();\n\t\tawait this.transport?.close();\n\t\tif (pid) {\n\t\t\tconst deadline = Date.now() + 5000;\n\t\t\tfor (;;) {\n\t\t\t\ttry {\n\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ESRCH\") break;\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t\tif (Date.now() >= deadline)\n\t\t\t\t\tthrow new Error(\"Owned computer process shutdown is unconfirmed. Desktop lease retained.\");\n\t\t\t\tawait delay(50);\n\t\t\t}\n\t\t}\n\t\tawait this.mac?.close();\n\t\tif (this.stateDirectory) await rm(this.stateDirectory, { recursive: true, force: true });\n\t\tthis.client = undefined;\n\t\tthis.transport = undefined;\n\t}\n}\n"]}
@@ -0,0 +1,18 @@
1
+ export declare class DesktopLease {
2
+ private readonly identity;
3
+ private owned;
4
+ private tail;
5
+ private closed;
6
+ private readonly controller;
7
+ get signal(): AbortSignal;
8
+ private readonly directory;
9
+ constructor(directory?: string);
10
+ private owner;
11
+ private withOwnerLock;
12
+ private writeOwner;
13
+ private acquire;
14
+ trackProcess(pid: number): Promise<void>;
15
+ run<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T>;
16
+ close(): Promise<void>;
17
+ }
18
+ //# sourceMappingURL=lease.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../../../src/core/computer-use/lease.ts"],"names":[],"mappings":"AAOA,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,IAAI,CAAuC;IACnD,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,IAAI,MAAM,IAAI,WAAW,CAExB;IACD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,YAAY,SAAS,SAA+C,EAEnE;YAEa,KAAK;YAwBL,aAAa;YAab,UAAU;YAUV,OAAO;IAwBf,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ7C;IAED,GAAG,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAepE;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAU3B;CACD","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { userInfo } from \"node:os\";\nimport { join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { assertOwnedPath } from \"./runtime.ts\";\n\nexport class DesktopLease {\n\tprivate readonly identity = randomUUID();\n\tprivate owned = false;\n\tprivate tail: Promise<unknown> = Promise.resolve();\n\tprivate closed = false;\n\tprivate readonly controller = new AbortController();\n\tget signal(): AbortSignal {\n\t\treturn this.controller.signal;\n\t}\n\tprivate readonly directory: string;\n\tconstructor(directory = join(userInfo().homedir, \".lunr\", \"desktop\")) {\n\t\tthis.directory = directory;\n\t}\n\n\tprivate async owner(): Promise<{ pid: number; identity: string; processes: number[] } | undefined> {\n\t\ttry {\n\t\t\tconst value: unknown = JSON.parse(await readFile(join(this.directory, \"workflow-owner.json\"), \"utf8\"));\n\t\t\tif (\n\t\t\t\t!value ||\n\t\t\t\ttypeof value !== \"object\" ||\n\t\t\t\t!(\"pid\" in value) ||\n\t\t\t\ttypeof value.pid !== \"number\" ||\n\t\t\t\t!Number.isInteger(value.pid) ||\n\t\t\t\tvalue.pid < 1 ||\n\t\t\t\t!(\"identity\" in value) ||\n\t\t\t\ttypeof value.identity !== \"string\"\n\t\t\t)\n\t\t\t\tthrow new Error(\"Invalid desktop owner record; refusing takeover.\");\n\t\t\tconst processes = \"processes\" in value ? value.processes : [];\n\t\t\tif (!Array.isArray(processes) || !processes.every((pid) => Number.isInteger(pid) && pid > 0))\n\t\t\t\tthrow new Error(\"Invalid runtime owner record; refusing takeover.\");\n\t\t\treturn { pid: value.pid, identity: value.identity, processes };\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async withOwnerLock(operation: () => Promise<void>): Promise<void> {\n\t\tconst release = await lockfile.lock(this.directory, {\n\t\t\tlockfilePath: join(this.directory, \"workflow-acquire.lock\"),\n\t\t\tretries: 0,\n\t\t\tstale: 10000,\n\t\t});\n\t\ttry {\n\t\t\tawait operation();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t}\n\n\tprivate async writeOwner(owner: { pid: number; identity: string; processes?: number[] }): Promise<void> {\n\t\tconst temporary = join(this.directory, `workflow-owner-${randomUUID()}.tmp`);\n\t\ttry {\n\t\t\tawait writeFile(temporary, JSON.stringify(owner), { mode: 0o600, flag: \"wx\" });\n\t\t\tawait rename(temporary, join(this.directory, \"workflow-owner.json\"));\n\t\t} finally {\n\t\t\tawait rm(temporary, { force: true });\n\t\t}\n\t}\n\n\tprivate async acquire(): Promise<void> {\n\t\tawait assertOwnedPath(this.directory);\n\t\tawait mkdir(this.directory, { recursive: true, mode: 0o700 });\n\t\tawait this.withOwnerLock(async () => {\n\t\t\tconst owner = await this.owner();\n\t\t\tif (owner) {\n\t\t\t\tconst alive = [owner.pid, ...owner.processes].some((pid) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treturn !(error instanceof Error && \"code\" in error && error.code === \"ESRCH\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (alive)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Desktop busy: another lunR workflow owns this user's desktop. Retry only after it ends.\",\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tawait this.writeOwner({ pid: process.pid, identity: this.identity });\n\t\t\tthis.owned = true;\n\t\t});\n\t}\n\n\tasync trackProcess(pid: number): Promise<void> {\n\t\tawait this.withOwnerLock(async () => {\n\t\t\tconst owner = await this.owner();\n\t\t\tif (!owner || owner.identity !== this.identity || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Cannot bind runtime to the desktop lease.\");\n\t\t\tif (!owner.processes.includes(pid)) owner.processes.push(pid);\n\t\t\tawait this.writeOwner(owner);\n\t\t});\n\t}\n\n\trun<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n\t\tconst result = this.tail.then(async () => {\n\t\t\tif (this.closed) throw new Error(\"Desktop workflow ended. Start a new workflow and observe again.\");\n\t\t\tsignal?.throwIfAborted();\n\t\t\tif (!this.owned) await this.acquire();\n\t\t\tif ((await this.owner())?.identity !== this.identity) {\n\t\t\t\tthis.closed = true;\n\t\t\t\tthis.controller.abort(new Error(\"Desktop lease lost.\"));\n\t\t\t\tthrow new Error(\"Desktop lease lost. Input refused.\");\n\t\t\t}\n\t\t\tsignal?.throwIfAborted();\n\t\t\treturn operation();\n\t\t});\n\t\tthis.tail = result.catch(() => undefined);\n\t\treturn result;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true;\n\t\tthis.controller.abort();\n\t\tawait this.tail;\n\t\tif (this.owned) {\n\t\t\tawait this.withOwnerLock(async () => {\n\t\t\t\tif ((await this.owner())?.identity === this.identity) await rm(join(this.directory, \"workflow-owner.json\"));\n\t\t\t});\n\t\t\tthis.owned = false;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,129 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
+ import { userInfo } from "node:os";
4
+ import { join } from "node:path";
5
+ import lockfile from "proper-lockfile";
6
+ import { assertOwnedPath } from "./runtime.js";
7
+ export class DesktopLease {
8
+ identity = randomUUID();
9
+ owned = false;
10
+ tail = Promise.resolve();
11
+ closed = false;
12
+ controller = new AbortController();
13
+ get signal() {
14
+ return this.controller.signal;
15
+ }
16
+ directory;
17
+ constructor(directory = join(userInfo().homedir, ".lunr", "desktop")) {
18
+ this.directory = directory;
19
+ }
20
+ async owner() {
21
+ try {
22
+ const value = JSON.parse(await readFile(join(this.directory, "workflow-owner.json"), "utf8"));
23
+ if (!value ||
24
+ typeof value !== "object" ||
25
+ !("pid" in value) ||
26
+ typeof value.pid !== "number" ||
27
+ !Number.isInteger(value.pid) ||
28
+ value.pid < 1 ||
29
+ !("identity" in value) ||
30
+ typeof value.identity !== "string")
31
+ throw new Error("Invalid desktop owner record; refusing takeover.");
32
+ const processes = "processes" in value ? value.processes : [];
33
+ if (!Array.isArray(processes) || !processes.every((pid) => Number.isInteger(pid) && pid > 0))
34
+ throw new Error("Invalid runtime owner record; refusing takeover.");
35
+ return { pid: value.pid, identity: value.identity, processes };
36
+ }
37
+ catch (error) {
38
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
39
+ return undefined;
40
+ throw error;
41
+ }
42
+ }
43
+ async withOwnerLock(operation) {
44
+ const release = await lockfile.lock(this.directory, {
45
+ lockfilePath: join(this.directory, "workflow-acquire.lock"),
46
+ retries: 0,
47
+ stale: 10000,
48
+ });
49
+ try {
50
+ await operation();
51
+ }
52
+ finally {
53
+ await release();
54
+ }
55
+ }
56
+ async writeOwner(owner) {
57
+ const temporary = join(this.directory, `workflow-owner-${randomUUID()}.tmp`);
58
+ try {
59
+ await writeFile(temporary, JSON.stringify(owner), { mode: 0o600, flag: "wx" });
60
+ await rename(temporary, join(this.directory, "workflow-owner.json"));
61
+ }
62
+ finally {
63
+ await rm(temporary, { force: true });
64
+ }
65
+ }
66
+ async acquire() {
67
+ await assertOwnedPath(this.directory);
68
+ await mkdir(this.directory, { recursive: true, mode: 0o700 });
69
+ await this.withOwnerLock(async () => {
70
+ const owner = await this.owner();
71
+ if (owner) {
72
+ const alive = [owner.pid, ...owner.processes].some((pid) => {
73
+ try {
74
+ process.kill(pid, 0);
75
+ return true;
76
+ }
77
+ catch (error) {
78
+ return !(error instanceof Error && "code" in error && error.code === "ESRCH");
79
+ }
80
+ });
81
+ if (alive)
82
+ throw new Error("Desktop busy: another lunR workflow owns this user's desktop. Retry only after it ends.");
83
+ }
84
+ await this.writeOwner({ pid: process.pid, identity: this.identity });
85
+ this.owned = true;
86
+ });
87
+ }
88
+ async trackProcess(pid) {
89
+ await this.withOwnerLock(async () => {
90
+ const owner = await this.owner();
91
+ if (!owner || owner.identity !== this.identity || !Number.isInteger(pid) || pid < 1)
92
+ throw new Error("Cannot bind runtime to the desktop lease.");
93
+ if (!owner.processes.includes(pid))
94
+ owner.processes.push(pid);
95
+ await this.writeOwner(owner);
96
+ });
97
+ }
98
+ run(operation, signal) {
99
+ const result = this.tail.then(async () => {
100
+ if (this.closed)
101
+ throw new Error("Desktop workflow ended. Start a new workflow and observe again.");
102
+ signal?.throwIfAborted();
103
+ if (!this.owned)
104
+ await this.acquire();
105
+ if ((await this.owner())?.identity !== this.identity) {
106
+ this.closed = true;
107
+ this.controller.abort(new Error("Desktop lease lost."));
108
+ throw new Error("Desktop lease lost. Input refused.");
109
+ }
110
+ signal?.throwIfAborted();
111
+ return operation();
112
+ });
113
+ this.tail = result.catch(() => undefined);
114
+ return result;
115
+ }
116
+ async close() {
117
+ this.closed = true;
118
+ this.controller.abort();
119
+ await this.tail;
120
+ if (this.owned) {
121
+ await this.withOwnerLock(async () => {
122
+ if ((await this.owner())?.identity === this.identity)
123
+ await rm(join(this.directory, "workflow-owner.json"));
124
+ });
125
+ this.owned = false;
126
+ }
127
+ }
128
+ }
129
+ //# sourceMappingURL=lease.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lease.js","sourceRoot":"","sources":["../../../src/core/computer-use/lease.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { userInfo } from \"node:os\";\nimport { join } from \"node:path\";\nimport lockfile from \"proper-lockfile\";\nimport { assertOwnedPath } from \"./runtime.ts\";\n\nexport class DesktopLease {\n\tprivate readonly identity = randomUUID();\n\tprivate owned = false;\n\tprivate tail: Promise<unknown> = Promise.resolve();\n\tprivate closed = false;\n\tprivate readonly controller = new AbortController();\n\tget signal(): AbortSignal {\n\t\treturn this.controller.signal;\n\t}\n\tprivate readonly directory: string;\n\tconstructor(directory = join(userInfo().homedir, \".lunr\", \"desktop\")) {\n\t\tthis.directory = directory;\n\t}\n\n\tprivate async owner(): Promise<{ pid: number; identity: string; processes: number[] } | undefined> {\n\t\ttry {\n\t\t\tconst value: unknown = JSON.parse(await readFile(join(this.directory, \"workflow-owner.json\"), \"utf8\"));\n\t\t\tif (\n\t\t\t\t!value ||\n\t\t\t\ttypeof value !== \"object\" ||\n\t\t\t\t!(\"pid\" in value) ||\n\t\t\t\ttypeof value.pid !== \"number\" ||\n\t\t\t\t!Number.isInteger(value.pid) ||\n\t\t\t\tvalue.pid < 1 ||\n\t\t\t\t!(\"identity\" in value) ||\n\t\t\t\ttypeof value.identity !== \"string\"\n\t\t\t)\n\t\t\t\tthrow new Error(\"Invalid desktop owner record; refusing takeover.\");\n\t\t\tconst processes = \"processes\" in value ? value.processes : [];\n\t\t\tif (!Array.isArray(processes) || !processes.every((pid) => Number.isInteger(pid) && pid > 0))\n\t\t\t\tthrow new Error(\"Invalid runtime owner record; refusing takeover.\");\n\t\t\treturn { pid: value.pid, identity: value.identity, processes };\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") return undefined;\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprivate async withOwnerLock(operation: () => Promise<void>): Promise<void> {\n\t\tconst release = await lockfile.lock(this.directory, {\n\t\t\tlockfilePath: join(this.directory, \"workflow-acquire.lock\"),\n\t\t\tretries: 0,\n\t\t\tstale: 10000,\n\t\t});\n\t\ttry {\n\t\t\tawait operation();\n\t\t} finally {\n\t\t\tawait release();\n\t\t}\n\t}\n\n\tprivate async writeOwner(owner: { pid: number; identity: string; processes?: number[] }): Promise<void> {\n\t\tconst temporary = join(this.directory, `workflow-owner-${randomUUID()}.tmp`);\n\t\ttry {\n\t\t\tawait writeFile(temporary, JSON.stringify(owner), { mode: 0o600, flag: \"wx\" });\n\t\t\tawait rename(temporary, join(this.directory, \"workflow-owner.json\"));\n\t\t} finally {\n\t\t\tawait rm(temporary, { force: true });\n\t\t}\n\t}\n\n\tprivate async acquire(): Promise<void> {\n\t\tawait assertOwnedPath(this.directory);\n\t\tawait mkdir(this.directory, { recursive: true, mode: 0o700 });\n\t\tawait this.withOwnerLock(async () => {\n\t\t\tconst owner = await this.owner();\n\t\t\tif (owner) {\n\t\t\t\tconst alive = [owner.pid, ...owner.processes].some((pid) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tprocess.kill(pid, 0);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treturn !(error instanceof Error && \"code\" in error && error.code === \"ESRCH\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (alive)\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"Desktop busy: another lunR workflow owns this user's desktop. Retry only after it ends.\",\n\t\t\t\t\t);\n\t\t\t}\n\t\t\tawait this.writeOwner({ pid: process.pid, identity: this.identity });\n\t\t\tthis.owned = true;\n\t\t});\n\t}\n\n\tasync trackProcess(pid: number): Promise<void> {\n\t\tawait this.withOwnerLock(async () => {\n\t\t\tconst owner = await this.owner();\n\t\t\tif (!owner || owner.identity !== this.identity || !Number.isInteger(pid) || pid < 1)\n\t\t\t\tthrow new Error(\"Cannot bind runtime to the desktop lease.\");\n\t\t\tif (!owner.processes.includes(pid)) owner.processes.push(pid);\n\t\t\tawait this.writeOwner(owner);\n\t\t});\n\t}\n\n\trun<T>(operation: () => Promise<T>, signal?: AbortSignal): Promise<T> {\n\t\tconst result = this.tail.then(async () => {\n\t\t\tif (this.closed) throw new Error(\"Desktop workflow ended. Start a new workflow and observe again.\");\n\t\t\tsignal?.throwIfAborted();\n\t\t\tif (!this.owned) await this.acquire();\n\t\t\tif ((await this.owner())?.identity !== this.identity) {\n\t\t\t\tthis.closed = true;\n\t\t\t\tthis.controller.abort(new Error(\"Desktop lease lost.\"));\n\t\t\t\tthrow new Error(\"Desktop lease lost. Input refused.\");\n\t\t\t}\n\t\t\tsignal?.throwIfAborted();\n\t\t\treturn operation();\n\t\t});\n\t\tthis.tail = result.catch(() => undefined);\n\t\treturn result;\n\t}\n\n\tasync close(): Promise<void> {\n\t\tthis.closed = true;\n\t\tthis.controller.abort();\n\t\tawait this.tail;\n\t\tif (this.owned) {\n\t\t\tawait this.withOwnerLock(async () => {\n\t\t\t\tif ((await this.owner())?.identity === this.identity) await rm(join(this.directory, \"workflow-owner.json\"));\n\t\t\t});\n\t\t\tthis.owned = false;\n\t\t}\n\t}\n}\n"]}
@@ -0,0 +1,14 @@
1
+ export declare function macLaunchArguments(app: string, socket: string, home: string, lifetime: string): string[];
2
+ export declare class MacRuntime {
3
+ private directory?;
4
+ private lifetime?;
5
+ private exited?;
6
+ private pid?;
7
+ get processId(): number | undefined;
8
+ private socket?;
9
+ private closing?;
10
+ start(app: string, signal: AbortSignal): Promise<string>;
11
+ close(): Promise<void>;
12
+ private stop;
13
+ }
14
+ //# sourceMappingURL=macos-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"macos-runtime.d.ts","sourceRoot":"","sources":["../../../src/core/computer-use/macos-runtime.ts"],"names":[],"mappings":"AAYA,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAwBxG;AAoCD,qBAAa,UAAU;IACtB,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,CAAa;IAC9B,OAAO,CAAC,MAAM,CAAC,CAAgB;IAC/B,OAAO,CAAC,GAAG,CAAC,CAAS;IACrB,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAElC;IACD,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,OAAO,CAAC,CAAgB;IAE1B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA8C7D;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAGrB;YAEa,IAAI;CAoBlB","sourcesContent":["import { execFile, spawn } from \"node:child_process\";\nimport { constants } from \"node:fs\";\nimport { type FileHandle, mkdtemp, open, realpath, rm } from \"node:fs/promises\";\nimport { connect } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { promisify } from \"node:util\";\nimport { CUA_VERSION, runtimeEnvironment } from \"./runtime.ts\";\n\nconst exec = promisify(execFile);\n\nexport function macLaunchArguments(app: string, socket: string, home: string, lifetime: string): string[] {\n\tconst environment = {\n\t\tHOME: home,\n\t\t...Object.fromEntries(Object.entries(runtimeEnvironment()).filter(([name]) => name.startsWith(\"CUA_\"))),\n\t};\n\treturn [\n\t\t\"-n\",\n\t\t\"-g\",\n\t\t\"-W\",\n\t\t\"-a\",\n\t\tapp,\n\t\t\"--stdin\",\n\t\tlifetime,\n\t\t...Object.entries(environment).flatMap(([name, value]) => [\"--env\", `${name}=${value}`]),\n\t\t\"--args\",\n\t\t\"serve\",\n\t\t\"--embedded\",\n\t\t\"--parent-liveness-stdio\",\n\t\t\"--socket\",\n\t\tsocket,\n\t\t\"--permission-mode\",\n\t\t\"standard\",\n\t\t\"--no-overlay\",\n\t];\n}\n\nfunction request(socket: string, method: string, args?: Record<string, unknown>): Promise<Record<string, unknown>> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst stream = connect(socket);\n\t\tlet buffer = \"\";\n\t\tstream.setTimeout(1000, () => stream.destroy(new Error(\"Private computer endpoint timed out.\")));\n\t\tstream.on(\"error\", reject);\n\t\tstream.on(\"connect\", () => stream.write(`${JSON.stringify({ method, args })}\\n`));\n\t\tstream.on(\"data\", (chunk) => {\n\t\t\tbuffer += chunk.toString();\n\t\t\tif (buffer.length > 65536) {\n\t\t\t\tstream.destroy(new Error(\"Invalid private endpoint metadata.\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!buffer.includes(\"\\n\")) return;\n\t\t\ttry {\n\t\t\t\tconst reply: unknown = JSON.parse(buffer.slice(0, buffer.indexOf(\"\\n\")));\n\t\t\t\tif (\n\t\t\t\t\t!reply ||\n\t\t\t\t\ttypeof reply !== \"object\" ||\n\t\t\t\t\t!(\"result\" in reply) ||\n\t\t\t\t\t!reply.result ||\n\t\t\t\t\ttypeof reply.result !== \"object\"\n\t\t\t\t)\n\t\t\t\t\tthrow new Error(\"Private endpoint refused metadata.\");\n\t\t\t\tresolve(Object.fromEntries(Object.entries(reply.result)));\n\t\t\t} catch (error) {\n\t\t\t\treject(error);\n\t\t\t}\n\t\t\tstream.destroy();\n\t\t});\n\t\tstream.on(\"end\", () => reject(new Error(\"Private computer endpoint closed.\")));\n\t});\n}\n\nexport class MacRuntime {\n\tprivate directory?: string;\n\tprivate lifetime?: FileHandle;\n\tprivate exited?: Promise<void>;\n\tprivate pid?: number;\n\tget processId(): number | undefined {\n\t\treturn this.pid;\n\t}\n\tprivate socket?: string;\n\tprivate closing?: Promise<void>;\n\n\tasync start(app: string, signal: AbortSignal): Promise<string> {\n\t\tconst directory = await mkdtemp(join(await realpath(tmpdir()), \"lunr-cua-\"));\n\t\tthis.directory = directory;\n\t\tconst socket = join(directory, \"driver.sock\");\n\t\tthis.socket = socket;\n\t\tconst lifetime = join(directory, \"lifetime\");\n\t\tawait exec(\"/usr/bin/mkfifo\", [\"-m\", \"600\", lifetime], { timeout: 5000, signal });\n\t\tthis.lifetime = await open(lifetime, constants.O_RDWR);\n\t\tsignal.throwIfAborted();\n\t\tconst launcher = spawn(\"/usr/bin/open\", macLaunchArguments(app, socket, directory, lifetime), {\n\t\t\tenv: runtimeEnvironment(),\n\t\t\tstdio: \"ignore\",\n\t\t});\n\t\tthis.exited = new Promise<void>((resolve, reject) => {\n\t\t\tlauncher.once(\"error\", reject);\n\t\t\tlauncher.once(\"exit\", (code) =>\n\t\t\t\tcode === 0 ? resolve() : reject(new Error(`LaunchServices exited ${code}.`)),\n\t\t\t);\n\t\t});\n\t\tvoid this.exited.catch(() => undefined);\n\t\tconst deadline = Date.now() + 15000;\n\t\twhile (Date.now() < deadline) {\n\t\t\tsignal.throwIfAborted();\n\t\t\ttry {\n\t\t\t\tconst metadata = await request(socket, \"metadata\");\n\t\t\t\tif (\n\t\t\t\t\tmetadata.driver_version !== CUA_VERSION ||\n\t\t\t\t\tmetadata.embedded !== true ||\n\t\t\t\t\ttypeof metadata.pid !== \"number\" ||\n\t\t\t\t\tmetadata.pid < 1\n\t\t\t\t)\n\t\t\t\t\tthrow new Error(\"Private runtime has incompatible metadata.\");\n\t\t\t\tthis.pid = metadata.pid;\n\t\t\t\treturn socket;\n\t\t\t} catch {\n\t\t\t\tawait Promise.race([\n\t\t\t\t\tdelay(100, undefined, { signal }),\n\t\t\t\t\tthis.exited.then(() => {\n\t\t\t\t\t\tthrow new Error(\"Computer app exited during startup.\");\n\t\t\t\t\t}),\n\t\t\t\t]);\n\t\t\t}\n\t\t}\n\t\tthrow new Error(\n\t\t\t\"Private macOS runtime startup timed out. Check CuaDriver Accessibility and Screen Recording grants.\",\n\t\t);\n\t}\n\n\tclose(): Promise<void> {\n\t\tthis.closing ??= this.stop();\n\t\treturn this.closing;\n\t}\n\n\tprivate async stop(): Promise<void> {\n\t\tawait this.lifetime?.close();\n\t\tthis.lifetime = undefined;\n\t\tif (this.socket && this.pid)\n\t\t\tawait request(this.socket, \"shutdown_if_pid\", { expected_pid: this.pid }).catch(() => undefined);\n\t\tif (this.exited) {\n\t\t\tconst timeout = new AbortController();\n\t\t\ttry {\n\t\t\t\tawait Promise.race([\n\t\t\t\t\tthis.exited,\n\t\t\t\t\tdelay(10000, undefined, { signal: timeout.signal }).then(() => {\n\t\t\t\t\t\tthrow new Error(\"Owned macOS app shutdown is unconfirmed. Desktop lease retained.\");\n\t\t\t\t\t}),\n\t\t\t\t]);\n\t\t\t} finally {\n\t\t\t\ttimeout.abort();\n\t\t\t}\n\t\t}\n\t\tif (this.directory) await rm(this.directory, { recursive: true, force: true });\n\t}\n}\n"]}