farming-code 2.2.30 → 2.2.32

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 (377) hide show
  1. package/THIRD_PARTY_NOTICES.md +7 -0
  2. package/backend/acp/{client-services.js → client-services.cjs} +132 -134
  3. package/backend/acp/packaged-claude-acp.cjs +37 -0
  4. package/backend/acp/packaged-codex-acp.cjs +37 -0
  5. package/backend/acp/patch-decisions.cjs +182 -0
  6. package/backend/acp/permission-security.cjs +131 -0
  7. package/backend/{acp-checkpoint-store.js → acp-checkpoint-store.cjs} +90 -59
  8. package/backend/{acp-runtime.js → acp-runtime.cjs} +1220 -1112
  9. package/backend/acp-session-state.cjs +622 -0
  10. package/backend/acp-transcript.cjs +525 -0
  11. package/backend/agent-env.cjs +257 -0
  12. package/backend/agent-extension-discovery.cjs +452 -0
  13. package/backend/agent-extension-inventory.cjs +116 -0
  14. package/backend/agent-json-stream.cjs +283 -0
  15. package/backend/agent-lifecycle-journal.cjs +185 -0
  16. package/backend/{agent-manager.js → agent-manager.cjs} +3116 -4275
  17. package/backend/agent-order-transaction.cjs +85 -0
  18. package/backend/agent-order.cjs +159 -0
  19. package/backend/agent-provider-session.cjs +98 -0
  20. package/backend/agent-runtime-binding.cjs +179 -0
  21. package/backend/agent-session-history.cjs +1022 -0
  22. package/backend/agent-session-inventory.cjs +291 -0
  23. package/backend/async-cache.cjs +104 -0
  24. package/backend/atomic-json-store.cjs +67 -0
  25. package/backend/auth.cjs +261 -0
  26. package/backend/authoritative-inventory-cache.cjs +383 -0
  27. package/backend/business-health.cjs +68 -0
  28. package/backend/chat-runtime.cjs +50 -0
  29. package/backend/claude-settings.cjs +132 -0
  30. package/backend/cli-agents.cjs +435 -0
  31. package/backend/codex-context-window.cjs +196 -0
  32. package/backend/codex-models.cjs +228 -0
  33. package/backend/codex-session-archive.cjs +82 -0
  34. package/backend/codex-session-history.cjs +590 -0
  35. package/backend/{codex-terminal-profile.js → codex-terminal-profile.cjs} +149 -155
  36. package/backend/codex-transcript-sanitizer.cjs +130 -0
  37. package/backend/codex-transcript.cjs +2107 -0
  38. package/backend/command-runner-child.cjs +105 -0
  39. package/backend/config-manager.cjs +1263 -0
  40. package/backend/control-api.cjs +439 -0
  41. package/backend/data/LICENSE.cua +21 -0
  42. package/backend/executable-discovery.cjs +204 -0
  43. package/backend/farming-agent-bootstrap.cjs +81 -0
  44. package/backend/farming-agent-bootstrap.zh_cn.md +6 -2
  45. package/backend/{farming-app-cli.js → farming-app-cli.cjs} +441 -493
  46. package/backend/farming-cli.cjs +414 -0
  47. package/backend/farming-net-pass.cjs +319 -0
  48. package/backend/farming-net-registry.cjs +123 -0
  49. package/backend/farming-net-server.cjs +309 -0
  50. package/backend/farming-session-store.cjs +651 -0
  51. package/backend/git-worktree-info.cjs +181 -0
  52. package/backend/haiku-token.cjs +828 -0
  53. package/backend/index-html.cjs +96 -0
  54. package/backend/input-parts.cjs +68 -0
  55. package/backend/input-routing.cjs +40 -0
  56. package/backend/{local-session-engine.js → local-session-engine.cjs} +276 -282
  57. package/backend/main-agent-skills.cjs +309 -0
  58. package/backend/main-page-session.cjs +132 -0
  59. package/backend/native-pty-controller-generation.cjs +139 -0
  60. package/backend/{native-pty-host-client.js → native-pty-host-client.cjs} +338 -346
  61. package/backend/native-pty-host-identity.cjs +125 -0
  62. package/backend/native-pty-host-path.cjs +68 -0
  63. package/backend/{native-pty-host.js → native-pty-host.cjs} +480 -569
  64. package/backend/native-session-engine.cjs +296 -0
  65. package/backend/network.cjs +57 -0
  66. package/backend/npm-update-helper.cjs +399 -0
  67. package/backend/packaged-node-pty.cjs +120 -0
  68. package/backend/preview-session-manager.cjs +89 -0
  69. package/backend/provider-adapters.cjs +492 -0
  70. package/backend/provider-home-configuration.cjs +211 -0
  71. package/backend/provider-session-id.cjs +79 -0
  72. package/backend/provider-session-service.cjs +333 -0
  73. package/backend/qr-share-tickets.cjs +119 -0
  74. package/backend/resource-broadcast-protocol.cjs +50 -0
  75. package/backend/review-diff-router.cjs +202 -0
  76. package/backend/review-diff-service.cjs +1267 -0
  77. package/backend/review-session-router.cjs +93 -0
  78. package/backend/review-session-service.cjs +470 -0
  79. package/backend/review-session-store.cjs +161 -0
  80. package/backend/review-state-router.cjs +132 -0
  81. package/backend/review-state-store.cjs +299 -0
  82. package/backend/run-history-store.cjs +97 -0
  83. package/backend/runtime-dependency-manager.cjs +893 -0
  84. package/backend/runtime-executable-invocation.cjs +37 -0
  85. package/backend/runtime-observation.cjs +96 -0
  86. package/backend/server-process-identity.cjs +70 -0
  87. package/backend/server.cjs +3356 -0
  88. package/backend/session-engine-bridge.cjs +144 -0
  89. package/backend/session-engine-router.cjs +105 -0
  90. package/backend/session-engine.cjs +64 -0
  91. package/backend/session-stream-protocol.cjs +181 -0
  92. package/backend/shell-busy-integration.cjs +442 -0
  93. package/backend/slash-command-discovery.cjs +423 -0
  94. package/backend/storage-layout.cjs +263 -0
  95. package/backend/system-monitor.cjs +96 -0
  96. package/backend/terminal-attach-checkpoint.cjs +73 -0
  97. package/backend/terminal-exit-quiescence.cjs +57 -0
  98. package/backend/{terminal-reducer-flow-control.js → terminal-reducer-flow-control.cjs} +45 -22
  99. package/backend/terminal-runtime-cleanup.cjs +99 -0
  100. package/backend/{terminal-screen-state.js → terminal-screen-state.cjs} +100 -108
  101. package/backend/{terminal-screen-worker-pool.js → terminal-screen-worker-pool.cjs} +89 -79
  102. package/backend/{terminal-screen-worker-thread.js → terminal-screen-worker-thread.cjs} +64 -65
  103. package/backend/terminal-screen-worker.cjs +352 -0
  104. package/backend/terminal-state-serialization.cjs +147 -0
  105. package/backend/{terminal-status.js → terminal-status.cjs} +137 -187
  106. package/backend/theme-manager.cjs +185 -0
  107. package/backend/{update-service.js → update-service.cjs} +258 -248
  108. package/backend/usage-forecast.cjs +95 -0
  109. package/backend/{usage-history-client.js → usage-history-client.cjs} +144 -94
  110. package/backend/usage-history-smoke.cjs +85 -0
  111. package/backend/usage-history-worker.cjs +60 -0
  112. package/backend/{usage-monitor.js → usage-monitor.cjs} +363 -390
  113. package/backend/workspace-directory.cjs +239 -0
  114. package/backend/workspace-discovery.cjs +271 -0
  115. package/backend/{workspace-file-router.js → workspace-file-router.cjs} +213 -282
  116. package/backend/{workspace-file-service.js → workspace-file-service.cjs} +1139 -1318
  117. package/backend/workspace-root-registry.cjs +192 -0
  118. package/bin/farming +1 -1
  119. package/dist/acp/codex-acp-1.1.4.mjs +18 -1
  120. package/dist/assets/App-BCkdpWB6.css +1 -0
  121. package/dist/assets/App-CRjKpaGp.js +697 -0
  122. package/dist/assets/CodeSelect-Ci8sKZPU.js +1 -0
  123. package/dist/assets/CodeSelect-T2eNzrOc.css +1 -0
  124. package/dist/assets/{FileEditorMarkdownPreview-Cs9cLv8a.js → FileEditorMarkdownPreview-V06QHlAg.js} +55 -55
  125. package/dist/assets/FileEditorPane-BX-Wjg9U.js +2 -0
  126. package/dist/assets/IconGlyphs-YhV7tqd4.js +1 -0
  127. package/dist/assets/ProjectFilesSection-BDT2_r0o.js +12 -0
  128. package/dist/assets/ReviewPage-BqAs5sG1.js +3 -0
  129. package/dist/assets/code-dark-B7eM_9G9.css +1 -0
  130. package/dist/assets/{cssMode-Bdg5RpcJ.js → cssMode-ADdAlxTO.js} +1 -1
  131. package/dist/assets/{editor.api2-D74ufkbr.js → editor.api2-BFLAr0YF.js} +162 -162
  132. package/dist/assets/file-icons-BpeqWkIB.js +1 -0
  133. package/dist/assets/{freemarker2-DfMDJfnE.js → freemarker2-C90q5jrp.js} +1 -1
  134. package/dist/assets/{handlebars-BEdPtzMT.js → handlebars-BwUQcEDq.js} +1 -1
  135. package/dist/assets/{html-B1fPb1QD.js → html-1s3uPKfh.js} +1 -1
  136. package/dist/assets/{htmlMode-CY2ZjHxH.js → htmlMode-xtKD99de.js} +1 -1
  137. package/dist/assets/{index-D-zetSol.js → index-C8MchCem.js} +3 -3
  138. package/dist/assets/{javascript-BV2OsWA0.js → javascript-Ph7ijyny.js} +1 -1
  139. package/dist/assets/{jsonMode-zd07aeuX.js → jsonMode-D-jGAnFH.js} +1 -1
  140. package/dist/assets/linkComputer-CbGyI_qx.js +1 -0
  141. package/dist/assets/{liquid-BParI24X.js → liquid-0IamE_cI.js} +1 -1
  142. package/dist/assets/{lspLanguageFeatures-BzredkoV.js → lspLanguageFeatures-BxnQunWF.js} +1 -1
  143. package/dist/assets/main-CLKXa6hf.css +1 -0
  144. package/dist/assets/{mdx-vGzUJN98.js → mdx-DdNmfivn.js} +1 -1
  145. package/dist/assets/{monaco.contribution-BmaeBQEc.js → monaco.contribution-B43jsUs1.js} +2 -2
  146. package/dist/assets/{python-CUwdLgsI.js → python-IAt4X5TS.js} +1 -1
  147. package/dist/assets/{razor-BScebUxU.js → razor-DRkFYW0S.js} +1 -1
  148. package/dist/assets/review-C8-oPKXk.css +1 -0
  149. package/dist/assets/{tsMode-DzUAibXK.js → tsMode-_d_4U2gf.js} +1 -1
  150. package/dist/assets/{typescript-D9EOeM7N.js → typescript-C7zcMq9l.js} +1 -1
  151. package/dist/assets/{workers-DAiomYZM.js → workers-D0nOyJzf.js} +1 -1
  152. package/dist/assets/workspace-editor-model-DND_Y-Bj.js +1 -0
  153. package/dist/assets/workspace-editor-monaco-BPWhgcIB.js +4 -0
  154. package/dist/assets/workspace-editor-monaco-N641qPjX.js +1 -0
  155. package/dist/assets/workspace-view-state-k1bTlJ_Z.js +13 -0
  156. package/dist/assets/{xml-wWl1dhkQ.js → xml-BR-HvxT8.js} +1 -1
  157. package/dist/assets/{yaml-Dc2WDaOZ.js → yaml-YtFQwh4q.js} +1 -1
  158. package/dist/index.html +1 -1
  159. package/extensions/browser/backend/agent-browser-runtime.cjs +1040 -0
  160. package/extensions/browser/backend/agent-capability.cjs +85 -0
  161. package/extensions/browser/backend/browser-mcp-server.cjs +655 -0
  162. package/extensions/browser/backend/browser-resource-manager.cjs +1486 -0
  163. package/extensions/browser/backend/browser-resource-store.cjs +228 -0
  164. package/extensions/browser/backend/browser-router.cjs +203 -0
  165. package/extensions/browser/backend/executable-discovery.cjs +248 -0
  166. package/extensions/browser/backend/farming-browser-client.cjs +116 -0
  167. package/extensions/browser/backend/index.cjs +32 -0
  168. package/extensions/browser/backend/managed-chromium-installer.cjs +833 -0
  169. package/extensions/browser/bin/farming-browser +16 -7
  170. package/extensions/computer/backend/agent-capability.cjs +72 -0
  171. package/extensions/computer/backend/computer-constants.cjs +59 -0
  172. package/extensions/computer/backend/computer-mcp-server.cjs +182 -0
  173. package/extensions/computer/backend/computer-resource-manager.cjs +1219 -0
  174. package/extensions/computer/backend/computer-resource-store.cjs +190 -0
  175. package/extensions/computer/backend/computer-router.cjs +257 -0
  176. package/extensions/computer/backend/cua-tools.json +3067 -0
  177. package/extensions/computer/backend/farming-computer-client.cjs +84 -0
  178. package/extensions/computer/backend/index.cjs +35 -0
  179. package/extensions/computer/backend/isolated-browser-provider.cjs +157 -0
  180. package/extensions/computer/bin/farming-computer +131 -0
  181. package/frontend/farming-net/app.js +255 -262
  182. package/frontend/ghostty-loader.js +24 -20
  183. package/frontend/reading-anchor.js +210 -193
  184. package/frontend/runtime-paths.js +24 -26
  185. package/frontend/session-bridge.js +90 -111
  186. package/frontend/session-modal-bridge.js +184 -302
  187. package/frontend/skin-bridge.js +20 -23
  188. package/frontend/skins/crt/app.js +7686 -7901
  189. package/frontend/skins/crt/effects.js +7 -6
  190. package/frontend/skins/crt/index.html +6 -6
  191. package/frontend/skins/crt/styles/markdown.css +4 -4
  192. package/frontend/terminal-bridge.js +174 -181
  193. package/frontend/terminal-replay.js +320 -345
  194. package/frontend/theme-loader.js +55 -71
  195. package/package.json +64 -37
  196. package/shared/backend-connection-status.js +38 -69
  197. package/shared/browser-protocol.js +235 -110
  198. package/shared/websocket-liveness.js +40 -0
  199. package/backend/acp/packaged-claude-acp.js +0 -13
  200. package/backend/acp/packaged-codex-acp.js +0 -13
  201. package/backend/acp/patch-decisions.js +0 -153
  202. package/backend/acp/permission-security.js +0 -108
  203. package/backend/acp-session-state.js +0 -634
  204. package/backend/acp-transcript.js +0 -512
  205. package/backend/agent-env.js +0 -250
  206. package/backend/agent-json-stream.js +0 -268
  207. package/backend/agent-lifecycle-journal.js +0 -133
  208. package/backend/agent-order.js +0 -166
  209. package/backend/agent-provider-session.js +0 -76
  210. package/backend/agent-runtime-binding.js +0 -174
  211. package/backend/agent-session-history.js +0 -986
  212. package/backend/async-cache.js +0 -94
  213. package/backend/atomic-json-store.js +0 -37
  214. package/backend/auth.js +0 -251
  215. package/backend/chat-runtime.js +0 -28
  216. package/backend/claude-settings.js +0 -121
  217. package/backend/cli-agents.js +0 -486
  218. package/backend/codex-context-window.js +0 -189
  219. package/backend/codex-models.js +0 -226
  220. package/backend/codex-session-archive.js +0 -65
  221. package/backend/codex-session-history.js +0 -647
  222. package/backend/codex-transcript-sanitizer.js +0 -115
  223. package/backend/codex-transcript.js +0 -2362
  224. package/backend/command-runner-child.js +0 -67
  225. package/backend/config-manager.js +0 -1117
  226. package/backend/control-api.js +0 -455
  227. package/backend/executable-discovery.js +0 -216
  228. package/backend/farming-agent-bootstrap.js +0 -49
  229. package/backend/farming-cli.js +0 -403
  230. package/backend/farming-net-pass.js +0 -285
  231. package/backend/farming-net-registry.js +0 -112
  232. package/backend/farming-net-server.js +0 -298
  233. package/backend/farming-session-store.js +0 -677
  234. package/backend/git-worktree-info.js +0 -181
  235. package/backend/haiku-token.js +0 -772
  236. package/backend/index-html.js +0 -80
  237. package/backend/input-parts.js +0 -54
  238. package/backend/input-routing.js +0 -24
  239. package/backend/json-cli-runtime.js +0 -275
  240. package/backend/main-agent-skills.js +0 -288
  241. package/backend/main-page-session.js +0 -122
  242. package/backend/native-pty-controller-generation.js +0 -106
  243. package/backend/native-pty-host-identity.js +0 -86
  244. package/backend/native-pty-host-path.js +0 -42
  245. package/backend/native-session-engine.js +0 -268
  246. package/backend/network.js +0 -23
  247. package/backend/npm-update-helper.js +0 -374
  248. package/backend/packaged-node-pty.js +0 -99
  249. package/backend/preview-session-manager.js +0 -68
  250. package/backend/provider-adapters.js +0 -399
  251. package/backend/provider-session-id.js +0 -47
  252. package/backend/provider-session-service.js +0 -345
  253. package/backend/qr-share-tickets.js +0 -100
  254. package/backend/review-diff-router.js +0 -180
  255. package/backend/review-diff-service.js +0 -1270
  256. package/backend/review-session-router.js +0 -74
  257. package/backend/review-session-service.js +0 -446
  258. package/backend/review-session-store.js +0 -151
  259. package/backend/review-state-router.js +0 -116
  260. package/backend/review-state-store.js +0 -286
  261. package/backend/run-history-store.js +0 -67
  262. package/backend/runtime-dependency-manager.js +0 -759
  263. package/backend/runtime-executable-invocation.js +0 -20
  264. package/backend/runtime-observation.js +0 -81
  265. package/backend/server-process-identity.js +0 -47
  266. package/backend/server.js +0 -3225
  267. package/backend/session-engine-bridge.js +0 -129
  268. package/backend/session-engine-router.js +0 -66
  269. package/backend/session-engine.js +0 -39
  270. package/backend/session-stream-protocol.js +0 -185
  271. package/backend/shell-busy-integration.js +0 -472
  272. package/backend/slash-command-discovery.js +0 -433
  273. package/backend/storage-layout.js +0 -205
  274. package/backend/system-monitor.js +0 -77
  275. package/backend/terminal-attach-checkpoint.js +0 -74
  276. package/backend/terminal-exit-quiescence.js +0 -39
  277. package/backend/terminal-runtime-cleanup.js +0 -80
  278. package/backend/terminal-screen-worker.js +0 -337
  279. package/backend/terminal-state-serialization.js +0 -127
  280. package/backend/theme-manager.js +0 -163
  281. package/backend/usage-forecast.js +0 -86
  282. package/backend/usage-history-scanner.ts +0 -2718
  283. package/backend/usage-history-smoke.js +0 -64
  284. package/backend/usage-history-worker.js +0 -34
  285. package/backend/workspace-directory.js +0 -232
  286. package/backend/workspace-discovery.js +0 -311
  287. package/backend/workspace-root-registry.js +0 -166
  288. package/dist/assets/App-BKNUILuL.css +0 -1
  289. package/dist/assets/App-Z1N7T0eM.js +0 -695
  290. package/dist/assets/FileEditorPane-CNtuGjQ3.js +0 -2
  291. package/dist/assets/IconGlyphs-BClgag6E.js +0 -1
  292. package/dist/assets/ProjectFilesSection-K3GHuQ4U.js +0 -12
  293. package/dist/assets/ReviewPage-BRuxFaH5.js +0 -3
  294. package/dist/assets/code-dark-kLsQLvpf.css +0 -1
  295. package/dist/assets/file-icons-BOlcJ0ZF.js +0 -1
  296. package/dist/assets/main-DUTz-Rd2.css +0 -1
  297. package/dist/assets/review-BcnwQtJv.css +0 -1
  298. package/dist/assets/workspace-editor-model-CSGCl21x.js +0 -1
  299. package/dist/assets/workspace-editor-monaco-CJNwbpCy.js +0 -4
  300. package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +0 -1
  301. package/dist/assets/workspace-view-state-BjKPYp0E.js +0 -7
  302. package/extensions/browser/backend/agent-browser-runtime.js +0 -1041
  303. package/extensions/browser/backend/agent-capability.js +0 -55
  304. package/extensions/browser/backend/browser-mcp-server.js +0 -621
  305. package/extensions/browser/backend/browser-resource-manager.js +0 -1331
  306. package/extensions/browser/backend/browser-resource-store.js +0 -190
  307. package/extensions/browser/backend/browser-router.js +0 -141
  308. package/extensions/browser/backend/executable-discovery.js +0 -238
  309. package/extensions/browser/backend/farming-browser-client.js +0 -83
  310. package/extensions/browser/backend/index.js +0 -7
  311. package/extensions/browser/backend/managed-chromium-installer.js +0 -593
  312. package/extensions/browser/frontend/BrowserSidebarPortals.tsx +0 -360
  313. package/extensions/browser/frontend/BrowserViewer.tsx +0 -500
  314. package/extensions/browser/frontend/browser-resource-state.ts +0 -60
  315. package/extensions/browser/frontend/browser.css +0 -567
  316. package/extensions/browser/frontend/types.ts +0 -38
  317. package/extensions/browser/frontend/useBrowserResources.ts +0 -166
  318. package/frontend/vendor/ghostty-web/index.d.ts +0 -1842
  319. package/shared/backend-connection-status.d.ts +0 -37
  320. package/shared/browser-protocol.d.ts +0 -5
  321. /package/dist/assets/{api-w2x5QfxB.js → api-ByCV9MEr.js} +0 -0
  322. /package/dist/assets/{core-vPkV8P_m.js → core-Czwdx12k.js} +0 -0
  323. /package/dist/assets/{fsharp-DNZNZyEE.js → fsharp-BjPpkoJe.js} +0 -0
  324. /package/dist/assets/{go-_kPJjNc_.js → go-BkIDmSUP.js} +0 -0
  325. /package/dist/assets/{graphql-4HCNVt5g.js → graphql-CCJTpqi1.js} +0 -0
  326. /package/dist/assets/{hcl-C87ymY0o.js → hcl-s4z8lUFg.js} +0 -0
  327. /package/dist/assets/{ini-BYrrGNTc.js → ini-CyUW1I7Z.js} +0 -0
  328. /package/dist/assets/{java-B211rJbk.js → java-CFCcGRiM.js} +0 -0
  329. /package/dist/assets/{julia-DVPsRtBm.js → julia-DQyH_EYb.js} +0 -0
  330. /package/dist/assets/{kotlin-BYyNerjp.js → kotlin-B8hA5O51.js} +0 -0
  331. /package/dist/assets/{less-EC9UblGE.js → less-DaVdaas0.js} +0 -0
  332. /package/dist/assets/{lexon-B1yuUdqW.js → lexon-DLBhPd3y.js} +0 -0
  333. /package/dist/assets/{lua-Bo6GFzxT.js → lua-gB1c_cif.js} +0 -0
  334. /package/dist/assets/{m3-C-Y9cBVI.js → m3-C2T3z3gB.js} +0 -0
  335. /package/dist/assets/{markdown-BHu-wLbe.js → markdown-CKq-Euj1.js} +0 -0
  336. /package/dist/assets/{mips-Dkds26rX.js → mips-Bcs5qIDX.js} +0 -0
  337. /package/dist/assets/{msdax-PU4g-8_g.js → msdax-CBP48FHF.js} +0 -0
  338. /package/dist/assets/{mysql-fPpuGpS7.js → mysql-c7tiPcFj.js} +0 -0
  339. /package/dist/assets/{objective-c-Wy1e5JUf.js → objective-c-D4BZkeEV.js} +0 -0
  340. /package/dist/assets/{pascal-BIXwvrqU.js → pascal-CJDZg0MN.js} +0 -0
  341. /package/dist/assets/{pascaligo-DwR0AtL_.js → pascaligo-Bygi8Ynl.js} +0 -0
  342. /package/dist/assets/{perl-CGHAl8my.js → perl-aS8bkf7E.js} +0 -0
  343. /package/dist/assets/{pgsql-B91M73E2.js → pgsql-CzNAYFYl.js} +0 -0
  344. /package/dist/assets/{php-C70ttrCx.js → php-DOtoEFTT.js} +0 -0
  345. /package/dist/assets/{pla-BNrXaRh0.js → pla-DugRnao1.js} +0 -0
  346. /package/dist/assets/{postiats-Dv2IAZR9.js → postiats-DsXwusKh.js} +0 -0
  347. /package/dist/assets/{powerquery-CkY5Wq7J.js → powerquery-DL3o72oD.js} +0 -0
  348. /package/dist/assets/{powershell-uGIYLU3C.js → powershell-C1qHekys.js} +0 -0
  349. /package/dist/assets/{protobuf-CavfmJu-.js → protobuf-DHgsc-cH.js} +0 -0
  350. /package/dist/assets/{pug-Drqnyitx.js → pug-FZXlE_Iu.js} +0 -0
  351. /package/dist/assets/{qrcode-7uGsTEmi.js → qrcode-DJDTdjL7.js} +0 -0
  352. /package/dist/assets/{qsharp-C7yF-Dti.js → qsharp-bLyhI3DT.js} +0 -0
  353. /package/dist/assets/{r-HXLGP0_-.js → r-DjFGXbAa.js} +0 -0
  354. /package/dist/assets/{redis-C4y6mf2p.js → redis-DSoZ_V6u.js} +0 -0
  355. /package/dist/assets/{redshift-DdQrFPrv.js → redshift-CzkdCsrg.js} +0 -0
  356. /package/dist/assets/{restructuredtext-CBrf2PNj.js → restructuredtext-B_XPrGCQ.js} +0 -0
  357. /package/dist/assets/{ruby-CVtMoX2B.js → ruby-Cry2RneJ.js} +0 -0
  358. /package/dist/assets/{rust-Ckq4sbMP.js → rust-CWzdbFq1.js} +0 -0
  359. /package/dist/assets/{sb-er66OpE3.js → sb-DmofU59h.js} +0 -0
  360. /package/dist/assets/{scala-BdWZz-hH.js → scala-BUC2l-vN.js} +0 -0
  361. /package/dist/assets/{scheme-kTV_s2kP.js → scheme-CNIB_72f.js} +0 -0
  362. /package/dist/assets/{scss-Bymy2VJQ.js → scss-DcL4-NbX.js} +0 -0
  363. /package/dist/assets/{shell-bwEP1LQ1.js → shell-CgAGvSSA.js} +0 -0
  364. /package/dist/assets/{solidity-DCddeBgL.js → solidity-DSkt6O_P.js} +0 -0
  365. /package/dist/assets/{sophia-BMN3AQig.js → sophia--5ytcjDN.js} +0 -0
  366. /package/dist/assets/{sparql-CSXOLjzi.js → sparql-C1Srr7cD.js} +0 -0
  367. /package/dist/assets/{sql-COg8ewmK.js → sql-2k_O5fj7.js} +0 -0
  368. /package/dist/assets/{st-CIaZtBS_.js → st-DCCCPqfz.js} +0 -0
  369. /package/dist/assets/{swift-DXiOhUHu.js → swift-Dd8mAfOt.js} +0 -0
  370. /package/dist/assets/{systemverilog-BTDE6Dr2.js → systemverilog-B0-aZYXu.js} +0 -0
  371. /package/dist/assets/{tcl-B0zy9NvV.js → tcl-CZAZwPVX.js} +0 -0
  372. /package/dist/assets/{twig-D594l4Z1.js → twig-D-Ag0tdS.js} +0 -0
  373. /package/dist/assets/{typespec-XKVjaPqo.js → typespec-B7kTFp0Z.js} +0 -0
  374. /package/dist/assets/{useWorkspaceMenuKeyboard-Bpy_s69Z.js → useWorkspaceMenuKeyboard-uYZpDxhU.js} +0 -0
  375. /package/dist/assets/{vb-B2wYoKRV.js → vb-20w1JPum.js} +0 -0
  376. /package/dist/assets/{wgsl-D0Yf2LbK.js → wgsl-CLJfqFt0.js} +0 -0
  377. /package/dist/assets/{workspace-working-copy-C3FSR3N6.js → workspace-working-copy-Cfz07cOd.js} +0 -0
