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
|
@@ -8,6 +8,12 @@ const { URLSearchParams } = require('url');
|
|
|
8
8
|
const { execFileSync, spawn } = require('child_process');
|
|
9
9
|
const { run: runControlCli } = require('./farming-cli');
|
|
10
10
|
const { PACKAGED_CODEX_ACP_ARG, runPackagedCodexAcp } = require('./acp/packaged-codex-acp');
|
|
11
|
+
const { PACKAGED_CLAUDE_ACP_ARG, runPackagedClaudeAcp } = require('./acp/packaged-claude-acp');
|
|
12
|
+
const {
|
|
13
|
+
SERVER_PROCESS_IDENTITY_FORMAT,
|
|
14
|
+
matchingProcessIdentity,
|
|
15
|
+
readServerProcessIdentity,
|
|
16
|
+
} = require('./server-process-identity');
|
|
11
17
|
const storageLayout = require('./storage-layout');
|
|
12
18
|
|
|
13
19
|
const SERVER_MODE_ARG = '--farming-server';
|
|
@@ -20,10 +26,9 @@ const DEFAULT_SERVER_START_TIMEOUT_MS = 30_000;
|
|
|
20
26
|
const DEFAULT_SERVER_START_STABILITY_MS = 1_500;
|
|
21
27
|
const DEFAULT_SERVER_STOP_TIMEOUT_MS = 30_000;
|
|
22
28
|
const SERVER_STOP_POLL_MS = 100;
|
|
23
|
-
const SERVER_PROCESS_IDENTITY_FORMAT = 'ps-lstart-c-utc-v1';
|
|
24
29
|
const SERVER_COMMANDS = new Set(['start', 'serve', 'daemon', 'stop', 'status', 'logs', 'url', 'help']);
|
|
25
|
-
const CONTROL_COMMANDS = new Set(['skills', 'memory', 'report', 'list', 'spawn', 'output', 'send', 'kill']);
|
|
26
|
-
const SERVER_BACKED_CONTROL_COMMANDS = new Set(['list', 'spawn', 'output', 'send', 'kill']);
|
|
30
|
+
const CONTROL_COMMANDS = new Set(['skills', 'capabilities', 'memory', 'report', 'list', 'spawn', 'output', 'send', 'kill']);
|
|
31
|
+
const SERVER_BACKED_CONTROL_COMMANDS = new Set(['capabilities', 'list', 'spawn', 'output', 'send', 'kill']);
|
|
27
32
|
|
|
28
33
|
function defaultConfigDir(env = process.env) {
|
|
29
34
|
return storageLayout.farmingConfigDir(env);
|
|
@@ -437,7 +442,9 @@ function childInvocation(env = process.env) {
|
|
|
437
442
|
// making daemon ownership impossible to prove on Linux.
|
|
438
443
|
return {
|
|
439
444
|
command: '/usr/bin/env',
|
|
440
|
-
|
|
445
|
+
// FARMING_RUN_SERVER selects the embedded server entry. Do not append a
|
|
446
|
+
// sentinel argument: pkg may interpret it as an external script path.
|
|
447
|
+
args: buildCleanEnvExecArgs(env, process.execPath),
|
|
441
448
|
};
|
|
442
449
|
}
|
|
443
450
|
const nodePath = env.FARMING_NODE_BIN || process.execPath;
|
|
@@ -482,45 +489,20 @@ function canonicalConfigDir(configDir) {
|
|
|
482
489
|
}
|
|
483
490
|
}
|
|
484
491
|
|
|
485
|
-
|
|
486
|
-
const processId = Number(pid);
|
|
487
|
-
if (!Number.isSafeInteger(processId) || processId <= 0 || process.platform === 'win32') return null;
|
|
488
|
-
let stdout;
|
|
489
|
-
try {
|
|
490
|
-
stdout = execFileSync(
|
|
491
|
-
'/bin/ps',
|
|
492
|
-
['-p', String(processId), '-o', 'pid=', '-o', 'pgid=', '-o', 'lstart='],
|
|
493
|
-
{
|
|
494
|
-
encoding: 'utf8',
|
|
495
|
-
timeout: 1_000,
|
|
496
|
-
maxBuffer: 16_384,
|
|
497
|
-
env: { ...process.env, LANG: 'C', LC_ALL: 'C', TZ: 'UTC' },
|
|
498
|
-
},
|
|
499
|
-
);
|
|
500
|
-
} catch (error) {
|
|
501
|
-
if (error?.status === 1 || error?.code === 'ESRCH') return null;
|
|
502
|
-
throw error;
|
|
503
|
-
}
|
|
504
|
-
const match = String(stdout || '').trim().match(/^(\d+)\s+(\d+)\s+(.+)$/);
|
|
505
|
-
if (!match || Number(match[1]) !== processId) return null;
|
|
506
|
-
return {
|
|
507
|
-
pid: processId,
|
|
508
|
-
processGroupId: Number(match[2]),
|
|
509
|
-
startedAt: match[3].trim(),
|
|
510
|
-
format: SERVER_PROCESS_IDENTITY_FORMAT,
|
|
511
|
-
};
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
function writeServerState(configDir, env, pid, processIdentity) {
|
|
492
|
+
function writeServerState(configDir, env, pid, processIdentity, phase = 'running') {
|
|
515
493
|
const state = {
|
|
516
494
|
pid,
|
|
517
495
|
port: Number(env.PORT || DEFAULT_PORT),
|
|
518
496
|
basePath: env.FARMING_BASE_PATH || DEFAULT_BASE_PATH,
|
|
519
497
|
configDir: canonicalConfigDir(configDir),
|
|
520
498
|
processIdentity,
|
|
499
|
+
phase,
|
|
521
500
|
updatedAt: new Date().toISOString(),
|
|
522
501
|
};
|
|
523
|
-
|
|
502
|
+
const target = serverStateFile(configDir);
|
|
503
|
+
const temporary = `${target}.${process.pid}.tmp`;
|
|
504
|
+
fs.writeFileSync(temporary, `${JSON.stringify(state, null, 2)}\n`, { mode: 0o600 });
|
|
505
|
+
fs.renameSync(temporary, target);
|
|
524
506
|
}
|
|
525
507
|
|
|
526
508
|
function processLooksLikeFarmingServer(pid) {
|
|
@@ -664,15 +646,6 @@ function processOwnsListeningPort(pid, port) {
|
|
|
664
646
|
}
|
|
665
647
|
}
|
|
666
648
|
|
|
667
|
-
function matchingProcessIdentity(expected, current) {
|
|
668
|
-
return Boolean(
|
|
669
|
-
current
|
|
670
|
-
&& current.pid === Number(expected?.pid)
|
|
671
|
-
&& current.processGroupId === Number(expected?.processGroupId)
|
|
672
|
-
&& current.startedAt === String(expected?.startedAt || '')
|
|
673
|
-
);
|
|
674
|
-
}
|
|
675
|
-
|
|
676
649
|
async function assertServerProcessIdentity(configDir, pid, state) {
|
|
677
650
|
const expected = state?.processIdentity;
|
|
678
651
|
if (
|
|
@@ -694,7 +667,7 @@ async function assertServerProcessIdentity(configDir, pid, state) {
|
|
|
694
667
|
`Refusing to stop Farming PID ${pid}: the live process identity does not match the server control metadata`,
|
|
695
668
|
);
|
|
696
669
|
}
|
|
697
|
-
if (!processOwnsListeningPort(pid, Number(state.port))) {
|
|
670
|
+
if (state.phase !== 'starting' && !processOwnsListeningPort(pid, Number(state.port))) {
|
|
698
671
|
throw new Error(`Refusing to stop Farming PID ${pid}: the process does not own listening port ${state.port}`);
|
|
699
672
|
}
|
|
700
673
|
return current;
|
|
@@ -752,7 +725,8 @@ function isRunning(pid) {
|
|
|
752
725
|
try {
|
|
753
726
|
process.kill(pid, 0);
|
|
754
727
|
return true;
|
|
755
|
-
} catch {
|
|
728
|
+
} catch (error) {
|
|
729
|
+
if (error?.code === 'EPERM' || error?.code === 'EACCES') return true;
|
|
756
730
|
return false;
|
|
757
731
|
}
|
|
758
732
|
}
|
|
@@ -840,12 +814,31 @@ function waitForProcessStability(pid, durationMs = DEFAULT_SERVER_START_STABILIT
|
|
|
840
814
|
});
|
|
841
815
|
}
|
|
842
816
|
|
|
843
|
-
function cleanupFailedDaemonStart(configDir, childPid) {
|
|
817
|
+
async function cleanupFailedDaemonStart(configDir, childPid, expectedIdentity = null) {
|
|
844
818
|
if (isRunning(childPid)) {
|
|
819
|
+
const expected = expectedIdentity || readServerState(configDir).processIdentity;
|
|
820
|
+
const current = readServerProcessIdentity(childPid);
|
|
821
|
+
if (!matchingProcessIdentity(expected, current)) {
|
|
822
|
+
throw new Error(`Failed Farming startup left live PID ${childPid} with an unproved identity; refusing to signal it`);
|
|
823
|
+
}
|
|
845
824
|
try {
|
|
846
|
-
process.kill(childPid, '
|
|
847
|
-
} catch {
|
|
848
|
-
|
|
825
|
+
process.kill(childPid, 'SIGKILL');
|
|
826
|
+
} catch (error) {
|
|
827
|
+
if (error?.code === 'EPERM' || error?.code === 'EACCES') {
|
|
828
|
+
throw new Error(
|
|
829
|
+
`Failed Farming startup left Server PID ${childPid} running because cleanup lacks permission. `
|
|
830
|
+
+ 'Stop it as the operating-system user that owns the process, then retry.',
|
|
831
|
+
{ cause: error },
|
|
832
|
+
);
|
|
833
|
+
}
|
|
834
|
+
if (error?.code !== 'ESRCH') throw error;
|
|
835
|
+
}
|
|
836
|
+
const startedAt = Date.now();
|
|
837
|
+
while (matchingProcessIdentity(expected, readServerProcessIdentity(childPid))) {
|
|
838
|
+
if (Date.now() - startedAt >= 5_000) {
|
|
839
|
+
throw new Error(`Failed Farming startup left Server PID ${childPid} running after SIGKILL`);
|
|
840
|
+
}
|
|
841
|
+
await new Promise(resolve => setTimeout(resolve, SERVER_STOP_POLL_MS));
|
|
849
842
|
}
|
|
850
843
|
}
|
|
851
844
|
if (readPid(configDir) !== childPid) return;
|
|
@@ -910,10 +903,31 @@ function waitForServer(env, timeoutMs = serverStartTimeoutMs(env), childPid = 0)
|
|
|
910
903
|
});
|
|
911
904
|
}
|
|
912
905
|
|
|
913
|
-
function runServerInCurrentProcess() {
|
|
906
|
+
async function runServerInCurrentProcess() {
|
|
914
907
|
process.env = buildServerEnv();
|
|
908
|
+
ensureConfigDir(process.env.FARMING_CONFIG_DIR);
|
|
909
|
+
fs.writeFileSync(pidFile(process.env.FARMING_CONFIG_DIR), String(process.pid), { mode: 0o600 });
|
|
910
|
+
const processIdentity = await readServerProcessIdentity(process.pid);
|
|
911
|
+
if (!processIdentity) throw new Error('server process identity could not be committed before startup');
|
|
912
|
+
writeServerState(process.env.FARMING_CONFIG_DIR, process.env, process.pid, processIdentity, 'starting');
|
|
915
913
|
const { startServer } = require('./server');
|
|
916
|
-
startServer();
|
|
914
|
+
const server = startServer();
|
|
915
|
+
server.once('listening', () => {
|
|
916
|
+
writeServerState(
|
|
917
|
+
process.env.FARMING_CONFIG_DIR,
|
|
918
|
+
process.env,
|
|
919
|
+
process.pid,
|
|
920
|
+
processIdentity,
|
|
921
|
+
'running',
|
|
922
|
+
);
|
|
923
|
+
const { pruneRuntimeDependencies } = require('./runtime-dependency-manager');
|
|
924
|
+
void pruneRuntimeDependencies({
|
|
925
|
+
configDir: process.env.FARMING_CONFIG_DIR,
|
|
926
|
+
env: process.env,
|
|
927
|
+
}).catch(error => {
|
|
928
|
+
console.warn(`Startup dependency cache cleanup failed: ${error?.message || error}`);
|
|
929
|
+
});
|
|
930
|
+
});
|
|
917
931
|
}
|
|
918
932
|
|
|
919
933
|
function runNativePtyHostInCurrentProcess() {
|
|
@@ -921,8 +935,24 @@ function runNativePtyHostInCurrentProcess() {
|
|
|
921
935
|
startNativePtyHostProcess();
|
|
922
936
|
}
|
|
923
937
|
|
|
938
|
+
async function prepareStartupDependencies(env, options = {}) {
|
|
939
|
+
if (
|
|
940
|
+
options.force !== true
|
|
941
|
+
&& (env.FARMING_SKIP_RUNTIME_PREPARE === '1' || env.NODE_ENV === 'test')
|
|
942
|
+
) {
|
|
943
|
+
return { skipped: true };
|
|
944
|
+
}
|
|
945
|
+
const { prepareRuntimeDependencies } = require('./runtime-dependency-manager');
|
|
946
|
+
return prepareRuntimeDependencies({
|
|
947
|
+
configDir: env.FARMING_CONFIG_DIR,
|
|
948
|
+
env,
|
|
949
|
+
});
|
|
950
|
+
}
|
|
951
|
+
|
|
924
952
|
async function startForeground(parsed) {
|
|
925
|
-
const env =
|
|
953
|
+
const env = buildServerEnv(parsed.env);
|
|
954
|
+
await prepareStartupDependencies(env);
|
|
955
|
+
await adaptServerPort(env, parsed);
|
|
926
956
|
env[SERVER_MODE_ENV] = '1';
|
|
927
957
|
ensureConfigDir(env.FARMING_CONFIG_DIR);
|
|
928
958
|
const invocation = childInvocation(env);
|
|
@@ -952,13 +982,33 @@ async function startDaemon(parsed) {
|
|
|
952
982
|
const existingPid = readPid(configDir);
|
|
953
983
|
if (isRunning(existingPid)) {
|
|
954
984
|
const state = readServerState(configDir);
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
985
|
+
try {
|
|
986
|
+
if (state.processIdentity?.format === SERVER_PROCESS_IDENTITY_FORMAT) {
|
|
987
|
+
await assertServerProcessIdentity(configDir, existingPid, state);
|
|
988
|
+
} else {
|
|
989
|
+
await migrateLegacyServerIdentity(configDir, existingPid, state);
|
|
990
|
+
}
|
|
991
|
+
} catch (error) {
|
|
992
|
+
console.error(
|
|
993
|
+
`Farming PID ${existingPid} is live, but this config directory does not prove that it owns the Server: `
|
|
994
|
+
+ `${error.message || error}`,
|
|
995
|
+
);
|
|
996
|
+
return 1;
|
|
997
|
+
}
|
|
998
|
+
if (state.phase === 'starting') {
|
|
999
|
+
console.warn(`Previous Farming startup (PID ${existingPid}) did not complete; replacing it.`);
|
|
1000
|
+
const stopCode = await stopDaemon({ env });
|
|
1001
|
+
if (stopCode !== 0) return stopCode;
|
|
1002
|
+
} else {
|
|
1003
|
+
if (state.port) env.PORT = String(state.port);
|
|
1004
|
+
if (state.basePath) env.FARMING_BASE_PATH = state.basePath;
|
|
1005
|
+
console.log(`Farming is already running (PID ${existingPid})`);
|
|
1006
|
+
console.log(entryUrl(env));
|
|
1007
|
+
return 0;
|
|
1008
|
+
}
|
|
960
1009
|
}
|
|
961
1010
|
|
|
1011
|
+
await prepareStartupDependencies(env);
|
|
962
1012
|
const out = fs.openSync(logFile(configDir), 'a');
|
|
963
1013
|
const invocation = childInvocation(env);
|
|
964
1014
|
if (env.FARMING_DEBUG_CLI === '1') {
|
|
@@ -979,9 +1029,11 @@ async function startDaemon(parsed) {
|
|
|
979
1029
|
child.unref();
|
|
980
1030
|
fs.writeFileSync(pidFile(configDir), String(child.pid));
|
|
981
1031
|
|
|
1032
|
+
let processIdentity = null;
|
|
982
1033
|
try {
|
|
983
|
-
|
|
1034
|
+
processIdentity = await readServerProcessIdentity(child.pid);
|
|
984
1035
|
if (!processIdentity) throw new Error('server process identity could not be verified after launch');
|
|
1036
|
+
writeServerState(configDir, env, child.pid, processIdentity, 'starting');
|
|
985
1037
|
await waitForServer(env, serverStartTimeoutMs(env), child.pid);
|
|
986
1038
|
await waitForProcessStability(child.pid, serverStartStabilityMs(env));
|
|
987
1039
|
await waitForServer(env, Math.min(serverStartTimeoutMs(env), 5_000), child.pid);
|
|
@@ -993,9 +1045,14 @@ async function startDaemon(parsed) {
|
|
|
993
1045
|
) {
|
|
994
1046
|
throw new Error('server process identity changed during startup');
|
|
995
1047
|
}
|
|
996
|
-
writeServerState(configDir, env, child.pid, stableIdentity);
|
|
1048
|
+
writeServerState(configDir, env, child.pid, stableIdentity, 'running');
|
|
997
1049
|
} catch (error) {
|
|
998
|
-
|
|
1050
|
+
try {
|
|
1051
|
+
await cleanupFailedDaemonStart(configDir, child.pid, processIdentity);
|
|
1052
|
+
} catch (cleanupError) {
|
|
1053
|
+
console.error(`${error.message}; cleanup failed: ${cleanupError.message || cleanupError}`);
|
|
1054
|
+
return 1;
|
|
1055
|
+
}
|
|
999
1056
|
console.error(error.message);
|
|
1000
1057
|
const logs = tailFile(logFile(configDir), 80);
|
|
1001
1058
|
if (logs) console.error(logs);
|
|
@@ -1031,8 +1088,15 @@ async function stopDaemon(parsed) {
|
|
|
1031
1088
|
await migrateLegacyServerIdentity(configDir, pid, state);
|
|
1032
1089
|
}
|
|
1033
1090
|
try {
|
|
1034
|
-
process.kill(pid, '
|
|
1091
|
+
process.kill(pid, 'SIGKILL');
|
|
1035
1092
|
} catch (error) {
|
|
1093
|
+
if (error?.code === 'EPERM' || error?.code === 'EACCES') {
|
|
1094
|
+
throw new Error(
|
|
1095
|
+
`Farming cannot stop server ${pid} because this command lacks permission. `
|
|
1096
|
+
+ 'Run it as the operating-system user that owns the process (or as an administrator), then start Farming again.',
|
|
1097
|
+
{ cause: error },
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1036
1100
|
if (error?.code !== 'ESRCH') throw error;
|
|
1037
1101
|
}
|
|
1038
1102
|
await waitForDaemonStop(pid, port, { timeoutMs: serverStopTimeoutMs(env) });
|
|
@@ -1042,7 +1106,7 @@ async function stopDaemon(parsed) {
|
|
|
1042
1106
|
return 0;
|
|
1043
1107
|
}
|
|
1044
1108
|
|
|
1045
|
-
function statusDaemon(parsed) {
|
|
1109
|
+
async function statusDaemon(parsed) {
|
|
1046
1110
|
const env = buildServerEnv(parsed.env);
|
|
1047
1111
|
const configDir = env.FARMING_CONFIG_DIR;
|
|
1048
1112
|
const pid = readPid(configDir);
|
|
@@ -1050,6 +1114,24 @@ function statusDaemon(parsed) {
|
|
|
1050
1114
|
console.log('Farming is not running.');
|
|
1051
1115
|
return 0;
|
|
1052
1116
|
}
|
|
1117
|
+
const state = readServerState(configDir);
|
|
1118
|
+
try {
|
|
1119
|
+
if (state.processIdentity?.format === SERVER_PROCESS_IDENTITY_FORMAT) {
|
|
1120
|
+
await assertServerProcessIdentity(configDir, pid, state);
|
|
1121
|
+
} else {
|
|
1122
|
+
await migrateLegacyServerIdentity(configDir, pid, state);
|
|
1123
|
+
}
|
|
1124
|
+
} catch (error) {
|
|
1125
|
+
console.error(
|
|
1126
|
+
`Farming PID ${pid} is live, but this config directory does not prove that it owns the Server: `
|
|
1127
|
+
+ `${error.message || error}`,
|
|
1128
|
+
);
|
|
1129
|
+
return 1;
|
|
1130
|
+
}
|
|
1131
|
+
if (state.phase === 'starting') {
|
|
1132
|
+
console.log(`Farming is starting (PID ${pid}). Run 'farming start' to replace an interrupted startup.`);
|
|
1133
|
+
return 1;
|
|
1134
|
+
}
|
|
1053
1135
|
console.log(`Farming is running (PID ${pid})`);
|
|
1054
1136
|
const logs = tailFile(logFile(configDir), 30);
|
|
1055
1137
|
if (logs) console.log(logs);
|
|
@@ -1082,10 +1164,13 @@ function usage() {
|
|
|
1082
1164
|
farming stop
|
|
1083
1165
|
farming logs
|
|
1084
1166
|
farming url
|
|
1167
|
+
farming runtime prepare [--config-dir ~/.farming]
|
|
1085
1168
|
farming review <git-dir> <old-revision> <new-revision|now> [--branch <branch>] [--no-open]
|
|
1086
1169
|
|
|
1087
1170
|
Agent control commands are also available:
|
|
1088
1171
|
farming skills
|
|
1172
|
+
farming capabilities [--json]
|
|
1173
|
+
farming browser ...
|
|
1089
1174
|
farming list [--json] [--parent <agentId>]
|
|
1090
1175
|
farming spawn --workspace <repo> -- <command...>
|
|
1091
1176
|
farming output <agentId> [--tail <chars>]
|
|
@@ -1104,7 +1189,12 @@ async function run(argv = process.argv.slice(2)) {
|
|
|
1104
1189
|
}
|
|
1105
1190
|
|
|
1106
1191
|
if (argv[0] === PACKAGED_CODEX_ACP_ARG) {
|
|
1107
|
-
runPackagedCodexAcp();
|
|
1192
|
+
await runPackagedCodexAcp();
|
|
1193
|
+
return 0;
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
if (argv[0] === PACKAGED_CLAUDE_ACP_ARG) {
|
|
1197
|
+
await runPackagedClaudeAcp();
|
|
1108
1198
|
return 0;
|
|
1109
1199
|
}
|
|
1110
1200
|
|
|
@@ -1121,7 +1211,20 @@ async function run(argv = process.argv.slice(2)) {
|
|
|
1121
1211
|
}
|
|
1122
1212
|
|
|
1123
1213
|
if (process.env[SERVER_MODE_ENV] === '1' || argv[0] === SERVER_MODE_ARG) {
|
|
1124
|
-
runServerInCurrentProcess();
|
|
1214
|
+
await runServerInCurrentProcess();
|
|
1215
|
+
return 0;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
if (argv[0] === 'browser') {
|
|
1219
|
+
const { run: runBrowserCli } = require('../extensions/browser/bin/farming-browser');
|
|
1220
|
+
return runBrowserCli(argv.slice(1));
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
if (argv[0] === 'runtime' && argv[1] === 'prepare') {
|
|
1224
|
+
const parsed = parseServerArgs(['start', ...argv.slice(2)]);
|
|
1225
|
+
const env = buildServerEnv(parsed.env);
|
|
1226
|
+
const result = await prepareStartupDependencies(env, { force: true });
|
|
1227
|
+
console.log(JSON.stringify(result, null, 2));
|
|
1125
1228
|
return 0;
|
|
1126
1229
|
}
|
|
1127
1230
|
|
package/backend/farming-cli.js
CHANGED
|
@@ -8,6 +8,7 @@ const storageLayout = require('./storage-layout');
|
|
|
8
8
|
function usage() {
|
|
9
9
|
return `Usage:
|
|
10
10
|
farming skills
|
|
11
|
+
farming capabilities [--json]
|
|
11
12
|
farming memory report [--period today|yesterday|week] [--since <time>] [--until <time>] [--home <path>] [--json]
|
|
12
13
|
farming list [--json] [--parent <agentId>]
|
|
13
14
|
farming spawn [--workspace <path>] [--task <text>] [--parent <agentId>] [--json] -- <command...>
|
|
@@ -20,6 +21,7 @@ Examples:
|
|
|
20
21
|
farming memory report --period today
|
|
21
22
|
farming memory report --period week --json
|
|
22
23
|
farming skills
|
|
24
|
+
farming capabilities
|
|
23
25
|
farming list --parent "$FARMING_AGENT_ID"
|
|
24
26
|
farming output agent-123 --tail 2000
|
|
25
27
|
farming send agent-123 "Please run the focused tests"`;
|
|
@@ -76,6 +78,13 @@ function parseArgs(argv) {
|
|
|
76
78
|
return { command };
|
|
77
79
|
}
|
|
78
80
|
|
|
81
|
+
if (command === 'capabilities') {
|
|
82
|
+
if (rest.some(arg => arg !== '--json')) {
|
|
83
|
+
throw new Error('capabilities accepts only --json');
|
|
84
|
+
}
|
|
85
|
+
return { command, options: { json: rest.includes('--json') } };
|
|
86
|
+
}
|
|
87
|
+
|
|
79
88
|
if (command === 'memory' || command === 'report') {
|
|
80
89
|
const subcommand = command === 'memory' ? rest.shift() : 'report';
|
|
81
90
|
if (subcommand !== 'report') {
|
|
@@ -293,6 +302,44 @@ function formatAgent(agent) {
|
|
|
293
302
|
return `${marker} ${agent.id} | ${agent.command} | ${agent.status} | ${agent.cwd}${parent}${task}`;
|
|
294
303
|
}
|
|
295
304
|
|
|
305
|
+
function farmingCapabilities(browser) {
|
|
306
|
+
const state = browser?.available === true
|
|
307
|
+
? 'available'
|
|
308
|
+
: (browser?.enabled === true ? 'unavailable' : 'disabled');
|
|
309
|
+
return {
|
|
310
|
+
runtime: 'farming',
|
|
311
|
+
agentId: process.env.FARMING_AGENT_ID || '',
|
|
312
|
+
projectWorkspace: process.env.FARMING_PROJECT_WORKSPACE || '',
|
|
313
|
+
capabilities: [{
|
|
314
|
+
id: 'browser',
|
|
315
|
+
state,
|
|
316
|
+
summary: state === 'available'
|
|
317
|
+
? (browser?.browser?.kind === 'external-cdp'
|
|
318
|
+
? 'Default browser path for web tasks. An externally managed CDP Browser can be created or attached as a shared, user-visible Farming Resource.'
|
|
319
|
+
: 'Default browser path for web tasks. An installed system Chromium Browser can be created or attached as a shared, user-visible Farming Resource.')
|
|
320
|
+
: (browser?.message || 'Browser integration is unavailable in Farming.'),
|
|
321
|
+
commands: state === 'available'
|
|
322
|
+
? {
|
|
323
|
+
list: 'farming browser list',
|
|
324
|
+
create: 'farming browser create',
|
|
325
|
+
workflow: 'farming browser help workflow',
|
|
326
|
+
}
|
|
327
|
+
: {},
|
|
328
|
+
}],
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function formatCapabilities(report) {
|
|
333
|
+
const lines = ['Farming runtime capabilities:'];
|
|
334
|
+
for (const capability of report.capabilities) {
|
|
335
|
+
lines.push(`- ${capability.id}: ${capability.state} — ${capability.summary}`);
|
|
336
|
+
for (const [label, command] of Object.entries(capability.commands || {})) {
|
|
337
|
+
lines.push(` ${label}: ${command}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return lines.join('\n');
|
|
341
|
+
}
|
|
342
|
+
|
|
296
343
|
async function run(argv = process.argv.slice(2), io = process) {
|
|
297
344
|
const parsed = parseArgs(argv);
|
|
298
345
|
|
|
@@ -306,6 +353,14 @@ async function run(argv = process.argv.slice(2), io = process) {
|
|
|
306
353
|
return 0;
|
|
307
354
|
}
|
|
308
355
|
|
|
356
|
+
if (parsed.command === 'capabilities') {
|
|
357
|
+
const report = farmingCapabilities(await request('/api/browsers/capability'));
|
|
358
|
+
io.stdout.write(parsed.options.json
|
|
359
|
+
? `${JSON.stringify(report, null, 2)}\n`
|
|
360
|
+
: `${formatCapabilities(report)}\n`);
|
|
361
|
+
return 0;
|
|
362
|
+
}
|
|
363
|
+
|
|
309
364
|
if (parsed.command === 'memory-report') {
|
|
310
365
|
const report = buildMemoryReport({
|
|
311
366
|
period: parsed.options.period,
|
|
@@ -382,6 +437,8 @@ async function run(argv = process.argv.slice(2), io = process) {
|
|
|
382
437
|
|
|
383
438
|
module.exports = {
|
|
384
439
|
formatAgent,
|
|
440
|
+
farmingCapabilities,
|
|
441
|
+
formatCapabilities,
|
|
385
442
|
getToken,
|
|
386
443
|
httpRequest,
|
|
387
444
|
isAuthDisabled,
|