farming-code 2.2.29 → 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 (385) hide show
  1. package/README.md +25 -66
  2. package/README.zh_cn.md +15 -66
  3. package/THIRD_PARTY_NOTICES.md +7 -0
  4. package/backend/acp/{client-services.js → client-services.cjs} +132 -134
  5. package/backend/acp/packaged-claude-acp.cjs +37 -0
  6. package/backend/acp/packaged-codex-acp.cjs +37 -0
  7. package/backend/acp/patch-decisions.cjs +182 -0
  8. package/backend/acp/permission-security.cjs +131 -0
  9. package/backend/{acp-checkpoint-store.js → acp-checkpoint-store.cjs} +90 -59
  10. package/backend/{acp-runtime.js → acp-runtime.cjs} +1219 -1125
  11. package/backend/acp-session-state.cjs +622 -0
  12. package/backend/acp-transcript.cjs +525 -0
  13. package/backend/agent-env.cjs +257 -0
  14. package/backend/agent-extension-discovery.cjs +452 -0
  15. package/backend/agent-extension-inventory.cjs +116 -0
  16. package/backend/agent-json-stream.cjs +283 -0
  17. package/backend/agent-lifecycle-journal.cjs +185 -0
  18. package/backend/{agent-manager.js → agent-manager.cjs} +3116 -4275
  19. package/backend/agent-order-transaction.cjs +85 -0
  20. package/backend/agent-order.cjs +159 -0
  21. package/backend/agent-provider-session.cjs +98 -0
  22. package/backend/agent-runtime-binding.cjs +179 -0
  23. package/backend/agent-session-history.cjs +1022 -0
  24. package/backend/agent-session-inventory.cjs +291 -0
  25. package/backend/async-cache.cjs +104 -0
  26. package/backend/atomic-json-store.cjs +67 -0
  27. package/backend/auth.cjs +261 -0
  28. package/backend/authoritative-inventory-cache.cjs +383 -0
  29. package/backend/business-health.cjs +68 -0
  30. package/backend/chat-runtime.cjs +50 -0
  31. package/backend/claude-settings.cjs +132 -0
  32. package/backend/cli-agents.cjs +435 -0
  33. package/backend/codex-context-window.cjs +196 -0
  34. package/backend/codex-models.cjs +228 -0
  35. package/backend/codex-session-archive.cjs +82 -0
  36. package/backend/codex-session-history.cjs +590 -0
  37. package/backend/{codex-terminal-profile.js → codex-terminal-profile.cjs} +149 -155
  38. package/backend/codex-transcript-sanitizer.cjs +130 -0
  39. package/backend/codex-transcript.cjs +2107 -0
  40. package/backend/command-runner-child.cjs +105 -0
  41. package/backend/config-manager.cjs +1263 -0
  42. package/backend/control-api.cjs +439 -0
  43. package/backend/data/LICENSE.cua +21 -0
  44. package/backend/executable-discovery.cjs +204 -0
  45. package/backend/farming-agent-bootstrap.cjs +81 -0
  46. package/backend/farming-agent-bootstrap.zh_cn.md +6 -2
  47. package/backend/{farming-app-cli.js → farming-app-cli.cjs} +441 -493
  48. package/backend/farming-cli.cjs +414 -0
  49. package/backend/farming-net-pass.cjs +319 -0
  50. package/backend/farming-net-registry.cjs +123 -0
  51. package/backend/farming-net-server.cjs +309 -0
  52. package/backend/farming-session-store.cjs +651 -0
  53. package/backend/git-worktree-info.cjs +181 -0
  54. package/backend/haiku-token.cjs +828 -0
  55. package/backend/index-html.cjs +96 -0
  56. package/backend/input-parts.cjs +68 -0
  57. package/backend/input-routing.cjs +40 -0
  58. package/backend/{local-session-engine.js → local-session-engine.cjs} +276 -282
  59. package/backend/main-agent-skills.cjs +309 -0
  60. package/backend/main-page-session.cjs +132 -0
  61. package/backend/native-pty-controller-generation.cjs +139 -0
  62. package/backend/{native-pty-host-client.js → native-pty-host-client.cjs} +338 -346
  63. package/backend/native-pty-host-identity.cjs +125 -0
  64. package/backend/native-pty-host-path.cjs +68 -0
  65. package/backend/{native-pty-host.js → native-pty-host.cjs} +480 -569
  66. package/backend/native-session-engine.cjs +296 -0
  67. package/backend/network.cjs +57 -0
  68. package/backend/npm-update-helper.cjs +399 -0
  69. package/backend/packaged-node-pty.cjs +120 -0
  70. package/backend/preview-session-manager.cjs +89 -0
  71. package/backend/provider-adapters.cjs +492 -0
  72. package/backend/provider-home-configuration.cjs +211 -0
  73. package/backend/provider-session-id.cjs +79 -0
  74. package/backend/provider-session-service.cjs +333 -0
  75. package/backend/qr-share-tickets.cjs +119 -0
  76. package/backend/resource-broadcast-protocol.cjs +50 -0
  77. package/backend/review-diff-router.cjs +202 -0
  78. package/backend/review-diff-service.cjs +1267 -0
  79. package/backend/review-session-router.cjs +93 -0
  80. package/backend/review-session-service.cjs +470 -0
  81. package/backend/review-session-store.cjs +161 -0
  82. package/backend/review-state-router.cjs +132 -0
  83. package/backend/review-state-store.cjs +299 -0
  84. package/backend/run-history-store.cjs +97 -0
  85. package/backend/runtime-dependency-manager.cjs +893 -0
  86. package/backend/runtime-executable-invocation.cjs +37 -0
  87. package/backend/runtime-observation.cjs +96 -0
  88. package/backend/server-process-identity.cjs +70 -0
  89. package/backend/server.cjs +3356 -0
  90. package/backend/session-engine-bridge.cjs +144 -0
  91. package/backend/session-engine-router.cjs +105 -0
  92. package/backend/session-engine.cjs +64 -0
  93. package/backend/session-stream-protocol.cjs +181 -0
  94. package/backend/shell-busy-integration.cjs +442 -0
  95. package/backend/slash-command-discovery.cjs +423 -0
  96. package/backend/storage-layout.cjs +263 -0
  97. package/backend/system-monitor.cjs +96 -0
  98. package/backend/terminal-attach-checkpoint.cjs +73 -0
  99. package/backend/terminal-exit-quiescence.cjs +57 -0
  100. package/backend/{terminal-reducer-flow-control.js → terminal-reducer-flow-control.cjs} +45 -22
  101. package/backend/terminal-runtime-cleanup.cjs +99 -0
  102. package/backend/{terminal-screen-state.js → terminal-screen-state.cjs} +100 -108
  103. package/backend/{terminal-screen-worker-pool.js → terminal-screen-worker-pool.cjs} +89 -79
  104. package/backend/{terminal-screen-worker-thread.js → terminal-screen-worker-thread.cjs} +64 -65
  105. package/backend/terminal-screen-worker.cjs +352 -0
  106. package/backend/terminal-state-serialization.cjs +147 -0
  107. package/backend/{terminal-status.js → terminal-status.cjs} +137 -187
  108. package/backend/theme-manager.cjs +185 -0
  109. package/backend/update-service.cjs +675 -0
  110. package/backend/usage-forecast.cjs +95 -0
  111. package/backend/{usage-history-client.js → usage-history-client.cjs} +144 -94
  112. package/backend/usage-history-smoke.cjs +85 -0
  113. package/backend/usage-history-worker.cjs +60 -0
  114. package/backend/{usage-monitor.js → usage-monitor.cjs} +363 -390
  115. package/backend/workspace-directory.cjs +239 -0
  116. package/backend/workspace-discovery.cjs +271 -0
  117. package/backend/{workspace-file-router.js → workspace-file-router.cjs} +213 -282
  118. package/backend/{workspace-file-service.js → workspace-file-service.cjs} +1139 -1318
  119. package/backend/workspace-root-registry.cjs +192 -0
  120. package/bin/farming +1 -1
  121. package/config/farming.deploy.env.example +1 -1
  122. package/config/farming.install.env.example +1 -1
  123. package/dist/acp/codex-acp-1.1.4.mjs +405 -8
  124. package/dist/assets/App-BCkdpWB6.css +1 -0
  125. package/dist/assets/App-CRjKpaGp.js +697 -0
  126. package/dist/assets/CodeSelect-Ci8sKZPU.js +1 -0
  127. package/dist/assets/CodeSelect-T2eNzrOc.css +1 -0
  128. package/dist/assets/{FileEditorMarkdownPreview-Cs9cLv8a.js → FileEditorMarkdownPreview-V06QHlAg.js} +55 -55
  129. package/dist/assets/FileEditorPane-BX-Wjg9U.js +2 -0
  130. package/dist/assets/IconGlyphs-YhV7tqd4.js +1 -0
  131. package/dist/assets/ProjectFilesSection-BDT2_r0o.js +12 -0
  132. package/dist/assets/ReviewPage-BqAs5sG1.js +3 -0
  133. package/dist/assets/code-dark-B7eM_9G9.css +1 -0
  134. package/dist/assets/{cssMode-Bdg5RpcJ.js → cssMode-ADdAlxTO.js} +1 -1
  135. package/dist/assets/{editor.api2-D74ufkbr.js → editor.api2-BFLAr0YF.js} +162 -162
  136. package/dist/assets/file-icons-BpeqWkIB.js +1 -0
  137. package/dist/assets/{freemarker2-DfMDJfnE.js → freemarker2-C90q5jrp.js} +1 -1
  138. package/dist/assets/{handlebars-BEdPtzMT.js → handlebars-BwUQcEDq.js} +1 -1
  139. package/dist/assets/{html-B1fPb1QD.js → html-1s3uPKfh.js} +1 -1
  140. package/dist/assets/{htmlMode-CY2ZjHxH.js → htmlMode-xtKD99de.js} +1 -1
  141. package/dist/assets/{index-CQNaZc3l.js → index-C8MchCem.js} +3 -3
  142. package/dist/assets/{javascript-BV2OsWA0.js → javascript-Ph7ijyny.js} +1 -1
  143. package/dist/assets/{jsonMode-zd07aeuX.js → jsonMode-D-jGAnFH.js} +1 -1
  144. package/dist/assets/linkComputer-CbGyI_qx.js +1 -0
  145. package/dist/assets/{liquid-BParI24X.js → liquid-0IamE_cI.js} +1 -1
  146. package/dist/assets/{lspLanguageFeatures-BzredkoV.js → lspLanguageFeatures-BxnQunWF.js} +1 -1
  147. package/dist/assets/main-CLKXa6hf.css +1 -0
  148. package/dist/assets/{mdx-vGzUJN98.js → mdx-DdNmfivn.js} +1 -1
  149. package/dist/assets/{monaco.contribution-BmaeBQEc.js → monaco.contribution-B43jsUs1.js} +2 -2
  150. package/dist/assets/{python-CUwdLgsI.js → python-IAt4X5TS.js} +1 -1
  151. package/dist/assets/{razor-BScebUxU.js → razor-DRkFYW0S.js} +1 -1
  152. package/dist/assets/review-C8-oPKXk.css +1 -0
  153. package/dist/assets/{tsMode-DzUAibXK.js → tsMode-_d_4U2gf.js} +1 -1
  154. package/dist/assets/{typescript-D9EOeM7N.js → typescript-C7zcMq9l.js} +1 -1
  155. package/dist/assets/{workers-DAiomYZM.js → workers-D0nOyJzf.js} +1 -1
  156. package/dist/assets/workspace-editor-model-DND_Y-Bj.js +1 -0
  157. package/dist/assets/workspace-editor-monaco-BPWhgcIB.js +4 -0
  158. package/dist/assets/workspace-editor-monaco-N641qPjX.js +1 -0
  159. package/dist/assets/workspace-view-state-k1bTlJ_Z.js +13 -0
  160. package/dist/assets/{xml-wWl1dhkQ.js → xml-BR-HvxT8.js} +1 -1
  161. package/dist/assets/{yaml-Dc2WDaOZ.js → yaml-YtFQwh4q.js} +1 -1
  162. package/dist/index.html +2 -1
  163. package/extensions/browser/backend/agent-browser-runtime.cjs +1040 -0
  164. package/extensions/browser/backend/agent-capability.cjs +85 -0
  165. package/extensions/browser/backend/browser-mcp-server.cjs +655 -0
  166. package/extensions/browser/backend/browser-resource-manager.cjs +1486 -0
  167. package/extensions/browser/backend/browser-resource-store.cjs +228 -0
  168. package/extensions/browser/backend/browser-router.cjs +203 -0
  169. package/extensions/browser/backend/executable-discovery.cjs +248 -0
  170. package/extensions/browser/backend/farming-browser-client.cjs +116 -0
  171. package/extensions/browser/backend/index.cjs +32 -0
  172. package/extensions/browser/backend/managed-chromium-installer.cjs +833 -0
  173. package/extensions/browser/bin/farming-browser +16 -7
  174. package/extensions/computer/backend/agent-capability.cjs +72 -0
  175. package/extensions/computer/backend/computer-constants.cjs +59 -0
  176. package/extensions/computer/backend/computer-mcp-server.cjs +182 -0
  177. package/extensions/computer/backend/computer-resource-manager.cjs +1219 -0
  178. package/extensions/computer/backend/computer-resource-store.cjs +190 -0
  179. package/extensions/computer/backend/computer-router.cjs +257 -0
  180. package/extensions/computer/backend/cua-tools.json +3067 -0
  181. package/extensions/computer/backend/farming-computer-client.cjs +84 -0
  182. package/extensions/computer/backend/index.cjs +35 -0
  183. package/extensions/computer/backend/isolated-browser-provider.cjs +157 -0
  184. package/extensions/computer/bin/farming-computer +131 -0
  185. package/frontend/farming-net/app.js +255 -262
  186. package/frontend/ghostty-loader.js +24 -20
  187. package/frontend/reading-anchor.js +210 -193
  188. package/frontend/runtime-paths.js +24 -26
  189. package/frontend/session-bridge.js +90 -111
  190. package/frontend/session-modal-bridge.js +184 -302
  191. package/frontend/skin-bridge.js +20 -23
  192. package/frontend/skins/crt/app.js +7686 -7901
  193. package/frontend/skins/crt/effects.js +7 -6
  194. package/frontend/skins/crt/index.html +6 -6
  195. package/frontend/skins/crt/styles/markdown.css +4 -4
  196. package/frontend/terminal-bridge.js +174 -181
  197. package/frontend/terminal-replay.js +320 -345
  198. package/frontend/theme-loader.js +55 -71
  199. package/index.html +1 -0
  200. package/package.json +64 -37
  201. package/shared/backend-connection-status.js +38 -69
  202. package/shared/browser-protocol.js +235 -110
  203. package/shared/websocket-liveness.js +40 -0
  204. package/backend/acp/packaged-claude-acp.js +0 -13
  205. package/backend/acp/packaged-codex-acp.js +0 -13
  206. package/backend/acp/patch-decisions.js +0 -153
  207. package/backend/acp/permission-security.js +0 -108
  208. package/backend/acp-session-state.js +0 -644
  209. package/backend/acp-transcript.js +0 -512
  210. package/backend/agent-env.js +0 -250
  211. package/backend/agent-json-stream.js +0 -268
  212. package/backend/agent-lifecycle-journal.js +0 -133
  213. package/backend/agent-memory-report.js +0 -583
  214. package/backend/agent-order.js +0 -166
  215. package/backend/agent-provider-session.js +0 -76
  216. package/backend/agent-runtime-binding.js +0 -174
  217. package/backend/agent-session-history.js +0 -953
  218. package/backend/async-cache.js +0 -94
  219. package/backend/atomic-json-store.js +0 -37
  220. package/backend/auth.js +0 -251
  221. package/backend/bundle-update-helper.js +0 -113
  222. package/backend/chat-runtime.js +0 -28
  223. package/backend/claude-settings.js +0 -121
  224. package/backend/cli-agents.js +0 -486
  225. package/backend/codex-context-window.js +0 -189
  226. package/backend/codex-models.js +0 -226
  227. package/backend/codex-rollout-follower.js +0 -326
  228. package/backend/codex-session-archive.js +0 -65
  229. package/backend/codex-session-history.js +0 -647
  230. package/backend/codex-transcript-sanitizer.js +0 -115
  231. package/backend/codex-transcript.js +0 -2564
  232. package/backend/command-runner-child.js +0 -67
  233. package/backend/config-manager.js +0 -1133
  234. package/backend/control-api.js +0 -455
  235. package/backend/executable-discovery.js +0 -216
  236. package/backend/farming-agent-bootstrap.js +0 -49
  237. package/backend/farming-cli.js +0 -457
  238. package/backend/farming-net-pass.js +0 -285
  239. package/backend/farming-net-registry.js +0 -112
  240. package/backend/farming-net-server.js +0 -298
  241. package/backend/farming-session-store.js +0 -677
  242. package/backend/git-worktree-info.js +0 -181
  243. package/backend/haiku-token.js +0 -772
  244. package/backend/index-html.js +0 -62
  245. package/backend/input-parts.js +0 -54
  246. package/backend/input-routing.js +0 -24
  247. package/backend/json-cli-runtime.js +0 -275
  248. package/backend/main-agent-skills.js +0 -305
  249. package/backend/main-page-session.js +0 -122
  250. package/backend/native-pty-controller-generation.js +0 -106
  251. package/backend/native-pty-host-identity.js +0 -86
  252. package/backend/native-pty-host-path.js +0 -42
  253. package/backend/native-session-engine.js +0 -268
  254. package/backend/network.js +0 -23
  255. package/backend/npm-update-helper.js +0 -374
  256. package/backend/packaged-node-pty.js +0 -99
  257. package/backend/preview-session-manager.js +0 -68
  258. package/backend/provider-adapters.js +0 -399
  259. package/backend/provider-session-id.js +0 -47
  260. package/backend/provider-session-service.js +0 -345
  261. package/backend/qr-share-tickets.js +0 -100
  262. package/backend/review-diff-router.js +0 -180
  263. package/backend/review-diff-service.js +0 -1270
  264. package/backend/review-session-router.js +0 -74
  265. package/backend/review-session-service.js +0 -446
  266. package/backend/review-session-store.js +0 -151
  267. package/backend/review-state-router.js +0 -116
  268. package/backend/review-state-store.js +0 -286
  269. package/backend/run-history-store.js +0 -67
  270. package/backend/runtime-dependency-manager.js +0 -759
  271. package/backend/runtime-executable-invocation.js +0 -20
  272. package/backend/runtime-observation.js +0 -81
  273. package/backend/server-process-identity.js +0 -47
  274. package/backend/server.js +0 -3267
  275. package/backend/session-engine-bridge.js +0 -129
  276. package/backend/session-engine-router.js +0 -66
  277. package/backend/session-engine.js +0 -39
  278. package/backend/session-stream-protocol.js +0 -185
  279. package/backend/shell-busy-integration.js +0 -472
  280. package/backend/slash-command-discovery.js +0 -433
  281. package/backend/storage-layout.js +0 -190
  282. package/backend/system-monitor.js +0 -77
  283. package/backend/terminal-attach-checkpoint.js +0 -74
  284. package/backend/terminal-exit-quiescence.js +0 -39
  285. package/backend/terminal-runtime-cleanup.js +0 -80
  286. package/backend/terminal-screen-worker.js +0 -337
  287. package/backend/terminal-state-serialization.js +0 -127
  288. package/backend/theme-manager.js +0 -163
  289. package/backend/update-service.js +0 -1545
  290. package/backend/usage-forecast.js +0 -86
  291. package/backend/usage-history-scanner.ts +0 -2718
  292. package/backend/usage-history-smoke.js +0 -64
  293. package/backend/usage-history-worker.js +0 -34
  294. package/backend/workspace-directory.js +0 -232
  295. package/backend/workspace-discovery.js +0 -311
  296. package/backend/workspace-root-registry.js +0 -166
  297. package/dist/assets/App-BKNUILuL.css +0 -1
  298. package/dist/assets/App-Ex2oVVXO.js +0 -693
  299. package/dist/assets/FileEditorPane-CNtuGjQ3.js +0 -2
  300. package/dist/assets/IconGlyphs-BClgag6E.js +0 -1
  301. package/dist/assets/ProjectFilesSection-Cf2BEcAN.js +0 -12
  302. package/dist/assets/ReviewPage-BRuxFaH5.js +0 -3
  303. package/dist/assets/code-dark-BEZTQwYZ.css +0 -1
  304. package/dist/assets/file-icons-BOlcJ0ZF.js +0 -1
  305. package/dist/assets/main-DK9Sy7-c.css +0 -1
  306. package/dist/assets/review-BcnwQtJv.css +0 -1
  307. package/dist/assets/workspace-editor-model-CSGCl21x.js +0 -1
  308. package/dist/assets/workspace-editor-monaco-CJNwbpCy.js +0 -4
  309. package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +0 -1
  310. package/dist/assets/workspace-view-state-BjKPYp0E.js +0 -7
  311. package/extensions/browser/backend/agent-browser-runtime.js +0 -1041
  312. package/extensions/browser/backend/agent-capability.js +0 -55
  313. package/extensions/browser/backend/browser-mcp-server.js +0 -621
  314. package/extensions/browser/backend/browser-resource-manager.js +0 -1309
  315. package/extensions/browser/backend/browser-resource-store.js +0 -190
  316. package/extensions/browser/backend/browser-router.js +0 -133
  317. package/extensions/browser/backend/executable-discovery.js +0 -224
  318. package/extensions/browser/backend/farming-browser-client.js +0 -83
  319. package/extensions/browser/backend/index.js +0 -7
  320. package/extensions/browser/frontend/BrowserSidebarPortals.tsx +0 -360
  321. package/extensions/browser/frontend/BrowserViewer.tsx +0 -500
  322. package/extensions/browser/frontend/browser-resource-state.ts +0 -60
  323. package/extensions/browser/frontend/browser.css +0 -567
  324. package/extensions/browser/frontend/types.ts +0 -31
  325. package/extensions/browser/frontend/useBrowserResources.ts +0 -158
  326. package/frontend/vendor/ghostty-web/index.d.ts +0 -1842
  327. package/shared/backend-connection-status.d.ts +0 -37
  328. package/shared/browser-protocol.d.ts +0 -5
  329. /package/dist/assets/{api-w2x5QfxB.js → api-ByCV9MEr.js} +0 -0
  330. /package/dist/assets/{core-vPkV8P_m.js → core-Czwdx12k.js} +0 -0
  331. /package/dist/assets/{fsharp-DNZNZyEE.js → fsharp-BjPpkoJe.js} +0 -0
  332. /package/dist/assets/{go-_kPJjNc_.js → go-BkIDmSUP.js} +0 -0
  333. /package/dist/assets/{graphql-4HCNVt5g.js → graphql-CCJTpqi1.js} +0 -0
  334. /package/dist/assets/{hcl-C87ymY0o.js → hcl-s4z8lUFg.js} +0 -0
  335. /package/dist/assets/{ini-BYrrGNTc.js → ini-CyUW1I7Z.js} +0 -0
  336. /package/dist/assets/{java-B211rJbk.js → java-CFCcGRiM.js} +0 -0
  337. /package/dist/assets/{julia-DVPsRtBm.js → julia-DQyH_EYb.js} +0 -0
  338. /package/dist/assets/{kotlin-BYyNerjp.js → kotlin-B8hA5O51.js} +0 -0
  339. /package/dist/assets/{less-EC9UblGE.js → less-DaVdaas0.js} +0 -0
  340. /package/dist/assets/{lexon-B1yuUdqW.js → lexon-DLBhPd3y.js} +0 -0
  341. /package/dist/assets/{lua-Bo6GFzxT.js → lua-gB1c_cif.js} +0 -0
  342. /package/dist/assets/{m3-C-Y9cBVI.js → m3-C2T3z3gB.js} +0 -0
  343. /package/dist/assets/{markdown-BHu-wLbe.js → markdown-CKq-Euj1.js} +0 -0
  344. /package/dist/assets/{mips-Dkds26rX.js → mips-Bcs5qIDX.js} +0 -0
  345. /package/dist/assets/{msdax-PU4g-8_g.js → msdax-CBP48FHF.js} +0 -0
  346. /package/dist/assets/{mysql-fPpuGpS7.js → mysql-c7tiPcFj.js} +0 -0
  347. /package/dist/assets/{objective-c-Wy1e5JUf.js → objective-c-D4BZkeEV.js} +0 -0
  348. /package/dist/assets/{pascal-BIXwvrqU.js → pascal-CJDZg0MN.js} +0 -0
  349. /package/dist/assets/{pascaligo-DwR0AtL_.js → pascaligo-Bygi8Ynl.js} +0 -0
  350. /package/dist/assets/{perl-CGHAl8my.js → perl-aS8bkf7E.js} +0 -0
  351. /package/dist/assets/{pgsql-B91M73E2.js → pgsql-CzNAYFYl.js} +0 -0
  352. /package/dist/assets/{php-C70ttrCx.js → php-DOtoEFTT.js} +0 -0
  353. /package/dist/assets/{pla-BNrXaRh0.js → pla-DugRnao1.js} +0 -0
  354. /package/dist/assets/{postiats-Dv2IAZR9.js → postiats-DsXwusKh.js} +0 -0
  355. /package/dist/assets/{powerquery-CkY5Wq7J.js → powerquery-DL3o72oD.js} +0 -0
  356. /package/dist/assets/{powershell-uGIYLU3C.js → powershell-C1qHekys.js} +0 -0
  357. /package/dist/assets/{protobuf-CavfmJu-.js → protobuf-DHgsc-cH.js} +0 -0
  358. /package/dist/assets/{pug-Drqnyitx.js → pug-FZXlE_Iu.js} +0 -0
  359. /package/dist/assets/{qrcode-7uGsTEmi.js → qrcode-DJDTdjL7.js} +0 -0
  360. /package/dist/assets/{qsharp-C7yF-Dti.js → qsharp-bLyhI3DT.js} +0 -0
  361. /package/dist/assets/{r-HXLGP0_-.js → r-DjFGXbAa.js} +0 -0
  362. /package/dist/assets/{redis-C4y6mf2p.js → redis-DSoZ_V6u.js} +0 -0
  363. /package/dist/assets/{redshift-DdQrFPrv.js → redshift-CzkdCsrg.js} +0 -0
  364. /package/dist/assets/{restructuredtext-CBrf2PNj.js → restructuredtext-B_XPrGCQ.js} +0 -0
  365. /package/dist/assets/{ruby-CVtMoX2B.js → ruby-Cry2RneJ.js} +0 -0
  366. /package/dist/assets/{rust-Ckq4sbMP.js → rust-CWzdbFq1.js} +0 -0
  367. /package/dist/assets/{sb-er66OpE3.js → sb-DmofU59h.js} +0 -0
  368. /package/dist/assets/{scala-BdWZz-hH.js → scala-BUC2l-vN.js} +0 -0
  369. /package/dist/assets/{scheme-kTV_s2kP.js → scheme-CNIB_72f.js} +0 -0
  370. /package/dist/assets/{scss-Bymy2VJQ.js → scss-DcL4-NbX.js} +0 -0
  371. /package/dist/assets/{shell-bwEP1LQ1.js → shell-CgAGvSSA.js} +0 -0
  372. /package/dist/assets/{solidity-DCddeBgL.js → solidity-DSkt6O_P.js} +0 -0
  373. /package/dist/assets/{sophia-BMN3AQig.js → sophia--5ytcjDN.js} +0 -0
  374. /package/dist/assets/{sparql-CSXOLjzi.js → sparql-C1Srr7cD.js} +0 -0
  375. /package/dist/assets/{sql-COg8ewmK.js → sql-2k_O5fj7.js} +0 -0
  376. /package/dist/assets/{st-CIaZtBS_.js → st-DCCCPqfz.js} +0 -0
  377. /package/dist/assets/{swift-DXiOhUHu.js → swift-Dd8mAfOt.js} +0 -0
  378. /package/dist/assets/{systemverilog-BTDE6Dr2.js → systemverilog-B0-aZYXu.js} +0 -0
  379. /package/dist/assets/{tcl-B0zy9NvV.js → tcl-CZAZwPVX.js} +0 -0
  380. /package/dist/assets/{twig-D594l4Z1.js → twig-D-Ag0tdS.js} +0 -0
  381. /package/dist/assets/{typespec-XKVjaPqo.js → typespec-B7kTFp0Z.js} +0 -0
  382. /package/dist/assets/{useWorkspaceMenuKeyboard-Bpy_s69Z.js → useWorkspaceMenuKeyboard-uYZpDxhU.js} +0 -0
  383. /package/dist/assets/{vb-B2wYoKRV.js → vb-20w1JPum.js} +0 -0
  384. /package/dist/assets/{wgsl-D0Yf2LbK.js → wgsl-CLJfqFt0.js} +0 -0
  385. /package/dist/assets/{workspace-working-copy-C3FSR3N6.js → workspace-working-copy-Cfz07cOd.js} +0 -0
