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,158 @@
|
|
|
1
|
+
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
2
|
+
import { appPath } from '@/lib/base-path'
|
|
3
|
+
import { projectFilesWorkspaceId } from '@/lib/project-workspaces'
|
|
4
|
+
import {
|
|
5
|
+
applyBrowserResource,
|
|
6
|
+
applyBrowserResourceDeletion,
|
|
7
|
+
applyBrowserResourceSnapshot,
|
|
8
|
+
type BrowserResourceCollection,
|
|
9
|
+
type BrowserResourceDeletion,
|
|
10
|
+
} from './browser-resource-state'
|
|
11
|
+
import type { BrowserCapability, BrowserResource } from './types'
|
|
12
|
+
|
|
13
|
+
async function browserRequest<T>(pathname: string, init?: RequestInit): Promise<T> {
|
|
14
|
+
const response = await fetch(appPath(pathname), {
|
|
15
|
+
...init,
|
|
16
|
+
headers: {
|
|
17
|
+
Accept: 'application/json',
|
|
18
|
+
...(init?.body ? { 'Content-Type': 'application/json' } : {}),
|
|
19
|
+
...init?.headers,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
const data = await response.json().catch(() => ({})) as { error?: string }
|
|
23
|
+
if (!response.ok) throw new Error(data.error || `Browser request failed (${response.status})`)
|
|
24
|
+
return data as T
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function useBrowserResources() {
|
|
28
|
+
const [collection, setCollection] = useState<BrowserResourceCollection>({
|
|
29
|
+
collectionRevision: 0,
|
|
30
|
+
resources: [],
|
|
31
|
+
})
|
|
32
|
+
const [capability, setCapability] = useState<BrowserCapability | null>(null)
|
|
33
|
+
const [loading, setLoading] = useState(true)
|
|
34
|
+
const [refreshVersion, setRefreshVersion] = useState(0)
|
|
35
|
+
|
|
36
|
+
const mergeResource = useCallback((resource: BrowserResource) => {
|
|
37
|
+
setCollection(current => applyBrowserResource(current, resource))
|
|
38
|
+
}, [])
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
let active = true
|
|
42
|
+
setLoading(true)
|
|
43
|
+
void browserRequest<BrowserCapability>('/api/browsers/capability').then(async nextCapability => {
|
|
44
|
+
if (!active) return
|
|
45
|
+
setCapability(nextCapability)
|
|
46
|
+
if (!nextCapability.available) {
|
|
47
|
+
setCollection({ collectionRevision: 0, resources: [] })
|
|
48
|
+
setLoading(false)
|
|
49
|
+
return
|
|
50
|
+
}
|
|
51
|
+
const list = await browserRequest<BrowserResourceCollection>('/api/browsers')
|
|
52
|
+
if (!active) return
|
|
53
|
+
setCollection(current => applyBrowserResourceSnapshot(current, list))
|
|
54
|
+
setLoading(false)
|
|
55
|
+
}).catch(() => {
|
|
56
|
+
if (active) setLoading(false)
|
|
57
|
+
})
|
|
58
|
+
return () => {
|
|
59
|
+
active = false
|
|
60
|
+
}
|
|
61
|
+
}, [refreshVersion])
|
|
62
|
+
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
if (capability?.available !== true) return undefined
|
|
65
|
+
let active = true
|
|
66
|
+
const events = new EventSource(appPath('/api/browsers/events'))
|
|
67
|
+
events.addEventListener('resources', event => {
|
|
68
|
+
if (!active) return
|
|
69
|
+
const payload = JSON.parse((event as MessageEvent<string>).data) as BrowserResourceCollection
|
|
70
|
+
setCollection(current => applyBrowserResourceSnapshot(current, payload))
|
|
71
|
+
})
|
|
72
|
+
events.addEventListener('resource', event => {
|
|
73
|
+
if (!active) return
|
|
74
|
+
mergeResource(JSON.parse((event as MessageEvent<string>).data) as BrowserResource)
|
|
75
|
+
})
|
|
76
|
+
events.addEventListener('deleted', event => {
|
|
77
|
+
if (!active) return
|
|
78
|
+
const payload = JSON.parse((event as MessageEvent<string>).data) as BrowserResourceDeletion
|
|
79
|
+
setCollection(current => applyBrowserResourceDeletion(current, payload))
|
|
80
|
+
})
|
|
81
|
+
return () => {
|
|
82
|
+
active = false
|
|
83
|
+
events.close()
|
|
84
|
+
}
|
|
85
|
+
}, [capability?.available, mergeResource])
|
|
86
|
+
|
|
87
|
+
const create = useCallback(async (workspace: string, options: { name?: string; url?: string } = {}) => {
|
|
88
|
+
const resource = await browserRequest<BrowserResource>('/api/browsers', {
|
|
89
|
+
method: 'POST',
|
|
90
|
+
body: JSON.stringify({
|
|
91
|
+
rootId: projectFilesWorkspaceId(workspace),
|
|
92
|
+
name: options.name,
|
|
93
|
+
url: options.url,
|
|
94
|
+
}),
|
|
95
|
+
})
|
|
96
|
+
mergeResource(resource)
|
|
97
|
+
return resource
|
|
98
|
+
}, [mergeResource])
|
|
99
|
+
|
|
100
|
+
const rename = useCallback(async (id: string, name: string) => {
|
|
101
|
+
const resource = await browserRequest<BrowserResource>(`/api/browsers/${encodeURIComponent(id)}`, {
|
|
102
|
+
method: 'PATCH',
|
|
103
|
+
body: JSON.stringify({ name }),
|
|
104
|
+
})
|
|
105
|
+
mergeResource(resource)
|
|
106
|
+
return resource
|
|
107
|
+
}, [mergeResource])
|
|
108
|
+
|
|
109
|
+
const transition = useCallback(async (id: string, operation: 'start' | 'stop') => {
|
|
110
|
+
const resource = await browserRequest<BrowserResource>(
|
|
111
|
+
`/api/browsers/${encodeURIComponent(id)}/${operation}`,
|
|
112
|
+
{ method: 'POST' },
|
|
113
|
+
)
|
|
114
|
+
mergeResource(resource)
|
|
115
|
+
return resource
|
|
116
|
+
}, [mergeResource])
|
|
117
|
+
|
|
118
|
+
const start = useCallback((id: string) => transition(id, 'start'), [transition])
|
|
119
|
+
const stop = useCallback((id: string) => transition(id, 'stop'), [transition])
|
|
120
|
+
|
|
121
|
+
const remove = useCallback(async (id: string) => {
|
|
122
|
+
const deletion = await browserRequest<BrowserResourceDeletion>(
|
|
123
|
+
`/api/browsers/${encodeURIComponent(id)}`,
|
|
124
|
+
{ method: 'DELETE' },
|
|
125
|
+
)
|
|
126
|
+
setCollection(current => applyBrowserResourceDeletion(current, deletion))
|
|
127
|
+
}, [])
|
|
128
|
+
|
|
129
|
+
const refreshCapability = useCallback(() => {
|
|
130
|
+
setRefreshVersion(version => version + 1)
|
|
131
|
+
}, [])
|
|
132
|
+
|
|
133
|
+
const byWorkspace = useMemo(() => {
|
|
134
|
+
const result = new Map<string, BrowserResource[]>()
|
|
135
|
+
for (const resource of collection.resources) {
|
|
136
|
+
const current = result.get(resource.workspace) ?? []
|
|
137
|
+
current.push(resource)
|
|
138
|
+
result.set(resource.workspace, current)
|
|
139
|
+
}
|
|
140
|
+
return result
|
|
141
|
+
}, [collection.resources])
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
resources: collection.resources,
|
|
145
|
+
byWorkspace,
|
|
146
|
+
capability,
|
|
147
|
+
loading,
|
|
148
|
+
create,
|
|
149
|
+
rename,
|
|
150
|
+
start,
|
|
151
|
+
stop,
|
|
152
|
+
remove,
|
|
153
|
+
mergeResource,
|
|
154
|
+
refreshCapability,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export type BrowserResourcesController = ReturnType<typeof useBrowserResources>
|
|
@@ -34,17 +34,18 @@
|
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
sendComposerMessage(agentId, message, attachments = [], options = {}) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
const requestedId = typeof options.requestId === 'string' ? options.requestId.trim() : '';
|
|
38
|
+
const requestId = requestedId
|
|
39
|
+
|| globalThis.crypto?.randomUUID?.()
|
|
40
|
+
|| `composer-${Date.now().toString(36)}-${++composerRequestSequence}`;
|
|
40
41
|
const sent = send({
|
|
41
42
|
type: 'composer-input',
|
|
42
43
|
agentId,
|
|
43
44
|
message,
|
|
44
|
-
|
|
45
|
+
requestId,
|
|
45
46
|
...(attachments.length > 0 ? { attachments } : {}),
|
|
46
47
|
});
|
|
47
|
-
if (sent &&
|
|
48
|
+
if (sent && options.onResult) composerResults.set(requestId, options.onResult);
|
|
48
49
|
return sent;
|
|
49
50
|
},
|
|
50
51
|
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
},
|
|
59
60
|
|
|
60
61
|
rejectPendingComposerMessages(message = 'Connection unavailable') {
|
|
61
|
-
composerResults.forEach(callback => callback({ accepted: false, message }));
|
|
62
|
+
composerResults.forEach(callback => callback({ accepted: false, message, uncertain: true }));
|
|
62
63
|
composerResults.clear();
|
|
63
64
|
},
|
|
64
65
|
|
|
@@ -101,6 +101,7 @@ let structuredComposerConfigId = '';
|
|
|
101
101
|
let structuredComposerAttachments = [];
|
|
102
102
|
const structuredComposerHistory = new Map();
|
|
103
103
|
const structuredComposerPendingFollowUps = new Map();
|
|
104
|
+
const structuredComposerRequestIds = new Map();
|
|
104
105
|
let structuredComposerHistoryIndex = -1;
|
|
105
106
|
let structuredComposerCompositionEndAt = 0;
|
|
106
107
|
let structuredComposerRestoreFocusAfterInterrupt = false;
|
|
@@ -6962,6 +6963,27 @@ function structuredComposerPromptAttachments() {
|
|
|
6962
6963
|
));
|
|
6963
6964
|
}
|
|
6964
6965
|
|
|
6966
|
+
function structuredComposerRequestKey(agentId, message, attachments = []) {
|
|
6967
|
+
return JSON.stringify({
|
|
6968
|
+
agentId,
|
|
6969
|
+
message,
|
|
6970
|
+
attachments: attachments.map((attachment) => ({
|
|
6971
|
+
kind: attachment.kind,
|
|
6972
|
+
path: attachment.path,
|
|
6973
|
+
type: attachment.type,
|
|
6974
|
+
})),
|
|
6975
|
+
});
|
|
6976
|
+
}
|
|
6977
|
+
|
|
6978
|
+
function structuredComposerRequestId(requestKey) {
|
|
6979
|
+
const existing = structuredComposerRequestIds.get(requestKey);
|
|
6980
|
+
if (existing) return existing;
|
|
6981
|
+
const requestId = globalThis.crypto?.randomUUID?.()
|
|
6982
|
+
|| `composer-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
6983
|
+
structuredComposerRequestIds.set(requestKey, requestId);
|
|
6984
|
+
return requestId;
|
|
6985
|
+
}
|
|
6986
|
+
|
|
6965
6987
|
function structuredComposerHistoryFor(agentId) {
|
|
6966
6988
|
if (!agentId) return [];
|
|
6967
6989
|
return structuredComposerHistory.get(agentId) || [];
|
|
@@ -7580,10 +7602,17 @@ function setupStructuredSessionComposer() {
|
|
|
7580
7602
|
const draft = input.value;
|
|
7581
7603
|
const message = structuredComposerMessage(draft);
|
|
7582
7604
|
const promptAttachments = structuredComposerPromptAttachments();
|
|
7605
|
+
const submittedAttachmentIds = structuredComposerAttachments.map((attachment) => attachment.id);
|
|
7583
7606
|
if (!message && promptAttachments.length === 0) return;
|
|
7584
7607
|
const statusNode = document.getElementById('crt-structured-composer-status');
|
|
7585
7608
|
const completeSubmission = () => {
|
|
7586
7609
|
addStructuredComposerHistory(agentId, draft);
|
|
7610
|
+
const ownsComposer = focusedAgentId === agentId
|
|
7611
|
+
&& structuredSessionGeneration === generation
|
|
7612
|
+
&& input.value === draft
|
|
7613
|
+
&& structuredComposerAttachments.length === submittedAttachmentIds.length
|
|
7614
|
+
&& structuredComposerAttachments.every((attachment, index) => attachment.id === submittedAttachmentIds[index]);
|
|
7615
|
+
if (!ownsComposer) return;
|
|
7587
7616
|
input.value = '';
|
|
7588
7617
|
structuredComposerAttachments = [];
|
|
7589
7618
|
renderStructuredComposerAttachments();
|
|
@@ -7595,17 +7624,48 @@ function setupStructuredSessionComposer() {
|
|
|
7595
7624
|
updateStructuredComposerState(agent);
|
|
7596
7625
|
setTimeout(() => void refreshStructuredSession(agentId, true, generation), 160);
|
|
7597
7626
|
};
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7627
|
+
if (action === 'send' && structuredRuntimeStatus(agent) !== 'idle') {
|
|
7628
|
+
queueStructuredComposerFollowUp(agentId, message, promptAttachments);
|
|
7629
|
+
completeSubmission();
|
|
7630
|
+
return;
|
|
7631
|
+
}
|
|
7632
|
+
const requestKey = structuredComposerRequestKey(agentId, message, promptAttachments);
|
|
7633
|
+
const requestId = structuredComposerRequestId(requestKey);
|
|
7634
|
+
const sent = getSessionClient()?.sendComposerMessage(agentId, message, promptAttachments, {
|
|
7635
|
+
requestId,
|
|
7636
|
+
onResult(result) {
|
|
7637
|
+
if (result?.accepted === true) {
|
|
7638
|
+
if (structuredComposerRequestIds.get(requestKey) === requestId) {
|
|
7639
|
+
structuredComposerRequestIds.delete(requestKey);
|
|
7640
|
+
}
|
|
7641
|
+
completeSubmission();
|
|
7642
|
+
return;
|
|
7643
|
+
}
|
|
7644
|
+
if (result?.uncertain !== true && structuredComposerRequestIds.get(requestKey) === requestId) {
|
|
7645
|
+
structuredComposerRequestIds.delete(requestKey);
|
|
7646
|
+
}
|
|
7647
|
+
if (focusedAgentId !== agentId || structuredSessionGeneration !== generation) return;
|
|
7648
|
+
if (statusNode) {
|
|
7649
|
+
statusNode.textContent = result?.message || 'Submission was not accepted';
|
|
7650
|
+
statusNode.classList.add('error');
|
|
7651
|
+
}
|
|
7652
|
+
input.focus();
|
|
7653
|
+
},
|
|
7654
|
+
});
|
|
7601
7655
|
if (!sent) {
|
|
7656
|
+
if (structuredComposerRequestIds.get(requestKey) === requestId) {
|
|
7657
|
+
structuredComposerRequestIds.delete(requestKey);
|
|
7658
|
+
}
|
|
7602
7659
|
if (statusNode) {
|
|
7603
7660
|
statusNode.textContent = 'Connection unavailable';
|
|
7604
7661
|
statusNode.classList.add('error');
|
|
7605
7662
|
}
|
|
7606
7663
|
return;
|
|
7607
7664
|
}
|
|
7608
|
-
|
|
7665
|
+
if (statusNode) {
|
|
7666
|
+
statusNode.textContent = 'SENDING...';
|
|
7667
|
+
statusNode.classList.remove('error');
|
|
7668
|
+
}
|
|
7609
7669
|
});
|
|
7610
7670
|
}
|
|
7611
7671
|
|
package/index.html
CHANGED
|
@@ -1,9 +1,38 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
2
|
+
<html lang="en" data-appearance-preference="system">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
6
|
-
<meta name="
|
|
6
|
+
<meta name="color-scheme" content="light dark" />
|
|
7
|
+
<meta name="theme-color" content="#ffffff" />
|
|
8
|
+
<style>
|
|
9
|
+
html,
|
|
10
|
+
body {
|
|
11
|
+
background: #ffffff;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
html[data-appearance='dark'],
|
|
15
|
+
html[data-appearance='dark'] body {
|
|
16
|
+
background: #181818;
|
|
17
|
+
color-scheme: dark;
|
|
18
|
+
}
|
|
19
|
+
</style>
|
|
20
|
+
<script>
|
|
21
|
+
(() => {
|
|
22
|
+
const root = document.documentElement
|
|
23
|
+
const preference = ['light', 'dark'].includes(root.dataset.appearancePreference)
|
|
24
|
+
? root.dataset.appearancePreference
|
|
25
|
+
: 'system'
|
|
26
|
+
const appearance = preference === 'system'
|
|
27
|
+
? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
|
|
28
|
+
: preference
|
|
29
|
+
root.dataset.appearance = appearance
|
|
30
|
+
document.querySelector('meta[name="theme-color"]')?.setAttribute(
|
|
31
|
+
'content',
|
|
32
|
+
appearance === 'dark' ? '#181818' : '#ffffff',
|
|
33
|
+
)
|
|
34
|
+
})()
|
|
35
|
+
</script>
|
|
7
36
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
8
37
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
9
38
|
<meta name="apple-mobile-web-app-title" content="Farming 2" />
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "farming-code",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.29",
|
|
4
4
|
"description": "Farming Code is a self-hosted browser workspace for running and supervising AI coding agents",
|
|
5
5
|
"main": "backend/server.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"farming": "bin/farming"
|
|
7
|
+
"farming": "bin/farming",
|
|
8
|
+
"farming-browser": "extensions/browser/bin/farming-browser"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
11
|
"backend/*.js",
|
|
12
|
+
"backend/farming-agent-bootstrap.zh_cn.md",
|
|
11
13
|
"backend/usage-history-scanner.ts",
|
|
12
14
|
"backend/acp/",
|
|
13
15
|
"backend/data/",
|
|
@@ -20,6 +22,7 @@
|
|
|
20
22
|
"frontend/skins/",
|
|
21
23
|
"frontend/themes/",
|
|
22
24
|
"frontend/vendor/ghostty-web/",
|
|
25
|
+
"extensions/browser/",
|
|
23
26
|
"shared/",
|
|
24
27
|
"LICENSE",
|
|
25
28
|
"README.md",
|
|
@@ -30,11 +33,12 @@
|
|
|
30
33
|
],
|
|
31
34
|
"scripts": {
|
|
32
35
|
"sync:ghostty-vendor": "node scripts/sync-ghostty-vendor.js",
|
|
33
|
-
"prepare:acp-vendor": "node scripts/prepare-codex-acp-vendor.js --copy",
|
|
36
|
+
"prepare:acp-vendor": "node scripts/prepare-codex-acp-vendor.js --copy && node scripts/prepare-claude-acp-vendor.js --copy",
|
|
37
|
+
"prepare:runtime-manifest": "node scripts/build-runtime-dependency-manifest.js",
|
|
34
38
|
"build:usage-history": "node scripts/build-usage-history-scanner.js",
|
|
35
|
-
"prebuild": "node scripts/build-usage-history-scanner.js && node scripts/sync-ghostty-vendor.js &&
|
|
39
|
+
"prebuild": "node scripts/build-usage-history-scanner.js && node scripts/sync-ghostty-vendor.js && npm run prepare:acp-vendor && npm run prepare:runtime-manifest",
|
|
36
40
|
"prepack": "FARMING_BASE_PATH=/farming npm run build",
|
|
37
|
-
"pretest": "npm run prepare:acp-vendor && npm run build:usage-history",
|
|
41
|
+
"pretest": "npm run prepare:acp-vendor && npm run prepare:runtime-manifest && npm run build:usage-history",
|
|
38
42
|
"start": "npm run build && node backend/server.js",
|
|
39
43
|
"start:net": "node backend/farming-net-server.js",
|
|
40
44
|
"start:no-auth": "FARMING_DISABLE_AUTH=1 npm start",
|
|
@@ -61,6 +65,7 @@
|
|
|
61
65
|
"test": "node scripts/run-tests.js",
|
|
62
66
|
"test:pre-release:codex-ui": "FARMING_REAL_CODEX_BIN=\"$(command -v codex)\" FARMING_CODEX_BIN=\"$PWD/tests/e2e/fixtures/real-codex-no-update\" FARMING_REAL_CODEX_RELEASE_CASE=1 FARMING_E2E_REAL_CODEX=1 FARMING_PLAYWRIGHT_INTERNAL=1 playwright test tests/e2e/internal/real-codex-release-case.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
|
|
63
67
|
"test:pre-release:terminal-input": "playwright test tests/e2e/terminal-input-performance.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
|
|
68
|
+
"test:performance:transcript": "node backend/tests/test-acp-transcript-performance.js",
|
|
64
69
|
"test:performance:audit": "node tests/performance/agent-usage-hotpath.js && FARMING_PLAYWRIGHT_INTERNAL=1 playwright test tests/e2e/internal/performance-bottlenecks.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
|
|
65
70
|
"test:performance:scale": "FARMING_PLAYWRIGHT_INTERNAL=1 playwright test tests/e2e/internal/performance-scaling.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
|
|
66
71
|
"test:update:platforms": "node scripts/test-update-platforms.js",
|
|
@@ -79,18 +84,17 @@
|
|
|
79
84
|
"check": "npm run typecheck && npm run lint && npm test"
|
|
80
85
|
},
|
|
81
86
|
"keywords": [
|
|
82
|
-
"
|
|
83
|
-
"
|
|
87
|
+
"coding-agent-workspace",
|
|
88
|
+
"agent-supervision",
|
|
89
|
+
"agent-orchestration",
|
|
90
|
+
"multi-agent",
|
|
84
91
|
"browser-terminal",
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"codex",
|
|
88
|
-
"codex-cli",
|
|
89
|
-
"developer-tools",
|
|
90
|
-
"farming-code",
|
|
91
|
-
"remote-workspace",
|
|
92
|
+
"browser-workspace",
|
|
93
|
+
"remote-development",
|
|
92
94
|
"self-hosted",
|
|
93
|
-
"
|
|
95
|
+
"codex",
|
|
96
|
+
"claude-code",
|
|
97
|
+
"opencode"
|
|
94
98
|
],
|
|
95
99
|
"author": "",
|
|
96
100
|
"license": "MIT",
|
|
@@ -109,9 +113,8 @@
|
|
|
109
113
|
"node": "^22.13.0 || >=24.0.0"
|
|
110
114
|
},
|
|
111
115
|
"dependencies": {
|
|
112
|
-
"@agentclientprotocol/claude-agent-acp": "0.59.0",
|
|
113
|
-
"@agentclientprotocol/codex-acp": "1.1.4",
|
|
114
116
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
117
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
115
118
|
"@xterm/addon-clipboard": "^0.2.0",
|
|
116
119
|
"@xterm/addon-fit": "^0.11.0",
|
|
117
120
|
"@xterm/addon-search": "^0.16.0",
|
|
@@ -125,6 +128,7 @@
|
|
|
125
128
|
"express": "^4.22.2",
|
|
126
129
|
"ghostty-web": "^0.4.0",
|
|
127
130
|
"highlight.js": "^11.11.1",
|
|
131
|
+
"html2canvas": "^1.4.1",
|
|
128
132
|
"katex": "^0.17.0",
|
|
129
133
|
"material-icon-theme": "^5.36.1",
|
|
130
134
|
"mermaid": "^11.16.0",
|
|
@@ -140,10 +144,14 @@
|
|
|
140
144
|
"remark-gfm": "^4.0.1",
|
|
141
145
|
"remark-math": "^6.0.0",
|
|
142
146
|
"ripgrep": "^0.3.1",
|
|
147
|
+
"tar": "7.5.19",
|
|
143
148
|
"ws": "^8.21.0",
|
|
144
|
-
"yaml": "^2.9.0"
|
|
149
|
+
"yaml": "^2.9.0",
|
|
150
|
+
"zod": "^3.25.76"
|
|
145
151
|
},
|
|
146
152
|
"devDependencies": {
|
|
153
|
+
"@agentclientprotocol/claude-agent-acp": "0.59.0",
|
|
154
|
+
"@agentclientprotocol/codex-acp": "1.1.4",
|
|
147
155
|
"@eslint/js": "^10.0.1",
|
|
148
156
|
"@playwright/test": "^1.59.1",
|
|
149
157
|
"@types/node": "^26.1.1",
|
|
@@ -151,6 +159,7 @@
|
|
|
151
159
|
"@types/react-dom": "^19.2.3",
|
|
152
160
|
"@vitejs/plugin-react": "^6.0.1",
|
|
153
161
|
"@yao-pkg/pkg": "6.20.0",
|
|
162
|
+
"agent-browser": "0.32.3",
|
|
154
163
|
"esbuild": "^0.27.7",
|
|
155
164
|
"eslint": "^10.2.0",
|
|
156
165
|
"patch-package": "8.0.1",
|
|
@@ -1,16 +1,28 @@
|
|
|
1
1
|
export const BACKEND_INITIAL_CONNECT_GRACE_MS: number
|
|
2
|
+
export const BACKEND_HEARTBEAT_FAILURE_MS: number
|
|
2
3
|
export const BACKEND_HEARTBEAT_STALE_MS: number
|
|
4
|
+
export const BACKEND_OBSERVER_LAG_RESET_MS: number
|
|
3
5
|
|
|
4
6
|
export type BackendConnectionState = 'connecting' | 'lost' | 'stale' | null
|
|
5
7
|
export interface PageVisibilitySnapshot {
|
|
6
8
|
visible: boolean
|
|
7
9
|
visibleSince: number
|
|
8
10
|
}
|
|
11
|
+
export interface BackendObservation {
|
|
12
|
+
now: number
|
|
13
|
+
continuousSince: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function advanceBackendObservation(
|
|
17
|
+
current: BackendObservation,
|
|
18
|
+
observedAt: number,
|
|
19
|
+
): BackendObservation
|
|
9
20
|
|
|
10
21
|
export function classifyBackendConnection(input: {
|
|
11
22
|
connected: boolean
|
|
12
23
|
everConnected: boolean
|
|
13
24
|
lastMessageAt: number
|
|
25
|
+
disconnectedAt: number | null
|
|
14
26
|
visibleSince: number
|
|
15
27
|
now: number
|
|
16
28
|
}): BackendConnectionState
|
|
@@ -1,18 +1,46 @@
|
|
|
1
|
-
const BACKEND_INITIAL_CONNECT_GRACE_MS =
|
|
1
|
+
const BACKEND_INITIAL_CONNECT_GRACE_MS = 8000;
|
|
2
2
|
const BACKEND_HEARTBEAT_STALE_MS = 6000;
|
|
3
|
+
const BACKEND_HEARTBEAT_FAILURE_MS = 14000;
|
|
4
|
+
const BACKEND_OBSERVER_LAG_RESET_MS = 2500;
|
|
5
|
+
|
|
6
|
+
function advanceBackendObservation(current, observedAt) {
|
|
7
|
+
const now = Number.isFinite(observedAt) ? observedAt : Date.now();
|
|
8
|
+
const previousNow = Number.isFinite(current?.now) ? current.now : now;
|
|
9
|
+
const continuousSince = Number.isFinite(current?.continuousSince)
|
|
10
|
+
? current.continuousSince
|
|
11
|
+
: previousNow;
|
|
12
|
+
return {
|
|
13
|
+
now,
|
|
14
|
+
continuousSince: now - previousNow > BACKEND_OBSERVER_LAG_RESET_MS
|
|
15
|
+
? now
|
|
16
|
+
: continuousSince,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
3
19
|
|
|
4
20
|
function classifyBackendConnection({
|
|
5
21
|
connected,
|
|
6
22
|
everConnected,
|
|
7
23
|
lastMessageAt,
|
|
24
|
+
disconnectedAt,
|
|
8
25
|
visibleSince,
|
|
9
26
|
now,
|
|
10
27
|
}) {
|
|
28
|
+
if (!connected) {
|
|
29
|
+
const disconnectObservedAt = Number.isFinite(disconnectedAt)
|
|
30
|
+
? disconnectedAt
|
|
31
|
+
: lastMessageAt;
|
|
32
|
+
const disconnectedElapsed = Math.max(
|
|
33
|
+
0,
|
|
34
|
+
now - Math.max(disconnectObservedAt, visibleSince),
|
|
35
|
+
);
|
|
36
|
+
return disconnectedElapsed >= BACKEND_INITIAL_CONNECT_GRACE_MS
|
|
37
|
+
? 'lost'
|
|
38
|
+
: 'connecting';
|
|
39
|
+
}
|
|
11
40
|
const observationStartedAt = Math.max(lastMessageAt, visibleSince);
|
|
12
41
|
const elapsed = Math.max(0, now - observationStartedAt);
|
|
13
|
-
if (
|
|
14
|
-
if (
|
|
15
|
-
if (connected && elapsed >= BACKEND_HEARTBEAT_STALE_MS) return 'stale';
|
|
42
|
+
if (elapsed >= BACKEND_HEARTBEAT_FAILURE_MS) return 'stale';
|
|
43
|
+
if (elapsed >= BACKEND_HEARTBEAT_STALE_MS) return 'connecting';
|
|
16
44
|
return null;
|
|
17
45
|
}
|
|
18
46
|
|
|
@@ -34,7 +62,10 @@ function reducePageVisibilitySnapshot(current, {
|
|
|
34
62
|
|
|
35
63
|
module.exports = {
|
|
36
64
|
BACKEND_INITIAL_CONNECT_GRACE_MS,
|
|
65
|
+
BACKEND_HEARTBEAT_FAILURE_MS,
|
|
37
66
|
BACKEND_HEARTBEAT_STALE_MS,
|
|
67
|
+
BACKEND_OBSERVER_LAG_RESET_MS,
|
|
68
|
+
advanceBackendObservation,
|
|
38
69
|
classifyBackendConnection,
|
|
39
70
|
reducePageVisibilitySnapshot,
|
|
40
71
|
};
|
|
@@ -101,7 +101,7 @@ function validateServerMessage(value) {
|
|
|
101
101
|
case 'error': valid = stringField(value, 'message'); break;
|
|
102
102
|
case 'command-ack': valid = stringField(value, 'requestId') && stringField(value, 'command'); break;
|
|
103
103
|
case 'state': valid = objectMessage(value.state) && Array.isArray(value.state.agents); break;
|
|
104
|
-
case 'composer-input-result': valid = stringField(value, 'requestId') && stringField(value, 'agentId') && typeof value.accepted === 'boolean' && stringField(value, 'message', true); break;
|
|
104
|
+
case 'composer-input-result': valid = stringField(value, 'requestId') && stringField(value, 'agentId') && typeof value.accepted === 'boolean' && stringField(value, 'message', true) && (!Object.prototype.hasOwnProperty.call(value, 'uncertain') || typeof value.uncertain === 'boolean'); break;
|
|
105
105
|
case 'agent-started': valid = stringField(value, 'agentId'); break;
|
|
106
106
|
case 'session-output': valid = objectMessage(value.stream) && stringField(value.stream, 'agentId'); break;
|
|
107
107
|
case 'session-preview': valid = objectMessage(value.preview) && stringField(value.preview, 'agentId'); break;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
const { deriveRuntimeObservation } = require('./runtime-observation');
|
|
2
|
-
|
|
3
|
-
function agentKindForCommand(command) {
|
|
4
|
-
const executable = String(command || '')
|
|
5
|
-
.trim()
|
|
6
|
-
.split(/\s+/)
|
|
7
|
-
.find(token => token !== 'env' && !/^[A-Za-z_][A-Za-z0-9_]*=/.test(token));
|
|
8
|
-
const basename = (executable || '').split('/').pop() || '';
|
|
9
|
-
if (basename === 'codex') return 'codex';
|
|
10
|
-
if (basename === 'claude') return 'claude';
|
|
11
|
-
if (['bash', 'zsh', 'sh', 'fish'].includes(basename)) return 'shell';
|
|
12
|
-
return executable ? 'agent' : null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function isRecoverableEngineAgent(agent) {
|
|
16
|
-
return agent && agent.engineName === 'native';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function isRestartBlockingAgent(agent) {
|
|
20
|
-
if (!agent || agent.isMain === true || agent.archived === true) return false;
|
|
21
|
-
if (agent.status === 'pending') return true;
|
|
22
|
-
if (agent.status !== 'running') return false;
|
|
23
|
-
if (isRecoverableEngineAgent(agent)) return false;
|
|
24
|
-
|
|
25
|
-
const observation = deriveRuntimeObservation(agent);
|
|
26
|
-
if (observation.phase === 'starting' || observation.phase === 'working' || observation.phase === 'waiting') return true;
|
|
27
|
-
if (observation.phase === 'idle' || observation.phase === 'exited') return false;
|
|
28
|
-
return observation.kind !== 'shell';
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
module.exports = {
|
|
32
|
-
agentKindForCommand,
|
|
33
|
-
isRecoverableEngineAgent,
|
|
34
|
-
isRestartBlockingAgent,
|
|
35
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.xterm{cursor:text;-webkit-user-select:none;user-select:none;position:relative}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{z-index:5;position:absolute;top:0}.xterm .xterm-helper-textarea{opacity:0;z-index:-5;white-space:nowrap;resize:none;border:0;width:0;height:0;margin:0;padding:0;position:absolute;top:0;left:-9999em;overflow:hidden}.xterm .composition-view{color:#fff;white-space:nowrap;z-index:1;background:#000;display:none;position:absolute}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{cursor:default;background-color:#000;position:absolute;inset:0;overflow-y:scroll}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;top:0;left:0}.xterm-char-measure-element{visibility:hidden;line-height:normal;display:inline-block;position:absolute;top:0;left:-9999em}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{z-index:10;color:#0000;pointer-events:none;position:absolute;inset:0}.xterm .xterm-accessibility-tree:not(.debug) ::selection{color:#0000}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre;font-family:monospace}.xterm .xterm-accessibility-tree>div{transform-origin:0;width:fit-content}.xterm .live-region{width:1px;height:1px;position:absolute;left:-9999px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{-webkit-text-decoration:underline double;text-decoration:underline double}.xterm-underline-3{-webkit-text-decoration:underline wavy;text-decoration:underline wavy}.xterm-underline-4{-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.xterm-underline-5{-webkit-text-decoration:underline dashed;text-decoration:underline dashed}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:underline overline}.xterm-overline.xterm-underline-2{-webkit-text-decoration:overline double underline;text-decoration:overline double underline}.xterm-overline.xterm-underline-3{-webkit-text-decoration:overline wavy underline;text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{-webkit-text-decoration:overline dotted underline;text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{-webkit-text-decoration:overline dashed underline;text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;pointer-events:none;position:absolute;top:0;right:0}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;z-index:11;background:0 0;transition:opacity .1s linear}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{display:none;position:absolute}.xterm .xterm-scrollable-element>.shadow.top{width:100%;height:3px;box-shadow:var(--vscode-scrollbar-shadow,#000) 0 6px 6px -6px inset;display:block;top:0;left:3px}.xterm .xterm-scrollable-element>.shadow.left{width:3px;height:100%;box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset;display:block;top:3px;left:0}.xterm .xterm-scrollable-element>.shadow.top-left-corner{width:3px;height:3px;display:block;top:0;left:0}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow,#000) 6px 0 6px -6px inset}
|