farming-code 2.2.27 → 2.2.29
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.
- package/README.md +15 -30
- package/README.zh_cn.md +15 -30
- package/THIRD_PARTY_NOTICES.md +28 -6
- package/backend/acp/packaged-claude-acp.js +13 -0
- package/backend/acp/packaged-codex-acp.js +2 -2
- package/backend/acp-runtime.js +52 -3
- package/backend/acp-transcript.js +174 -9
- package/backend/agent-manager.js +1081 -96
- package/backend/atomic-json-store.js +37 -0
- package/backend/cli-agents.js +9 -7
- package/backend/config-manager.js +211 -58
- package/backend/control-api.js +2 -1
- package/backend/data/LICENSE.agent-browser +201 -0
- package/backend/data/runtime-dependency-manifest.json +199 -0
- package/backend/data/runtime-dependency-sources.json +5 -0
- package/backend/executable-discovery.js +7 -0
- package/backend/farming-agent-bootstrap.js +49 -0
- package/backend/farming-agent-bootstrap.zh_cn.md +7 -0
- package/backend/farming-app-cli.js +168 -65
- package/backend/farming-cli.js +57 -0
- package/backend/farming-session-store.js +92 -89
- package/backend/index-html.js +13 -0
- package/backend/main-agent-skills.js +13 -0
- package/backend/npm-update-helper.js +43 -6
- package/backend/preview-session-manager.js +68 -0
- package/backend/provider-adapters.js +54 -5
- package/backend/review-session-store.js +32 -25
- package/backend/review-state-store.js +13 -14
- package/backend/run-history-store.js +13 -16
- package/backend/runtime-dependency-manager.js +759 -0
- package/backend/runtime-executable-invocation.js +20 -0
- package/backend/server-process-identity.js +47 -0
- package/backend/server.js +231 -223
- package/backend/slash-command-discovery.js +138 -1
- package/backend/storage-layout.js +35 -0
- package/backend/update-service.js +27 -1
- package/backend/workspace-file-router.js +141 -0
- package/backend/workspace-file-service.js +19 -0
- package/backend/workspace-root-registry.js +6 -4
- package/config/farming.install.env.example +4 -0
- package/dist/acp/LICENSE.claude-agent-acp +191 -0
- package/dist/acp/LICENSE.claude-agent-sdk +1 -0
- package/dist/acp/claude-agent-acp-0.59.0.mjs +41606 -0
- package/dist/assets/App-BKNUILuL.css +1 -0
- package/dist/assets/App-Ex2oVVXO.js +693 -0
- package/dist/assets/{FileEditorMarkdownPreview-Da5jguUs.js → FileEditorMarkdownPreview-Cs9cLv8a.js} +5 -5
- package/dist/assets/FileEditorPane-CNtuGjQ3.js +2 -0
- package/dist/assets/IconGlyphs-BClgag6E.js +1 -0
- package/dist/assets/ProjectFilesSection-Cf2BEcAN.js +12 -0
- package/dist/assets/ReviewPage-BRuxFaH5.js +3 -0
- package/dist/assets/{abnfDiagram-VRR7QNED-nnglrXFi.js → abnfDiagram-VRR7QNED-BY1qwq8A.js} +1 -1
- package/dist/assets/api-w2x5QfxB.js +1 -0
- package/dist/assets/{arc-CWoVlxJw.js → arc-DgZRAlwj.js} +1 -1
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-BEXMaFfY.js → architectureDiagram-ZJ3FMSHR-jFn144od.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-1mCezSBk.js → blockDiagram-677ZJIJ3-BmRjlV0H.js} +1 -1
- package/dist/assets/{c4Diagram-LMCZKHZV-DhTiI6Uv.js → c4Diagram-LMCZKHZV-DUKul6tT.js} +1 -1
- package/dist/assets/{workspace-editor-monaco-DLlws5Ig.js → channel-CI9j3QFD.js} +1 -1
- package/dist/assets/chunk-2Q5K7J3B-87UnWaoh.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-CCdsKd73.js → chunk-32BRIVSS-rGVu23o5.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-Gncjk4LF.js → chunk-52WLFC77-CvFDKgbB.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-Dlw7AXWp.js → chunk-5VM5RSS4-CFgnRW1C.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-ZBRhjLOh.js → chunk-7BUUIJ7U-Cp7bqW6s.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-CiDVUP82.js → chunk-C7G6YPKG-BIS1gjZO.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-z6gXP2_N.js → chunk-EX3LRPZG-BKG-cR9j.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-DMZBccQa.js → chunk-FWX5IMBZ-B8PsTr8a.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-D8tIeoPk.js → chunk-HOUHSVGY-BHFOAiXT.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-b6oQ2Q17.js → chunk-ICXQ74PX-CvLE1J9X.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-DSyBRaRG.js → chunk-JWPE2WC7-D8misks7.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-DAVH_p2a.js → chunk-MOJQB5TN-D-oNgSNH.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-DxoiMCI-.js → chunk-OGEWGWER-C2N-la9e.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-NsOWh7HM.js → chunk-PUDLZKDR-BwI3Jz8q.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-Di4H7L21.js → chunk-Q4XR5HBZ-BuqGfsXA.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-CZA9pvFX.js → chunk-RYQCIY6F-Bq4XZcGt.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-DttpZg9Y.js → chunk-V7JOEXUC-QZLzdTTJ.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-Cb0-kQ9g.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-D-Fmtd4Z.js → chunk-VR4S4FIN-DcZTpML_.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-CUxMtfK2.js → chunk-WYO6CB5R-DCU8wuny.js} +2 -2
- package/dist/assets/chunk-XXDRQBXY-BZAC1Krv.js +1 -0
- package/dist/assets/{chunk-ZGVPDNZ5-CoV2QEl0.js → chunk-ZGVPDNZ5-B7r85QbY.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-DncwlQQc.js → chunk-ZIRB5QZD-BgEnDWhQ.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-DcvGOuvi.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-DDYUSofQ.js +1 -0
- package/dist/assets/code-dark-BEZTQwYZ.css +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-BNIAz0nN.js → cose-bilkent-JH36ORCC-CThXS2qG.js} +1 -1
- package/dist/assets/{cssMode-DDWxTPm_.js → cssMode-Bdg5RpcJ.js} +1 -1
- package/dist/assets/{cynefinDiagram-TSTJHNR4-0xPI92Lg.js → cynefinDiagram-TSTJHNR4-DxBgzw25.js} +1 -1
- package/dist/assets/{dagre-DXlcHgr3.js → dagre-BM-GvGUZ.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-DfuMG4gU.js → dagre-VKFMJZFB-B7UCRmxR.js} +1 -1
- package/dist/assets/{diagram-FQU43EPY-CT00bLZ6.js → diagram-FQU43EPY-CeL2DwKx.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-Xbh7zXUx.js → diagram-G47NLZAW-BEirglCC.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-SRDVPfn7.js → diagram-NH7WQ7WH-C6wcI-Rl.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-CQRli4Np.js → diagram-OA4YK3LP-DpM-XXtJ.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-DMf17WQi.js → diagram-WEI45ONY-BQyaut9k.js} +1 -1
- package/dist/assets/{ebnfDiagram-CCIWWBDH-DhpFkgJ5.js → ebnfDiagram-CCIWWBDH-UmAXsUhr.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-1IwxWmJo.js → erDiagram-Q63AITRT-CdYLEOch.js} +1 -1
- package/dist/assets/file-icons-BOlcJ0ZF.js +1 -0
- package/dist/assets/flowDiagram-23GEKE2U-CO-z9-tq.js +1 -0
- package/dist/assets/{freemarker2-QBsTERH-.js → freemarker2-DfMDJfnE.js} +1 -1
- package/dist/assets/{ganttDiagram-NO4QXBWP-BNCdfyr1.js → ganttDiagram-NO4QXBWP-DgSUNdUB.js} +1 -1
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-pbyWZuiX.js → gitGraphDiagram-IHSO6WYX-DjwjtRtF.js} +1 -1
- package/dist/assets/{handlebars-CuoxPo5A.js → handlebars-BEdPtzMT.js} +1 -1
- package/dist/assets/{html-gX5PEu0Q.js → html-B1fPb1QD.js} +1 -1
- package/dist/assets/html2canvas-DsczWxBa.js +5 -0
- package/dist/assets/{htmlMode-DIWUbUxd.js → htmlMode-CY2ZjHxH.js} +1 -1
- package/dist/assets/{index-CtwKYTiC.js → index-CQNaZc3l.js} +2 -2
- package/dist/assets/{infoDiagram-FWYZ7A6U-BcTOgDbe.js → infoDiagram-FWYZ7A6U-Bi9076l2.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-DCdvGKrn.js → ishikawaDiagram-FXEZZL3T-DaMaNZN7.js} +1 -1
- package/dist/assets/{javascript-BYKGIUGs.js → javascript-BV2OsWA0.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-BZ-1q_IT.js → journeyDiagram-5HDEW3XC-CfDy69EZ.js} +1 -1
- package/dist/assets/{jsonMode-AFmQQP6u.js → jsonMode-zd07aeuX.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-BIgejCjj.js → kanban-definition-HUTT4EX6-XFvZ722B.js} +1 -1
- package/dist/assets/{line-CfptFMmX.js → line-BXK9PKLn.js} +1 -1
- package/dist/assets/{linear-Dld3_ERu.js → linear-CULvmq2Z.js} +1 -1
- package/dist/assets/{liquid-DBIl-f0z.js → liquid-BParI24X.js} +1 -1
- package/dist/assets/{lspLanguageFeatures-DK6tqicV.js → lspLanguageFeatures-BzredkoV.js} +1 -1
- package/dist/assets/main-DK9Sy7-c.css +1 -0
- package/dist/assets/{map-LZWWoeWa.js → map-C9Qw9eWh.js} +1 -1
- package/dist/assets/{mdx-DS-bVtZN.js → mdx-vGzUJN98.js} +1 -1
- package/dist/assets/{mermaid.core-gSpX30pV.js → mermaid.core-CzazaIKr.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-BKBaI4LW.js → mindmap-definition-LN4V7U3C-Uoff7hZ3.js} +1 -1
- package/dist/assets/{monaco.contribution-BXz-lfFB.js → monaco.contribution-BmaeBQEc.js} +2 -2
- package/dist/assets/{ordinal-BLrOss5K.js → ordinal-r6pIwRdZ.js} +1 -1
- package/dist/assets/{pegDiagram-2B236MQR-sBvDY3VX.js → pegDiagram-2B236MQR-CCBiHQjk.js} +1 -1
- package/dist/assets/{pieDiagram-ENE6RG2P-DWlWcu08.js → pieDiagram-ENE6RG2P-D61s7l75.js} +1 -1
- package/dist/assets/{python-C93q3xXz.js → python-CUwdLgsI.js} +1 -1
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-DZutUd3J.js → quadrantDiagram-ABIIQ3AL-D_CWk2DQ.js} +1 -1
- package/dist/assets/{railroadDiagram-RFXS5EU6-DQb3lXGM.js → railroadDiagram-RFXS5EU6-CdlCHtxN.js} +1 -1
- package/dist/assets/{razor-CBifNGXO.js → razor-BScebUxU.js} +1 -1
- package/dist/assets/{requirementDiagram-TGXJPOKE-DqFGXu2e.js → requirementDiagram-TGXJPOKE-BLpHtkoC.js} +1 -1
- package/dist/assets/{sankeyDiagram-HTMAVEWB-d7ECahnO.js → sankeyDiagram-HTMAVEWB-CkhYZN2j.js} +1 -1
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-DdsbKqct.js → sequenceDiagram-DBY2YBRQ-8bploKJl.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-daTB6OcF.js → sizeCapture-X5ZJPWSS-DtSdkS0d.js} +1 -1
- package/dist/assets/{src-WBW1QxJt.js → src-6yeq6WBA.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-P6iSrgwR.js → stateDiagram-2N3HPSRC-DfmVGpfA.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-B2c9CQ-J.js +1 -0
- package/dist/assets/{swimlanes-5IMT3BWC-BGnZJx1M.js → swimlanes-5IMT3BWC-DRLk2zRF.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-B7_APh_h.js +8 -0
- package/dist/assets/{timeline-definition-FHXFAJF6-rA-r3aUR.js → timeline-definition-FHXFAJF6-Cngfy588.js} +1 -1
- package/dist/assets/{tsMode-B0oUTcXQ.js → tsMode-DzUAibXK.js} +1 -1
- package/dist/assets/{typescript-KJKfYO7K.js → typescript-D9EOeM7N.js} +1 -1
- package/dist/assets/{vennDiagram-L72KCM5P-DiVKUjA9.js → vennDiagram-L72KCM5P-DeJn63Lq.js} +1 -1
- package/dist/assets/{wardleyDiagram-EHGQE667-Cfxh7UOn.js → wardleyDiagram-EHGQE667-BH1nzy77.js} +1 -1
- package/dist/assets/{workers-BSQRIkqa.js → workers-DAiomYZM.js} +1 -1
- package/dist/assets/workspace-editor-model-CSGCl21x.js +1 -0
- package/dist/assets/{workspace-editor-monaco-BIpqcWf1.js → workspace-editor-monaco-CJNwbpCy.js} +3 -3
- package/dist/assets/workspace-editor-monaco-CO9w8YV0.js +1 -0
- package/dist/assets/workspace-view-state-BjKPYp0E.js +7 -0
- package/dist/assets/{xml-C8FAcN6j.js → xml-wWl1dhkQ.js} +1 -1
- package/dist/assets/{xychartDiagram-FW5EYKEG--hmryQeL.js → xychartDiagram-FW5EYKEG-SkO2prCU.js} +1 -1
- package/dist/assets/{yaml-BQ4NrRhG.js → yaml-Dc2WDaOZ.js} +1 -1
- package/dist/crt-markdown-renderer.js +46 -46
- package/dist/index.html +32 -3
- package/extensions/browser/backend/agent-browser-runtime.js +1041 -0
- package/extensions/browser/backend/agent-capability.js +55 -0
- package/extensions/browser/backend/browser-mcp-server.js +621 -0
- package/extensions/browser/backend/browser-resource-manager.js +1309 -0
- package/extensions/browser/backend/browser-resource-store.js +190 -0
- package/extensions/browser/backend/browser-router.js +133 -0
- package/extensions/browser/backend/executable-discovery.js +224 -0
- package/extensions/browser/backend/farming-browser-client.js +83 -0
- package/extensions/browser/backend/index.js +7 -0
- package/extensions/browser/bin/farming-browser +471 -0
- package/extensions/browser/frontend/BrowserSidebarPortals.tsx +360 -0
- package/extensions/browser/frontend/BrowserViewer.tsx +500 -0
- package/extensions/browser/frontend/browser-resource-state.ts +60 -0
- package/extensions/browser/frontend/browser.css +567 -0
- package/extensions/browser/frontend/types.ts +31 -0
- package/extensions/browser/frontend/useBrowserResources.ts +158 -0
- package/frontend/session-bridge.js +7 -6
- package/frontend/skins/crt/app.js +64 -4
- package/index.html +31 -2
- package/package.json +27 -18
- package/shared/backend-connection-status.d.ts +12 -0
- package/shared/backend-connection-status.js +35 -4
- package/shared/browser-protocol.js +1 -1
- package/backend/agent-activity.js +0 -35
- package/dist/assets/App-BrP-ENHg.css +0 -1
- package/dist/assets/App-Cm8qTjsc.js +0 -210
- package/dist/assets/FileEditorPane-fFqHA4wW.js +0 -2
- package/dist/assets/IconGlyphs-C2WFcoJS.js +0 -1
- package/dist/assets/ProjectFilesSection-Cyy3Vcn8.js +0 -12
- package/dist/assets/ReviewPage-L1vh1Ggs.js +0 -3
- package/dist/assets/api-D8nyOEbz.js +0 -1
- package/dist/assets/channel-BVWNatUB.js +0 -1
- package/dist/assets/chunk-2Q5K7J3B-d5WWh8jo.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-UHNr_yhX.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-BBXwjhUx.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-Db0ib5iE.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-Bkf69XF9.js +0 -1
- package/dist/assets/code-dark-BKtvf0Xc.css +0 -1
- package/dist/assets/file-icons-BqiH0rDI.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-DYFo2xmB.js +0 -1
- package/dist/assets/main-XMXgyJJt.css +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-DIYSf_qh.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-BIkrlKrZ.js +0 -8
- package/dist/assets/workspace-editor-model-D0Im34S5.js +0 -1
- package/dist/assets/workspace-view-state-BiuEbmRr.js +0 -7
- /package/dist/acp/{codex-acp-1.1.4.js → codex-acp-1.1.4.mjs} +0 -0
- /package/dist/assets/{abap-Cc5D5h5i.js → abap-CtX5nWyX.js} +0 -0
- /package/dist/assets/{apex-BKopwLmx.js → apex-DQJRAHwc.js} +0 -0
- /package/dist/assets/{array-HeX70jSN.js → array-BTwzYU0x.js} +0 -0
- /package/dist/assets/{azcli-DI-C34WA.js → azcli-9SMrOQ4q.js} +0 -0
- /package/dist/assets/{bat-Cbp6u42z.js → bat-CBGLUsw1.js} +0 -0
- /package/dist/assets/{bicep-4QA1jTCM.js → bicep-pDx8da1v.js} +0 -0
- /package/dist/assets/{cameligo-Dda_adPs.js → cameligo-hZV3vQ6_.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-Di0sYzi1.js → chunk-Y2CYZVJY-BYi0W5ea.js} +0 -0
- /package/dist/assets/{clojure-CvY8A83L.js → clojure-BhCwU3gq.js} +0 -0
- /package/dist/assets/{coffee-4LX2Sv8A.js → coffee-BVB1PsgH.js} +0 -0
- /package/dist/assets/{core-B9MwRjDE.js → core-vPkV8P_m.js} +0 -0
- /package/dist/assets/{cpp-D4AzSV28.js → cpp-eTjuiNPq.js} +0 -0
- /package/dist/assets/{csharp-C4nWN4Yd.js → csharp-1kP-kKZT.js} +0 -0
- /package/dist/assets/{csp-CiEaaS5Z.js → csp-C_iQqIes.js} +0 -0
- /package/dist/assets/{css-DXxBRsbk.js → css-CxOs7IfP.js} +0 -0
- /package/dist/assets/{cypher-DOMzqyFA.js → cypher-Cd-a9Y82.js} +0 -0
- /package/dist/assets/{cytoscape.esm-Cl8iC3D7.js → cytoscape.esm-OLojuicg.js} +0 -0
- /package/dist/assets/{dart-BWS7MXt_.js → dart-whhXpexn.js} +0 -0
- /package/dist/assets/{defaultLocale-GJwWH1Jr.js → defaultLocale-CPimVhfE.js} +0 -0
- /package/dist/assets/{dist-ClAL-Tv5.js → dist-CLPYXg1u.js} +0 -0
- /package/dist/assets/{dockerfile-Baf4U3xT.js → dockerfile-DibBi8b6.js} +0 -0
- /package/dist/assets/{ecl-CT7udlkQ.js → ecl-DlF1KdoW.js} +0 -0
- /package/dist/assets/{editor.api2-B9h6iFPK.js → editor.api2-D74ufkbr.js} +0 -0
- /package/dist/assets/{elixir-CIbAZw5l.js → elixir-CHQ8uFT3.js} +0 -0
- /package/dist/assets/{flow9-Dqiw45WV.js → flow9-8nUnVKk1.js} +0 -0
- /package/dist/assets/{fsharp-E8E2L9jU.js → fsharp-DNZNZyEE.js} +0 -0
- /package/dist/assets/{go-CouVSN4D.js → go-_kPJjNc_.js} +0 -0
- /package/dist/assets/{graphlib-CbSvZcZU.js → graphlib-CBGF9gA9.js} +0 -0
- /package/dist/assets/{graphql-a6h6h5-t.js → graphql-4HCNVt5g.js} +0 -0
- /package/dist/assets/{hcl-vso3e6N-.js → hcl-C87ymY0o.js} +0 -0
- /package/dist/assets/{ini-SwZZkotR.js → ini-BYrrGNTc.js} +0 -0
- /package/dist/assets/{init-BPLPMQ3Y.js → init-8_PCa3LO.js} +0 -0
- /package/dist/assets/{java-CtRLC4_3.js → java-B211rJbk.js} +0 -0
- /package/dist/assets/{julia-CuJWFKQH.js → julia-DVPsRtBm.js} +0 -0
- /package/dist/assets/{katex-C8DPyI6s.js → katex-C2iYad0m.js} +0 -0
- /package/dist/assets/{kotlin-B_kBhsre.js → kotlin-BYyNerjp.js} +0 -0
- /package/dist/assets/{less-CtrHIfz3.js → less-EC9UblGE.js} +0 -0
- /package/dist/assets/{lexon-yVt1pJLu.js → lexon-B1yuUdqW.js} +0 -0
- /package/dist/assets/{lua-prOwgJ4U.js → lua-Bo6GFzxT.js} +0 -0
- /package/dist/assets/{m3-DhrdTQ84.js → m3-C-Y9cBVI.js} +0 -0
- /package/dist/assets/{markdown-DoI5HwSM.js → markdown-BHu-wLbe.js} +0 -0
- /package/dist/assets/{mermaid-parser.core-BQtepoLd.js → mermaid-parser.core-IxcGtNYG.js} +0 -0
- /package/dist/assets/{mips-Dye5jsBU.js → mips-Dkds26rX.js} +0 -0
- /package/dist/assets/{msdax-TkNOyIL8.js → msdax-PU4g-8_g.js} +0 -0
- /package/dist/assets/{mysql-CEc-RKZF.js → mysql-fPpuGpS7.js} +0 -0
- /package/dist/assets/{objective-c-CqqCsQz0.js → objective-c-Wy1e5JUf.js} +0 -0
- /package/dist/assets/{pascal-DO_pj8yg.js → pascal-BIXwvrqU.js} +0 -0
- /package/dist/assets/{pascaligo-1cbdZdF3.js → pascaligo-DwR0AtL_.js} +0 -0
- /package/dist/assets/{path-YdFzr2W6.js → path-BxQuywGl.js} +0 -0
- /package/dist/assets/{perl-B_N3PYfC.js → perl-CGHAl8my.js} +0 -0
- /package/dist/assets/{pgsql-9iYk1FQ7.js → pgsql-B91M73E2.js} +0 -0
- /package/dist/assets/{php-rO2sgoUM.js → php-C70ttrCx.js} +0 -0
- /package/dist/assets/{pla-Cbgv60kq.js → pla-BNrXaRh0.js} +0 -0
- /package/dist/assets/{postiats-y6xrhy_M.js → postiats-Dv2IAZR9.js} +0 -0
- /package/dist/assets/{powerquery-BaD8gWNE.js → powerquery-CkY5Wq7J.js} +0 -0
- /package/dist/assets/{powershell-BMhG4JVe.js → powershell-uGIYLU3C.js} +0 -0
- /package/dist/assets/{protobuf-CdOP5kN3.js → protobuf-CavfmJu-.js} +0 -0
- /package/dist/assets/{pug-Ck60hNF9.js → pug-Drqnyitx.js} +0 -0
- /package/dist/assets/{qrcode-DV-_rjU8.js → qrcode-7uGsTEmi.js} +0 -0
- /package/dist/assets/{qsharp-BcaKFfP-.js → qsharp-C7yF-Dti.js} +0 -0
- /package/dist/assets/{r-rFNes0iK.js → r-HXLGP0_-.js} +0 -0
- /package/dist/assets/{redis-DkpQ3K6G.js → redis-C4y6mf2p.js} +0 -0
- /package/dist/assets/{redshift-Di9N5TI3.js → redshift-DdQrFPrv.js} +0 -0
- /package/dist/assets/{restructuredtext-By5ZzLt6.js → restructuredtext-CBrf2PNj.js} +0 -0
- /package/dist/assets/{rough.esm-c4PR5shF.js → rough.esm-6CnTHTkH.js} +0 -0
- /package/dist/assets/{ruby-fF5zGiLp.js → ruby-CVtMoX2B.js} +0 -0
- /package/dist/assets/{rust-C5b3AYY6.js → rust-Ckq4sbMP.js} +0 -0
- /package/dist/assets/{sb-CD07UNRs.js → sb-er66OpE3.js} +0 -0
- /package/dist/assets/{scala-jtn1ip9G.js → scala-BdWZz-hH.js} +0 -0
- /package/dist/assets/{scheme-C4vqMkn_.js → scheme-kTV_s2kP.js} +0 -0
- /package/dist/assets/{scss-I4Glxjbz.js → scss-Bymy2VJQ.js} +0 -0
- /package/dist/assets/{shell-DubUcuns.js → shell-bwEP1LQ1.js} +0 -0
- /package/dist/assets/{solidity-CNy2KSl2.js → solidity-DCddeBgL.js} +0 -0
- /package/dist/assets/{sophia-D9_URt84.js → sophia-BMN3AQig.js} +0 -0
- /package/dist/assets/{sparql-DviXpm4C.js → sparql-CSXOLjzi.js} +0 -0
- /package/dist/assets/{sql-vDRbAZgK.js → sql-COg8ewmK.js} +0 -0
- /package/dist/assets/{st-CnpnRqA7.js → st-CIaZtBS_.js} +0 -0
- /package/dist/assets/{swift-D_g8Ganz.js → swift-DXiOhUHu.js} +0 -0
- /package/dist/assets/{systemverilog-OuZa5h1M.js → systemverilog-BTDE6Dr2.js} +0 -0
- /package/dist/assets/{tcl-DBm9ucsV.js → tcl-B0zy9NvV.js} +0 -0
- /package/dist/assets/{twig-BRzEqX5Y.js → twig-D594l4Z1.js} +0 -0
- /package/dist/assets/{typespec-D4ZgGeX8.js → typespec-XKVjaPqo.js} +0 -0
- /package/dist/assets/{useWorkspaceMenuKeyboard-Brws6Ar9.js → useWorkspaceMenuKeyboard-Bpy_s69Z.js} +0 -0
- /package/dist/assets/{vb-DcP4s6WS.js → vb-B2wYoKRV.js} +0 -0
- /package/dist/assets/{wgsl-CnRJ_QUf.js → wgsl-D0Yf2LbK.js} +0 -0
- /package/dist/assets/{workspace-working-copy-D8-s_Sgh.js → workspace-working-copy-C3FSR3N6.js} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const crypto = require('crypto');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
function atomicWriteJson(file, value, options = {}) {
|
|
6
|
+
const fileSystem = options.fileSystem || fs;
|
|
7
|
+
const temporaryFile = `${file}.${process.pid}.${crypto.randomUUID()}.tmp`;
|
|
8
|
+
const suffix = options.trailingNewline ? '\n' : '';
|
|
9
|
+
let descriptor = null;
|
|
10
|
+
|
|
11
|
+
fileSystem.mkdirSync(path.dirname(file), { recursive: true });
|
|
12
|
+
try {
|
|
13
|
+
descriptor = fileSystem.openSync(temporaryFile, 'wx', options.mode);
|
|
14
|
+
fileSystem.writeFileSync(descriptor, `${JSON.stringify(value, null, 2)}${suffix}`, 'utf8');
|
|
15
|
+
fileSystem.fdatasyncSync(descriptor);
|
|
16
|
+
fileSystem.closeSync(descriptor);
|
|
17
|
+
descriptor = null;
|
|
18
|
+
fileSystem.renameSync(temporaryFile, file);
|
|
19
|
+
} finally {
|
|
20
|
+
if (descriptor !== null) {
|
|
21
|
+
try {
|
|
22
|
+
fileSystem.closeSync(descriptor);
|
|
23
|
+
} catch {
|
|
24
|
+
// Preserve the original write failure.
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
fileSystem.unlinkSync(temporaryFile);
|
|
29
|
+
} catch {
|
|
30
|
+
// A successful rename already removed the temporary path.
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
module.exports = {
|
|
36
|
+
atomicWriteJson,
|
|
37
|
+
};
|
package/backend/cli-agents.js
CHANGED
|
@@ -49,7 +49,8 @@ const CLI_AGENTS = [
|
|
|
49
49
|
permissions: {
|
|
50
50
|
supportsDangerousSkip: true,
|
|
51
51
|
dangerousSkipArgs: ['--dangerously-skip-permissions']
|
|
52
|
-
}
|
|
52
|
+
},
|
|
53
|
+
systemPromptArg: '--append-system-prompt'
|
|
53
54
|
},
|
|
54
55
|
{
|
|
55
56
|
name: 'bash',
|
|
@@ -459,12 +460,13 @@ function resolveLaunchCommand(command, options = {}) {
|
|
|
459
460
|
launchArgs.unshift('--permission-mode', claudePermissionMode);
|
|
460
461
|
}
|
|
461
462
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
463
|
+
const systemPrompt = [options.farmingSystemPrompt, options.mainAgentSystemPrompt]
|
|
464
|
+
.filter(value => typeof value === 'string' && value.trim())
|
|
465
|
+
.join('\n\n');
|
|
466
|
+
if (systemPrompt && spec && typeof spec.systemPromptArg === 'string') {
|
|
467
|
+
launchArgs.push(spec.systemPromptArg, systemPrompt);
|
|
468
|
+
} else if (systemPrompt && spec?.name === 'codex') {
|
|
469
|
+
launchArgs.unshift('-c', `developer_instructions=${JSON.stringify(systemPrompt)}`);
|
|
468
470
|
}
|
|
469
471
|
|
|
470
472
|
return {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const os = require('os');
|
|
4
|
+
const { atomicWriteJson } = require('./atomic-json-store');
|
|
4
5
|
const { ensureMainAgentSkillFiles } = require('./main-agent-skills');
|
|
6
|
+
const { ensureFarmingAgentBootstrapFile } = require('./farming-agent-bootstrap');
|
|
5
7
|
const { normalizeClaudeModelValue } = require('./claude-settings');
|
|
6
8
|
const { isTemporaryProviderSessionId } = require('./provider-session-id');
|
|
7
9
|
const { FarmingSessionStore, MAX_MAIN_PAGE_SESSION_KEYS } = require('./farming-session-store');
|
|
@@ -68,6 +70,8 @@ const DEFAULT_CRT_TERMINAL_FONT_SIZE = 15;
|
|
|
68
70
|
const MIN_CRT_TERMINAL_FONT_SIZE = 10;
|
|
69
71
|
const MAX_CRT_TERMINAL_FONT_SIZE = 20;
|
|
70
72
|
const MAX_INSTANCE_NAME_LENGTH = 80;
|
|
73
|
+
const MAX_PROJECT_OPERATIONS = 32;
|
|
74
|
+
const PROJECT_OPERATION_ID_PATTERN = /^[A-Za-z0-9._:-]{1,160}$/;
|
|
71
75
|
|
|
72
76
|
const PERSISTED_SETTING_KEYS = new Set([
|
|
73
77
|
'workspace',
|
|
@@ -76,12 +80,18 @@ const PERSISTED_SETTING_KEYS = new Set([
|
|
|
76
80
|
'projectWorkspaces',
|
|
77
81
|
'pinnedProjectWorkspaces',
|
|
78
82
|
'projectNames',
|
|
83
|
+
'projectOperations',
|
|
79
84
|
'instanceName',
|
|
80
85
|
'theme',
|
|
81
86
|
'appearance',
|
|
82
87
|
'language',
|
|
88
|
+
'restReminderIntervalSeconds',
|
|
83
89
|
'heartbeatInterval',
|
|
84
90
|
'dangerouslySkipAgentPermissionsByDefault',
|
|
91
|
+
'browserExtensionEnabled',
|
|
92
|
+
'browserSource',
|
|
93
|
+
'browserExecutablePath',
|
|
94
|
+
'browserExternalCdpUrl',
|
|
85
95
|
'crtSkinEffectsEnabled',
|
|
86
96
|
'crtDynamicHeatEnabled',
|
|
87
97
|
'crtTerminalFontSize',
|
|
@@ -113,8 +123,8 @@ function cloneAgentHomes(agentHomes) {
|
|
|
113
123
|
}
|
|
114
124
|
|
|
115
125
|
class ConfigManager {
|
|
116
|
-
constructor() {
|
|
117
|
-
this.farmingDir = storageLayout.farmingConfigDir();
|
|
126
|
+
constructor(options = {}) {
|
|
127
|
+
this.farmingDir = options.configDir || storageLayout.farmingConfigDir();
|
|
118
128
|
this.settingsFile = storageLayout.settingsFile(this.farmingDir);
|
|
119
129
|
this.sessionStore = new FarmingSessionStore(this.farmingDir, {
|
|
120
130
|
normalizeMainPageSessionKeys: keys => this.normalizeMainPageSessionKeys(keys),
|
|
@@ -122,6 +132,7 @@ class ConfigManager {
|
|
|
122
132
|
this.runHistoryStore = new RunHistoryStore(this.farmingDir, {
|
|
123
133
|
normalizeTaskHistory: entries => this.normalizeTaskHistory(entries),
|
|
124
134
|
});
|
|
135
|
+
this.writeJson = typeof options.writeJson === 'function' ? options.writeJson : atomicWriteJson;
|
|
125
136
|
this.settings = null;
|
|
126
137
|
}
|
|
127
138
|
|
|
@@ -221,7 +232,7 @@ class ConfigManager {
|
|
|
221
232
|
const expanded = this.expandWorkspacePath(entry);
|
|
222
233
|
if (!expanded) continue;
|
|
223
234
|
const resolved = path.resolve(expanded);
|
|
224
|
-
if (
|
|
235
|
+
if (this.isInternalWorkspace(resolved)) continue;
|
|
225
236
|
let canonical = resolved;
|
|
226
237
|
try {
|
|
227
238
|
canonical = fs.realpathSync(resolved);
|
|
@@ -305,12 +316,18 @@ class ConfigManager {
|
|
|
305
316
|
projectWorkspaces: [],
|
|
306
317
|
pinnedProjectWorkspaces: [],
|
|
307
318
|
projectNames: {},
|
|
319
|
+
projectOperations: {},
|
|
308
320
|
instanceName: '',
|
|
309
321
|
theme: 'terminal',
|
|
310
322
|
appearance: 'system',
|
|
311
323
|
language: 'en',
|
|
324
|
+
restReminderIntervalSeconds: null,
|
|
312
325
|
heartbeatInterval: 1000,
|
|
313
326
|
dangerouslySkipAgentPermissionsByDefault: false,
|
|
327
|
+
browserExtensionEnabled: false,
|
|
328
|
+
browserSource: process.env.FARMING_BROWSER_CDP_URL ? 'external-cdp' : 'system',
|
|
329
|
+
browserExecutablePath: process.env.FARMING_BROWSER_EXECUTABLE || '',
|
|
330
|
+
browserExternalCdpUrl: process.env.FARMING_BROWSER_CDP_URL || 'http://127.0.0.1:9222',
|
|
314
331
|
crtSkinEffectsEnabled: true,
|
|
315
332
|
crtDynamicHeatEnabled: false,
|
|
316
333
|
crtTerminalFontSize: DEFAULT_CRT_TERMINAL_FONT_SIZE,
|
|
@@ -329,7 +346,7 @@ class ConfigManager {
|
|
|
329
346
|
codexModelPreset: 'gpt-5.5:xhigh',
|
|
330
347
|
version: '2'
|
|
331
348
|
};
|
|
332
|
-
|
|
349
|
+
this.writeSettingsFile(defaultSettings);
|
|
333
350
|
console.log('Created default settings:', this.settingsFile);
|
|
334
351
|
}
|
|
335
352
|
|
|
@@ -341,12 +358,18 @@ class ConfigManager {
|
|
|
341
358
|
projectWorkspaces: [],
|
|
342
359
|
pinnedProjectWorkspaces: [],
|
|
343
360
|
projectNames: {},
|
|
361
|
+
projectOperations: {},
|
|
344
362
|
instanceName: '',
|
|
345
363
|
theme: 'terminal',
|
|
346
364
|
appearance: 'system',
|
|
347
365
|
language: 'en',
|
|
366
|
+
restReminderIntervalSeconds: null,
|
|
348
367
|
heartbeatInterval: 1000,
|
|
349
368
|
dangerouslySkipAgentPermissionsByDefault: false,
|
|
369
|
+
browserExtensionEnabled: false,
|
|
370
|
+
browserSource: process.env.FARMING_BROWSER_CDP_URL ? 'external-cdp' : 'system',
|
|
371
|
+
browserExecutablePath: process.env.FARMING_BROWSER_EXECUTABLE || '',
|
|
372
|
+
browserExternalCdpUrl: process.env.FARMING_BROWSER_CDP_URL || 'http://127.0.0.1:9222',
|
|
350
373
|
crtSkinEffectsEnabled: true,
|
|
351
374
|
crtDynamicHeatEnabled: false,
|
|
352
375
|
crtTerminalFontSize: DEFAULT_CRT_TERMINAL_FONT_SIZE,
|
|
@@ -391,6 +414,7 @@ class ConfigManager {
|
|
|
391
414
|
this.settings.projectWorkspaces = this.normalizeProjectWorkspaces(this.settings.projectWorkspaces);
|
|
392
415
|
this.settings.pinnedProjectWorkspaces = this.normalizeProjectWorkspaces(this.settings.pinnedProjectWorkspaces);
|
|
393
416
|
this.settings.projectNames = this.normalizeProjectNames(this.settings.projectNames);
|
|
417
|
+
this.settings.projectOperations = this.normalizeProjectOperations(this.settings.projectOperations);
|
|
394
418
|
this.settings.instanceName = this.normalizeInstanceName(this.settings.instanceName);
|
|
395
419
|
this.settings.agentHomes = this.normalizeAgentHomes(this.settings.agentHomes);
|
|
396
420
|
if (this.settings.updateUrl === LEGACY_DEFAULT_UPDATE_URL || this.settings.updateUrl === API_DEFAULT_UPDATE_URL) {
|
|
@@ -407,20 +431,29 @@ class ConfigManager {
|
|
|
407
431
|
this.runHistoryStore.init({ legacyTaskHistory });
|
|
408
432
|
this.settings.appearance = this.normalizeAppearance(this.settings.appearance);
|
|
409
433
|
this.settings.language = this.normalizeLanguage(this.settings.language);
|
|
434
|
+
this.settings.restReminderIntervalSeconds = this.normalizeRestReminderIntervalSeconds(
|
|
435
|
+
this.settings.restReminderIntervalSeconds,
|
|
436
|
+
);
|
|
437
|
+
this.settings.browserExtensionEnabled = this.settings.browserExtensionEnabled === true;
|
|
438
|
+
this.settings.browserSource = this.normalizeBrowserSource(this.settings.browserSource);
|
|
439
|
+
this.settings.browserExecutablePath = this.normalizeBrowserSetting(this.settings.browserExecutablePath);
|
|
440
|
+
this.settings.browserExternalCdpUrl = this.normalizeBrowserSetting(this.settings.browserExternalCdpUrl)
|
|
441
|
+
|| 'http://127.0.0.1:9222';
|
|
410
442
|
this.settings.crtSkinEffectsEnabled = this.settings.crtSkinEffectsEnabled !== false;
|
|
411
443
|
this.settings.crtDynamicHeatEnabled = this.settings.crtDynamicHeatEnabled === true;
|
|
412
444
|
this.settings.crtTerminalFontSize = this.normalizeCrtTerminalFontSize(this.settings.crtTerminalFontSize);
|
|
413
445
|
this.normalizeAgentLaunchSettings(launchRawSettings);
|
|
414
446
|
this.pruneUnknownSettings();
|
|
415
447
|
ensureMainAgentSkillFiles(this.farmingDir);
|
|
448
|
+
ensureFarmingAgentBootstrapFile(this.farmingDir);
|
|
416
449
|
this.writeSettingsFile();
|
|
417
450
|
console.log('Loaded settings:', this.settings);
|
|
418
451
|
}
|
|
419
452
|
|
|
420
|
-
pruneUnknownSettings() {
|
|
421
|
-
for (const key of Object.keys(
|
|
453
|
+
pruneUnknownSettings(settings = this.settings) {
|
|
454
|
+
for (const key of Object.keys(settings || {})) {
|
|
422
455
|
if (!PERSISTED_SETTING_KEYS.has(key)) {
|
|
423
|
-
delete
|
|
456
|
+
delete settings[key];
|
|
424
457
|
}
|
|
425
458
|
}
|
|
426
459
|
}
|
|
@@ -438,6 +471,16 @@ class ConfigManager {
|
|
|
438
471
|
);
|
|
439
472
|
}
|
|
440
473
|
|
|
474
|
+
normalizeRestReminderIntervalSeconds(value) {
|
|
475
|
+
if (value === null || value === undefined || value === '') return null;
|
|
476
|
+
const seconds = Number(value);
|
|
477
|
+
if (!Number.isInteger(seconds)) return null;
|
|
478
|
+
if (seconds === 0 || seconds === 5) return seconds;
|
|
479
|
+
return seconds >= 60 && seconds <= 240 * 60 && seconds % 60 === 0
|
|
480
|
+
? seconds
|
|
481
|
+
: null;
|
|
482
|
+
}
|
|
483
|
+
|
|
441
484
|
normalizeCrtTerminalFontSize(value) {
|
|
442
485
|
const fontSize = Number(value);
|
|
443
486
|
if (!Number.isFinite(fontSize)) return DEFAULT_CRT_TERMINAL_FONT_SIZE;
|
|
@@ -498,16 +541,59 @@ class ConfigManager {
|
|
|
498
541
|
return normalized;
|
|
499
542
|
}
|
|
500
543
|
|
|
544
|
+
normalizeProjectOperations(projectOperations) {
|
|
545
|
+
if (!projectOperations || typeof projectOperations !== 'object' || Array.isArray(projectOperations)) return {};
|
|
546
|
+
const entries = Object.entries(projectOperations)
|
|
547
|
+
.filter(([id, operation]) => (
|
|
548
|
+
PROJECT_OPERATION_ID_PATTERN.test(id)
|
|
549
|
+
&& operation
|
|
550
|
+
&& typeof operation === 'object'
|
|
551
|
+
&& ['create-worktree', 'delete-worktree'].includes(operation.type)
|
|
552
|
+
&& ['pending', 'unknown', 'succeeded', 'failed', 'blocked'].includes(operation.state)
|
|
553
|
+
))
|
|
554
|
+
.sort((left, right) => (Number(right[1].updatedAt) || 0) - (Number(left[1].updatedAt) || 0))
|
|
555
|
+
.map(([id, operation]) => [id, {
|
|
556
|
+
id,
|
|
557
|
+
type: operation.type,
|
|
558
|
+
state: operation.state,
|
|
559
|
+
signature: typeof operation.signature === 'string' ? operation.signature.slice(0, 128) : '',
|
|
560
|
+
request: operation.request && typeof operation.request === 'object'
|
|
561
|
+
? JSON.parse(JSON.stringify(operation.request))
|
|
562
|
+
: {},
|
|
563
|
+
result: operation.result && typeof operation.result === 'object'
|
|
564
|
+
? JSON.parse(JSON.stringify(operation.result))
|
|
565
|
+
: null,
|
|
566
|
+
error: typeof operation.error === 'string' ? operation.error.slice(0, 2000) : '',
|
|
567
|
+
startedAt: Number(operation.startedAt) || 0,
|
|
568
|
+
updatedAt: Number(operation.updatedAt) || 0,
|
|
569
|
+
finishedAt: Number(operation.finishedAt) || null,
|
|
570
|
+
}]);
|
|
571
|
+
const unresolved = entries.filter(([, operation]) => (
|
|
572
|
+
['pending', 'unknown', 'blocked'].includes(operation.state)
|
|
573
|
+
));
|
|
574
|
+
const terminal = entries.filter(([, operation]) => (
|
|
575
|
+
!['pending', 'unknown', 'blocked'].includes(operation.state)
|
|
576
|
+
));
|
|
577
|
+
return Object.fromEntries([
|
|
578
|
+
...unresolved,
|
|
579
|
+
...terminal.slice(0, Math.max(0, MAX_PROJECT_OPERATIONS - unresolved.length)),
|
|
580
|
+
]);
|
|
581
|
+
}
|
|
582
|
+
|
|
501
583
|
setProjectName(workspace, name) {
|
|
502
584
|
const normalized = this.normalizeProjectNames({ [workspace]: name });
|
|
503
585
|
const entry = Object.entries(normalized)[0];
|
|
504
586
|
if (!entry) throw new Error('Project workspace and name are required');
|
|
505
587
|
const [normalizedWorkspace, normalizedName] = entry;
|
|
506
|
-
|
|
507
|
-
...this.settings
|
|
508
|
-
|
|
588
|
+
const nextSettings = {
|
|
589
|
+
...this.settings,
|
|
590
|
+
projectNames: {
|
|
591
|
+
...this.settings.projectNames,
|
|
592
|
+
[normalizedWorkspace]: normalizedName,
|
|
593
|
+
},
|
|
509
594
|
};
|
|
510
|
-
this.writeSettingsFile();
|
|
595
|
+
this.writeSettingsFile(nextSettings);
|
|
596
|
+
this.settings = nextSettings;
|
|
511
597
|
return {
|
|
512
598
|
workspace: normalizedWorkspace,
|
|
513
599
|
name: normalizedName,
|
|
@@ -522,6 +608,14 @@ class ConfigManager {
|
|
|
522
608
|
return ['en', 'zh'].includes(language) ? language : 'en';
|
|
523
609
|
}
|
|
524
610
|
|
|
611
|
+
normalizeBrowserSource(source) {
|
|
612
|
+
return source === 'external-cdp' ? source : 'system';
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
normalizeBrowserSetting(value) {
|
|
616
|
+
return String(value || '').trim().slice(0, 2000);
|
|
617
|
+
}
|
|
618
|
+
|
|
525
619
|
normalizeUpdateUrl(value) {
|
|
526
620
|
const url = String(value || '').trim();
|
|
527
621
|
if (!url) return DEFAULT_UPDATE_URL;
|
|
@@ -668,23 +762,23 @@ class ConfigManager {
|
|
|
668
762
|
return merged;
|
|
669
763
|
}
|
|
670
764
|
|
|
671
|
-
applyCodexProfileToLegacySettings(codexProfile) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
765
|
+
applyCodexProfileToLegacySettings(codexProfile, settings = this.settings) {
|
|
766
|
+
settings.codexApprovalMode = codexProfile.approvalMode;
|
|
767
|
+
settings.codexModel = codexProfile.model;
|
|
768
|
+
settings.codexReasoningEffort = codexProfile.reasoningEffort;
|
|
769
|
+
settings.codexServiceTier = codexProfile.serviceTier;
|
|
770
|
+
settings.codexModelPreset = codexProfile.modelPreset;
|
|
677
771
|
}
|
|
678
772
|
|
|
679
|
-
normalizeAgentLaunchSettings(rawSettings = {}) {
|
|
773
|
+
normalizeAgentLaunchSettings(rawSettings = {}, settings = this.settings) {
|
|
680
774
|
const changedProfiles = this.getChangedAgentLaunchProfiles(rawSettings);
|
|
681
|
-
const mergedProfiles = this.mergeAgentLaunchProfiles(
|
|
682
|
-
|
|
775
|
+
const mergedProfiles = this.mergeAgentLaunchProfiles(settings.agentLaunchProfiles, changedProfiles);
|
|
776
|
+
settings.agentLaunchProfiles = {
|
|
683
777
|
codex: this.normalizeCodexLaunchProfile(mergedProfiles.codex, changedProfiles.codex || {}),
|
|
684
778
|
claude: this.normalizeClaudeLaunchProfile(mergedProfiles.claude),
|
|
685
779
|
};
|
|
686
|
-
|
|
687
|
-
this.applyCodexProfileToLegacySettings(
|
|
780
|
+
settings.defaultLaunchAgent = this.normalizeDefaultLaunchAgent(settings.defaultLaunchAgent);
|
|
781
|
+
this.applyCodexProfileToLegacySettings(settings.agentLaunchProfiles.codex, settings);
|
|
688
782
|
}
|
|
689
783
|
|
|
690
784
|
getWorkspace() {
|
|
@@ -760,8 +854,10 @@ class ConfigManager {
|
|
|
760
854
|
}
|
|
761
855
|
|
|
762
856
|
getSettings() {
|
|
857
|
+
const publicSettings = { ...this.settings };
|
|
858
|
+
delete publicSettings.projectOperations;
|
|
763
859
|
return {
|
|
764
|
-
...
|
|
860
|
+
...publicSettings,
|
|
765
861
|
instanceName: this.getInstanceName(),
|
|
766
862
|
workspace: this.farmingDir,
|
|
767
863
|
mainPageSessionKeys: this.getMainPageSessionKeys(),
|
|
@@ -783,7 +879,6 @@ class ConfigManager {
|
|
|
783
879
|
}
|
|
784
880
|
if (
|
|
785
881
|
!canonicalWorkspace
|
|
786
|
-
|| canonicalWorkspace === path.parse(canonicalWorkspace).root
|
|
787
882
|
|| this.isInternalWorkspace(canonicalWorkspace)
|
|
788
883
|
) {
|
|
789
884
|
throw new Error('Project workspace is invalid or unavailable');
|
|
@@ -860,6 +955,64 @@ class ConfigManager {
|
|
|
860
955
|
}
|
|
861
956
|
}
|
|
862
957
|
|
|
958
|
+
getProjectOperation(requestId) {
|
|
959
|
+
const id = String(requestId || '').trim();
|
|
960
|
+
if (!PROJECT_OPERATION_ID_PATTERN.test(id)) return null;
|
|
961
|
+
const operation = this.settings.projectOperations?.[id];
|
|
962
|
+
return operation ? JSON.parse(JSON.stringify(operation)) : null;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
commitProjectOperation(operation, membership = {}) {
|
|
966
|
+
const normalized = this.normalizeProjectOperations({ [operation?.id]: operation });
|
|
967
|
+
const nextOperation = normalized[operation?.id];
|
|
968
|
+
if (!nextOperation) throw new Error('Project operation is invalid');
|
|
969
|
+
const existingOperation = this.settings.projectOperations?.[nextOperation.id];
|
|
970
|
+
const unresolvedCount = Object.values(this.settings.projectOperations || {})
|
|
971
|
+
.filter(candidate => ['pending', 'unknown', 'blocked'].includes(candidate.state)).length;
|
|
972
|
+
if (!existingOperation && nextOperation.state === 'pending' && unresolvedCount >= MAX_PROJECT_OPERATIONS) {
|
|
973
|
+
throw new Error('Too many unresolved Project operations require reconciliation');
|
|
974
|
+
}
|
|
975
|
+
const nextOperations = this.normalizeProjectOperations({
|
|
976
|
+
...this.settings.projectOperations,
|
|
977
|
+
[nextOperation.id]: nextOperation,
|
|
978
|
+
});
|
|
979
|
+
const nextSettings = {
|
|
980
|
+
...this.settings,
|
|
981
|
+
projectOperations: nextOperations,
|
|
982
|
+
};
|
|
983
|
+
if (membership.mountWorkspace) {
|
|
984
|
+
const mounted = this.normalizeProjectWorkspaces([
|
|
985
|
+
membership.mountWorkspace,
|
|
986
|
+
...(this.settings.projectWorkspaces || []),
|
|
987
|
+
]);
|
|
988
|
+
nextSettings.projectWorkspaces = mounted;
|
|
989
|
+
nextSettings.pinnedProjectWorkspaces = this.normalizeProjectWorkspaces(
|
|
990
|
+
this.settings.pinnedProjectWorkspaces,
|
|
991
|
+
);
|
|
992
|
+
}
|
|
993
|
+
if (membership.removeWorkspace) {
|
|
994
|
+
const expanded = this.expandWorkspacePath(membership.removeWorkspace);
|
|
995
|
+
const resolved = expanded ? path.resolve(expanded) : '';
|
|
996
|
+
const candidates = new Set([expanded, resolved].filter(Boolean));
|
|
997
|
+
try {
|
|
998
|
+
candidates.add(fs.realpathSync(resolved));
|
|
999
|
+
} catch {
|
|
1000
|
+
// A deleted worktree is removed by its last canonical path.
|
|
1001
|
+
}
|
|
1002
|
+
nextSettings.projectWorkspaces = (this.settings.projectWorkspaces || [])
|
|
1003
|
+
.filter(workspace => !candidates.has(workspace));
|
|
1004
|
+
nextSettings.pinnedProjectWorkspaces = (this.settings.pinnedProjectWorkspaces || [])
|
|
1005
|
+
.filter(workspace => !candidates.has(workspace));
|
|
1006
|
+
}
|
|
1007
|
+
this.writeSettingsFile(nextSettings);
|
|
1008
|
+
this.settings = nextSettings;
|
|
1009
|
+
return {
|
|
1010
|
+
operation: JSON.parse(JSON.stringify(nextOperation)),
|
|
1011
|
+
projectWorkspaces: [...(nextSettings.projectWorkspaces || [])],
|
|
1012
|
+
pinnedProjectWorkspaces: [...(nextSettings.pinnedProjectWorkspaces || [])],
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
|
|
863
1016
|
getMainPageSessionKeys() {
|
|
864
1017
|
return this.sessionStore ? this.sessionStore.getMainPageSessionKeys() : [];
|
|
865
1018
|
}
|
|
@@ -904,19 +1057,8 @@ class ConfigManager {
|
|
|
904
1057
|
return this.runHistoryStore ? this.runHistoryStore.getEntries() : [];
|
|
905
1058
|
}
|
|
906
1059
|
|
|
907
|
-
writeSettingsFile() {
|
|
908
|
-
|
|
909
|
-
const tempFile = `${this.settingsFile}.${process.pid}.${Date.now()}.tmp`;
|
|
910
|
-
try {
|
|
911
|
-
fs.writeFileSync(tempFile, JSON.stringify(this.settings, null, 2));
|
|
912
|
-
fs.renameSync(tempFile, this.settingsFile);
|
|
913
|
-
} finally {
|
|
914
|
-
try {
|
|
915
|
-
fs.unlinkSync(tempFile);
|
|
916
|
-
} catch {
|
|
917
|
-
// A successful rename already removed the temporary path.
|
|
918
|
-
}
|
|
919
|
-
}
|
|
1060
|
+
writeSettingsFile(settings = this.settings) {
|
|
1061
|
+
this.writeJson(this.settingsFile, settings);
|
|
920
1062
|
}
|
|
921
1063
|
|
|
922
1064
|
appendTaskHistory(entry) {
|
|
@@ -930,6 +1072,7 @@ class ConfigManager {
|
|
|
930
1072
|
: undefined;
|
|
931
1073
|
const settingsPatch = { ...(newSettings || {}) };
|
|
932
1074
|
delete settingsPatch.mainPageSessionKeys;
|
|
1075
|
+
delete settingsPatch.projectOperations;
|
|
933
1076
|
const incomingTaskHistory = Object.prototype.hasOwnProperty.call(settingsPatch, 'taskHistory')
|
|
934
1077
|
? settingsPatch.taskHistory
|
|
935
1078
|
: undefined;
|
|
@@ -937,38 +1080,48 @@ class ConfigManager {
|
|
|
937
1080
|
const previousMainWorkspace = this.settings.lastMainWorkspace || this.farmingDir;
|
|
938
1081
|
const previousProfiles = this.settings.agentLaunchProfiles || {};
|
|
939
1082
|
const incomingProfiles = settingsPatch.agentLaunchProfiles || {};
|
|
940
|
-
|
|
1083
|
+
const nextSettings = {
|
|
941
1084
|
...this.settings,
|
|
942
1085
|
...settingsPatch,
|
|
943
1086
|
agentLaunchProfiles: this.mergeAgentLaunchProfiles(previousProfiles, incomingProfiles),
|
|
944
1087
|
workspace: this.farmingDir
|
|
945
1088
|
};
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
delete
|
|
957
|
-
delete
|
|
1089
|
+
nextSettings.lastMainWorkspace = this.normalizeMainWorkspace(nextSettings.lastMainWorkspace, previousMainWorkspace);
|
|
1090
|
+
nextSettings.workspaceHistory = this.normalizeWorkspaceHistory(nextSettings.workspaceHistory);
|
|
1091
|
+
nextSettings.projectWorkspaces = this.normalizeProjectWorkspaces(nextSettings.projectWorkspaces);
|
|
1092
|
+
nextSettings.pinnedProjectWorkspaces = this.normalizeProjectWorkspaces(nextSettings.pinnedProjectWorkspaces);
|
|
1093
|
+
nextSettings.projectNames = this.normalizeProjectNames(nextSettings.projectNames);
|
|
1094
|
+
nextSettings.projectOperations = this.normalizeProjectOperations(nextSettings.projectOperations);
|
|
1095
|
+
nextSettings.instanceName = this.normalizeInstanceName(nextSettings.instanceName);
|
|
1096
|
+
nextSettings.agentHomes = this.normalizeAgentHomes(nextSettings.agentHomes);
|
|
1097
|
+
nextSettings.updateUrl = this.normalizeUpdateUrl(nextSettings.updateUrl);
|
|
1098
|
+
nextSettings.searchTimeoutMs = this.normalizeSearchTimeoutMs(nextSettings.searchTimeoutMs);
|
|
1099
|
+
delete nextSettings.codexRuntimeMode;
|
|
1100
|
+
delete nextSettings.mainPageSessionKeys;
|
|
1101
|
+
delete nextSettings.taskHistory;
|
|
958
1102
|
if (incomingMainPageSessionKeys !== undefined) {
|
|
959
1103
|
this.setMainPageSessionKeys(incomingMainPageSessionKeys);
|
|
960
1104
|
}
|
|
961
1105
|
if (incomingTaskHistory !== undefined && this.runHistoryStore) {
|
|
962
1106
|
this.runHistoryStore.setEntries(incomingTaskHistory);
|
|
963
1107
|
}
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
this.
|
|
971
|
-
this.
|
|
1108
|
+
nextSettings.appearance = this.normalizeAppearance(nextSettings.appearance);
|
|
1109
|
+
nextSettings.language = this.normalizeLanguage(nextSettings.language);
|
|
1110
|
+
nextSettings.restReminderIntervalSeconds = this.normalizeRestReminderIntervalSeconds(
|
|
1111
|
+
nextSettings.restReminderIntervalSeconds,
|
|
1112
|
+
);
|
|
1113
|
+
nextSettings.browserExtensionEnabled = nextSettings.browserExtensionEnabled === true;
|
|
1114
|
+
nextSettings.browserSource = this.normalizeBrowserSource(nextSettings.browserSource);
|
|
1115
|
+
nextSettings.browserExecutablePath = this.normalizeBrowserSetting(nextSettings.browserExecutablePath);
|
|
1116
|
+
nextSettings.browserExternalCdpUrl = this.normalizeBrowserSetting(nextSettings.browserExternalCdpUrl)
|
|
1117
|
+
|| 'http://127.0.0.1:9222';
|
|
1118
|
+
nextSettings.crtSkinEffectsEnabled = nextSettings.crtSkinEffectsEnabled !== false;
|
|
1119
|
+
nextSettings.crtDynamicHeatEnabled = nextSettings.crtDynamicHeatEnabled === true;
|
|
1120
|
+
nextSettings.crtTerminalFontSize = this.normalizeCrtTerminalFontSize(nextSettings.crtTerminalFontSize);
|
|
1121
|
+
this.normalizeAgentLaunchSettings(settingsPatch, nextSettings);
|
|
1122
|
+
this.pruneUnknownSettings(nextSettings);
|
|
1123
|
+
this.writeSettingsFile(nextSettings);
|
|
1124
|
+
this.settings = nextSettings;
|
|
972
1125
|
}
|
|
973
1126
|
}
|
|
974
1127
|
|
package/backend/control-api.js
CHANGED
|
@@ -419,9 +419,10 @@ function createControlRouter(agentManager, options = {}) {
|
|
|
419
419
|
|
|
420
420
|
router.delete('/agents/:agentId', async (req, res) => {
|
|
421
421
|
const agentId = req.params.agentId;
|
|
422
|
+
const recordHistory = req.query?.recordHistory !== '0';
|
|
422
423
|
let requested;
|
|
423
424
|
try {
|
|
424
|
-
requested = await agentManager.requestKillAgent(agentId);
|
|
425
|
+
requested = await agentManager.requestKillAgent(agentId, { recordHistory });
|
|
425
426
|
} catch (error) {
|
|
426
427
|
res.status(503).json({
|
|
427
428
|
error: error?.message || 'Agent lifecycle recovery is unavailable',
|