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,1117 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const os = require('os');
4
- const { atomicWriteJson } = require('./atomic-json-store');
5
- const { ensureMainAgentSkillFiles } = require('./main-agent-skills');
6
- const { ensureFarmingAgentBootstrapFile } = require('./farming-agent-bootstrap');
7
- const { normalizeClaudeModelValue } = require('./claude-settings');
8
- const { isTemporaryProviderSessionId } = require('./provider-session-id');
9
- const { FarmingSessionStore, MAX_MAIN_PAGE_SESSION_KEYS } = require('./farming-session-store');
10
- const { RunHistoryStore } = require('./run-history-store');
11
- const { isSupportedHistoryAgent } = require('./cli-agents');
12
- const storageLayout = require('./storage-layout');
13
-
14
- function splitCodexModelPreset(preset) {
15
- if (preset === 'config') {
16
- return { model: 'config', effort: 'config' };
17
- }
18
- if (typeof preset !== 'string') {
19
- return { model: 'gpt-5.5', effort: 'xhigh' };
20
- }
21
-
22
- const [model, effort] = preset.split(':');
23
- return {
24
- model: model || 'gpt-5.5',
25
- effort: effort || 'xhigh',
26
- };
27
- }
28
-
29
- function joinCodexModelPreset(model, effort) {
30
- if (model === 'config') return 'config';
31
- return effort ? `${model}:${effort}` : model;
32
- }
33
-
34
- const DEFAULT_CODEX_LAUNCH_PROFILE = {
35
- approvalMode: 'approve',
36
- model: 'gpt-5.5',
37
- reasoningEffort: 'xhigh',
38
- serviceTier: 'default',
39
- modelPreset: 'gpt-5.5:xhigh',
40
- };
41
-
42
- const DEFAULT_CLAUDE_LAUNCH_PROFILE = {
43
- permissionMode: 'default',
44
- model: 'config',
45
- effort: 'config',
46
- };
47
-
48
- const DEFAULT_AGENT_LAUNCH_PROFILES = {
49
- codex: DEFAULT_CODEX_LAUNCH_PROFILE,
50
- claude: DEFAULT_CLAUDE_LAUNCH_PROFILE,
51
- };
52
-
53
- const DEFAULT_LAUNCH_AGENT_NAMES = new Set(['codex', 'claude', 'opencode', 'qoder', 'bash', 'zsh']);
54
-
55
- const DEFAULT_AGENT_HOMES = {
56
- codex: [{ id: 'default', path: '~/.codex' }],
57
- claude: [{ id: 'default', path: '~/.claude' }],
58
- opencode: [{ id: 'default', path: '~/.opencode' }],
59
- qoder: [{ id: 'default', path: '~/.qoder' }],
60
- };
61
-
62
- const LEGACY_DEFAULT_WORKSPACE_FILE_SEARCH_TIMEOUT_MS = 3000;
63
- const DEFAULT_SEARCH_TIMEOUT_MS = 15000;
64
- const MIN_SEARCH_TIMEOUT_MS = 3000;
65
- const MAX_SEARCH_TIMEOUT_MS = 180000;
66
- const DEFAULT_CRT_TERMINAL_FONT_SIZE = 15;
67
- const MIN_CRT_TERMINAL_FONT_SIZE = 10;
68
- const MAX_CRT_TERMINAL_FONT_SIZE = 20;
69
- const MAX_INSTANCE_NAME_LENGTH = 80;
70
- const MAX_PROJECT_OPERATIONS = 32;
71
- const PROJECT_OPERATION_ID_PATTERN = /^[A-Za-z0-9._:-]{1,160}$/;
72
-
73
- const PERSISTED_SETTING_KEYS = new Set([
74
- 'workspace',
75
- 'lastMainWorkspace',
76
- 'workspaceHistory',
77
- 'projectWorkspaces',
78
- 'pinnedProjectWorkspaces',
79
- 'projectNames',
80
- 'projectOperations',
81
- 'instanceName',
82
- 'theme',
83
- 'appearance',
84
- 'language',
85
- 'restReminderIntervalSeconds',
86
- 'heartbeatInterval',
87
- 'dangerouslySkipAgentPermissionsByDefault',
88
- 'browserExtensionEnabled',
89
- 'browserSource',
90
- 'browserExecutablePath',
91
- 'browserExternalCdpUrl',
92
- 'crtSkinEffectsEnabled',
93
- 'crtDynamicHeatEnabled',
94
- 'crtTerminalFontSize',
95
- 'defaultLaunchAgent',
96
- 'agentLaunchProfiles',
97
- 'agentHomes',
98
- 'searchTimeoutMs',
99
- 'codexApprovalMode',
100
- 'codexModel',
101
- 'codexReasoningEffort',
102
- 'codexServiceTier',
103
- 'codexModelPreset',
104
- 'version',
105
- ]);
106
-
107
- function cloneLaunchProfile(profile) {
108
- return { ...profile };
109
- }
110
-
111
- function cloneAgentHomes(agentHomes) {
112
- const cloned = {};
113
- Object.entries(agentHomes || {}).forEach(([provider, homes]) => {
114
- cloned[provider] = Array.isArray(homes)
115
- ? homes.map(home => ({ ...home }))
116
- : [];
117
- });
118
- return cloned;
119
- }
120
-
121
- class ConfigManager {
122
- constructor(options = {}) {
123
- this.farmingDir = options.configDir || storageLayout.farmingConfigDir();
124
- this.settingsFile = storageLayout.settingsFile(this.farmingDir);
125
- this.sessionStore = new FarmingSessionStore(this.farmingDir, {
126
- normalizeMainPageSessionKeys: keys => this.normalizeMainPageSessionKeys(keys),
127
- });
128
- this.runHistoryStore = new RunHistoryStore(this.farmingDir, {
129
- normalizeTaskHistory: entries => this.normalizeTaskHistory(entries),
130
- });
131
- this.writeJson = typeof options.writeJson === 'function' ? options.writeJson : atomicWriteJson;
132
- this.settings = null;
133
- }
134
-
135
- expandWorkspacePath(workspace) {
136
- if (typeof workspace !== 'string') return '';
137
- const value = workspace.trim();
138
- if (!value) return '';
139
- if (value === '~') return os.homedir();
140
- if (value.startsWith('~/')) return path.join(os.homedir(), value.slice(2));
141
- return value;
142
- }
143
-
144
- isTemporaryWorkspace(workspace) {
145
- const resolved = path.resolve(this.expandWorkspacePath(workspace));
146
- return resolved === '/tmp'
147
- || resolved.startsWith('/tmp/')
148
- || resolved === '/private/tmp'
149
- || resolved.startsWith('/private/tmp/')
150
- || resolved === '/var/tmp'
151
- || resolved.startsWith('/var/tmp/')
152
- || resolved === '/private/var/tmp'
153
- || resolved.startsWith('/private/var/tmp/')
154
- || resolved === '/var/folders'
155
- || resolved.startsWith('/var/folders/')
156
- || resolved === '/private/var/folders'
157
- || resolved.startsWith('/private/var/folders/');
158
- }
159
-
160
- isUsableWorkspace(workspace) {
161
- const expanded = this.expandWorkspacePath(workspace);
162
- if (!expanded || this.isTemporaryWorkspace(expanded)) return false;
163
-
164
- try {
165
- return fs.statSync(expanded).isDirectory();
166
- } catch {
167
- return false;
168
- }
169
- }
170
-
171
- isInternalWorkspace(workspace) {
172
- const expanded = this.expandWorkspacePath(workspace);
173
- if (!expanded) return false;
174
-
175
- const resolvedWorkspace = path.resolve(expanded);
176
- const resolvedFarmingDir = path.resolve(this.farmingDir);
177
- return resolvedWorkspace === resolvedFarmingDir || path.basename(resolvedWorkspace) === '.farming';
178
- }
179
-
180
- normalizeMainWorkspace(workspace, fallback = this.farmingDir) {
181
- const expanded = this.expandWorkspacePath(workspace);
182
- if (this.isUsableWorkspace(expanded)) {
183
- return expanded;
184
- }
185
-
186
- const expandedFallback = this.expandWorkspacePath(fallback);
187
- if (this.isUsableWorkspace(expandedFallback)) {
188
- return expandedFallback;
189
- }
190
-
191
- return this.farmingDir;
192
- }
193
-
194
- normalizeInstanceName(value) {
195
- if (typeof value !== 'string') return '';
196
- return value
197
- .replace(/[\x00-\x1f\x7f]/g, ' ')
198
- .replace(/\s+/g, ' ')
199
- .trim()
200
- .slice(0, MAX_INSTANCE_NAME_LENGTH);
201
- }
202
-
203
- getInstanceName() {
204
- return this.settings?.instanceName || this.normalizeInstanceName(os.hostname()) || 'Farming';
205
- }
206
-
207
- normalizeWorkspaceHistory(history) {
208
- const entries = Array.isArray(history) ? history : [];
209
- const result = [];
210
- const seen = new Set();
211
-
212
- for (const entry of entries) {
213
- const expanded = this.expandWorkspacePath(entry);
214
- if (!this.isUsableWorkspace(expanded) || this.isInternalWorkspace(expanded) || seen.has(expanded)) continue;
215
- seen.add(expanded);
216
- result.push(expanded);
217
- }
218
-
219
- return result.slice(0, 5);
220
- }
221
-
222
- normalizeProjectWorkspaces(projects) {
223
- const entries = Array.isArray(projects) ? projects : [];
224
- const result = [];
225
- const seen = new Set();
226
-
227
- for (const entry of entries) {
228
- const expanded = this.expandWorkspacePath(entry);
229
- if (!expanded) continue;
230
- const resolved = path.resolve(expanded);
231
- if (this.isInternalWorkspace(resolved)) continue;
232
- let canonical = resolved;
233
- try {
234
- canonical = fs.realpathSync(resolved);
235
- } catch {
236
- // Project membership is durable. A temporarily unavailable path remains
237
- // until the user explicitly removes it.
238
- }
239
- if (this.isInternalWorkspace(canonical)) continue;
240
- if (seen.has(canonical)) continue;
241
- seen.add(canonical);
242
- result.push(canonical);
243
- }
244
-
245
- return result.slice(0, 200);
246
- }
247
-
248
- normalizeMainPageSessionKeys(keys) {
249
- const entries = Array.isArray(keys) ? keys : [];
250
- const result = [];
251
- const seen = new Set();
252
-
253
- for (const entry of entries) {
254
- if (typeof entry !== 'string') continue;
255
- const value = entry.trim();
256
- if (!/^agent-session:[a-z][a-z0-9_-]*:.+$/i.test(value)) continue;
257
- const sessionId = value.replace(/^agent-session:[^:]+:/i, '');
258
- if (sessionId.startsWith('-')) continue;
259
- if (isTemporaryProviderSessionId(sessionId)) continue;
260
- if (seen.has(value)) continue;
261
- seen.add(value);
262
- result.push(value);
263
- }
264
-
265
- return result.slice(0, MAX_MAIN_PAGE_SESSION_KEYS);
266
- }
267
-
268
- normalizeTaskHistory(history) {
269
- const entries = Array.isArray(history) ? history : [];
270
- const normalized = [];
271
- for (const entry of entries) {
272
- if (!entry || typeof entry !== 'object') continue;
273
- if (typeof entry.id !== 'string' || !entry.id) continue;
274
- if (typeof entry.agentId !== 'string' || !entry.agentId) continue;
275
- if (typeof entry.reason !== 'string' || !entry.reason) continue;
276
- if (typeof entry.archivedAt !== 'number' || !Number.isFinite(entry.archivedAt)) continue;
277
- if (!isSupportedHistoryAgent(entry.command)) continue;
278
- normalized.push({
279
- id: entry.id,
280
- agentId: entry.agentId,
281
- command: typeof entry.command === 'string' ? entry.command : '',
282
- cwd: typeof entry.cwd === 'string' ? entry.cwd : '',
283
- projectWorkspace: typeof entry.projectWorkspace === 'string' ? entry.projectWorkspace : '',
284
- title: typeof entry.title === 'string' ? entry.title : '',
285
- customTitle: typeof entry.customTitle === 'string' ? entry.customTitle.trim().slice(0, 80) : '',
286
- task: typeof entry.task === 'string' ? entry.task : '',
287
- workflowTemplate: typeof entry.workflowTemplate === 'string' ? entry.workflowTemplate : '',
288
- source: typeof entry.source === 'string' ? entry.source : 'ui',
289
- reason: entry.reason,
290
- status: typeof entry.status === 'string' ? entry.status : 'stopped',
291
- startedAt: typeof entry.startedAt === 'number' ? entry.startedAt : null,
292
- lastActivity: typeof entry.lastActivity === 'number' ? entry.lastActivity : null,
293
- archivedAt: entry.archivedAt,
294
- });
295
- }
296
- return normalized
297
- .sort((a, b) => b.archivedAt - a.archivedAt)
298
- .slice(0, 200);
299
- }
300
-
301
- init() {
302
- if (!fs.existsSync(this.farmingDir)) {
303
- fs.mkdirSync(this.farmingDir, { recursive: true });
304
- console.log('Created farming directory:', this.farmingDir);
305
- }
306
-
307
- if (!fs.existsSync(this.settingsFile)) {
308
- const defaultSettings = {
309
- workspace: this.farmingDir,
310
- lastMainWorkspace: this.farmingDir,
311
- workspaceHistory: [],
312
- projectWorkspaces: [],
313
- pinnedProjectWorkspaces: [],
314
- projectNames: {},
315
- projectOperations: {},
316
- instanceName: '',
317
- theme: 'terminal',
318
- appearance: 'system',
319
- language: 'en',
320
- restReminderIntervalSeconds: null,
321
- heartbeatInterval: 1000,
322
- dangerouslySkipAgentPermissionsByDefault: false,
323
- browserExtensionEnabled: false,
324
- browserSource: process.env.FARMING_BROWSER_CDP_URL ? 'external-cdp' : 'system',
325
- browserExecutablePath: process.env.FARMING_BROWSER_EXECUTABLE || '',
326
- browserExternalCdpUrl: process.env.FARMING_BROWSER_CDP_URL || 'http://127.0.0.1:9222',
327
- crtSkinEffectsEnabled: true,
328
- crtDynamicHeatEnabled: false,
329
- crtTerminalFontSize: DEFAULT_CRT_TERMINAL_FONT_SIZE,
330
- defaultLaunchAgent: 'codex',
331
- agentLaunchProfiles: {
332
- codex: cloneLaunchProfile(DEFAULT_CODEX_LAUNCH_PROFILE),
333
- claude: cloneLaunchProfile(DEFAULT_CLAUDE_LAUNCH_PROFILE),
334
- },
335
- agentHomes: cloneAgentHomes(DEFAULT_AGENT_HOMES),
336
- searchTimeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,
337
- codexApprovalMode: 'approve',
338
- codexModel: 'gpt-5.5',
339
- codexReasoningEffort: 'xhigh',
340
- codexServiceTier: 'default',
341
- codexModelPreset: 'gpt-5.5:xhigh',
342
- version: '2'
343
- };
344
- this.writeSettingsFile(defaultSettings);
345
- console.log('Created default settings:', this.settingsFile);
346
- }
347
-
348
- const rawSettings = JSON.parse(fs.readFileSync(this.settingsFile, 'utf8'));
349
- this.settings = {
350
- workspace: this.farmingDir,
351
- lastMainWorkspace: this.farmingDir,
352
- workspaceHistory: [],
353
- projectWorkspaces: [],
354
- pinnedProjectWorkspaces: [],
355
- projectNames: {},
356
- projectOperations: {},
357
- instanceName: '',
358
- theme: 'terminal',
359
- appearance: 'system',
360
- language: 'en',
361
- restReminderIntervalSeconds: null,
362
- heartbeatInterval: 1000,
363
- dangerouslySkipAgentPermissionsByDefault: false,
364
- browserExtensionEnabled: false,
365
- browserSource: process.env.FARMING_BROWSER_CDP_URL ? 'external-cdp' : 'system',
366
- browserExecutablePath: process.env.FARMING_BROWSER_EXECUTABLE || '',
367
- browserExternalCdpUrl: process.env.FARMING_BROWSER_CDP_URL || 'http://127.0.0.1:9222',
368
- crtSkinEffectsEnabled: true,
369
- crtDynamicHeatEnabled: false,
370
- crtTerminalFontSize: DEFAULT_CRT_TERMINAL_FONT_SIZE,
371
- defaultLaunchAgent: 'codex',
372
- agentLaunchProfiles: {
373
- codex: cloneLaunchProfile(DEFAULT_CODEX_LAUNCH_PROFILE),
374
- claude: cloneLaunchProfile(DEFAULT_CLAUDE_LAUNCH_PROFILE),
375
- },
376
- agentHomes: cloneAgentHomes(DEFAULT_AGENT_HOMES),
377
- searchTimeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,
378
- codexApprovalMode: 'approve',
379
- codexModel: 'gpt-5.5',
380
- codexReasoningEffort: 'xhigh',
381
- codexServiceTier: 'default',
382
- codexModelPreset: 'gpt-5.5:xhigh',
383
- version: '2',
384
- ...rawSettings
385
- };
386
- if (rawSettings.searchTimeoutMs === undefined && rawSettings.workspaceFileSearchTimeoutMs !== undefined) {
387
- const legacyTimeoutMs = Number(rawSettings.workspaceFileSearchTimeoutMs);
388
- this.settings.searchTimeoutMs = legacyTimeoutMs === LEGACY_DEFAULT_WORKSPACE_FILE_SEARCH_TIMEOUT_MS
389
- ? DEFAULT_SEARCH_TIMEOUT_MS
390
- : rawSettings.workspaceFileSearchTimeoutMs;
391
- }
392
- delete this.settings.workspaceFileSearchTimeoutMs;
393
- if (
394
- this.settings.dangerouslySkipAgentPermissionsByDefault === undefined
395
- && this.settings.skipPermissionCheckByDefault !== undefined
396
- ) {
397
- this.settings.dangerouslySkipAgentPermissionsByDefault = this.settings.skipPermissionCheckByDefault === true;
398
- }
399
- delete this.settings.skipPermissionCheckByDefault;
400
- const launchRawSettings = { ...rawSettings };
401
- if (rawSettings.codexApprovalMode === undefined && this.settings.dangerouslySkipAgentPermissionsByDefault === true) {
402
- this.settings.codexApprovalMode = 'full';
403
- launchRawSettings.codexApprovalMode = 'full';
404
- }
405
- this.settings.workspace = this.farmingDir;
406
- this.settings.lastMainWorkspace = this.normalizeMainWorkspace(this.settings.lastMainWorkspace, this.farmingDir);
407
- this.settings.workspaceHistory = this.normalizeWorkspaceHistory(this.settings.workspaceHistory);
408
- this.settings.projectWorkspaces = this.normalizeProjectWorkspaces(this.settings.projectWorkspaces);
409
- this.settings.pinnedProjectWorkspaces = this.normalizeProjectWorkspaces(this.settings.pinnedProjectWorkspaces);
410
- this.settings.projectNames = this.normalizeProjectNames(this.settings.projectNames);
411
- this.settings.projectOperations = this.normalizeProjectOperations(this.settings.projectOperations);
412
- this.settings.instanceName = this.normalizeInstanceName(this.settings.instanceName);
413
- this.settings.agentHomes = this.normalizeAgentHomes(this.settings.agentHomes);
414
- delete this.settings.updateUrl;
415
- this.settings.searchTimeoutMs = this.normalizeSearchTimeoutMs(this.settings.searchTimeoutMs);
416
- delete this.settings.codexRuntimeMode;
417
- const legacyMainPageSessionKeys = this.normalizeMainPageSessionKeys(this.settings.mainPageSessionKeys);
418
- delete this.settings.mainPageSessionKeys;
419
- this.sessionStore.init({ legacyMainPageSessionKeys });
420
- const legacyTaskHistory = this.normalizeTaskHistory(this.settings.taskHistory);
421
- delete this.settings.taskHistory;
422
- this.runHistoryStore.init({ legacyTaskHistory });
423
- this.settings.appearance = this.normalizeAppearance(this.settings.appearance);
424
- this.settings.language = this.normalizeLanguage(this.settings.language);
425
- this.settings.restReminderIntervalSeconds = this.normalizeRestReminderIntervalSeconds(
426
- this.settings.restReminderIntervalSeconds,
427
- );
428
- this.settings.browserExtensionEnabled = this.settings.browserExtensionEnabled === true;
429
- this.settings.browserSource = this.normalizeBrowserSource(this.settings.browserSource);
430
- this.settings.browserExecutablePath = this.normalizeBrowserSetting(this.settings.browserExecutablePath);
431
- this.settings.browserExternalCdpUrl = this.normalizeBrowserSetting(this.settings.browserExternalCdpUrl)
432
- || 'http://127.0.0.1:9222';
433
- this.settings.crtSkinEffectsEnabled = this.settings.crtSkinEffectsEnabled !== false;
434
- this.settings.crtDynamicHeatEnabled = this.settings.crtDynamicHeatEnabled === true;
435
- this.settings.crtTerminalFontSize = this.normalizeCrtTerminalFontSize(this.settings.crtTerminalFontSize);
436
- this.normalizeAgentLaunchSettings(launchRawSettings);
437
- this.pruneUnknownSettings();
438
- ensureMainAgentSkillFiles(this.farmingDir);
439
- ensureFarmingAgentBootstrapFile(this.farmingDir);
440
- this.writeSettingsFile();
441
- console.log('Loaded settings:', this.settings);
442
- }
443
-
444
- pruneUnknownSettings(settings = this.settings) {
445
- for (const key of Object.keys(settings || {})) {
446
- if (!PERSISTED_SETTING_KEYS.has(key)) {
447
- delete settings[key];
448
- }
449
- }
450
- }
451
-
452
- normalizeDefaultLaunchAgent(agentName) {
453
- return DEFAULT_LAUNCH_AGENT_NAMES.has(agentName) ? agentName : 'codex';
454
- }
455
-
456
- normalizeSearchTimeoutMs(value) {
457
- const timeoutMs = Number(value);
458
- if (!Number.isFinite(timeoutMs)) return DEFAULT_SEARCH_TIMEOUT_MS;
459
- return Math.min(
460
- MAX_SEARCH_TIMEOUT_MS,
461
- Math.max(MIN_SEARCH_TIMEOUT_MS, Math.round(timeoutMs))
462
- );
463
- }
464
-
465
- normalizeRestReminderIntervalSeconds(value) {
466
- if (value === null || value === undefined || value === '') return null;
467
- const seconds = Number(value);
468
- if (!Number.isInteger(seconds)) return null;
469
- if (seconds === 0 || seconds === 5) return seconds;
470
- return seconds >= 60 && seconds <= 240 * 60 && seconds % 60 === 0
471
- ? seconds
472
- : null;
473
- }
474
-
475
- normalizeCrtTerminalFontSize(value) {
476
- const fontSize = Number(value);
477
- if (!Number.isFinite(fontSize)) return DEFAULT_CRT_TERMINAL_FONT_SIZE;
478
- return Math.min(
479
- MAX_CRT_TERMINAL_FONT_SIZE,
480
- Math.max(MIN_CRT_TERMINAL_FONT_SIZE, Math.round(fontSize))
481
- );
482
- }
483
-
484
- normalizeAgentHomes(agentHomes) {
485
- const source = agentHomes && typeof agentHomes === 'object' && !Array.isArray(agentHomes)
486
- ? agentHomes
487
- : {};
488
- const normalized = {};
489
-
490
- Object.entries(source).forEach(([rawProvider, rawHomes]) => {
491
- const provider = String(rawProvider || '').trim().toLowerCase();
492
- if (!/^[a-z0-9._-]+$/.test(provider)) return;
493
- if (!Object.prototype.hasOwnProperty.call(DEFAULT_AGENT_HOMES, provider)) return;
494
- if (!Array.isArray(rawHomes)) return;
495
-
496
- const seenIds = new Set();
497
- const homes = [];
498
- rawHomes.forEach(rawHome => {
499
- if (!rawHome || typeof rawHome !== 'object') return;
500
- const id = String(rawHome.id || '').trim();
501
- const homePath = String(rawHome.path || '').trim();
502
- if (!id || !homePath) return;
503
- if (!/^[A-Za-z0-9._-]+$/.test(id)) return;
504
- const idKey = id.toLowerCase();
505
- if (seenIds.has(idKey)) return;
506
- seenIds.add(idKey);
507
- homes.push({ id, path: homePath });
508
- });
509
- if (homes.length > 0) normalized[provider] = homes;
510
- });
511
-
512
- for (const [provider, homes] of Object.entries(DEFAULT_AGENT_HOMES)) {
513
- const defaultHome = homes[0];
514
- const providerHomes = normalized[provider] || [];
515
- if (!providerHomes.some(home => String(home.id || '').toLowerCase() === 'default')) {
516
- normalized[provider] = [{ ...defaultHome }, ...providerHomes];
517
- }
518
- }
519
-
520
- return normalized;
521
- }
522
-
523
- normalizeProjectNames(projectNames) {
524
- if (!projectNames || typeof projectNames !== 'object' || Array.isArray(projectNames)) return {};
525
- const normalized = {};
526
- Object.entries(projectNames).forEach(([workspace, name]) => {
527
- const key = this.expandWorkspacePath(String(workspace || '').trim());
528
- const value = String(name || '').trim().slice(0, 80);
529
- if (!key || !value) return;
530
- normalized[key] = value;
531
- });
532
- return normalized;
533
- }
534
-
535
- normalizeProjectOperations(projectOperations) {
536
- if (!projectOperations || typeof projectOperations !== 'object' || Array.isArray(projectOperations)) return {};
537
- const entries = Object.entries(projectOperations)
538
- .filter(([id, operation]) => (
539
- PROJECT_OPERATION_ID_PATTERN.test(id)
540
- && operation
541
- && typeof operation === 'object'
542
- && ['create-worktree', 'delete-worktree'].includes(operation.type)
543
- && ['pending', 'unknown', 'succeeded', 'failed', 'blocked'].includes(operation.state)
544
- ))
545
- .sort((left, right) => (Number(right[1].updatedAt) || 0) - (Number(left[1].updatedAt) || 0))
546
- .map(([id, operation]) => [id, {
547
- id,
548
- type: operation.type,
549
- state: operation.state,
550
- signature: typeof operation.signature === 'string' ? operation.signature.slice(0, 128) : '',
551
- request: operation.request && typeof operation.request === 'object'
552
- ? JSON.parse(JSON.stringify(operation.request))
553
- : {},
554
- result: operation.result && typeof operation.result === 'object'
555
- ? JSON.parse(JSON.stringify(operation.result))
556
- : null,
557
- error: typeof operation.error === 'string' ? operation.error.slice(0, 2000) : '',
558
- startedAt: Number(operation.startedAt) || 0,
559
- updatedAt: Number(operation.updatedAt) || 0,
560
- finishedAt: Number(operation.finishedAt) || null,
561
- }]);
562
- const unresolved = entries.filter(([, operation]) => (
563
- ['pending', 'unknown', 'blocked'].includes(operation.state)
564
- ));
565
- const terminal = entries.filter(([, operation]) => (
566
- !['pending', 'unknown', 'blocked'].includes(operation.state)
567
- ));
568
- return Object.fromEntries([
569
- ...unresolved,
570
- ...terminal.slice(0, Math.max(0, MAX_PROJECT_OPERATIONS - unresolved.length)),
571
- ]);
572
- }
573
-
574
- setProjectName(workspace, name) {
575
- const normalized = this.normalizeProjectNames({ [workspace]: name });
576
- const entry = Object.entries(normalized)[0];
577
- if (!entry) throw new Error('Project workspace and name are required');
578
- const [normalizedWorkspace, normalizedName] = entry;
579
- const nextSettings = {
580
- ...this.settings,
581
- projectNames: {
582
- ...this.settings.projectNames,
583
- [normalizedWorkspace]: normalizedName,
584
- },
585
- };
586
- this.writeSettingsFile(nextSettings);
587
- this.settings = nextSettings;
588
- return {
589
- workspace: normalizedWorkspace,
590
- name: normalizedName,
591
- };
592
- }
593
-
594
- normalizeAppearance(appearance) {
595
- return ['system', 'light', 'dark'].includes(appearance) ? appearance : 'system';
596
- }
597
-
598
- normalizeLanguage(language) {
599
- return ['en', 'zh'].includes(language) ? language : 'en';
600
- }
601
-
602
- normalizeBrowserSource(source) {
603
- return ['external-cdp', 'managed'].includes(source) ? source : 'system';
604
- }
605
-
606
- normalizeBrowserSetting(value) {
607
- return String(value || '').trim().slice(0, 2000);
608
- }
609
-
610
- normalizeClaudePermissionMode(mode) {
611
- return ['acceptEdits', 'auto', 'bypassPermissions', 'default', 'dontAsk', 'plan'].includes(mode)
612
- ? mode
613
- : 'default';
614
- }
615
-
616
- normalizeClaudeModel(model) {
617
- if (model === 'config') return model;
618
- return normalizeClaudeModelValue(model) || 'config';
619
- }
620
-
621
- normalizeClaudeEffort(effort) {
622
- if (effort === 'config') return effort;
623
- if (['low', 'medium', 'high', 'xhigh', 'max'].includes(effort)) return effort;
624
- return 'config';
625
- }
626
-
627
- normalizeCodexApprovalMode(mode) {
628
- return ['ask', 'approve', 'full', 'custom'].includes(mode) ? mode : 'approve';
629
- }
630
-
631
- normalizeCodexModelPreset(preset) {
632
- if (preset === 'config') return preset;
633
- if (typeof preset !== 'string') return 'gpt-5.5:xhigh';
634
- if (/^[A-Za-z0-9._-]+(?::[A-Za-z0-9._-]+)?$/.test(preset)) return preset;
635
- return 'gpt-5.5:xhigh';
636
- }
637
-
638
- normalizeCodexModelId(model) {
639
- if (model === 'config') return model;
640
- if (typeof model !== 'string') return 'gpt-5.5';
641
- if (/^[A-Za-z0-9._-]+$/.test(model)) return model;
642
- return 'gpt-5.5';
643
- }
644
-
645
- normalizeCodexReasoningEffort(effort) {
646
- if (effort === 'config') return effort;
647
- if (typeof effort !== 'string') return 'xhigh';
648
- if (/^[A-Za-z0-9._-]+$/.test(effort)) return effort;
649
- return 'xhigh';
650
- }
651
-
652
- normalizeCodexServiceTier(tier) {
653
- if (typeof tier !== 'string') return 'default';
654
- if (/^[A-Za-z0-9._-]+$/.test(tier)) return tier;
655
- return 'default';
656
- }
657
-
658
- normalizeCodexModelSettings(rawSettings = {}) {
659
- const codexProfile = this.normalizeCodexLaunchProfile({
660
- approvalMode: this.settings.codexApprovalMode,
661
- model: this.settings.codexModel,
662
- reasoningEffort: this.settings.codexReasoningEffort,
663
- serviceTier: this.settings.codexServiceTier,
664
- modelPreset: this.settings.codexModelPreset,
665
- }, {
666
- approvalMode: rawSettings.codexApprovalMode,
667
- model: rawSettings.codexModel,
668
- reasoningEffort: rawSettings.codexReasoningEffort,
669
- serviceTier: rawSettings.codexServiceTier,
670
- modelPreset: rawSettings.codexModelPreset,
671
- });
672
- this.applyCodexProfileToLegacySettings(codexProfile);
673
- }
674
-
675
- normalizeCodexLaunchProfile(profile = {}, changed = {}) {
676
- const next = {
677
- ...DEFAULT_CODEX_LAUNCH_PROFILE,
678
- ...(profile && typeof profile === 'object' ? profile : {}),
679
- };
680
- next.approvalMode = this.normalizeCodexApprovalMode(next.approvalMode);
681
-
682
- const hasDirectModelChange = changed.model !== undefined || changed.reasoningEffort !== undefined;
683
- const hasPresetChange = changed.modelPreset !== undefined;
684
- const normalizedPreset = this.normalizeCodexModelPreset(next.modelPreset);
685
- if (hasPresetChange && !hasDirectModelChange) {
686
- const fromPreset = splitCodexModelPreset(normalizedPreset);
687
- next.model = fromPreset.model;
688
- next.reasoningEffort = fromPreset.effort;
689
- } else {
690
- next.model = this.normalizeCodexModelId(next.model);
691
- next.reasoningEffort = this.normalizeCodexReasoningEffort(next.reasoningEffort);
692
- }
693
- next.serviceTier = this.normalizeCodexServiceTier(next.serviceTier);
694
- next.modelPreset = joinCodexModelPreset(
695
- next.model,
696
- next.reasoningEffort === 'config' ? '' : next.reasoningEffort
697
- );
698
- return next;
699
- }
700
-
701
- normalizeClaudeLaunchProfile(profile = {}) {
702
- const next = {
703
- ...DEFAULT_CLAUDE_LAUNCH_PROFILE,
704
- ...(profile && typeof profile === 'object' ? profile : {}),
705
- };
706
- return {
707
- permissionMode: this.normalizeClaudePermissionMode(next.permissionMode),
708
- model: this.normalizeClaudeModel(next.model),
709
- effort: this.normalizeClaudeEffort(next.effort),
710
- };
711
- }
712
-
713
- getChangedAgentLaunchProfiles(rawSettings = {}) {
714
- const changedProfiles = {};
715
- if (rawSettings.agentLaunchProfiles && typeof rawSettings.agentLaunchProfiles === 'object') {
716
- for (const [agentName, profile] of Object.entries(rawSettings.agentLaunchProfiles)) {
717
- if (!Object.prototype.hasOwnProperty.call(DEFAULT_AGENT_LAUNCH_PROFILES, agentName)) continue;
718
- if (profile && typeof profile === 'object') changedProfiles[agentName] = profile;
719
- }
720
- }
721
-
722
- const codexChanged = {};
723
- if (rawSettings.codexApprovalMode !== undefined) codexChanged.approvalMode = rawSettings.codexApprovalMode;
724
- if (rawSettings.codexModel !== undefined) codexChanged.model = rawSettings.codexModel;
725
- if (rawSettings.codexReasoningEffort !== undefined) codexChanged.reasoningEffort = rawSettings.codexReasoningEffort;
726
- if (rawSettings.codexServiceTier !== undefined) codexChanged.serviceTier = rawSettings.codexServiceTier;
727
- if (rawSettings.codexModelPreset !== undefined) codexChanged.modelPreset = rawSettings.codexModelPreset;
728
- if (Object.keys(codexChanged).length > 0) {
729
- changedProfiles.codex = {
730
- ...(changedProfiles.codex || {}),
731
- ...codexChanged,
732
- };
733
- }
734
-
735
- return changedProfiles;
736
- }
737
-
738
- mergeAgentLaunchProfiles(existingProfiles = {}, incomingProfiles = {}) {
739
- const merged = {};
740
- for (const [agentName, defaultProfile] of Object.entries(DEFAULT_AGENT_LAUNCH_PROFILES)) {
741
- merged[agentName] = {
742
- ...defaultProfile,
743
- ...(existingProfiles && typeof existingProfiles === 'object' ? existingProfiles[agentName] : {}),
744
- ...(incomingProfiles && typeof incomingProfiles === 'object' ? incomingProfiles[agentName] : {}),
745
- };
746
- }
747
- return merged;
748
- }
749
-
750
- applyCodexProfileToLegacySettings(codexProfile, settings = this.settings) {
751
- settings.codexApprovalMode = codexProfile.approvalMode;
752
- settings.codexModel = codexProfile.model;
753
- settings.codexReasoningEffort = codexProfile.reasoningEffort;
754
- settings.codexServiceTier = codexProfile.serviceTier;
755
- settings.codexModelPreset = codexProfile.modelPreset;
756
- }
757
-
758
- normalizeAgentLaunchSettings(rawSettings = {}, settings = this.settings) {
759
- const changedProfiles = this.getChangedAgentLaunchProfiles(rawSettings);
760
- const mergedProfiles = this.mergeAgentLaunchProfiles(settings.agentLaunchProfiles, changedProfiles);
761
- settings.agentLaunchProfiles = {
762
- codex: this.normalizeCodexLaunchProfile(mergedProfiles.codex, changedProfiles.codex || {}),
763
- claude: this.normalizeClaudeLaunchProfile(mergedProfiles.claude),
764
- };
765
- settings.defaultLaunchAgent = this.normalizeDefaultLaunchAgent(settings.defaultLaunchAgent);
766
- this.applyCodexProfileToLegacySettings(settings.agentLaunchProfiles.codex, settings);
767
- }
768
-
769
- getWorkspace() {
770
- return this.settings ? this.settings.workspace : this.farmingDir;
771
- }
772
-
773
- getHeartbeatInterval() {
774
- return this.settings ? (this.settings.heartbeatInterval || 1000) : 1000;
775
- }
776
-
777
- getDangerouslySkipAgentPermissionsByDefault() {
778
- return this.settings ? this.settings.dangerouslySkipAgentPermissionsByDefault === true : false;
779
- }
780
-
781
- getCodexApprovalMode() {
782
- if (!this.settings) return 'approve';
783
- return this.getAgentLaunchProfile('codex').approvalMode;
784
- }
785
-
786
- getCodexModelPreset() {
787
- if (!this.settings) return 'gpt-5.5:xhigh';
788
- return this.getAgentLaunchProfile('codex').modelPreset;
789
- }
790
-
791
- getCodexModel() {
792
- if (!this.settings) return 'gpt-5.5';
793
- return this.getAgentLaunchProfile('codex').model;
794
- }
795
-
796
- getCodexReasoningEffort() {
797
- if (!this.settings) return 'xhigh';
798
- return this.getAgentLaunchProfile('codex').reasoningEffort;
799
- }
800
-
801
- getCodexServiceTier() {
802
- if (!this.settings) return 'default';
803
- return this.getAgentLaunchProfile('codex').serviceTier;
804
- }
805
-
806
-
807
- getAgentHomes(provider) {
808
- const homes = this.settings && this.settings.agentHomes && this.settings.agentHomes[provider]
809
- ? this.settings.agentHomes[provider]
810
- : [];
811
- return homes.map(home => ({ ...home, path: this.expandWorkspacePath(home.path) }));
812
- }
813
-
814
- getAgentHome(provider, homeId = 'default') {
815
- const normalizedProvider = String(provider || '').trim().toLowerCase();
816
- const normalizedHomeId = String(homeId || 'default').trim();
817
- const homes = this.getAgentHomes(normalizedProvider);
818
- return homes.find(home => home.id === normalizedHomeId) || null;
819
- }
820
-
821
- getDefaultLaunchAgent() {
822
- return this.settings ? this.normalizeDefaultLaunchAgent(this.settings.defaultLaunchAgent) : 'codex';
823
- }
824
-
825
- getAgentLaunchProfiles() {
826
- const profiles = this.settings && this.settings.agentLaunchProfiles
827
- ? this.settings.agentLaunchProfiles
828
- : DEFAULT_AGENT_LAUNCH_PROFILES;
829
- return {
830
- codex: { ...profiles.codex },
831
- claude: { ...profiles.claude },
832
- };
833
- }
834
-
835
- getAgentLaunchProfile(agentName) {
836
- const profiles = this.getAgentLaunchProfiles();
837
- const profile = profiles[agentName] || DEFAULT_AGENT_LAUNCH_PROFILES[agentName];
838
- return profile ? { ...profile } : {};
839
- }
840
-
841
- getSettings() {
842
- const publicSettings = { ...this.settings };
843
- delete publicSettings.projectOperations;
844
- return {
845
- ...publicSettings,
846
- instanceName: this.getInstanceName(),
847
- workspace: this.farmingDir,
848
- mainPageSessionKeys: this.getMainPageSessionKeys(),
849
- taskHistory: this.getTaskHistory(),
850
- };
851
- }
852
-
853
- mountProjectWorkspace(workspace) {
854
- const expanded = this.expandWorkspacePath(workspace);
855
- const resolved = expanded ? path.resolve(expanded) : '';
856
- let canonicalWorkspace = '';
857
- if (resolved) {
858
- try {
859
- canonicalWorkspace = fs.realpathSync(resolved);
860
- if (!fs.statSync(canonicalWorkspace).isDirectory()) canonicalWorkspace = '';
861
- } catch {
862
- canonicalWorkspace = '';
863
- }
864
- }
865
- if (
866
- !canonicalWorkspace
867
- || this.isInternalWorkspace(canonicalWorkspace)
868
- ) {
869
- throw new Error('Project workspace is invalid or unavailable');
870
- }
871
- const current = this.settings.projectWorkspaces || [];
872
- if (!current.includes(canonicalWorkspace)) {
873
- this.commitProjectMembership({
874
- projectWorkspaces: [canonicalWorkspace, ...current],
875
- });
876
- }
877
- return {
878
- workspace: canonicalWorkspace,
879
- projectWorkspaces: [...(this.settings.projectWorkspaces || [])],
880
- pinnedProjectWorkspaces: [...(this.settings.pinnedProjectWorkspaces || [])],
881
- };
882
- }
883
-
884
- removeProjectWorkspace(workspace) {
885
- const expanded = this.expandWorkspacePath(workspace);
886
- if (!expanded) throw new Error('Project workspace is required');
887
- const resolved = path.resolve(expanded);
888
- const candidates = new Set([expanded, resolved]);
889
- try {
890
- candidates.add(fs.realpathSync(resolved));
891
- } catch {
892
- // A deleted worktree can still be removed by its last canonical path.
893
- }
894
- const current = this.settings.projectWorkspaces || [];
895
- const nextProjects = current.filter(entry => !candidates.has(entry));
896
- const currentPinned = this.settings.pinnedProjectWorkspaces || [];
897
- const nextPinned = currentPinned.filter(entry => !candidates.has(entry));
898
- if (nextProjects.length !== current.length || nextPinned.length !== currentPinned.length) {
899
- this.commitProjectMembership({
900
- projectWorkspaces: nextProjects,
901
- pinnedProjectWorkspaces: nextPinned,
902
- });
903
- }
904
- return {
905
- workspace: current.find(entry => candidates.has(entry)) || resolved,
906
- projectWorkspaces: [...(this.settings.projectWorkspaces || [])],
907
- pinnedProjectWorkspaces: [...(this.settings.pinnedProjectWorkspaces || [])],
908
- };
909
- }
910
-
911
- setProjectWorkspacePinned(workspace, pinned) {
912
- const [canonicalWorkspace] = this.normalizeProjectWorkspaces([workspace]);
913
- if (!canonicalWorkspace || !(this.settings.projectWorkspaces || []).includes(canonicalWorkspace)) {
914
- throw new Error('Project does not exist');
915
- }
916
- const current = this.settings.pinnedProjectWorkspaces || [];
917
- const nextPinned = pinned
918
- ? [...current.filter(entry => entry !== canonicalWorkspace), canonicalWorkspace]
919
- : current.filter(entry => entry !== canonicalWorkspace);
920
- if (
921
- nextPinned.length !== current.length
922
- || nextPinned.some((entry, index) => entry !== current[index])
923
- ) {
924
- this.commitProjectMembership({ pinnedProjectWorkspaces: nextPinned });
925
- }
926
- return {
927
- workspace: canonicalWorkspace,
928
- projectWorkspaces: [...(this.settings.projectWorkspaces || [])],
929
- pinnedProjectWorkspaces: [...(this.settings.pinnedProjectWorkspaces || [])],
930
- };
931
- }
932
-
933
- commitProjectMembership(settingsPatch) {
934
- const previousSettings = this.settings;
935
- try {
936
- this.updateSettings(settingsPatch);
937
- } catch (error) {
938
- this.settings = previousSettings;
939
- throw error;
940
- }
941
- }
942
-
943
- getProjectOperation(requestId) {
944
- const id = String(requestId || '').trim();
945
- if (!PROJECT_OPERATION_ID_PATTERN.test(id)) return null;
946
- const operation = this.settings.projectOperations?.[id];
947
- return operation ? JSON.parse(JSON.stringify(operation)) : null;
948
- }
949
-
950
- commitProjectOperation(operation, membership = {}) {
951
- const normalized = this.normalizeProjectOperations({ [operation?.id]: operation });
952
- const nextOperation = normalized[operation?.id];
953
- if (!nextOperation) throw new Error('Project operation is invalid');
954
- const existingOperation = this.settings.projectOperations?.[nextOperation.id];
955
- const unresolvedCount = Object.values(this.settings.projectOperations || {})
956
- .filter(candidate => ['pending', 'unknown', 'blocked'].includes(candidate.state)).length;
957
- if (!existingOperation && nextOperation.state === 'pending' && unresolvedCount >= MAX_PROJECT_OPERATIONS) {
958
- throw new Error('Too many unresolved Project operations require reconciliation');
959
- }
960
- const nextOperations = this.normalizeProjectOperations({
961
- ...this.settings.projectOperations,
962
- [nextOperation.id]: nextOperation,
963
- });
964
- const nextSettings = {
965
- ...this.settings,
966
- projectOperations: nextOperations,
967
- };
968
- if (membership.mountWorkspace) {
969
- const mounted = this.normalizeProjectWorkspaces([
970
- membership.mountWorkspace,
971
- ...(this.settings.projectWorkspaces || []),
972
- ]);
973
- nextSettings.projectWorkspaces = mounted;
974
- nextSettings.pinnedProjectWorkspaces = this.normalizeProjectWorkspaces(
975
- this.settings.pinnedProjectWorkspaces,
976
- );
977
- }
978
- if (membership.removeWorkspace) {
979
- const expanded = this.expandWorkspacePath(membership.removeWorkspace);
980
- const resolved = expanded ? path.resolve(expanded) : '';
981
- const candidates = new Set([expanded, resolved].filter(Boolean));
982
- try {
983
- candidates.add(fs.realpathSync(resolved));
984
- } catch {
985
- // A deleted worktree is removed by its last canonical path.
986
- }
987
- nextSettings.projectWorkspaces = (this.settings.projectWorkspaces || [])
988
- .filter(workspace => !candidates.has(workspace));
989
- nextSettings.pinnedProjectWorkspaces = (this.settings.pinnedProjectWorkspaces || [])
990
- .filter(workspace => !candidates.has(workspace));
991
- }
992
- this.writeSettingsFile(nextSettings);
993
- this.settings = nextSettings;
994
- return {
995
- operation: JSON.parse(JSON.stringify(nextOperation)),
996
- projectWorkspaces: [...(nextSettings.projectWorkspaces || [])],
997
- pinnedProjectWorkspaces: [...(nextSettings.pinnedProjectWorkspaces || [])],
998
- };
999
- }
1000
-
1001
- getMainPageSessionKeys() {
1002
- return this.sessionStore ? this.sessionStore.getMainPageSessionKeys() : [];
1003
- }
1004
-
1005
- setMainPageSessionKeys(keys) {
1006
- return this.sessionStore ? this.sessionStore.setMainPageSessionKeys(keys) : [];
1007
- }
1008
-
1009
- rememberMainPageSessionKey(sessionKey, patch = {}) {
1010
- return this.sessionStore ? this.sessionStore.rememberMainPageSessionKey(sessionKey, patch) : [];
1011
- }
1012
-
1013
- removeMainPageSessionKey(sessionKey) {
1014
- return this.sessionStore ? this.sessionStore.removeMainPageSessionKey(sessionKey) : false;
1015
- }
1016
-
1017
- removeMainPageSessionKeys(keys) {
1018
- return this.sessionStore ? this.sessionStore.removeMainPageSessionKeys(keys) : [];
1019
- }
1020
-
1021
- ensureAgentSessionRecord(agent, patch = {}) {
1022
- return this.sessionStore ? this.sessionStore.ensureRecordForAgent(agent, patch) : '';
1023
- }
1024
-
1025
- getAgentSessionRecordForProviderSessionKey(sessionKey) {
1026
- return this.sessionStore ? this.sessionStore.getRecordForProviderSessionKey(sessionKey) : null;
1027
- }
1028
-
1029
- setProviderSessionDisplayState(sessionKey, patch = {}) {
1030
- return this.sessionStore ? this.sessionStore.setProviderSessionDisplayState(sessionKey, patch) : '';
1031
- }
1032
-
1033
- listAgentSessionRecords() {
1034
- return this.sessionStore ? this.sessionStore.listAgentRecords() : [];
1035
- }
1036
-
1037
- rememberAgentSessionRecord(agent) {
1038
- return this.sessionStore ? this.sessionStore.rememberAgent(agent) : '';
1039
- }
1040
-
1041
- getTaskHistory() {
1042
- return this.runHistoryStore ? this.runHistoryStore.getEntries() : [];
1043
- }
1044
-
1045
- writeSettingsFile(settings = this.settings) {
1046
- this.writeJson(this.settingsFile, settings);
1047
- }
1048
-
1049
- appendTaskHistory(entry) {
1050
- if (!this.runHistoryStore) return;
1051
- this.runHistoryStore.appendEntry(entry);
1052
- }
1053
-
1054
- updateSettings(newSettings) {
1055
- const incomingMainPageSessionKeys = Object.prototype.hasOwnProperty.call(newSettings || {}, 'mainPageSessionKeys')
1056
- ? newSettings.mainPageSessionKeys
1057
- : undefined;
1058
- const settingsPatch = { ...(newSettings || {}) };
1059
- delete settingsPatch.mainPageSessionKeys;
1060
- delete settingsPatch.projectOperations;
1061
- const incomingTaskHistory = Object.prototype.hasOwnProperty.call(settingsPatch, 'taskHistory')
1062
- ? settingsPatch.taskHistory
1063
- : undefined;
1064
- delete settingsPatch.taskHistory;
1065
- const previousMainWorkspace = this.settings.lastMainWorkspace || this.farmingDir;
1066
- const previousProfiles = this.settings.agentLaunchProfiles || {};
1067
- const incomingProfiles = settingsPatch.agentLaunchProfiles || {};
1068
- const nextSettings = {
1069
- ...this.settings,
1070
- ...settingsPatch,
1071
- agentLaunchProfiles: this.mergeAgentLaunchProfiles(previousProfiles, incomingProfiles),
1072
- workspace: this.farmingDir
1073
- };
1074
- nextSettings.lastMainWorkspace = this.normalizeMainWorkspace(nextSettings.lastMainWorkspace, previousMainWorkspace);
1075
- nextSettings.workspaceHistory = this.normalizeWorkspaceHistory(nextSettings.workspaceHistory);
1076
- nextSettings.projectWorkspaces = this.normalizeProjectWorkspaces(nextSettings.projectWorkspaces);
1077
- nextSettings.pinnedProjectWorkspaces = this.normalizeProjectWorkspaces(nextSettings.pinnedProjectWorkspaces);
1078
- nextSettings.projectNames = this.normalizeProjectNames(nextSettings.projectNames);
1079
- nextSettings.projectOperations = this.normalizeProjectOperations(nextSettings.projectOperations);
1080
- nextSettings.instanceName = this.normalizeInstanceName(nextSettings.instanceName);
1081
- nextSettings.agentHomes = this.normalizeAgentHomes(nextSettings.agentHomes);
1082
- delete nextSettings.updateUrl;
1083
- nextSettings.searchTimeoutMs = this.normalizeSearchTimeoutMs(nextSettings.searchTimeoutMs);
1084
- delete nextSettings.codexRuntimeMode;
1085
- delete nextSettings.mainPageSessionKeys;
1086
- delete nextSettings.taskHistory;
1087
- if (incomingMainPageSessionKeys !== undefined) {
1088
- this.setMainPageSessionKeys(incomingMainPageSessionKeys);
1089
- }
1090
- if (incomingTaskHistory !== undefined && this.runHistoryStore) {
1091
- this.runHistoryStore.setEntries(incomingTaskHistory);
1092
- }
1093
- nextSettings.appearance = this.normalizeAppearance(nextSettings.appearance);
1094
- nextSettings.language = this.normalizeLanguage(nextSettings.language);
1095
- nextSettings.restReminderIntervalSeconds = this.normalizeRestReminderIntervalSeconds(
1096
- nextSettings.restReminderIntervalSeconds,
1097
- );
1098
- nextSettings.browserExtensionEnabled = nextSettings.browserExtensionEnabled === true;
1099
- nextSettings.browserSource = this.normalizeBrowserSource(nextSettings.browserSource);
1100
- nextSettings.browserExecutablePath = this.normalizeBrowserSetting(nextSettings.browserExecutablePath);
1101
- nextSettings.browserExternalCdpUrl = this.normalizeBrowserSetting(nextSettings.browserExternalCdpUrl)
1102
- || 'http://127.0.0.1:9222';
1103
- nextSettings.crtSkinEffectsEnabled = nextSettings.crtSkinEffectsEnabled !== false;
1104
- nextSettings.crtDynamicHeatEnabled = nextSettings.crtDynamicHeatEnabled === true;
1105
- nextSettings.crtTerminalFontSize = this.normalizeCrtTerminalFontSize(nextSettings.crtTerminalFontSize);
1106
- this.normalizeAgentLaunchSettings(settingsPatch, nextSettings);
1107
- this.pruneUnknownSettings(nextSettings);
1108
- this.writeSettingsFile(nextSettings);
1109
- this.settings = nextSettings;
1110
- }
1111
- }
1112
-
1113
- module.exports = ConfigManager;
1114
- module.exports.DEFAULT_SEARCH_TIMEOUT_MS = DEFAULT_SEARCH_TIMEOUT_MS;
1115
- module.exports.DEFAULT_CRT_TERMINAL_FONT_SIZE = DEFAULT_CRT_TERMINAL_FONT_SIZE;
1116
- module.exports.MIN_CRT_TERMINAL_FONT_SIZE = MIN_CRT_TERMINAL_FONT_SIZE;
1117
- module.exports.MAX_CRT_TERMINAL_FONT_SIZE = MAX_CRT_TERMINAL_FONT_SIZE;