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
@@ -1,986 +0,0 @@
1
- const fs = require('fs');
2
- const fsp = require('fs/promises');
3
- const os = require('os');
4
- const path = require('path');
5
- const readline = require('readline');
6
- const { execFile } = require('child_process');
7
- const {
8
- formatAutomationRRuleLabel,
9
- hasTemporaryWorkspaceReference,
10
- isTemporaryWorkspace,
11
- listCodexSessions,
12
- } = require('./codex-session-history');
13
- const { isSafeProviderSessionId } = require('./provider-session-id');
14
-
15
- const DEFAULT_LIMIT = 60;
16
- const DEFAULT_SCAN_LIMIT = 500;
17
- const MAX_AGENT_SESSION_HISTORY_LIMIT = 5000;
18
- const MAX_AGENT_SESSION_SCAN_LIMIT = 5000;
19
- const CLAUDE_HISTORY_TAIL_BYTES = 2 * 1024 * 1024;
20
- const QODER_HISTORY_TAIL_BYTES = 2 * 1024 * 1024;
21
- const MAX_RECENT_FILE_SCAN_DIRECTORIES = 2000;
22
- const PROVIDERS = new Set(['codex', 'claude', 'opencode', 'qoder']);
23
-
24
- function quoteCommandArg(value) {
25
- return `'${String(value).replace(/'/g, `'\\''`)}'`;
26
- }
27
-
28
- function tomlStringAssignment(line, key) {
29
- const match = String(line || '').match(new RegExp(`^\\s*${key}\\s*=\\s*("(?:[^"\\\\]|\\\\.)*"|'[^']*')\\s*(?:#.*)?$`));
30
- if (!match) return '';
31
- const literal = match[1];
32
- if (literal.startsWith('"')) {
33
- try {
34
- return JSON.parse(literal).trim();
35
- } catch {
36
- return '';
37
- }
38
- }
39
- return literal.slice(1, -1).trim();
40
- }
41
-
42
- function codexProfileNameForSection(section) {
43
- const match = String(section || '').trim().match(/^profiles\.(?:"([^"]+)"|'([^']+)'|([A-Za-z0-9_-]+))$/);
44
- return match ? (match[1] || match[2] || match[3] || '') : '';
45
- }
46
-
47
- function resolveCodexResumeModelProvider(codexHome) {
48
- const home = normalizePathValue(codexHome)
49
- || normalizePathValue(process.env.CODEX_HOME)
50
- || path.join(os.homedir(), '.codex');
51
- let config = '';
52
- try {
53
- config = fs.readFileSync(path.join(home, 'config.toml'), 'utf8');
54
- } catch {
55
- return 'openai';
56
- }
57
-
58
- let section = '';
59
- let activeProfile = '';
60
- let topLevelProvider = '';
61
- const profileProviders = new Map();
62
- for (const line of config.split(/\r?\n/)) {
63
- const sectionMatch = line.match(/^\s*\[([^\]]+)]\s*(?:#.*)?$/);
64
- if (sectionMatch) {
65
- section = sectionMatch[1].trim();
66
- continue;
67
- }
68
- if (!section) {
69
- activeProfile = tomlStringAssignment(line, 'profile') || activeProfile;
70
- topLevelProvider = tomlStringAssignment(line, 'model_provider') || topLevelProvider;
71
- continue;
72
- }
73
- const profileName = codexProfileNameForSection(section);
74
- if (profileName) {
75
- const provider = tomlStringAssignment(line, 'model_provider');
76
- if (provider) profileProviders.set(profileName, provider);
77
- }
78
- }
79
-
80
- return (activeProfile && profileProviders.get(activeProfile)) || topLevelProvider || 'openai';
81
- }
82
-
83
- function normalizePathValue(value) {
84
- if (typeof value !== 'string') return '';
85
- const trimmed = value.trim();
86
- if (!trimmed || trimmed === path.sep) return trimmed;
87
- return trimmed.replace(/[\\/]+$/, '');
88
- }
89
-
90
- function timestampMs(value) {
91
- const parsed = Date.parse(value || '');
92
- return Number.isFinite(parsed) ? parsed : 0;
93
- }
94
-
95
- function agentSessionIdentity(session) {
96
- return [
97
- String(session?.provider || ''),
98
- String(session?.providerHomeId || 'default'),
99
- String(session?.id || ''),
100
- ].join('\u0000');
101
- }
102
-
103
- function compareAgentSessions(a, b) {
104
- const timeDelta = timestampMs(b?.updatedAt || b?.createdAt) - timestampMs(a?.updatedAt || a?.createdAt);
105
- return timeDelta || agentSessionIdentity(a).localeCompare(agentSessionIdentity(b));
106
- }
107
-
108
- function dedupeAgentSessions(sessions) {
109
- const sessionsByIdentity = new Map();
110
- for (const session of sessions) {
111
- const identity = agentSessionIdentity(session);
112
- const current = sessionsByIdentity.get(identity);
113
- if (!current || timestampMs(session?.updatedAt || session?.createdAt) > timestampMs(current?.updatedAt || current?.createdAt)) {
114
- sessionsByIdentity.set(identity, session);
115
- }
116
- }
117
- return Array.from(sessionsByIdentity.values());
118
- }
119
-
120
- function encodeAgentSessionCursor(session) {
121
- if (!session?.provider || !session?.id) return '';
122
- return Buffer.from(JSON.stringify({
123
- version: 1,
124
- provider: String(session.provider),
125
- providerHomeId: String(session.providerHomeId || 'default'),
126
- id: String(session.id),
127
- updatedAt: String(session.updatedAt || session.createdAt || ''),
128
- })).toString('base64url');
129
- }
130
-
131
- function decodeAgentSessionCursor(value) {
132
- try {
133
- const parsed = JSON.parse(Buffer.from(String(value || ''), 'base64url').toString('utf8'));
134
- if (parsed?.version !== 1 || !parsed.provider || !parsed.id) return null;
135
- return {
136
- provider: String(parsed.provider),
137
- providerHomeId: String(parsed.providerHomeId || 'default'),
138
- id: String(parsed.id),
139
- updatedAt: String(parsed.updatedAt || ''),
140
- };
141
- } catch {
142
- return null;
143
- }
144
- }
145
-
146
- function paginateAgentSessions(sessions, options = {}) {
147
- const limit = Number.isFinite(options.limit)
148
- ? Math.max(1, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit)))
149
- : DEFAULT_LIMIT;
150
- const cursorValue = String(options.cursor || '').trim();
151
- let start = 0;
152
- if (cursorValue) {
153
- const cursor = decodeAgentSessionCursor(cursorValue);
154
- if (!cursor) return { sessions: [], nextCursor: '', hasMore: false, invalidCursor: true };
155
- const exactIndex = sessions.findIndex(session => (
156
- agentSessionIdentity(session) === agentSessionIdentity(cursor)
157
- && String(session.updatedAt || session.createdAt || '') === cursor.updatedAt
158
- ));
159
- if (exactIndex >= 0) {
160
- start = exactIndex + 1;
161
- } else {
162
- const nextIndex = sessions.findIndex(session => compareAgentSessions(session, cursor) > 0);
163
- start = nextIndex >= 0 ? nextIndex : sessions.length;
164
- }
165
- }
166
- const page = sessions.slice(start, start + limit);
167
- const hasMore = start + page.length < sessions.length;
168
- return {
169
- sessions: page,
170
- nextCursor: hasMore && page.length > 0 ? encodeAgentSessionCursor(page[page.length - 1]) : '',
171
- hasMore,
172
- invalidCursor: false,
173
- };
174
- }
175
-
176
- function searchAgentSessions(sessions, query, options = {}) {
177
- const normalizedQuery = String(query || '').trim().toLowerCase();
178
- const limit = Number.isFinite(options.limit)
179
- ? Math.max(1, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit)))
180
- : DEFAULT_LIMIT;
181
- if (!normalizedQuery) {
182
- return { sessions: [], total: 0, query: '', scope: 'id-title-project' };
183
- }
184
-
185
- const projectNames = options.projectNames && typeof options.projectNames === 'object'
186
- ? options.projectNames
187
- : {};
188
- const matches = sessions.filter(session => {
189
- const projectPaths = [session?.workspace, session?.cwd];
190
- return [
191
- session?.id,
192
- session?.title,
193
- ...projectPaths,
194
- ...projectPaths.map(workspace => projectNames[String(workspace || '')]),
195
- ].some(value => String(value || '').toLowerCase().includes(normalizedQuery));
196
- });
197
-
198
- return {
199
- sessions: matches.slice(0, limit),
200
- total: matches.length,
201
- query: normalizedQuery,
202
- scope: 'id-title-project',
203
- };
204
- }
205
-
206
- function isAgentManagedWorktree(workspace) {
207
- const value = normalizePathValue(workspace);
208
- return value.includes(`${path.sep}.codex${path.sep}worktrees${path.sep}`)
209
- || value.includes(`${path.sep}.claude${path.sep}worktrees${path.sep}`);
210
- }
211
-
212
- function isDefaultClaudeSessionTitle(title) {
213
- return String(title || '').trim().toLowerCase() === 'claude session';
214
- }
215
-
216
- function firstTrimmedString(...values) {
217
- for (const value of values) {
218
- if (typeof value !== 'string') continue;
219
- const trimmed = value.trim();
220
- if (trimmed) return trimmed;
221
- }
222
- return '';
223
- }
224
-
225
- function extractClaudeModel(event) {
226
- return firstTrimmedString(
227
- event?.model,
228
- event?.message?.model,
229
- event?.metadata?.model,
230
- event?.message?.metadata?.model,
231
- event?.request?.model,
232
- event?.options?.model
233
- );
234
- }
235
-
236
- function extractClaudeEffort(event) {
237
- return firstTrimmedString(
238
- event?.effort,
239
- event?.message?.effort,
240
- event?.metadata?.effort,
241
- event?.message?.metadata?.effort,
242
- event?.request?.effort,
243
- event?.options?.effort
244
- );
245
- }
246
-
247
- function extractQoderModel(event) {
248
- return firstTrimmedString(
249
- event?.model,
250
- event?.message?.model,
251
- event?.metadata?.model,
252
- event?.message?.metadata?.model
253
- );
254
- }
255
-
256
- function extractQoderEffort(event) {
257
- return firstTrimmedString(
258
- event?.reasoningEffort,
259
- event?.reasoning_effort,
260
- event?.effort,
261
- event?.metadata?.reasoningEffort,
262
- event?.metadata?.reasoning_effort,
263
- event?.message?.metadata?.reasoningEffort,
264
- event?.message?.metadata?.reasoning_effort
265
- );
266
- }
267
-
268
- function isoTimestamp(value) {
269
- if (typeof value === 'string') {
270
- const parsed = Date.parse(value);
271
- return Number.isFinite(parsed) ? new Date(parsed).toISOString() : '';
272
- }
273
- if (typeof value === 'number' && Number.isFinite(value) && value > 0) {
274
- try {
275
- const date = new Date(value);
276
- return Number.isFinite(date.getTime()) ? date.toISOString() : '';
277
- } catch {
278
- return '';
279
- }
280
- }
281
- return '';
282
- }
283
-
284
- function qoderTextFromMessage(message) {
285
- if (typeof message === 'string') return message.trim();
286
- if (!message || typeof message !== 'object') return '';
287
- const content = message.content;
288
- if (typeof content === 'string') return content.trim();
289
- if (!Array.isArray(content)) return '';
290
- return content
291
- .map(part => {
292
- if (typeof part === 'string') return part;
293
- if (!part || typeof part !== 'object') return '';
294
- if (typeof part.text === 'string') return part.text;
295
- if (typeof part.content === 'string') return part.content;
296
- return '';
297
- })
298
- .join('\n')
299
- .trim();
300
- }
301
-
302
- function isVisibleAgentSession(session) {
303
- const provider = String(session?.provider || '').trim().toLowerCase();
304
- if (provider === 'claude') {
305
- if (isDefaultClaudeSessionTitle(session?.title)) return false;
306
- if (isAgentManagedWorktree(session?.cwd) || isAgentManagedWorktree(session?.workspace)) return false;
307
- }
308
-
309
- return !isTemporaryWorkspace(session?.cwd)
310
- && !isTemporaryWorkspace(session?.workspace)
311
- && !hasTemporaryWorkspaceReference(session?.title);
312
- }
313
-
314
- function activeScheduleFromMetadata(value, sessionId = '') {
315
- if (!value || typeof value !== 'object') return null;
316
- const rrule = typeof value.rrule === 'string' ? value.rrule.trim() : '';
317
- if (!rrule) return null;
318
-
319
- const targetThreadId = typeof value.target_thread_id === 'string'
320
- ? value.target_thread_id.trim()
321
- : typeof value.targetThreadId === 'string'
322
- ? value.targetThreadId.trim()
323
- : '';
324
- if (targetThreadId && sessionId && targetThreadId !== sessionId) return null;
325
-
326
- const rawStatus = typeof value.status === 'string' ? value.status.trim().toUpperCase() : '';
327
- const enabled = value.enabled !== false && value.active !== false;
328
- if (rawStatus && !['ACTIVE', 'ENABLED'].includes(rawStatus)) return null;
329
- if (!enabled) return null;
330
-
331
- return {
332
- id: typeof value.id === 'string' ? value.id.trim() : '',
333
- kind: typeof value.kind === 'string' ? value.kind.trim() : '',
334
- name: typeof value.name === 'string' ? value.name.trim() : '',
335
- status: rawStatus || 'ACTIVE',
336
- rrule,
337
- label: formatAutomationRRuleLabel(rrule),
338
- };
339
- }
340
-
341
- function scheduleFromClaudeEvent(event, sessionId) {
342
- const candidates = [
343
- event?.automation,
344
- event?.schedule,
345
- event?.metadata?.automation,
346
- event?.metadata?.schedule,
347
- event?.message?.metadata?.automation,
348
- event?.message?.metadata?.schedule,
349
- ];
350
-
351
- for (const candidate of candidates) {
352
- const schedule = activeScheduleFromMetadata(candidate, sessionId);
353
- if (schedule) return schedule;
354
- }
355
-
356
- return null;
357
- }
358
-
359
- async function collectRecentFiles(
360
- root,
361
- extension,
362
- limit,
363
- acceptFile = () => true,
364
- descendDirectory = () => true
365
- ) {
366
- const directories = [root];
367
- let files = [];
368
- let visitedDirectories = 0;
369
-
370
- while (directories.length > 0 && visitedDirectories < MAX_RECENT_FILE_SCAN_DIRECTORIES) {
371
- const directory = directories.pop();
372
- let entries = [];
373
- try {
374
- entries = await fsp.readdir(directory, { withFileTypes: true });
375
- } catch {
376
- continue;
377
- }
378
- visitedDirectories += 1;
379
- entries.sort((a, b) => {
380
- if (a.isDirectory() !== b.isDirectory()) return a.isDirectory() ? -1 : 1;
381
- return a.name.localeCompare(b.name);
382
- });
383
-
384
- for (const entry of entries) {
385
- const fullPath = path.join(directory, entry.name);
386
- if (entry.isDirectory()) {
387
- if (descendDirectory(fullPath)) directories.push(fullPath);
388
- } else if (entry.isFile() && entry.name.endsWith(extension) && acceptFile(fullPath)) {
389
- let mtimeMs = 0;
390
- try {
391
- mtimeMs = (await fsp.stat(fullPath)).mtimeMs;
392
- } catch {
393
- mtimeMs = 0;
394
- }
395
- files.push({ filePath: fullPath, mtimeMs });
396
- if (files.length > limit * 2) {
397
- files = files.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, limit);
398
- }
399
- }
400
- }
401
- }
402
-
403
- return files.sort((a, b) => b.mtimeMs - a.mtimeMs).slice(0, limit);
404
- }
405
-
406
- async function readTextTail(filePath, maxBytes) {
407
- let handle = null;
408
- try {
409
- const stat = await fsp.stat(filePath);
410
- const start = Math.max(0, stat.size - maxBytes);
411
- const length = stat.size - start;
412
- const buffer = Buffer.alloc(length);
413
- handle = await fsp.open(filePath, 'r');
414
- await handle.read(buffer, 0, length, start);
415
- const text = buffer.toString('utf8');
416
- return start > 0 ? text.replace(/^[^\n]*(\n|$)/, '') : text;
417
- } catch {
418
- return '';
419
- } finally {
420
- if (handle) {
421
- await handle.close().catch(() => {});
422
- }
423
- }
424
- }
425
-
426
- async function readClaudePromptHistory(claudeHome) {
427
- const historyPath = path.join(claudeHome, 'history.jsonl');
428
- const entries = new Map();
429
-
430
- const lines = (await readTextTail(historyPath, CLAUDE_HISTORY_TAIL_BYTES)).split('\n').filter(Boolean);
431
- for (const line of lines) {
432
- try {
433
- const entry = JSON.parse(line);
434
- if (!entry || typeof entry.sessionId !== 'string') continue;
435
- entries.set(entry.sessionId, {
436
- title: typeof entry.display === 'string' ? entry.display.trim() : '',
437
- workspace: typeof entry.project === 'string' ? normalizePathValue(entry.project) : '',
438
- updatedAt: typeof entry.timestamp === 'string' ? entry.timestamp : '',
439
- });
440
- } catch {
441
- // Ignore individual corrupt prompt history lines.
442
- }
443
- }
444
-
445
- return entries;
446
- }
447
-
448
- function claudeSessionIdFromFilePath(filePath) {
449
- const match = path.basename(filePath).match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
450
- return match ? match[1] : '';
451
- }
452
-
453
- async function readClaudeSessionMetadata(filePath, promptHistory, maxLines = 160) {
454
- const stream = fs.createReadStream(filePath, { encoding: 'utf8' });
455
- const reader = readline.createInterface({ input: stream, crlfDelay: Infinity });
456
- const fileSessionId = claudeSessionIdFromFilePath(filePath);
457
- const metadata = {
458
- filePath,
459
- id: fileSessionId,
460
- title: '',
461
- cwd: '',
462
- workspace: '',
463
- createdAt: '',
464
- updatedAt: '',
465
- model: '',
466
- effort: '',
467
- source: '',
468
- schedule: null,
469
- };
470
- let lineCount = 0;
471
-
472
- try {
473
- for await (const line of reader) {
474
- if (!line) continue;
475
- lineCount += 1;
476
-
477
- try {
478
- const event = JSON.parse(line);
479
- if (typeof event.sessionId === 'string') {
480
- metadata.id = event.sessionId;
481
- }
482
- if (typeof event.timestamp === 'string') {
483
- metadata.updatedAt = event.timestamp;
484
- metadata.createdAt = metadata.createdAt || event.timestamp;
485
- }
486
- if (typeof event.cwd === 'string' && event.cwd.trim()) {
487
- metadata.cwd = normalizePathValue(event.cwd);
488
- }
489
- if (typeof event.entrypoint === 'string' && event.entrypoint.trim()) {
490
- metadata.source = event.entrypoint.trim();
491
- }
492
- if (event.type === 'ai-title' && typeof event.aiTitle === 'string' && event.aiTitle.trim()) {
493
- metadata.title = event.aiTitle.trim();
494
- }
495
- metadata.model = extractClaudeModel(event) || metadata.model;
496
- metadata.effort = extractClaudeEffort(event) || metadata.effort;
497
- if (!metadata.schedule) {
498
- metadata.schedule = scheduleFromClaudeEvent(event, metadata.id || fileSessionId);
499
- }
500
- } catch {
501
- // Ignore individual corrupt session lines.
502
- }
503
-
504
- if (lineCount >= maxLines || (metadata.id && metadata.title && metadata.cwd && metadata.model)) {
505
- break;
506
- }
507
- }
508
- } finally {
509
- reader.close();
510
- stream.destroy();
511
- }
512
-
513
- if (!metadata.id) return null;
514
-
515
- const indexed = promptHistory.get(metadata.id);
516
- metadata.title = metadata.title || indexed?.title || 'Claude session';
517
- metadata.workspace = normalizePathValue(indexed?.workspace || metadata.cwd || '');
518
- metadata.updatedAt = metadata.updatedAt || indexed?.updatedAt || '';
519
- metadata.source = metadata.source || 'claude';
520
-
521
- return metadata;
522
- }
523
-
524
- async function listClaudeSessions(options = {}) {
525
- const claudeHome = options.claudeHome || path.join(os.homedir(), '.claude');
526
- const limit = Number.isFinite(options.limit)
527
- ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit)))
528
- : DEFAULT_LIMIT;
529
- const scanLimit = Number.isFinite(options.scanLimit)
530
- ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit)))
531
- : DEFAULT_SCAN_LIMIT;
532
- const promptHistory = await readClaudePromptHistory(claudeHome);
533
- const projectsRoot = path.join(claudeHome, 'projects');
534
- // Claude child-agent transcripts live below <project>/<session-id>/subagents
535
- // and inherit the parent session id. Only direct project session files are
536
- // resumable roots and should count as History entries.
537
- const sessionFiles = await collectRecentFiles(
538
- projectsRoot,
539
- '.jsonl',
540
- scanLimit,
541
- filePath => path.relative(projectsRoot, filePath).split(path.sep).length === 2,
542
- directoryPath => path.relative(projectsRoot, directoryPath).split(path.sep).length === 1
543
- );
544
-
545
- const sessions = [];
546
- for (const { filePath, mtimeMs } of sessionFiles) {
547
- const metadata = await readClaudeSessionMetadata(filePath, promptHistory);
548
- if (!metadata) continue;
549
- const mtimeIso = mtimeMs > 0 ? new Date(mtimeMs).toISOString() : '';
550
- const updatedAt = timestampMs(mtimeIso) > timestampMs(metadata.updatedAt)
551
- ? mtimeIso
552
- : (metadata.updatedAt || mtimeIso);
553
- const session = {
554
- provider: 'claude',
555
- providerName: 'Claude',
556
- id: metadata.id,
557
- title: metadata.title,
558
- cwd: metadata.cwd,
559
- workspace: metadata.workspace,
560
- updatedAt,
561
- createdAt: metadata.createdAt,
562
- archived: false,
563
- pinned: false,
564
- unread: false,
565
- projectless: !metadata.workspace,
566
- model: metadata.model,
567
- effort: metadata.effort,
568
- source: metadata.source,
569
- schedule: metadata.schedule || undefined,
570
- capabilities: ['resume', 'fork'],
571
- };
572
- if (isVisibleAgentSession(session)) {
573
- sessions.push(session);
574
- }
575
- }
576
-
577
- return dedupeAgentSessions(sessions)
578
- .sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt))
579
- .slice(0, limit);
580
- }
581
-
582
- function qoderSessionIdFromFilePath(filePath) {
583
- const match = path.basename(filePath).match(/^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i);
584
- return match ? match[1] : '';
585
- }
586
-
587
- function applyQoderSessionEvent(metadata, event, fileSessionId) {
588
- if (!event || typeof event !== 'object') return;
589
- const eventSessionId = typeof event.sessionId === 'string'
590
- ? event.sessionId
591
- : typeof event.session_id === 'string'
592
- ? event.session_id
593
- : '';
594
- if (eventSessionId && isSafeProviderSessionId(eventSessionId)) {
595
- metadata.id = eventSessionId;
596
- }
597
-
598
- const timestamp = isoTimestamp(event.timestamp);
599
- if (timestamp) {
600
- metadata.updatedAt = timestamp;
601
- metadata.createdAt = metadata.createdAt || timestamp;
602
- }
603
-
604
- if (typeof event.cwd === 'string' && event.cwd.trim()) {
605
- metadata.cwd = normalizePathValue(event.cwd);
606
- }
607
- if (typeof event.entrypoint === 'string' && event.entrypoint.trim()) {
608
- metadata.source = event.entrypoint.trim();
609
- }
610
- if (event.type === 'system' && typeof event.qodercli_version === 'string') {
611
- metadata.cliVersion = event.qodercli_version.trim();
612
- }
613
- if (typeof event.version === 'string' && event.version.trim()) {
614
- metadata.cliVersion = event.version.trim();
615
- }
616
- if (event.type === 'runtime-config' && typeof event.version === 'string') {
617
- metadata.cliVersion = event.version.trim();
618
- }
619
- if (event.type === 'ai-title' && typeof event.aiTitle === 'string' && event.aiTitle.trim()) {
620
- metadata.title = event.aiTitle.trim();
621
- }
622
- if (event.type === 'last-prompt' && typeof event.lastPrompt === 'string' && event.lastPrompt.trim()) {
623
- metadata.lastPrompt = event.lastPrompt.trim();
624
- }
625
- if (!metadata.firstPrompt && event.type === 'user') {
626
- metadata.firstPrompt = qoderTextFromMessage(event.message);
627
- }
628
-
629
- metadata.model = extractQoderModel(event) || metadata.model;
630
- metadata.effort = extractQoderEffort(event) || metadata.effort;
631
-
632
- if (!metadata.id && fileSessionId) {
633
- metadata.id = fileSessionId;
634
- }
635
- }
636
-
637
- async function readQoderSessionMetadata(filePath, maxLines = 160) {
638
- const fileSessionId = qoderSessionIdFromFilePath(filePath);
639
- const metadata = {
640
- filePath,
641
- id: fileSessionId,
642
- title: '',
643
- lastPrompt: '',
644
- firstPrompt: '',
645
- cwd: '',
646
- workspace: '',
647
- createdAt: '',
648
- updatedAt: '',
649
- model: '',
650
- effort: '',
651
- source: '',
652
- cliVersion: '',
653
- };
654
-
655
- const stream = fs.createReadStream(filePath, { encoding: 'utf8' });
656
- const reader = readline.createInterface({ input: stream, crlfDelay: Infinity });
657
- let lineCount = 0;
658
-
659
- try {
660
- for await (const line of reader) {
661
- if (!line) continue;
662
- lineCount += 1;
663
- try {
664
- applyQoderSessionEvent(metadata, JSON.parse(line), fileSessionId);
665
- } catch {
666
- // Ignore individual corrupt session lines.
667
- }
668
- if (lineCount >= maxLines || (metadata.id && metadata.cwd && metadata.model && metadata.title)) {
669
- break;
670
- }
671
- }
672
- } finally {
673
- reader.close();
674
- stream.destroy();
675
- }
676
-
677
- const tail = await readTextTail(filePath, QODER_HISTORY_TAIL_BYTES);
678
- for (const line of tail.split('\n').filter(Boolean)) {
679
- try {
680
- applyQoderSessionEvent(metadata, JSON.parse(line), fileSessionId);
681
- } catch {
682
- // Ignore individual corrupt session lines.
683
- }
684
- }
685
-
686
- if (!metadata.id || !isSafeProviderSessionId(metadata.id)) return null;
687
- metadata.title = firstTrimmedString(metadata.title, metadata.lastPrompt, metadata.firstPrompt, 'Qoder session');
688
- metadata.workspace = normalizePathValue(metadata.cwd || '');
689
- metadata.source = metadata.source || 'qodercli';
690
-
691
- return metadata;
692
- }
693
-
694
- async function listQoderSessions(options = {}) {
695
- const qoderHome = options.qoderHome || path.join(os.homedir(), '.qoder');
696
- const limit = Number.isFinite(options.limit)
697
- ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit)))
698
- : DEFAULT_LIMIT;
699
- const scanLimit = Number.isFinite(options.scanLimit)
700
- ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit)))
701
- : DEFAULT_SCAN_LIMIT;
702
- const projectsRoot = path.join(qoderHome, 'projects');
703
- // Child-agent transcripts live deeper under <project>/<session-id>/subagents
704
- // and may repeat the parent id, so only count direct project session files.
705
- const sessionFiles = await collectRecentFiles(
706
- projectsRoot,
707
- '.jsonl',
708
- scanLimit,
709
- filePath => path.relative(projectsRoot, filePath).split(path.sep).length === 2,
710
- directoryPath => path.relative(projectsRoot, directoryPath).split(path.sep).length === 1
711
- );
712
-
713
- const sessions = [];
714
- for (const { filePath, mtimeMs } of sessionFiles) {
715
- const metadata = await readQoderSessionMetadata(filePath);
716
- if (!metadata) continue;
717
- const mtimeIso = mtimeMs > 0 ? new Date(mtimeMs).toISOString() : '';
718
- const updatedAt = timestampMs(mtimeIso) > timestampMs(metadata.updatedAt)
719
- ? mtimeIso
720
- : (metadata.updatedAt || mtimeIso);
721
- const session = {
722
- provider: 'qoder',
723
- providerName: 'Qoder',
724
- id: metadata.id,
725
- title: metadata.title,
726
- cwd: metadata.cwd,
727
- workspace: metadata.workspace,
728
- updatedAt,
729
- createdAt: metadata.createdAt,
730
- archived: false,
731
- pinned: false,
732
- unread: false,
733
- projectless: !metadata.workspace,
734
- model: metadata.model,
735
- effort: metadata.effort,
736
- source: metadata.source,
737
- cliVersion: metadata.cliVersion,
738
- capabilities: ['resume', 'fork'],
739
- };
740
- if (isVisibleAgentSession(session)) {
741
- sessions.push(session);
742
- }
743
- }
744
-
745
- return dedupeAgentSessions(sessions)
746
- .sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt))
747
- .slice(0, limit);
748
- }
749
-
750
- function runOpenCodeSessionList(options = {}) {
751
- const executable = options.opencodeBin || process.env.FARMING_OPENCODE_BIN || 'opencode';
752
- const maxCount = Number.isFinite(options.maxCount) ? Math.max(1, Math.floor(options.maxCount)) : DEFAULT_SCAN_LIMIT;
753
- const env = { ...process.env };
754
- if (options.opencodeHome) env.OPENCODE_CONFIG_DIR = options.opencodeHome;
755
- return new Promise((resolve, reject) => {
756
- execFile(executable, ['session', 'list', '--format', 'json', '--max-count', String(maxCount)], {
757
- env,
758
- maxBuffer: 4 * 1024 * 1024,
759
- timeout: 15_000,
760
- }, (error, stdout) => {
761
- if (error) {
762
- reject(error);
763
- return;
764
- }
765
- resolve(stdout);
766
- });
767
- });
768
- }
769
-
770
- async function listOpenCodeSessions(options = {}) {
771
- const limit = Number.isFinite(options.limit)
772
- ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit)))
773
- : DEFAULT_LIMIT;
774
- const scanLimit = Number.isFinite(options.scanLimit)
775
- ? Math.max(limit, Math.min(MAX_AGENT_SESSION_SCAN_LIMIT, Math.floor(options.scanLimit)))
776
- : DEFAULT_SCAN_LIMIT;
777
- const listCommand = options.runOpenCodeSessionList || runOpenCodeSessionList;
778
- let rawSessions = [];
779
- try {
780
- const output = await listCommand({
781
- maxCount: scanLimit,
782
- opencodeBin: options.opencodeBin,
783
- opencodeHome: options.opencodeHome,
784
- });
785
- rawSessions = JSON.parse(String(output || '[]'));
786
- } catch {
787
- return [];
788
- }
789
- if (!Array.isArray(rawSessions)) return [];
790
-
791
- return dedupeAgentSessions(rawSessions
792
- .map(raw => {
793
- const id = firstTrimmedString(raw?.id);
794
- const cwd = normalizePathValue(raw?.directory || '');
795
- if (!id || !isSafeProviderSessionId(id)) return null;
796
- return {
797
- provider: 'opencode',
798
- providerName: 'OpenCode',
799
- id,
800
- title: firstTrimmedString(raw?.title, 'OpenCode session'),
801
- cwd,
802
- workspace: cwd,
803
- updatedAt: isoTimestamp(raw?.updated),
804
- createdAt: isoTimestamp(raw?.created),
805
- archived: false,
806
- pinned: false,
807
- unread: false,
808
- projectless: !cwd,
809
- source: 'opencode',
810
- capabilities: ['resume', 'fork'],
811
- };
812
- })
813
- .filter(session => session && isVisibleAgentSession(session)))
814
- .sort((a, b) => timestampMs(b.updatedAt) - timestampMs(a.updatedAt))
815
- .slice(0, limit);
816
- }
817
-
818
- function normalizeCodexSession(session) {
819
- return {
820
- provider: 'codex',
821
- providerName: 'Codex',
822
- ...session,
823
- capabilities: ['resume', 'fork'],
824
- };
825
- }
826
-
827
- function normalizeProvider(provider) {
828
- const normalized = String(provider || '').trim().toLowerCase();
829
- return PROVIDERS.has(normalized) ? normalized : '';
830
- }
831
-
832
- function isSafeSessionId(sessionId) {
833
- return isSafeProviderSessionId(sessionId);
834
- }
835
-
836
- function buildAgentSessionResumeCommand(provider, sessionId, options = {}) {
837
- const normalizedProvider = normalizeProvider(provider);
838
- const normalizedSessionId = String(sessionId || '').trim();
839
- if (!normalizedProvider || !isSafeSessionId(normalizedSessionId)) return '';
840
-
841
- if (normalizedProvider === 'codex') {
842
- const cwd = normalizePathValue(options.cwd);
843
- const modelProvider = String(
844
- options.modelProvider
845
- || (Object.prototype.hasOwnProperty.call(options, 'providerHomePath')
846
- ? resolveCodexResumeModelProvider(options.providerHomePath)
847
- : '')
848
- ).trim();
849
- const providerArgs = modelProvider
850
- ? ` -c ${quoteCommandArg(`model_provider=${JSON.stringify(modelProvider)}`)}`
851
- : '';
852
- const cwdArgs = cwd ? ` -C ${quoteCommandArg(cwd)}` : '';
853
- return `codex ${options.fork === true ? 'fork' : 'resume'}${providerArgs}${cwdArgs} ${normalizedSessionId}`;
854
- }
855
-
856
- if (normalizedProvider === 'claude') {
857
- return options.fork === true
858
- ? `claude --resume ${normalizedSessionId} --fork-session`
859
- : `claude --resume ${normalizedSessionId}`;
860
- }
861
-
862
- if (normalizedProvider === 'qoder') {
863
- return options.fork === true
864
- ? `qodercli --resume ${normalizedSessionId} --fork-session`
865
- : `qodercli --resume ${normalizedSessionId}`;
866
- }
867
-
868
- if (normalizedProvider === 'opencode') {
869
- return `opencode --session ${normalizedSessionId}${options.fork === true ? ' --fork' : ''}`;
870
- }
871
-
872
- return '';
873
- }
874
-
875
- async function listAgentSessions(options = {}) {
876
- const limit = Number.isFinite(options.limit)
877
- ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.limit)))
878
- : DEFAULT_LIMIT;
879
- const requestedProviders = Array.isArray(options.providers)
880
- ? options.providers.map(normalizeProvider).filter(Boolean)
881
- : ['codex', 'claude', 'opencode', 'qoder'];
882
- const providers = Array.from(new Set(requestedProviders));
883
- const sessions = [];
884
-
885
- const providerHomes = options.providerHomes && typeof options.providerHomes === 'object'
886
- ? options.providerHomes
887
- : {};
888
-
889
- async function listForHomes(provider, homes, fallbackHomeKey, listFn, homeOptionKey, normalize = session => session) {
890
- const configuredHomes = Array.isArray(homes) && homes.length > 0
891
- ? homes
892
- : [{ id: 'default', path: options[fallbackHomeKey] }];
893
- const perHomeLimit = Number.isFinite(options.providerLimit)
894
- ? Math.max(0, Math.min(MAX_AGENT_SESSION_HISTORY_LIMIT, Math.floor(options.providerLimit)))
895
- : limit;
896
- for (const home of configuredHomes) {
897
- const providerHomeId = String(home && home.id || 'default').trim() || 'default';
898
- const providerHomePath = String(home && home.path || '').trim();
899
- const listOptions = {
900
- limit: perHomeLimit,
901
- scanLimit: options.scanLimit,
902
- opencodeBin: options.opencodeBin,
903
- runOpenCodeSessionList: options.runOpenCodeSessionList,
904
- };
905
- if (providerHomePath) listOptions[homeOptionKey] = providerHomePath;
906
- const homeSessions = await listFn(listOptions);
907
- sessions.push(...homeSessions.map(session => normalize({
908
- ...session,
909
- providerHomeId,
910
- providerHomePath,
911
- })).filter(isVisibleAgentSession));
912
- }
913
- }
914
-
915
- if (providers.includes('codex')) {
916
- await listForHomes('codex', providerHomes.codex, 'codexHome', listCodexSessions, 'codexHome', normalizeCodexSession);
917
- }
918
-
919
- if (providers.includes('claude')) {
920
- await listForHomes('claude', providerHomes.claude, 'claudeHome', listClaudeSessions, 'claudeHome');
921
- }
922
-
923
- if (providers.includes('qoder')) {
924
- await listForHomes('qoder', providerHomes.qoder, 'qoderHome', listQoderSessions, 'qoderHome');
925
- }
926
-
927
- if (providers.includes('opencode')) {
928
- const configuredHomes = Array.isArray(providerHomes.opencode) && providerHomes.opencode.length > 0
929
- ? providerHomes.opencode
930
- : [{ id: 'default', path: options.opencodeHome }];
931
- const home = configuredHomes.find(candidate => String(candidate?.id || '') === 'default') || configuredHomes[0];
932
- const providerHomeId = String(home?.id || 'default').trim() || 'default';
933
- const providerHomePath = String(home?.path || '').trim();
934
- const homeSessions = await listOpenCodeSessions({
935
- limit: Number.isFinite(options.providerLimit) ? options.providerLimit : limit,
936
- scanLimit: options.scanLimit,
937
- opencodeBin: options.opencodeBin,
938
- opencodeHome: providerHomePath,
939
- runOpenCodeSessionList: options.runOpenCodeSessionList,
940
- });
941
- sessions.push(...homeSessions.map(session => ({
942
- ...session,
943
- providerHomeId,
944
- providerHomePath,
945
- })));
946
- }
947
-
948
- return dedupeAgentSessions(sessions)
949
- .sort(compareAgentSessions)
950
- .slice(0, limit);
951
- }
952
-
953
- async function findAgentSession(provider, sessionId, options = {}) {
954
- const normalizedProvider = normalizeProvider(provider);
955
- const normalizedSessionId = String(sessionId || '').trim();
956
- if (!normalizedProvider || !isSafeSessionId(normalizedSessionId)) return null;
957
-
958
- const sessions = await listAgentSessions({
959
- ...options,
960
- providers: [normalizedProvider],
961
- limit: options.limit || 200,
962
- providerLimit: options.providerLimit || 200,
963
- });
964
- const requestedHomeId = typeof options.providerHomeId === 'string' ? options.providerHomeId.trim() : '';
965
- return sessions.find(session => session.id === normalizedSessionId && (!requestedHomeId || (session.providerHomeId || 'default') === requestedHomeId)) || null;
966
- }
967
-
968
- module.exports = {
969
- buildAgentSessionResumeCommand,
970
- compareAgentSessions,
971
- findAgentSession,
972
- hasTemporaryWorkspaceReference,
973
- isAgentManagedWorktree,
974
- isDefaultClaudeSessionTitle,
975
- isSafeSessionId,
976
- isTemporaryWorkspace,
977
- isVisibleAgentSession,
978
- listAgentSessions,
979
- listClaudeSessions,
980
- listOpenCodeSessions,
981
- listQoderSessions,
982
- normalizeProvider,
983
- paginateAgentSessions,
984
- resolveCodexResumeModelProvider,
985
- searchAgentSessions,
986
- };