@@ -0,0 +1,1219 @@
1
+ // Generated by scripts/build-backend-runtime.ts. Do not edit.
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
13
+ var __copyProps = (to, from, except, desc) => {
14
+ if (from && typeof from === "object" || typeof from === "function") {
15
+ for (let key of __getOwnPropNames(from))
16
+ if (!__hasOwnProp.call(to, key) && key !== except)
17
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
18
+ }
19
+ return to;
20
+ };
21
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
22
+ // If the importer is in node compatibility mode or this is not an ESM
23
+ // file that has been converted to a CommonJS file using a Babel-
24
+ // compatible transform (i.e. "__esModule" has not been set), then set
25
+ // "default" to the CommonJS "module.exports" for node compatibility.
26
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
27
+ mod
28
+ ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
+ var computer_resource_manager_exports = {};
31
+ __export(computer_resource_manager_exports, {
32
+ ComputerResourceManager: () => ComputerResourceManager,
33
+ exactImageRef: () => exactImageRef
34
+ });
35
+ module.exports = __toCommonJS(computer_resource_manager_exports);
36
+ var storageLayout = __toESM(require("../../../backend/storage-layout.cjs"));
37
+ var import_computer_constants = require("./computer-constants.cjs");
38
+ var import_computer_resource_store = require("./computer-resource-store.cjs");
39
+ const { EventEmitter } = require("events");
40
+ const { execFile } = require("child_process");
41
+ const { promisify } = require("util");
42
+ const crypto = require("crypto");
43
+ const fs = require("fs");
44
+ const http = require("http");
45
+ const path = require("path");
46
+ const WebSocket = require("ws");
47
+ const execFileAsync = promisify(execFile);
48
+ const INACTIVE_AGENT_STATUSES = /* @__PURE__ */ new Set(["dead", "error", "exited", "stopped"]);
49
+ const CUA_TOOL_MANIFEST = require("./cua-tools.json");
50
+ const SUPPORTED_UPSTREAM_TOOLS = new Set(
51
+ (CUA_TOOL_MANIFEST.tools || []).map((tool) => String(tool.upstreamName || "").trim()).filter(Boolean)
52
+ );
53
+ const READ_ONLY_TOOLS = new Set(
54
+ (CUA_TOOL_MANIFEST.tools || []).filter((tool) => tool.annotations?.readOnlyHint === true).map((tool) => String(tool.upstreamName || "").trim()).filter(Boolean)
55
+ );
56
+ const STATE_OBSERVATION_TOOLS = /* @__PURE__ */ new Set([
57
+ "get_accessibility_tree",
58
+ "get_browser_state",
59
+ "get_desktop_state",
60
+ "get_window_state"
61
+ ]);
62
+ const SCREENSHOT_TOOLS = /* @__PURE__ */ new Set([
63
+ "get_browser_state",
64
+ "get_desktop_state",
65
+ "get_window_state",
66
+ "zoom"
67
+ ]);
68
+ const DRIVER_CALL_TIMEOUT_MS = 45e3;
69
+ const DOCKER_TIMEOUT_MS = 9e4;
70
+ const START_TIMEOUT_MS = 45e3;
71
+ const COMPUTER_BROWSER_CDP_PORT = "9223/tcp";
72
+ const COMPUTER_BROWSER_MOUNT = "/opt/farming/chromium";
73
+ const COMPUTER_BROWSER_RELAY_SCRIPT = [
74
+ "import select,socket",
75
+ "listener=socket.socket()",
76
+ "listener.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)",
77
+ 'listener.bind(("0.0.0.0",9223))',
78
+ "listener.listen(32)",
79
+ "while True:",
80
+ " client,_=listener.accept()",
81
+ ' upstream=socket.create_connection(("127.0.0.1",9222),timeout=5)',
82
+ " sockets=[client,upstream]",
83
+ " while sockets:",
84
+ " readable,_,failed=select.select(sockets,[],sockets,30)",
85
+ " if failed: break",
86
+ " if not readable: continue",
87
+ " for source in readable:",
88
+ " data=source.recv(65536)",
89
+ " if not data: sockets=[]; break",
90
+ " (upstream if source is client else client).sendall(data)",
91
+ " client.close()",
92
+ " upstream.close()"
93
+ ].join("\n");
94
+ function recordValue(value) {
95
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
96
+ }
97
+ function pathInside(root, candidate) {
98
+ const relative = path.relative(path.resolve(root), path.resolve(candidate));
99
+ return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
100
+ }
101
+ function computerError(message, status, code, extra = {}) {
102
+ return Object.assign(new Error(message), { status, code, ...extra });
103
+ }
104
+ function randomPassword() {
105
+ return crypto.randomBytes(9).toString("base64url").slice(0, 12);
106
+ }
107
+ function exactImageRef(value) {
108
+ const requested = String(value || "").trim() || import_computer_constants.COMPUTER_IMAGE;
109
+ if (!requested.endsWith(`@${import_computer_constants.COMPUTER_IMAGE_INDEX_DIGEST}`)) {
110
+ throw computerError(
111
+ `Computer image must be pinned to ${import_computer_constants.COMPUTER_IMAGE_INDEX_DIGEST}`,
112
+ 400,
113
+ "COMPUTER_IMAGE_NOT_PINNED"
114
+ );
115
+ }
116
+ return requested;
117
+ }
118
+ function safeNamePart(value) {
119
+ return value.toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 42);
120
+ }
121
+ function parsePort(inspect) {
122
+ return parsePublishedPort(inspect, "6901/tcp");
123
+ }
124
+ function parsePublishedPort(inspect, containerPort) {
125
+ const networkSettings = recordValue(inspect.NetworkSettings);
126
+ const ports = recordValue(networkSettings.Ports);
127
+ const mappings = ports[containerPort];
128
+ if (!Array.isArray(mappings) || mappings.length !== 1) return 0;
129
+ const mapping = recordValue(mappings[0]);
130
+ if (mapping.HostIp !== "127.0.0.1") return 0;
131
+ const port = Number(mapping.HostPort);
132
+ return Number.isSafeInteger(port) && port > 0 && port <= 65535 ? port : 0;
133
+ }
134
+ function waitForHttpPath(port, requestPath, failureMessage, failureCode, timeoutMs = START_TIMEOUT_MS) {
135
+ const deadline = Date.now() + timeoutMs;
136
+ return new Promise((resolve, reject) => {
137
+ const attempt = () => {
138
+ if (Date.now() >= deadline) {
139
+ reject(computerError(failureMessage, 504, failureCode));
140
+ return;
141
+ }
142
+ let successfulResponse = false;
143
+ let attemptFinished = false;
144
+ const retry = () => {
145
+ if (attemptFinished) return;
146
+ attemptFinished = true;
147
+ setTimeout(attempt, 250);
148
+ };
149
+ const request = http.get({
150
+ hostname: "127.0.0.1",
151
+ port,
152
+ path: requestPath,
153
+ timeout: 2e3,
154
+ agent: false,
155
+ headers: { Connection: "close" }
156
+ }, (response) => {
157
+ response.resume();
158
+ if (Number(response.statusCode) >= 200 && Number(response.statusCode) < 500) {
159
+ successfulResponse = true;
160
+ return;
161
+ }
162
+ });
163
+ request.on("timeout", () => request.destroy());
164
+ request.on("error", () => {
165
+ if (!successfulResponse) retry();
166
+ });
167
+ request.on("close", () => {
168
+ if (attemptFinished) return;
169
+ attemptFinished = true;
170
+ if (successfulResponse) resolve();
171
+ else setTimeout(attempt, 250);
172
+ });
173
+ };
174
+ attempt();
175
+ });
176
+ }
177
+ function waitForHttp(port, timeoutMs = START_TIMEOUT_MS) {
178
+ return waitForHttpPath(
179
+ port,
180
+ "/vnc.html",
181
+ "Computer Viewer did not become ready in time",
182
+ "COMPUTER_VIEWER_TIMEOUT",
183
+ timeoutMs
184
+ );
185
+ }
186
+ function waitForCdp(port, timeoutMs = START_TIMEOUT_MS) {
187
+ return waitForHttpPath(
188
+ port,
189
+ "/json/version",
190
+ "Computer Chromium did not expose DevTools in time",
191
+ "COMPUTER_BROWSER_CDP_TIMEOUT",
192
+ timeoutMs
193
+ );
194
+ }
195
+ class ComputerResourceManager extends EventEmitter {
196
+ configDir;
197
+ isEnabled;
198
+ getSettings;
199
+ store;
200
+ docker;
201
+ configFingerprint;
202
+ operations = /* @__PURE__ */ new Map();
203
+ stopAdmissions = /* @__PURE__ */ new Map();
204
+ controlAdmissions = /* @__PURE__ */ new Map();
205
+ viewerSockets = /* @__PURE__ */ new Map();
206
+ browserLeases = /* @__PURE__ */ new Map();
207
+ capabilityCache = null;
208
+ preparePromise = null;
209
+ constructor(options) {
210
+ super();
211
+ this.configDir = options.configDir;
212
+ this.isEnabled = options.isEnabled || (() => false);
213
+ this.getSettings = options.getSettings || (() => ({}));
214
+ this.store = new import_computer_resource_store.ComputerResourceStore(options.configDir);
215
+ this.configFingerprint = crypto.createHash("sha256").update(options.configDir).digest("hex").slice(0, 12);
216
+ this.docker = options.dockerRunner || (async (args, runOptions = {}) => {
217
+ const result = await execFileAsync("docker", args, {
218
+ encoding: "utf8",
219
+ timeout: runOptions.timeoutMs || DOCKER_TIMEOUT_MS,
220
+ maxBuffer: runOptions.maxBuffer || 20 * 1024 * 1024
221
+ });
222
+ return {
223
+ stdout: String(result.stdout || ""),
224
+ stderr: String(result.stderr || "")
225
+ };
226
+ });
227
+ }
228
+ async init() {
229
+ this.store.init();
230
+ for (const resource of this.store.list()) {
231
+ if (!resource.containerId) {
232
+ if (resource.status !== "stopped") {
233
+ this.patch(resource.id, {
234
+ status: "failed",
235
+ error: "Owned Computer container identity is missing",
236
+ viewerPort: 0,
237
+ sessionId: ""
238
+ });
239
+ }
240
+ continue;
241
+ }
242
+ try {
243
+ const inspect = await this.inspectOwnedContainer(resource);
244
+ const running = recordValue(inspect.State).Running === true;
245
+ if (!running) {
246
+ this.patch(resource.id, {
247
+ status: "stopped",
248
+ viewerPort: 0,
249
+ sessionId: "",
250
+ error: ""
251
+ });
252
+ continue;
253
+ }
254
+ const viewerPort = parsePort(inspect);
255
+ if (!viewerPort) throw new Error("Computer container has no loopback Viewer port");
256
+ await this.ensureDriver(resource, resource.sessionId || this.sessionId(resource));
257
+ this.patch(resource.id, {
258
+ status: "running",
259
+ viewerPort,
260
+ sessionId: resource.sessionId || this.sessionId(resource),
261
+ error: ""
262
+ });
263
+ } catch (caught) {
264
+ const error = caught;
265
+ this.patch(resource.id, {
266
+ status: "failed",
267
+ viewerPort: 0,
268
+ sessionId: "",
269
+ error: error.message || "Computer recovery failed"
270
+ });
271
+ }
272
+ }
273
+ }
274
+ requireEnabled() {
275
+ if (!this.isEnabled()) {
276
+ throw computerError("Computer plugin is disabled", 409, "COMPUTER_DISABLED");
277
+ }
278
+ }
279
+ imageRef() {
280
+ return exactImageRef(this.getSettings().computerImage);
281
+ }
282
+ compatibilityMode() {
283
+ return this.getSettings().computerCompatibilityMode === true;
284
+ }
285
+ list() {
286
+ return this.store.snapshot();
287
+ }
288
+ get(id) {
289
+ const resource = this.store.get(id);
290
+ if (!resource) throw computerError("Computer Resource was not found", 404, "COMPUTER_NOT_FOUND");
291
+ return (0, import_computer_resource_store.publicResource)(resource, this.store.revision);
292
+ }
293
+ privateResource(id) {
294
+ const resource = this.store.get(id);
295
+ if (!resource) throw computerError("Computer Resource was not found", 404, "COMPUTER_NOT_FOUND");
296
+ return resource;
297
+ }
298
+ create(input) {
299
+ this.requireEnabled();
300
+ const existing = this.store.list().find(
301
+ (resource2) => resource2.ownerAgentId === input.ownerAgentId
302
+ );
303
+ if (existing) return (0, import_computer_resource_store.publicResource)(existing, this.store.revision);
304
+ const resource = this.store.create(input);
305
+ this.emitResource(resource);
306
+ return (0, import_computer_resource_store.publicResource)(resource, this.store.revision);
307
+ }
308
+ async acquireBrowser(input) {
309
+ this.requireEnabled();
310
+ const executablePath = this.browserExecutableInContainer(input.executablePath);
311
+ this.ensureBrowserCacheTraversal(input.executablePath);
312
+ const resource = this.create({
313
+ ownerAgentId: input.ownerAgentId,
314
+ projectRootId: input.projectRootId,
315
+ workspace: input.workspace,
316
+ name: "Desktop"
317
+ });
318
+ if (resource.projectRootId !== input.projectRootId || resource.workspace !== input.workspace) {
319
+ throw computerError(
320
+ "The Agent Computer belongs to a different Project workspace",
321
+ 409,
322
+ "COMPUTER_BROWSER_OWNER_MISMATCH"
323
+ );
324
+ }
325
+ await this.ensureBrowserCacheMount(resource.id);
326
+ await this.start(resource.id);
327
+ const result = await this.enqueue(resource.id, async () => {
328
+ const current = this.privateResource(resource.id);
329
+ if (current.status !== "running" || !current.containerId) {
330
+ throw computerError(
331
+ "Computer stopped before Chromium could start",
332
+ 409,
333
+ "COMPUTER_NOT_RUNNING"
334
+ );
335
+ }
336
+ const inspect = await this.inspectOwnedContainer(current);
337
+ const cdpPort = parsePublishedPort(inspect, COMPUTER_BROWSER_CDP_PORT);
338
+ if (!cdpPort) {
339
+ throw computerError(
340
+ "Computer container has no loopback DevTools port",
341
+ 409,
342
+ "COMPUTER_BROWSER_PORT_MISSING"
343
+ );
344
+ }
345
+ try {
346
+ await waitForCdp(cdpPort, 500);
347
+ } catch {
348
+ const displayReady = await this.waitForContainer(current.containerId, [
349
+ "test",
350
+ "-S",
351
+ "/tmp/.X11-unix/X1"
352
+ ]);
353
+ if (!displayReady) {
354
+ throw computerError(
355
+ "Computer desktop did not become ready for Chromium",
356
+ 504,
357
+ "COMPUTER_BROWSER_DISPLAY_TIMEOUT"
358
+ );
359
+ }
360
+ let chromiumReady = await this.waitForContainer(current.containerId, [
361
+ "python3",
362
+ "-c",
363
+ 'import urllib.request; urllib.request.urlopen("http://127.0.0.1:9222/json/version", timeout=1)'
364
+ ], 500);
365
+ if (!chromiumReady) {
366
+ await this.docker([
367
+ "exec",
368
+ "-d",
369
+ "-u",
370
+ import_computer_constants.COMPUTER_USER,
371
+ "-e",
372
+ "HOME=/home/cua",
373
+ "-e",
374
+ "DISPLAY=:1",
375
+ current.containerId,
376
+ executablePath,
377
+ "--no-sandbox",
378
+ "--remote-debugging-port=9222",
379
+ "--user-data-dir=/home/cua/.farming-browser",
380
+ "--no-first-run",
381
+ "--no-default-browser-check",
382
+ "about:blank"
383
+ ], { timeoutMs: 1e4 });
384
+ chromiumReady = await this.waitForContainer(current.containerId, [
385
+ "python3",
386
+ "-c",
387
+ 'import urllib.request; urllib.request.urlopen("http://127.0.0.1:9222/json/version", timeout=1)'
388
+ ]);
389
+ }
390
+ if (!chromiumReady) {
391
+ throw computerError(
392
+ "Chromium did not expose its internal DevTools endpoint",
393
+ 504,
394
+ "COMPUTER_BROWSER_CHROMIUM_TIMEOUT"
395
+ );
396
+ }
397
+ await this.docker([
398
+ "exec",
399
+ "-d",
400
+ current.containerId,
401
+ "python3",
402
+ "-c",
403
+ COMPUTER_BROWSER_RELAY_SCRIPT
404
+ ], { timeoutMs: 1e4 });
405
+ await waitForCdp(cdpPort);
406
+ }
407
+ this.browserLeases.set(
408
+ resource.id,
409
+ (this.browserLeases.get(resource.id) || 0) + 1
410
+ );
411
+ return { cdpUrl: `http://127.0.0.1:${cdpPort}`, leaseKey: resource.id };
412
+ });
413
+ return result;
414
+ }
415
+ releaseBrowser(leaseKey) {
416
+ const current = this.browserLeases.get(leaseKey) || 0;
417
+ if (current <= 1) this.browserLeases.delete(leaseKey);
418
+ else this.browserLeases.set(leaseKey, current - 1);
419
+ return Promise.resolve();
420
+ }
421
+ async verifyBrowserExecutable(executablePath) {
422
+ const containerPath = this.browserExecutableInContainer(executablePath);
423
+ this.ensureBrowserCacheTraversal(executablePath);
424
+ const result = await this.docker([
425
+ "run",
426
+ "--rm",
427
+ "--label",
428
+ "farming.dev/kind=computer-browser-probe",
429
+ "--label",
430
+ `farming.dev/config=${this.configFingerprint}`,
431
+ ...this.compatibilityMode() ? ["--security-opt", "seccomp=unconfined"] : [],
432
+ "--user",
433
+ import_computer_constants.COMPUTER_USER,
434
+ "-e",
435
+ "HOME=/home/cua",
436
+ "--entrypoint",
437
+ containerPath,
438
+ "-v",
439
+ `${this.browserCacheRoot()}:${COMPUTER_BROWSER_MOUNT}:ro`,
440
+ this.imageRef(),
441
+ "--no-sandbox",
442
+ "--version"
443
+ ], { timeoutMs: 3e4 });
444
+ const version = result.stdout.trim() || result.stderr.trim();
445
+ if (!/(?:Google Chrome|Chromium)/i.test(version)) {
446
+ throw computerError(
447
+ `Computer Chromium verification returned an unexpected version: ${version}`,
448
+ 409,
449
+ "COMPUTER_BROWSER_VERSION_MISMATCH"
450
+ );
451
+ }
452
+ return version;
453
+ }
454
+ rename(id, name) {
455
+ const normalized = String(name || "").trim().slice(0, 120);
456
+ if (!normalized) throw computerError("Computer name is required", 400, "COMPUTER_NAME_REQUIRED");
457
+ return this.patch(id, { name: normalized });
458
+ }
459
+ snapshot() {
460
+ return this.stateSnapshot();
461
+ }
462
+ stateSnapshot() {
463
+ return this.store.snapshot();
464
+ }
465
+ async capability(refresh = false) {
466
+ if (this.capabilityCache && !refresh) {
467
+ return { ...this.capabilityCache, enabled: this.isEnabled() };
468
+ }
469
+ const probe = await this.probeSettings(this.getSettings());
470
+ this.capabilityCache = {
471
+ available: probe.dockerAvailable && probe.imageReady,
472
+ enabled: this.isEnabled(),
473
+ ...probe,
474
+ imageDigest: import_computer_constants.COMPUTER_IMAGE_INDEX_DIGEST,
475
+ driverVersion: import_computer_constants.COMPUTER_DRIVER_VERSION,
476
+ compatibilityMode: this.compatibilityMode()
477
+ };
478
+ return this.capabilityCache;
479
+ }
480
+ async probeSettings(settings) {
481
+ const image = exactImageRef(settings.computerImage);
482
+ let dockerAvailable = false;
483
+ let imageReady = false;
484
+ let error = "";
485
+ try {
486
+ await this.docker(["version", "--format", "{{.Server.Version}}"], { timeoutMs: 8e3 });
487
+ dockerAvailable = true;
488
+ await this.docker(["image", "inspect", image, "--format", "{{.Id}}"], { timeoutMs: 8e3 });
489
+ imageReady = true;
490
+ } catch (caught) {
491
+ error = caught.message || String(caught);
492
+ }
493
+ return { dockerAvailable, imageReady, image, error };
494
+ }
495
+ prepare() {
496
+ if (this.preparePromise) return this.preparePromise;
497
+ this.preparePromise = (async () => {
498
+ await this.docker(["version", "--format", "{{.Server.Version}}"], { timeoutMs: 8e3 });
499
+ await this.docker(["pull", this.imageRef()], { timeoutMs: 20 * 6e4, maxBuffer: 64 * 1024 * 1024 });
500
+ const probeName = `farming-computer-probe-${this.configFingerprint}-${crypto.randomBytes(3).toString("hex")}`;
501
+ const args = [
502
+ "run",
503
+ "--rm",
504
+ "--name",
505
+ probeName,
506
+ "--label",
507
+ "farming.dev/kind=computer-probe",
508
+ "--label",
509
+ `farming.dev/config=${this.configFingerprint}`,
510
+ ...this.compatibilityMode() ? ["--security-opt", "seccomp=unconfined"] : [],
511
+ "--entrypoint",
512
+ "/bin/sh",
513
+ this.imageRef(),
514
+ "-lc",
515
+ `su -s /bin/sh -c 'HOME=/home/cua ${import_computer_constants.COMPUTER_DRIVER_BIN} --version' ${import_computer_constants.COMPUTER_USER}`
516
+ ];
517
+ try {
518
+ const result = await this.docker(args, { timeoutMs: 6e4 });
519
+ if (!result.stdout.includes(import_computer_constants.COMPUTER_DRIVER_VERSION)) {
520
+ throw computerError(
521
+ `Computer image contains an unexpected Cua Driver version: ${result.stdout.trim()}`,
522
+ 409,
523
+ "COMPUTER_DRIVER_VERSION_MISMATCH"
524
+ );
525
+ }
526
+ } catch (caught) {
527
+ const message = caught.message || String(caught);
528
+ const compatibilityRequired = /operation not permitted|pthread_create|clone3/i.test(
529
+ `${message}
530
+ ${caught.stderr || ""}`
531
+ );
532
+ throw computerError(
533
+ compatibilityRequired ? "This Docker Engine requires explicit Computer compatibility mode" : `Computer runtime probe failed: ${message}`,
534
+ 409,
535
+ compatibilityRequired ? "COMPUTER_COMPATIBILITY_REQUIRED" : "COMPUTER_PROBE_FAILED",
536
+ { compatibilityRequired }
537
+ );
538
+ }
539
+ this.capabilityCache = null;
540
+ return this.capability(true);
541
+ })().finally(() => {
542
+ this.preparePromise = null;
543
+ });
544
+ return this.preparePromise;
545
+ }
546
+ start(id) {
547
+ this.requireEnabled();
548
+ this.assertTransitionAdmissionOpen(id);
549
+ return this.enqueue(id, async () => {
550
+ this.assertTransitionAdmissionOpen(id);
551
+ let resource = this.privateResource(id);
552
+ if (resource.status === "running") return (0, import_computer_resource_store.publicResource)(resource, this.store.revision);
553
+ const generation = resource.generation + 1;
554
+ const password = resource.vncPassword || randomPassword();
555
+ const containerName = resource.containerName || this.containerName(resource);
556
+ resource = this.patch(id, {
557
+ status: "starting",
558
+ generation,
559
+ controlOwner: "agent",
560
+ controlEpoch: resource.controlEpoch + 1,
561
+ needsObserve: false,
562
+ vncPassword: password,
563
+ containerName,
564
+ viewerPort: 0,
565
+ sessionId: "",
566
+ error: ""
567
+ }, true);
568
+ try {
569
+ let containerId = resource.containerId;
570
+ if (containerId) {
571
+ await this.inspectOwnedContainer(resource);
572
+ } else {
573
+ const labels = this.containerLabels(resource);
574
+ const create = await this.docker([
575
+ "create",
576
+ "--name",
577
+ containerName,
578
+ ...labels.flatMap(([key, value]) => ["--label", `${key}=${value}`]),
579
+ "--cpus",
580
+ import_computer_constants.COMPUTER_CONTAINER_CPUS,
581
+ "--memory",
582
+ import_computer_constants.COMPUTER_CONTAINER_MEMORY,
583
+ "--shm-size",
584
+ import_computer_constants.COMPUTER_CONTAINER_SHM_SIZE,
585
+ "--pids-limit",
586
+ import_computer_constants.COMPUTER_CONTAINER_PIDS,
587
+ "--add-host",
588
+ "host.docker.internal:host-gateway",
589
+ "-p",
590
+ "127.0.0.1::6901",
591
+ "-p",
592
+ "127.0.0.1::9223",
593
+ "-v",
594
+ `${this.browserCacheRoot()}:${COMPUTER_BROWSER_MOUNT}:ro`,
595
+ "-e",
596
+ `VNC_PW=${password}`,
597
+ ...this.compatibilityMode() ? ["--security-opt", "seccomp=unconfined"] : [],
598
+ this.imageRef()
599
+ ]);
600
+ containerId = create.stdout.trim();
601
+ if (!/^[a-f0-9]{12,64}$/i.test(containerId)) {
602
+ throw new Error("Docker did not return an exact Computer container identity");
603
+ }
604
+ resource = this.patch(id, { containerId }, true);
605
+ await this.inspectOwnedContainer(resource);
606
+ }
607
+ await this.docker(["start", containerId]);
608
+ const inspect = await this.inspectOwnedContainer(this.privateResource(id));
609
+ const viewerPort = parsePort(inspect);
610
+ if (!viewerPort) throw new Error("Docker did not publish the Computer Viewer on loopback");
611
+ await waitForHttp(viewerPort);
612
+ const sessionId = this.sessionId(this.privateResource(id));
613
+ await this.ensureDriver(this.privateResource(id), sessionId);
614
+ return this.patch(id, {
615
+ status: "running",
616
+ viewerPort,
617
+ sessionId,
618
+ error: ""
619
+ });
620
+ } catch (caught) {
621
+ const error = caught;
622
+ this.patch(id, {
623
+ status: "failed",
624
+ viewerPort: 0,
625
+ sessionId: "",
626
+ error: error.message || "Computer start failed"
627
+ });
628
+ throw error;
629
+ }
630
+ });
631
+ }
632
+ stop(id, internal = false) {
633
+ if (!internal) this.requireEnabled();
634
+ if (!internal && (this.browserLeases.get(id) || 0) > 0) {
635
+ throw computerError(
636
+ "Stop the Agent Browsers using this Computer first",
637
+ 409,
638
+ "COMPUTER_IN_USE_BY_BROWSER"
639
+ );
640
+ }
641
+ this.holdStopAdmission(id);
642
+ return this.enqueue(id, async () => {
643
+ const resource = this.privateResource(id);
644
+ if (!resource.containerId || resource.status === "stopped") {
645
+ return this.patch(id, {
646
+ status: "stopped",
647
+ viewerPort: 0,
648
+ sessionId: "",
649
+ controlOwner: "agent",
650
+ needsObserve: false,
651
+ error: ""
652
+ });
653
+ }
654
+ this.patch(id, { status: "stopping" });
655
+ this.closeViewers(id, 4e3, "Computer stopped");
656
+ try {
657
+ if (resource.sessionId) {
658
+ await this.driverCall(resource, "end_session", { session: resource.sessionId }).catch(() => null);
659
+ }
660
+ await this.inspectOwnedContainer(resource);
661
+ await this.docker(["stop", "--time", "10", resource.containerId], { timeoutMs: 3e4 });
662
+ return this.patch(id, {
663
+ status: "stopped",
664
+ viewerPort: 0,
665
+ sessionId: "",
666
+ controlOwner: "agent",
667
+ controlEpoch: resource.controlEpoch + 1,
668
+ needsObserve: false,
669
+ error: ""
670
+ });
671
+ } catch (caught) {
672
+ const error = caught;
673
+ this.patch(id, { status: "failed", error: error.message || "Computer stop failed" });
674
+ throw error;
675
+ }
676
+ }).finally(() => this.releaseStopAdmission(id));
677
+ }
678
+ async delete(id, internal = false) {
679
+ if (!internal) this.requireEnabled();
680
+ if (!internal && (this.browserLeases.get(id) || 0) > 0) {
681
+ throw computerError(
682
+ "Delete the Agent Browsers using this Computer first",
683
+ 409,
684
+ "COMPUTER_IN_USE_BY_BROWSER"
685
+ );
686
+ }
687
+ this.holdStopAdmission(id);
688
+ try {
689
+ await this.stop(id, true);
690
+ return await this.enqueue(id, async () => {
691
+ const resource = this.privateResource(id);
692
+ if (resource.containerId) {
693
+ await this.inspectOwnedContainer(resource);
694
+ await this.docker(["rm", resource.containerId], { timeoutMs: 3e4 });
695
+ }
696
+ this.closeViewers(id, 4e3, "Computer deleted");
697
+ this.browserLeases.delete(id);
698
+ this.store.remove(id);
699
+ this.emit("deleted", { id, collectionRevision: this.store.revision });
700
+ return { id, collectionRevision: this.store.revision };
701
+ });
702
+ } finally {
703
+ this.releaseStopAdmission(id);
704
+ }
705
+ }
706
+ takeControl(id, owner) {
707
+ this.requireEnabled();
708
+ const resource = this.privateResource(id);
709
+ if (resource.status !== "running") {
710
+ throw computerError("Computer is not running", 409, "COMPUTER_NOT_RUNNING");
711
+ }
712
+ if (owner === resource.controlOwner) {
713
+ return Promise.resolve((0, import_computer_resource_store.publicResource)(resource, this.store.revision));
714
+ }
715
+ if (this.isStopping(id)) {
716
+ throw computerError("Computer is stopping", 409, "COMPUTER_STOPPING");
717
+ }
718
+ if (this.isControlChanging(id)) {
719
+ throw computerError("Computer control is changing", 409, "COMPUTER_CONTROL_CHANGING");
720
+ }
721
+ this.holdControlAdmission(id);
722
+ return this.enqueue(id, async () => {
723
+ const current = this.privateResource(id);
724
+ if (current.status !== "running") {
725
+ throw computerError("Computer is not running", 409, "COMPUTER_NOT_RUNNING");
726
+ }
727
+ if (owner === current.controlOwner) {
728
+ return (0, import_computer_resource_store.publicResource)(current, this.store.revision);
729
+ }
730
+ this.closeViewers(id, 4002, "Computer control changed");
731
+ return this.patch(id, {
732
+ controlOwner: owner,
733
+ controlEpoch: current.controlEpoch + 1,
734
+ needsObserve: owner === "agent"
735
+ });
736
+ }).finally(() => this.releaseControlAdmission(id));
737
+ }
738
+ callTool(id, tool, input, caller = "agent") {
739
+ this.requireEnabled();
740
+ if (!SUPPORTED_UPSTREAM_TOOLS.has(tool)) {
741
+ throw computerError(`Computer tool is not supported: ${tool}`, 400, "COMPUTER_TOOL_NOT_SUPPORTED");
742
+ }
743
+ const resource = this.privateResource(id);
744
+ if (this.isStopping(id)) {
745
+ throw computerError("Computer is stopping", 409, "COMPUTER_STOPPING");
746
+ }
747
+ if (this.isControlChanging(id)) {
748
+ throw computerError("Computer control is changing", 409, "COMPUTER_CONTROL_CHANGING");
749
+ }
750
+ if (resource.status !== "running") {
751
+ throw computerError("Computer is not running", 409, "COMPUTER_NOT_RUNNING");
752
+ }
753
+ if (resource.controlOwner !== caller) {
754
+ throw computerError(
755
+ caller === "agent" ? "A human currently controls this Computer" : "The Agent currently controls this Computer",
756
+ 409,
757
+ "COMPUTER_CONTROL_OWNER_MISMATCH"
758
+ );
759
+ }
760
+ if (caller === "agent" && resource.needsObserve && !READ_ONLY_TOOLS.has(tool)) {
761
+ throw computerError(
762
+ "Observe the Computer after human control before sending another action",
763
+ 409,
764
+ "COMPUTER_OBSERVE_REQUIRED"
765
+ );
766
+ }
767
+ const admittedGeneration = resource.generation;
768
+ const admittedEpoch = resource.controlEpoch;
769
+ return this.enqueue(id, async () => {
770
+ const current = this.privateResource(id);
771
+ if (current.generation !== admittedGeneration || current.controlEpoch !== admittedEpoch || current.status !== "running" || current.controlOwner !== caller) {
772
+ throw computerError("Computer ownership changed before this action ran", 409, "COMPUTER_STALE_ADMISSION");
773
+ }
774
+ const args = { ...input };
775
+ if ("session" in args || this.toolAcceptsSession(tool)) args.session = current.sessionId;
776
+ if (tool === "start_session") {
777
+ return { content: [{ type: "text", text: `Farming manages session ${current.sessionId}` }] };
778
+ }
779
+ if (tool === "end_session") {
780
+ return { content: [{ type: "text", text: "Farming keeps this Computer session alive until Stop." }] };
781
+ }
782
+ const screenshotPath = SCREENSHOT_TOOLS.has(tool) ? `/tmp/farming-${current.id}-${crypto.randomBytes(5).toString("hex")}.png` : "";
783
+ let result;
784
+ try {
785
+ result = await this.driverCall(current, tool, args, screenshotPath);
786
+ } catch (caught) {
787
+ const error = caught;
788
+ if (error.killed || error.signal || /timed out/i.test(error.message || "")) {
789
+ this.patch(id, { needsObserve: true, error: `Uncertain ${tool} outcome; observe before retrying` });
790
+ throw computerError(
791
+ `Computer action ${tool} timed out with an uncertain outcome; observe before retrying`,
792
+ 504,
793
+ "COMPUTER_ACTION_UNCERTAIN",
794
+ { uncertain: true }
795
+ );
796
+ }
797
+ throw error;
798
+ }
799
+ const latest = this.privateResource(id);
800
+ if (caller === "agent" && STATE_OBSERVATION_TOOLS.has(tool) && latest.needsObserve) {
801
+ this.patch(id, { needsObserve: false, error: "" });
802
+ }
803
+ return result;
804
+ });
805
+ }
806
+ async reconcileAgentLifecycle(agentStates) {
807
+ const agents = new Map(agentStates.map((agent) => [String(agent.id || ""), agent]));
808
+ for (const resource of this.store.list()) {
809
+ const owner = agents.get(resource.ownerAgentId);
810
+ if (!owner) {
811
+ await this.delete(resource.id, true);
812
+ continue;
813
+ }
814
+ const operation = String(owner.lifecycleOperation?.type || "");
815
+ const preservesRuntime = ["permission-restart", "runtime-switch"].includes(operation);
816
+ const stopped = owner.archived === true || !preservesRuntime && INACTIVE_AGENT_STATUSES.has(String(owner.status || ""));
817
+ if (stopped && resource.status !== "stopped") {
818
+ await this.stop(resource.id, true);
819
+ }
820
+ }
821
+ }
822
+ async stopAll() {
823
+ for (const resource of this.store.list()) {
824
+ if (resource.status !== "stopped" || resource.containerId) {
825
+ await this.stop(resource.id, true);
826
+ }
827
+ }
828
+ }
829
+ async resetAllContainers() {
830
+ for (const candidate of this.store.list()) {
831
+ this.holdStopAdmission(candidate.id);
832
+ try {
833
+ await this.stop(candidate.id, true);
834
+ await this.enqueue(candidate.id, async () => {
835
+ const resource = this.privateResource(candidate.id);
836
+ if (resource.containerId) {
837
+ await this.inspectOwnedContainer(resource);
838
+ await this.docker(["rm", resource.containerId], { timeoutMs: 3e4 });
839
+ }
840
+ this.patch(resource.id, {
841
+ containerId: "",
842
+ containerName: "",
843
+ vncPassword: "",
844
+ viewerPort: 0,
845
+ sessionId: "",
846
+ status: "stopped",
847
+ error: ""
848
+ });
849
+ });
850
+ } finally {
851
+ this.releaseStopAdmission(candidate.id);
852
+ }
853
+ }
854
+ }
855
+ viewerConfig(id) {
856
+ const resource = this.privateResource(id);
857
+ if (resource.status !== "running" || !resource.viewerPort) {
858
+ throw computerError("Computer Viewer is not running", 409, "COMPUTER_NOT_RUNNING");
859
+ }
860
+ return {
861
+ host: "127.0.0.1",
862
+ port: resource.viewerPort,
863
+ password: resource.vncPassword,
864
+ viewOnly: resource.controlOwner !== "human",
865
+ generation: resource.generation,
866
+ controlEpoch: resource.controlEpoch
867
+ };
868
+ }
869
+ attachViewer(id, client) {
870
+ const config = this.viewerConfig(id);
871
+ const upstream = new WebSocket(`ws://127.0.0.1:${config.port}/websockify`);
872
+ const sockets = this.viewerSockets.get(id) || /* @__PURE__ */ new Set();
873
+ sockets.add(client);
874
+ this.viewerSockets.set(id, sockets);
875
+ const close = () => {
876
+ sockets.delete(client);
877
+ if (sockets.size === 0) this.viewerSockets.delete(id);
878
+ if (upstream.readyState === WebSocket.OPEN || upstream.readyState === WebSocket.CONNECTING) {
879
+ upstream.close();
880
+ }
881
+ };
882
+ upstream.on("message", (data, isBinary) => {
883
+ if (client.readyState === WebSocket.OPEN) client.send(data, { binary: isBinary });
884
+ });
885
+ client.on("message", (data, isBinary) => {
886
+ const latest = this.privateResource(id);
887
+ if (latest.generation !== config.generation || latest.controlEpoch !== config.controlEpoch) {
888
+ client.close(4003, "Computer Viewer is stale");
889
+ return;
890
+ }
891
+ if (upstream.readyState === WebSocket.OPEN) upstream.send(data, { binary: isBinary });
892
+ });
893
+ upstream.on("close", () => client.close(4e3, "Computer Viewer closed"));
894
+ upstream.on("error", () => client.close(4005, "Computer Viewer failed"));
895
+ client.on("close", close);
896
+ client.on("error", close);
897
+ }
898
+ closeViewers(id, code, reason) {
899
+ const sockets = this.viewerSockets.get(id);
900
+ if (!sockets) return;
901
+ this.viewerSockets.delete(id);
902
+ for (const socket of sockets) socket.close(code, reason);
903
+ }
904
+ containerName(resource) {
905
+ return safeNamePart(`farming-computer-${this.configFingerprint}-${resource.id.slice(-12)}`);
906
+ }
907
+ containerLabels(resource) {
908
+ return [
909
+ ["farming.dev/kind", "computer"],
910
+ ["farming.dev/config", this.configFingerprint],
911
+ ["farming.dev/resource", resource.id],
912
+ ["farming.dev/owner-agent", resource.ownerAgentId],
913
+ ["farming.dev/image-digest", import_computer_constants.COMPUTER_IMAGE_INDEX_DIGEST]
914
+ ];
915
+ }
916
+ browserCacheRoot() {
917
+ const root = storageLayout.managedChromiumRootDir(this.configDir);
918
+ fs.mkdirSync(root, { recursive: true, mode: 448 });
919
+ return root;
920
+ }
921
+ hasBrowserRuntimeWiring(inspect) {
922
+ const mounts = Array.isArray(inspect.Mounts) ? inspect.Mounts : [];
923
+ return mounts.some(
924
+ (mount) => recordValue(mount).Destination === COMPUTER_BROWSER_MOUNT && recordValue(mount).RW === false
925
+ ) && Boolean(recordValue(recordValue(inspect.HostConfig).PortBindings)[COMPUTER_BROWSER_CDP_PORT]);
926
+ }
927
+ async ensureBrowserCacheMount(id) {
928
+ const resource = this.privateResource(id);
929
+ if (!resource.containerId) return;
930
+ const inspect = await this.inspectOwnedContainer(resource);
931
+ if (this.hasBrowserRuntimeWiring(inspect)) return;
932
+ await this.resetContainer(id);
933
+ }
934
+ async resetContainer(id) {
935
+ await this.stop(id, true);
936
+ this.holdStopAdmission(id);
937
+ try {
938
+ await this.enqueue(id, async () => {
939
+ const resource = this.privateResource(id);
940
+ if (resource.containerId) {
941
+ await this.inspectOwnedContainer(resource);
942
+ await this.docker(["rm", resource.containerId], { timeoutMs: 3e4 });
943
+ }
944
+ this.patch(resource.id, {
945
+ containerId: "",
946
+ containerName: "",
947
+ vncPassword: "",
948
+ viewerPort: 0,
949
+ sessionId: "",
950
+ status: "stopped",
951
+ error: ""
952
+ });
953
+ });
954
+ } finally {
955
+ this.releaseStopAdmission(id);
956
+ }
957
+ }
958
+ browserExecutableInContainer(executablePath) {
959
+ const root = this.browserCacheRoot();
960
+ const resolved = path.resolve(String(executablePath || "").trim());
961
+ const relative = path.relative(root, resolved);
962
+ if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
963
+ throw computerError(
964
+ "Computer Chromium must come from Farming managed runtime storage",
965
+ 400,
966
+ "COMPUTER_BROWSER_EXECUTABLE_INVALID"
967
+ );
968
+ }
969
+ return `${COMPUTER_BROWSER_MOUNT}/${relative.split(path.sep).join("/")}`;
970
+ }
971
+ ensureBrowserCacheTraversal(executablePath) {
972
+ const root = path.resolve(this.browserCacheRoot());
973
+ let current = path.dirname(path.resolve(String(executablePath || "").trim()));
974
+ while (current === root || pathInside(root, current)) {
975
+ const mode = fs.statSync(current).mode & 511;
976
+ if ((mode & 9) !== 9) fs.chmodSync(current, mode | 9);
977
+ if (current === root) return;
978
+ current = path.dirname(current);
979
+ }
980
+ throw computerError(
981
+ "Computer Chromium must come from Farming managed runtime storage",
982
+ 400,
983
+ "COMPUTER_BROWSER_EXECUTABLE_INVALID"
984
+ );
985
+ }
986
+ async waitForContainer(containerId, command, timeoutMs = START_TIMEOUT_MS) {
987
+ const deadline = Date.now() + timeoutMs;
988
+ while (Date.now() < deadline) {
989
+ try {
990
+ await this.docker(["exec", containerId, ...command], { timeoutMs: 3e3 });
991
+ return true;
992
+ } catch {
993
+ await new Promise((resolve) => setTimeout(resolve, 250));
994
+ }
995
+ }
996
+ return false;
997
+ }
998
+ async inspectOwnedContainer(resource) {
999
+ if (!resource.containerId) {
1000
+ throw computerError("Computer container identity is missing", 409, "COMPUTER_CONTAINER_IDENTITY_MISSING");
1001
+ }
1002
+ const result = await this.docker(["inspect", resource.containerId], { timeoutMs: 1e4 });
1003
+ const parsed = JSON.parse(result.stdout);
1004
+ const inspect = Array.isArray(parsed) ? recordValue(parsed[0]) : {};
1005
+ if (!inspect.Id || String(inspect.Id) !== resource.containerId) {
1006
+ throw computerError("Docker returned a different Computer container identity", 409, "COMPUTER_CONTAINER_MISMATCH");
1007
+ }
1008
+ const labels = recordValue(recordValue(inspect.Config).Labels);
1009
+ for (const [key, value] of this.containerLabels(resource)) {
1010
+ if (labels[key] !== value) {
1011
+ throw computerError(`Computer container ownership label mismatch: ${key}`, 409, "COMPUTER_CONTAINER_OWNER_MISMATCH");
1012
+ }
1013
+ }
1014
+ return inspect;
1015
+ }
1016
+ sessionId(resource) {
1017
+ return `${resource.id}-g${resource.generation}`;
1018
+ }
1019
+ async ensureDriver(resource, sessionId) {
1020
+ await this.docker([
1021
+ "exec",
1022
+ "-u",
1023
+ import_computer_constants.COMPUTER_USER,
1024
+ "-e",
1025
+ "HOME=/home/cua",
1026
+ resource.containerId,
1027
+ import_computer_constants.COMPUTER_DRIVER_BIN,
1028
+ "telemetry",
1029
+ "disable"
1030
+ ], { timeoutMs: 1e4 }).catch(() => null);
1031
+ await this.docker([
1032
+ "exec",
1033
+ "-d",
1034
+ "-u",
1035
+ import_computer_constants.COMPUTER_USER,
1036
+ "-e",
1037
+ "HOME=/home/cua",
1038
+ "-e",
1039
+ "DISPLAY=:1",
1040
+ resource.containerId,
1041
+ import_computer_constants.COMPUTER_DRIVER_BIN,
1042
+ "serve",
1043
+ "--dangerously-bypass-approvals"
1044
+ ], { timeoutMs: 1e4 }).catch(() => null);
1045
+ const deadline = Date.now() + START_TIMEOUT_MS;
1046
+ let lastError = null;
1047
+ while (Date.now() < deadline) {
1048
+ try {
1049
+ const version = await this.docker([
1050
+ "exec",
1051
+ "-u",
1052
+ import_computer_constants.COMPUTER_USER,
1053
+ "-e",
1054
+ "HOME=/home/cua",
1055
+ "-e",
1056
+ "DISPLAY=:1",
1057
+ resource.containerId,
1058
+ import_computer_constants.COMPUTER_DRIVER_BIN,
1059
+ "--version"
1060
+ ], { timeoutMs: 5e3 });
1061
+ if (!version.stdout.includes(import_computer_constants.COMPUTER_DRIVER_VERSION)) {
1062
+ throw new Error(`Expected Cua Driver ${import_computer_constants.COMPUTER_DRIVER_VERSION}, got ${version.stdout.trim()}`);
1063
+ }
1064
+ await this.driverCall(resource, "start_session", {
1065
+ session: sessionId,
1066
+ capture_scope: "desktop"
1067
+ });
1068
+ return;
1069
+ } catch (caught) {
1070
+ lastError = caught;
1071
+ await new Promise((resolve) => setTimeout(resolve, 300));
1072
+ }
1073
+ }
1074
+ throw lastError || new Error("Cua Driver did not become ready");
1075
+ }
1076
+ async driverCall(resource, tool, input, screenshotPath = "") {
1077
+ const args = [
1078
+ "exec",
1079
+ "-u",
1080
+ import_computer_constants.COMPUTER_USER,
1081
+ "-e",
1082
+ "HOME=/home/cua",
1083
+ "-e",
1084
+ "DISPLAY=:1",
1085
+ resource.containerId,
1086
+ import_computer_constants.COMPUTER_DRIVER_BIN,
1087
+ "call",
1088
+ tool,
1089
+ JSON.stringify(input),
1090
+ ...screenshotPath ? ["--screenshot-out-file", screenshotPath] : []
1091
+ ];
1092
+ const result = await this.docker(args, {
1093
+ timeoutMs: DRIVER_CALL_TIMEOUT_MS,
1094
+ maxBuffer: 32 * 1024 * 1024
1095
+ });
1096
+ let structuredContent;
1097
+ const text = result.stdout.trim();
1098
+ try {
1099
+ structuredContent = JSON.parse(text);
1100
+ } catch {
1101
+ structuredContent = void 0;
1102
+ }
1103
+ const content = [{
1104
+ type: "text",
1105
+ text: text || result.stderr.trim() || `${tool} completed`
1106
+ }];
1107
+ if (screenshotPath) {
1108
+ try {
1109
+ await this.docker([
1110
+ "exec",
1111
+ "-u",
1112
+ import_computer_constants.COMPUTER_USER,
1113
+ resource.containerId,
1114
+ "test",
1115
+ "-s",
1116
+ screenshotPath
1117
+ ], { timeoutMs: 5e3 });
1118
+ const image = await this.docker([
1119
+ "exec",
1120
+ "-u",
1121
+ import_computer_constants.COMPUTER_USER,
1122
+ resource.containerId,
1123
+ "base64",
1124
+ "-w",
1125
+ "0",
1126
+ screenshotPath
1127
+ ], { timeoutMs: 1e4, maxBuffer: 24 * 1024 * 1024 });
1128
+ if (image.stdout.trim()) content.push({
1129
+ type: "image",
1130
+ data: image.stdout.trim(),
1131
+ mimeType: "image/png"
1132
+ });
1133
+ } catch {
1134
+ } finally {
1135
+ await this.docker([
1136
+ "exec",
1137
+ "-u",
1138
+ import_computer_constants.COMPUTER_USER,
1139
+ resource.containerId,
1140
+ "rm",
1141
+ "-f",
1142
+ screenshotPath
1143
+ ], { timeoutMs: 5e3 }).catch(() => null);
1144
+ }
1145
+ }
1146
+ return {
1147
+ content,
1148
+ ...structuredContent === void 0 ? {} : { structuredContent }
1149
+ };
1150
+ }
1151
+ toolAcceptsSession(tool) {
1152
+ return ![
1153
+ "check_for_update",
1154
+ "check_permissions",
1155
+ "get_config",
1156
+ "health_report",
1157
+ "install_ffmpeg",
1158
+ "list_apps",
1159
+ "list_windows",
1160
+ "set_config",
1161
+ "start_recording",
1162
+ "stop_recording",
1163
+ "get_recording_state",
1164
+ "replay_trajectory"
1165
+ ].includes(tool);
1166
+ }
1167
+ holdStopAdmission(id) {
1168
+ this.stopAdmissions.set(id, (this.stopAdmissions.get(id) || 0) + 1);
1169
+ }
1170
+ releaseStopAdmission(id) {
1171
+ const next = (this.stopAdmissions.get(id) || 1) - 1;
1172
+ if (next <= 0) this.stopAdmissions.delete(id);
1173
+ else this.stopAdmissions.set(id, next);
1174
+ }
1175
+ isStopping(id) {
1176
+ return (this.stopAdmissions.get(id) || 0) > 0;
1177
+ }
1178
+ holdControlAdmission(id) {
1179
+ this.controlAdmissions.set(id, (this.controlAdmissions.get(id) || 0) + 1);
1180
+ }
1181
+ releaseControlAdmission(id) {
1182
+ const next = (this.controlAdmissions.get(id) || 1) - 1;
1183
+ if (next <= 0) this.controlAdmissions.delete(id);
1184
+ else this.controlAdmissions.set(id, next);
1185
+ }
1186
+ isControlChanging(id) {
1187
+ return (this.controlAdmissions.get(id) || 0) > 0;
1188
+ }
1189
+ assertTransitionAdmissionOpen(id) {
1190
+ if (this.isStopping(id)) {
1191
+ throw computerError("Computer is stopping", 409, "COMPUTER_STOPPING");
1192
+ }
1193
+ if (this.isControlChanging(id)) {
1194
+ throw computerError("Computer control is changing", 409, "COMPUTER_CONTROL_CHANGING");
1195
+ }
1196
+ }
1197
+ enqueue(id, action) {
1198
+ const previous = this.operations.get(id) || Promise.resolve();
1199
+ const next = previous.catch(() => null).then(action);
1200
+ this.operations.set(id, next);
1201
+ return next.finally(() => {
1202
+ if (this.operations.get(id) === next) this.operations.delete(id);
1203
+ });
1204
+ }
1205
+ patch(id, patch, privateResult = false) {
1206
+ const resource = this.store.patch(id, patch);
1207
+ this.emitResource(resource);
1208
+ return privateResult ? resource : (0, import_computer_resource_store.publicResource)(resource, this.store.revision);
1209
+ }
1210
+ emitResource(resource) {
1211
+ this.emit("resource", (0, import_computer_resource_store.publicResource)(resource, this.store.revision));
1212
+ this.emit("resources", this.store.snapshot());
1213
+ }
1214
+ }
1215
+ // Annotate the CommonJS export names for ESM import in node:
1216
+ 0 && (module.exports = {
1217
+ ComputerResourceManager,
1218
+ exactImageRef
1219
+ });