@@ -1,455 +0,0 @@
1
- const express = require('express');
2
- const crypto = require('crypto');
3
- const { runtimeKind } = require('./agent-runtime-binding');
4
- const { terminalInputReady } = require('./terminal-status');
5
-
6
- const DEFAULT_INITIAL_INPUT_TIMEOUT_MS = 30000;
7
-
8
- function ensureTrailingNewline(value) {
9
- const text = String(value || '');
10
- return text.endsWith('\r') || text.endsWith('\n') ? text : `${text}\r`;
11
- }
12
-
13
- function findAgent(state, agentId) {
14
- return state.agents.find((agent) => agent.id === agentId) || null;
15
- }
16
-
17
- function normalizeTail(value, fallback = 4000) {
18
- const tail = Number(value);
19
- if (!Number.isFinite(tail)) return fallback;
20
- return Math.max(0, Math.min(100000, Math.floor(tail)));
21
- }
22
-
23
- function stableJsonValue(value) {
24
- if (Array.isArray(value)) return value.map(stableJsonValue);
25
- if (!value || typeof value !== 'object') return value;
26
- return Object.keys(value).sort().reduce((result, key) => {
27
- result[key] = stableJsonValue(value[key]);
28
- return result;
29
- }, {});
30
- }
31
-
32
- function requestSignature(value) {
33
- return crypto.createHash('sha256')
34
- .update(JSON.stringify(stableJsonValue(value)))
35
- .digest('hex');
36
- }
37
-
38
- function terminalReadinessOptions(agent) {
39
- return {
40
- command: agent.command,
41
- cwd: agent.terminalStatus?.cwd || agent.cwd,
42
- status: agent.status === 'running' ? 'running' : agent.status,
43
- title: agent.terminalStatus?.title || agent.sessionTitle || '',
44
- previewText: agent.previewText || '',
45
- terminalBusy: typeof agent.terminalBusy === 'boolean' ? agent.terminalBusy : null,
46
- shellLastEvent: agent.terminalStatus?.source === 'shell-status-marker' ? 'finish' : '',
47
- shellLastExitCode: agent.terminalStatus?.lastExitCode,
48
- shellCommand: agent.terminalStatus?.runningCommand || '',
49
- };
50
- }
51
-
52
- function waitForTerminalInputReadiness(agentManager, agentId, options = {}) {
53
- const expectedStartedAt = Number(options.expectedStartedAt);
54
- const initialRuntimeEpoch = typeof options.expectedRuntimeEpoch === 'string'
55
- ? options.expectedRuntimeEpoch
56
- : '';
57
- const timeoutMs = Number.isFinite(options.timeoutMs)
58
- ? Math.max(1, options.timeoutMs)
59
- : DEFAULT_INITIAL_INPUT_TIMEOUT_MS;
60
-
61
- return new Promise((resolve, reject) => {
62
- let settled = false;
63
- let expectedRuntimeEpoch = initialRuntimeEpoch;
64
- const removeUpdateListener = () => {
65
- if (typeof agentManager.off === 'function') agentManager.off('update', inspect);
66
- else if (typeof agentManager.removeListener === 'function') agentManager.removeListener('update', inspect);
67
- };
68
- const finish = (error, value) => {
69
- if (settled) return;
70
- settled = true;
71
- clearTimeout(timeout);
72
- removeUpdateListener();
73
- if (error) reject(error);
74
- else resolve(value);
75
- };
76
- const fail = (code, message) => {
77
- const error = new Error(message);
78
- error.code = code;
79
- finish(error);
80
- };
81
- const inspect = () => {
82
- const agent = findAgent(agentManager.getState(), agentId);
83
- if (!agent) {
84
- fail('agent-removed', 'Agent disappeared before its initial Terminal task was delivered');
85
- return;
86
- }
87
- if (Number(agent.startedAt) !== expectedStartedAt) {
88
- fail('runtime-replaced', 'Agent runtime was replaced before its initial Terminal task was delivered');
89
- return;
90
- }
91
- if (agent.terminalInputReceived === true) {
92
- fail('terminal-already-used', 'Terminal received user input before its initial task was delivered');
93
- return;
94
- }
95
- if (agent.status === 'dead' || agent.status === 'stopped') {
96
- fail('runtime-exited', 'Agent exited before its initial Terminal task was delivered');
97
- return;
98
- }
99
- const runtimeEpoch = typeof agent.runtimeEpoch === 'string' ? agent.runtimeEpoch : '';
100
- if (!runtimeEpoch) return;
101
- if (expectedRuntimeEpoch && runtimeEpoch !== expectedRuntimeEpoch) {
102
- fail('runtime-replaced', 'Agent runtime changed before its initial Terminal task was delivered');
103
- return;
104
- }
105
- expectedRuntimeEpoch = runtimeEpoch;
106
- if (agent.status !== 'running' || !terminalInputReady(terminalReadinessOptions(agent))) return;
107
- finish(null, {
108
- expectedStartedAt,
109
- expectedRuntimeEpoch,
110
- });
111
- };
112
- const timeout = setTimeout(() => {
113
- fail('initial-input-timeout', 'Terminal did not become ready for its initial task before the timeout');
114
- }, timeoutMs);
115
- timeout.unref?.();
116
- if (typeof agentManager.on === 'function') agentManager.on('update', inspect);
117
- Promise.resolve().then(inspect);
118
- });
119
- }
120
-
121
- function createControlRouter(agentManager, options = {}) {
122
- const router = express.Router();
123
- const createRequestAdmissions = new Map();
124
- const notifyUpdate = typeof options.notifyUpdate === 'function' ? options.notifyUpdate : () => {};
125
- const initialInputTimeoutMs = Number.isFinite(options.initialInputTimeoutMs)
126
- ? Math.max(1, options.initialInputTimeoutMs)
127
- : DEFAULT_INITIAL_INPUT_TIMEOUT_MS;
128
-
129
- async function runTerminalMutation(agentId, expectedRuntimeEpoch, operation) {
130
- const current = findAgent(agentManager.getState(), agentId);
131
- if (!current || current.runtimeEpoch !== expectedRuntimeEpoch) {
132
- return { status: 'rejected', reason: 'runtime-epoch-mismatch' };
133
- }
134
- return operation({ expectedRuntimeEpoch });
135
- }
136
-
137
- router.use(express.json({ limit: '1mb' }));
138
-
139
- router.get('/agents', (req, res) => {
140
- const state = agentManager.getState();
141
- const parent = typeof req.query.parent === 'string' ? req.query.parent : '';
142
- const agents = parent
143
- ? state.agents.filter((agent) => agent.parentAgentId === parent)
144
- : state.agents;
145
-
146
- res.json({
147
- mainAgentId: state.mainAgentId,
148
- agents,
149
- });
150
- });
151
-
152
- router.post('/agents', (req, res) => {
153
- const body = req.body || {};
154
- const command = typeof body.command === 'string' ? body.command.trim() : '';
155
- const workspace = typeof body.workspace === 'string' ? body.workspace : null;
156
- const task = typeof body.task === 'string' ? body.task.trim() : '';
157
- const initialInput = typeof body.initialInput === 'string' ? body.initialInput : task;
158
- const createRequestId = typeof body.requestId === 'string' && body.requestId.trim()
159
- ? body.requestId
160
- : req.get('Idempotency-Key') || '';
161
- const controlRequestSignature = requestSignature(body);
162
-
163
- if (!command) {
164
- res.status(400).json({ error: 'command is required' });
165
- return;
166
- }
167
-
168
- const pendingRequest = createRequestId
169
- ? createRequestAdmissions.get(createRequestId)
170
- : null;
171
- if (pendingRequest) {
172
- if (pendingRequest.signature !== controlRequestSignature) {
173
- res.status(409).json({
174
- error: `Create request ${createRequestId} is already in progress with different parameters`,
175
- });
176
- return;
177
- }
178
- void pendingRequest.promise.then(outcome => {
179
- res.status(outcome.status).json(outcome.body);
180
- });
181
- return;
182
- }
183
-
184
- agentManager.startAgent(command, workspace, (agentId, error, metadata = {}) => {
185
- if (error) {
186
- res.status(400).json({ error });
187
- return;
188
- }
189
-
190
- if (!agentId) {
191
- res.status(500).json({ error: 'failed to start agent' });
192
- return;
193
- }
194
-
195
- if (metadata.deduplicated === true) {
196
- const recorded = metadata.createResult?.controlApi;
197
- if (recorded && Number.isInteger(recorded.status) && recorded.body) {
198
- res.status(recorded.status).json(recorded.body);
199
- return;
200
- }
201
- const admitted = createRequestId
202
- ? createRequestAdmissions.get(createRequestId)
203
- : null;
204
- if (admitted) {
205
- void admitted.promise.then(outcome => {
206
- res.status(outcome.status).json(outcome.body);
207
- });
208
- return;
209
- }
210
- res.status(409).json({
211
- error: 'Create succeeded, but the initial-input outcome is unknown; input was not replayed',
212
- code: 'create-result-unknown',
213
- agentId,
214
- });
215
- return;
216
- }
217
-
218
- const deliveryPromise = (async () => {
219
- if (!initialInput) {
220
- notifyUpdate();
221
- return {
222
- status: 201,
223
- body: { agentId, initialInputDelivered: false },
224
- };
225
- }
226
-
227
- const started = findAgent(agentManager.getState(), agentId);
228
- if (!started) throw Object.assign(new Error('Agent disappeared before initial input delivery'), {
229
- code: 'agent-removed',
230
- });
231
- const structuredRuntime = runtimeKind(started) !== 'terminal';
232
- if (structuredRuntime) {
233
- await agentManager.sendComposerMessage(agentId, initialInput);
234
- notifyUpdate();
235
- return {
236
- status: 201,
237
- body: { agentId, initialInputDelivered: true, inputMode: 'structured' },
238
- };
239
- }
240
-
241
- const readiness = await waitForTerminalInputReadiness(agentManager, agentId, {
242
- expectedStartedAt: started.startedAt,
243
- expectedRuntimeEpoch: started.runtimeEpoch,
244
- timeoutMs: initialInputTimeoutMs,
245
- });
246
- const result = await runTerminalMutation(
247
- agentId,
248
- readiness.expectedRuntimeEpoch,
249
- async ({ expectedRuntimeEpoch }) => {
250
- const current = findAgent(agentManager.getState(), agentId);
251
- if (
252
- !current ||
253
- Number(current.startedAt) !== readiness.expectedStartedAt ||
254
- current.runtimeEpoch !== readiness.expectedRuntimeEpoch ||
255
- current.terminalInputReceived === true ||
256
- current.status !== 'running' ||
257
- !terminalInputReady(terminalReadinessOptions(current))
258
- ) {
259
- return { status: 'rejected', reason: 'startup-state-changed' };
260
- }
261
- return agentManager.sendInput(agentId, ensureTrailingNewline(initialInput), {
262
- expectedRuntimeEpoch,
263
- });
264
- },
265
- );
266
- if (!result || result.status === 'rejected' || result.status === 'input-rejected') {
267
- const reason = result?.reason || 'initial-input-rejected';
268
- throw Object.assign(new Error(`Initial Terminal task was not delivered: ${reason}`), { code: reason });
269
- }
270
- notifyUpdate();
271
- return {
272
- status: 201,
273
- body: { agentId, initialInputDelivered: true, inputMode: 'terminal' },
274
- };
275
- })().catch(deliveryError => {
276
- const status = deliveryError?.code === 'initial-input-timeout' ? 504 : 409;
277
- return {
278
- status,
279
- body: {
280
- error: deliveryError?.message || 'Initial input delivery failed',
281
- code: deliveryError?.code || 'initial-input-failed',
282
- agentId,
283
- initialInputDelivered: false,
284
- },
285
- };
286
- });
287
- const durableDeliveryPromise = deliveryPromise.then(outcome => {
288
- if (!createRequestId) return outcome;
289
- let persisted;
290
- try {
291
- persisted = agentManager.recordCreateRequestResult(
292
- agentId,
293
- createRequestId,
294
- { controlApi: outcome },
295
- );
296
- } catch (error) {
297
- persisted = { error: error?.message || 'Create result persistence failed' };
298
- }
299
- if (persisted?.error) {
300
- return {
301
- status: 409,
302
- body: {
303
- error: `${persisted.error}; Create outcome was not persisted and initial input was not replayed`,
304
- code: 'create-result-not-durable',
305
- agentId,
306
- initialInputDelivered: outcome.body?.initialInputDelivered === true,
307
- createResultDurable: false,
308
- },
309
- };
310
- }
311
- return outcome;
312
- });
313
- if (createRequestId) {
314
- const admission = {
315
- signature: controlRequestSignature,
316
- promise: durableDeliveryPromise,
317
- };
318
- createRequestAdmissions.set(createRequestId, admission);
319
- void durableDeliveryPromise.finally(() => {
320
- if (createRequestAdmissions.get(createRequestId) === admission) {
321
- createRequestAdmissions.delete(createRequestId);
322
- }
323
- }).catch(() => {});
324
- }
325
- void durableDeliveryPromise.then(outcome => {
326
- res.status(outcome.status).json(outcome.body);
327
- });
328
- }, {
329
- wantsMain: false,
330
- parentAgentId: typeof body.parentAgentId === 'string' ? body.parentAgentId : '',
331
- task,
332
- source: 'control-cli',
333
- createRequestId,
334
- createInitialInputSignature: requestSignature(initialInput),
335
- agentRuntimeMode: ['json', 'acp', 'chat'].includes(body.agentRuntimeMode) ? body.agentRuntimeMode : 'terminal',
336
- acpHistoryMode: body.acpHistoryMode === 'resume' ? 'resume' : 'load',
337
- providerSessionTitle: typeof body.providerSessionTitle === 'string' ? body.providerSessionTitle : '',
338
- ...(Array.isArray(body.additionalDirectories) ? { additionalDirectories: body.additionalDirectories } : {}),
339
- ...(Array.isArray(body.mcpServers) ? { mcpServers: body.mcpServers } : {}),
340
- dangerouslySkipPermissions: body.dangerouslySkipPermissions === true,
341
- });
342
- });
343
-
344
- router.post('/agents/:agentId/input', async (req, res) => {
345
- const agentId = req.params.agentId;
346
- const state = agentManager.getState();
347
- if (!findAgent(state, agentId)) {
348
- res.status(404).json({ error: 'agent not found' });
349
- return;
350
- }
351
-
352
- if (agentManager.agentSupportsTerminalInput?.(agentId) === false) {
353
- res.status(409).json({ error: 'raw input is only available for Terminal Agents' });
354
- return;
355
- }
356
- const expectedRuntimeEpoch = typeof findAgent(agentManager.getState(), agentId)?.runtimeEpoch === 'string'
357
- ? findAgent(agentManager.getState(), agentId).runtimeEpoch
358
- : '';
359
- if (!expectedRuntimeEpoch) {
360
- res.status(409).json({ error: 'terminal runtime is not ready' });
361
- return;
362
- }
363
- const input = typeof req.body.input === 'string' ? req.body.input : '';
364
- const result = await runTerminalMutation(agentId, expectedRuntimeEpoch, ({ expectedRuntimeEpoch: epoch }) => (
365
- agentManager.sendInput(agentId, input, { expectedRuntimeEpoch: epoch })
366
- ));
367
- if (!result || result.status === 'rejected' || result.status === 'input-rejected') {
368
- res.status(409).json({ error: result?.reason || 'terminal input rejected' });
369
- return;
370
- }
371
- res.json({ success: true });
372
- });
373
-
374
- router.post('/agents/:agentId/clear', async (req, res) => {
375
- const agentId = req.params.agentId;
376
- const state = agentManager.getState();
377
- if (!findAgent(state, agentId)) {
378
- res.status(404).json({ error: 'agent not found' });
379
- return;
380
- }
381
-
382
- if (agentManager.agentSupportsTerminalInput?.(agentId) === false) {
383
- res.status(409).json({ error: 'clear is only available for Terminal Agents' });
384
- return;
385
- }
386
- const expectedRuntimeEpoch = typeof findAgent(agentManager.getState(), agentId)?.runtimeEpoch === 'string'
387
- ? findAgent(agentManager.getState(), agentId).runtimeEpoch
388
- : '';
389
- if (!expectedRuntimeEpoch) {
390
- res.status(409).json({ error: 'terminal runtime is not ready' });
391
- return;
392
- }
393
- const result = await runTerminalMutation(agentId, expectedRuntimeEpoch, ({ expectedRuntimeEpoch: epoch }) => (
394
- agentManager.clearAgentSessionBuffer(agentId, { expectedRuntimeEpoch: epoch })
395
- ));
396
- if (!result || result.status === 'rejected' || result.cleared === false) {
397
- res.status(409).json({ error: result?.reason || result?.error || 'terminal clear rejected' });
398
- return;
399
- }
400
- notifyUpdate();
401
- res.json({ success: Boolean(result && result.cleared), ...result });
402
- });
403
-
404
- router.get('/agents/:agentId/output', async (req, res) => {
405
- const agentId = req.params.agentId;
406
- const state = agentManager.getState();
407
- if (!findAgent(state, agentId)) {
408
- res.status(404).json({ error: 'agent not found' });
409
- return;
410
- }
411
-
412
- const output = await agentManager.getAgentSessionText(agentId);
413
- const tail = normalizeTail(req.query.tail);
414
- const text = tail > 0 ? String(output || '').slice(-tail) : String(output || '');
415
-
416
- res.type('text/plain');
417
- res.send(text);
418
- });
419
-
420
- router.delete('/agents/:agentId', async (req, res) => {
421
- const agentId = req.params.agentId;
422
- const recordHistory = req.query?.recordHistory !== '0';
423
- let requested;
424
- try {
425
- requested = await agentManager.requestKillAgent(agentId, { recordHistory });
426
- } catch (error) {
427
- res.status(503).json({
428
- error: error?.message || 'Agent lifecycle recovery is unavailable',
429
- retryable: true,
430
- });
431
- return;
432
- }
433
- const result = requested.result;
434
- if (result?.error) {
435
- res.status(409).json({ error: result.error });
436
- return;
437
- }
438
- if (result?.accepted) {
439
- void requested.completion.finally(() => notifyUpdate()).catch(() => {});
440
- res.status(202).json(result);
441
- return;
442
- }
443
- notifyUpdate();
444
- res.json({ success: true, agentId, ...result });
445
- });
446
-
447
- return router;
448
- }
449
-
450
- module.exports = {
451
- DEFAULT_INITIAL_INPUT_TIMEOUT_MS,
452
- createControlRouter,
453
- ensureTrailingNewline,
454
- waitForTerminalInputReadiness,
455
- };
@@ -1,216 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const { execFileSync } = require('child_process');
4
- const { getUserLaunchAgents } = require('./cli-agents');
5
-
6
- const DEFAULT_CODEX_APP_BIN = '/Applications/Codex.app/Contents/Resources/codex';
7
- const DEFAULT_CHATGPT_APP_CODEX_BIN = '/Applications/ChatGPT.app/Contents/Resources/codex';
8
- const executableVersionCache = new Map();
9
-
10
- function getPathDirectories(pathEnv = process.env.PATH || '') {
11
- return String(pathEnv)
12
- .split(path.delimiter)
13
- .map((entry) => entry.trim())
14
- .filter(Boolean);
15
- }
16
-
17
- function isExecutable(filePath) {
18
- try {
19
- fs.accessSync(filePath, fs.constants.X_OK);
20
- return true;
21
- } catch {
22
- return false;
23
- }
24
- }
25
-
26
- function parseCliVersion(value) {
27
- const match = String(value || '').match(/(\d+\.\d+\.\d+)/);
28
- return match ? match[1] : '';
29
- }
30
-
31
- function compareCliVersions(left, right) {
32
- const leftParts = parseCliVersion(left).split('.').map(part => Number(part));
33
- const rightParts = parseCliVersion(right).split('.').map(part => Number(part));
34
- if (leftParts.length !== 3 || rightParts.length !== 3) return 0;
35
-
36
- for (let index = 0; index < 3; index += 1) {
37
- const delta = leftParts[index] - rightParts[index];
38
- if (delta !== 0) return delta;
39
- }
40
- return 0;
41
- }
42
-
43
- function readExecutableCliVersion(filePath, runner = execFileSync) {
44
- try {
45
- return parseCliVersion(runner(filePath, ['--version'], {
46
- encoding: 'utf8',
47
- stdio: ['ignore', 'pipe', 'pipe'],
48
- timeout: 2000,
49
- }));
50
- } catch {
51
- return '';
52
- }
53
- }
54
-
55
- function getExecutableVersionCacheKey(filePath) {
56
- try {
57
- const stats = fs.statSync(filePath);
58
- return `${filePath}:${stats.size}:${stats.mtimeMs}`;
59
- } catch {
60
- return `${filePath}:missing`;
61
- }
62
- }
63
-
64
- function readCachedExecutableCliVersion(filePath, readVersion, options = {}) {
65
- if (options.cacheVersions === false) {
66
- return readVersion(filePath);
67
- }
68
-
69
- const cacheToken = getExecutableVersionCacheKey(filePath);
70
- if (executableVersionCache.has(cacheToken)) {
71
- return executableVersionCache.get(cacheToken);
72
- }
73
-
74
- const version = readVersion(filePath);
75
- const prefix = `${filePath}:`;
76
- Array.from(executableVersionCache.keys())
77
- .filter(key => key.startsWith(prefix) && key !== cacheToken)
78
- .forEach(key => executableVersionCache.delete(key));
79
- executableVersionCache.set(cacheToken, version);
80
- return version;
81
- }
82
-
83
- function clearExecutableVersionCache() {
84
- executableVersionCache.clear();
85
- }
86
-
87
- function getPreferredExecutableCandidates(agentName, pathEnv = process.env.PATH || '') {
88
- const pathCandidates = getPathDirectories(pathEnv).map((dir) => path.join(dir, agentName));
89
- if (agentName === 'claude') {
90
- return [
91
- process.env.FARMING_CLAUDE_BIN || '',
92
- process.env.CLAUDE_CODE_EXECUTABLE || '',
93
- ...pathCandidates,
94
- ].filter(Boolean);
95
- }
96
- if (agentName !== 'codex') return pathCandidates;
97
-
98
- return [
99
- process.env.FARMING_CODEX_BIN || '',
100
- DEFAULT_CODEX_APP_BIN,
101
- DEFAULT_CHATGPT_APP_CODEX_BIN,
102
- ...pathCandidates,
103
- ].filter(Boolean);
104
- }
105
-
106
- function resolveAgentExecutable(agentName, pathEnv = process.env.PATH || '') {
107
- return getPreferredExecutableCandidates(agentName, pathEnv).find(isExecutable) || '';
108
- }
109
-
110
- function resolveCompatibleCodexExecutable(requiredVersion = '', pathEnv = process.env.PATH || '', options = {}) {
111
- const normalizedRequired = parseCliVersion(requiredVersion);
112
- const readVersion = typeof options.readVersion === 'function'
113
- ? options.readVersion
114
- : readExecutableCliVersion;
115
- const rawCandidates = Array.isArray(options.candidates)
116
- ? options.candidates
117
- : getPreferredExecutableCandidates('codex', pathEnv);
118
- const seen = new Set();
119
- const inspected = rawCandidates
120
- .filter(Boolean)
121
- .filter(candidate => {
122
- if (seen.has(candidate)) return false;
123
- seen.add(candidate);
124
- return true;
125
- })
126
- .filter(isExecutable)
127
- .map(candidate => ({
128
- path: candidate,
129
- version: readCachedExecutableCliVersion(candidate, readVersion, options),
130
- }));
131
-
132
- if (inspected.length === 0) {
133
- return {
134
- path: '',
135
- version: '',
136
- requiredVersion: normalizedRequired,
137
- compatible: false,
138
- error: 'Codex executable not found',
139
- };
140
- }
141
-
142
- if (!normalizedRequired) {
143
- const selected = inspected[0];
144
- return {
145
- path: selected.path,
146
- version: selected.version,
147
- requiredVersion: '',
148
- compatible: true,
149
- error: '',
150
- };
151
- }
152
-
153
- const compatibleKnown = inspected.find(candidate => (
154
- candidate.version && compareCliVersions(candidate.version, normalizedRequired) >= 0
155
- ));
156
- if (compatibleKnown) {
157
- return {
158
- path: compatibleKnown.path,
159
- version: compatibleKnown.version,
160
- requiredVersion: normalizedRequired,
161
- compatible: true,
162
- error: '',
163
- };
164
- }
165
-
166
- const unknownVersion = inspected.find(candidate => !candidate.version);
167
- if (unknownVersion) {
168
- return {
169
- path: unknownVersion.path,
170
- version: '',
171
- requiredVersion: normalizedRequired,
172
- compatible: true,
173
- error: '',
174
- };
175
- }
176
-
177
- const newestKnown = inspected
178
- .filter(candidate => candidate.version)
179
- .sort((left, right) => compareCliVersions(right.version, left.version))[0];
180
- const newestVersion = newestKnown ? newestKnown.version : '';
181
- return {
182
- path: newestKnown ? newestKnown.path : inspected[0].path,
183
- version: newestVersion,
184
- requiredVersion: normalizedRequired,
185
- compatible: false,
186
- error: newestVersion
187
- ? `Codex CLI ${newestVersion} is older than this session (${normalizedRequired}). Update Codex or set FARMING_CODEX_BIN to a newer Codex executable.`
188
- : `Codex CLI version could not be verified for session ${normalizedRequired}. Update Codex or set FARMING_CODEX_BIN to a newer Codex executable.`,
189
- };
190
- }
191
-
192
- function listAvailableAgents(pathEnv = process.env.PATH || '') {
193
- return getUserLaunchAgents()
194
- .map((agent) => ({
195
- ...agent,
196
- resolvedPath: resolveAgentExecutable(agent.command || agent.name, pathEnv),
197
- }))
198
- .filter((agent) => Boolean(agent.resolvedPath))
199
- .map((agent) => ({
200
- ...agent,
201
- available: true
202
- }));
203
- }
204
-
205
- module.exports = {
206
- getPathDirectories,
207
- getPreferredExecutableCandidates,
208
- compareCliVersions,
209
- clearExecutableVersionCache,
210
- isExecutable,
211
- listAvailableAgents,
212
- parseCliVersion,
213
- readExecutableCliVersion,
214
- resolveAgentExecutable,
215
- resolveCompatibleCodexExecutable
216
- };