@shawnstack/quickforge 1.7.3 → 1.7.4
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 +1 -1
- package/bin/quickforge.mjs +0 -21
- package/dist/assets/AgentProfilesPage-B84w-r9S.js +1 -0
- package/dist/assets/{ChatPanelHost-wfGCaCzD.js → ChatPanelHost-CyO8fEoj.js} +91 -91
- package/dist/assets/{PluginsPage-NAGroBm3.js → PluginsPage-D2862wul.js} +1 -1
- package/dist/assets/{ScheduledTasksPage-Bp0MNfQD.js → ScheduledTasksPage-GqbiJDPX.js} +2 -2
- package/dist/assets/SettingsWorkspacePage-B53_eDf2.js +1628 -0
- package/dist/assets/SharedConversationPage-Cw2QFnbC.js +1 -0
- package/dist/assets/TerminalDock-Dgg-_ZmU.js +2 -0
- package/dist/assets/WorkspaceInspector-3uLiu6Bv.js +13 -0
- package/dist/assets/{abnfDiagram-VRR7QNED-Dl_Fvlqg.js → abnfDiagram-VRR7QNED-Dy7veffk.js} +1 -1
- package/dist/assets/{arc-Bhg4c0ht.js → arc-Bo3p2lGy.js} +1 -1
- package/dist/assets/architecture-TIHT7OUA-7FQo5GbP.js +1 -0
- package/dist/assets/{architectureDiagram-ZJ3FMSHR-BuojN27B.js → architectureDiagram-ZJ3FMSHR-Cwx8qOvu.js} +1 -1
- package/dist/assets/{blockDiagram-677ZJIJ3-alDLbrR1.js → blockDiagram-677ZJIJ3-BiuaAOFa.js} +1 -1
- package/dist/assets/{c4Diagram-LMCZKHZV-D1lKa4VT.js → c4Diagram-LMCZKHZV-BTcGfhK2.js} +1 -1
- package/dist/assets/channel-DToA8d-4.js +1 -0
- package/dist/assets/chunk-2Q5K7J3B-D_Wxpk-T.js +1 -0
- package/dist/assets/{chunk-32BRIVSS-CwWLNjMZ.js → chunk-32BRIVSS-B9PuF_RF.js} +1 -1
- package/dist/assets/{chunk-52WLFC77-Be569m7d.js → chunk-52WLFC77-3zGItfIM.js} +1 -1
- package/dist/assets/{chunk-5FCAYU7R-BSvoiWV1.js → chunk-5FCAYU7R-DQ66qlmt.js} +1 -1
- package/dist/assets/{chunk-5HE753X5-CRgsy8WS.js → chunk-5HE753X5-CLqTO-VF.js} +1 -1
- package/dist/assets/{chunk-5JV3BV7I-CdW477UR.js → chunk-5JV3BV7I-Csxv1jr6.js} +1 -1
- package/dist/assets/{chunk-5TONJI2A-CdtKzSmp.js → chunk-5TONJI2A-BCQttpBr.js} +1 -1
- package/dist/assets/{chunk-5VM5RSS4-BKjjssLZ.js → chunk-5VM5RSS4-DEWJGSTb.js} +1 -1
- package/dist/assets/{chunk-7BUUIJ7U-ByAXiXdn.js → chunk-7BUUIJ7U-DNorm9MM.js} +1 -1
- package/dist/assets/{chunk-BIQX33UG-DeG8SCT1.js → chunk-BIQX33UG-DgvY_BOT.js} +1 -1
- package/dist/assets/{chunk-C7G6YPKG-D_zHT68Q.js → chunk-C7G6YPKG-DMvn9IPs.js} +1 -1
- package/dist/assets/{chunk-CQNSW5MT-CHpHoUSu.js → chunk-CQNSW5MT-Dq2duUgr.js} +1 -1
- package/dist/assets/{chunk-CYSBUYHQ-CRP50Vov.js → chunk-CYSBUYHQ-BovYyc4Y.js} +1 -1
- package/dist/assets/{chunk-EMLP6XTP-DX6uQQ2v.js → chunk-EMLP6XTP-BMDOpuYN.js} +1 -1
- package/dist/assets/{chunk-EX3LRPZG-DAJRNkHR.js → chunk-EX3LRPZG-6eP2UPOf.js} +1 -1
- package/dist/assets/{chunk-FWX5IMBZ-XbM5yomC.js → chunk-FWX5IMBZ-D4q-wTSy.js} +2 -2
- package/dist/assets/{chunk-HOUHSVGY-Ci0ljnb1.js → chunk-HOUHSVGY-XjIcuzH7.js} +1 -1
- package/dist/assets/{chunk-ICXQ74PX-Dy2WJ71z.js → chunk-ICXQ74PX-YBXbanq9.js} +1 -1
- package/dist/assets/{chunk-JG7HCLWE-2PrkzHkt.js → chunk-JG7HCLWE-CcN3uNXF.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-D32uacSM.js → chunk-JWPE2WC7-Cwg6AUAt.js} +1 -1
- package/dist/assets/{chunk-MOJQB5TN-DIAFLtiS.js → chunk-MOJQB5TN-NNspcGIU.js} +1 -1
- package/dist/assets/{chunk-MOZMSUNE-BbscOaEz.js → chunk-MOZMSUNE-pMJ_jMos.js} +1 -1
- package/dist/assets/{chunk-OGEWGWER-ivBVxzKe.js → chunk-OGEWGWER-CJy-3Ldv.js} +1 -1
- package/dist/assets/{chunk-OSBZ3O6U-frD0hkdx.js → chunk-OSBZ3O6U-D7cLHHOA.js} +1 -1
- package/dist/assets/{chunk-PUDLZKDR-B-37Rxae.js → chunk-PUDLZKDR-D5YBi1Pi.js} +1 -1
- package/dist/assets/{chunk-Q4XR5HBZ-Y90m2RTe.js → chunk-Q4XR5HBZ-DYmqQdIf.js} +1 -1
- package/dist/assets/{chunk-QBLGF6JB-DixBqslB.js → chunk-QBLGF6JB-Bfcx00X0.js} +1 -1
- package/dist/assets/{chunk-R7FJI6CG-DXS1UXn_.js → chunk-R7FJI6CG-oXzadpZY.js} +1 -1
- package/dist/assets/{chunk-RYQCIY6F-n4JxhNd0.js → chunk-RYQCIY6F-Dt3-8yUh.js} +1 -1
- package/dist/assets/{chunk-U6XO7XAA-yHlgxMmn.js → chunk-U6XO7XAA-B55eSvpx.js} +1 -1
- package/dist/assets/{chunk-V7JOEXUC-Z6kuZfbl.js → chunk-V7JOEXUC-Btk4JwCt.js} +1 -1
- package/dist/assets/chunk-VAUOI2AC-CIZseNLi.js +1 -0
- package/dist/assets/{chunk-VR4S4FIN-Cs_SIQma.js → chunk-VR4S4FIN-DgaSiVOY.js} +1 -1
- package/dist/assets/{chunk-WYO6CB5R-CGExYbV-.js → chunk-WYO6CB5R-rRDZ_Tta.js} +3 -3
- package/dist/assets/chunk-XXDRQBXY-Do-XYxat.js +1 -0
- package/dist/assets/{chunk-YOTPTUD7-DopPXWSl.js → chunk-YOTPTUD7-BnFxj5o4.js} +1 -1
- package/dist/assets/{chunk-ZGVPDNZ5-CJHOeqMb.js → chunk-ZGVPDNZ5-CrnlPlmJ.js} +1 -1
- package/dist/assets/{chunk-ZIRB5QZD-BBVc5mf6.js → chunk-ZIRB5QZD-BYTiATIH.js} +1 -1
- package/dist/assets/classDiagram-OUVF2IWQ-Bu24Sy-k.js +1 -0
- package/dist/assets/classDiagram-v2-EOCWNBFH-DKhh5HSW.js +1 -0
- package/dist/assets/{cose-bilkent-JH36ORCC-DLjV-dTm.js → cose-bilkent-JH36ORCC-BORKJRwF.js} +1 -1
- package/dist/assets/cynefin-VYW2F7L2-oyiAgYC4.js +1 -0
- package/dist/assets/{cynefinDiagram-TSTJHNR4-BfH3zVS-.js → cynefinDiagram-TSTJHNR4-BXKeaSl8.js} +1 -1
- package/dist/assets/{dagre-CY3D84Cl.js → dagre-CrA0XVwJ.js} +1 -1
- package/dist/assets/{dagre-VKFMJZFB-BIhwZCIZ.js → dagre-VKFMJZFB-ouq_lA1a.js} +1 -1
- package/dist/assets/{diagram-FQU43EPY-BHnzNM2w.js → diagram-FQU43EPY-BxR5kUiQ.js} +1 -1
- package/dist/assets/{diagram-G47NLZAW-C7-ZlmFT.js → diagram-G47NLZAW-DWonk1sL.js} +1 -1
- package/dist/assets/{diagram-NH7WQ7WH-C-P9Y7IR.js → diagram-NH7WQ7WH-fmV_wV5e.js} +1 -1
- package/dist/assets/{diagram-OA4YK3LP-Ci5lZ_T5.js → diagram-OA4YK3LP-DvOSRRiV.js} +1 -1
- package/dist/assets/{diagram-WEI45ONY-C1xuK2bs.js → diagram-WEI45ONY-Bp-xb3uS.js} +1 -1
- package/dist/assets/dist-DLKC_odd.js +1 -0
- package/dist/assets/{ebnfDiagram-CCIWWBDH-DKQ5NWMD.js → ebnfDiagram-CCIWWBDH-BTlnwneA.js} +1 -1
- package/dist/assets/{erDiagram-Q63AITRT-HAWySadP.js → erDiagram-Q63AITRT-C3fFWGCm.js} +1 -1
- package/dist/assets/esm-oa69b5u4.js +2 -0
- package/dist/assets/eventmodeling-45OFAUF4-YB_0MefX.js +1 -0
- package/dist/assets/flowDiagram-23GEKE2U-Bc73xdBd.js +1 -0
- package/dist/assets/{ganttDiagram-NO4QXBWP-C1hwIcOA.js → ganttDiagram-NO4QXBWP-DzAiojNi.js} +1 -1
- package/dist/assets/gitGraph-TEB2WS4Q-Bvp27L0n.js +1 -0
- package/dist/assets/{gitGraphDiagram-IHSO6WYX-DYUYxs1R.js → gitGraphDiagram-IHSO6WYX-Cv57oNEA.js} +1 -1
- package/dist/assets/icons-cTkqD_Gi.js +1 -0
- package/dist/assets/index-B48prgLL.js +65 -0
- package/dist/assets/index-DQhwHHer.css +3 -0
- package/dist/assets/info-DKCQHKI2-BsLOivgq.js +1 -0
- package/dist/assets/{infoDiagram-FWYZ7A6U-CnIL6tv4.js → infoDiagram-FWYZ7A6U-B5Z_O3Ro.js} +1 -1
- package/dist/assets/{ishikawaDiagram-FXEZZL3T-B7WXNycQ.js → ishikawaDiagram-FXEZZL3T-CKTK_TKV.js} +1 -1
- package/dist/assets/{journeyDiagram-5HDEW3XC-D4HvioyY.js → journeyDiagram-5HDEW3XC-Cm9k4ywW.js} +1 -1
- package/dist/assets/{kanban-definition-HUTT4EX6-CDs763eS.js → kanban-definition-HUTT4EX6-DzNteLwx.js} +1 -1
- package/dist/assets/{line-ikKkQiFp.js → line-BG78c_WJ.js} +1 -1
- package/dist/assets/{linear-GqPyxQkN.js → linear-1X20_EGu.js} +1 -1
- package/dist/assets/{map-CJwjCvwr.js → map-CCI8WZkS.js} +1 -1
- package/dist/assets/{mcp-servers-dialog-BQbFywVL.js → mcp-servers-dialog-GXXD9K0U.js} +2 -2
- package/dist/assets/{mermaid-parser.core-CoE8cccr.js → mermaid-parser.core-Bb8HI_OS.js} +2 -2
- package/dist/assets/{mermaid-renderer-BmbSAmpG.js → mermaid-renderer-PIaNiXAz.js} +2 -2
- package/dist/assets/{mermaid.core-DlFSL90j.js → mermaid.core-DUHOIwL5.js} +3 -3
- package/dist/assets/{mindmap-definition-LN4V7U3C-DLdq0K9C.js → mindmap-definition-LN4V7U3C-Tnbszo7b.js} +1 -1
- package/dist/assets/{monaco-BTsVCDWS.js → monaco-BVtCspYZ.js} +1 -1
- package/dist/assets/{ordinal-CibZU3PM.js → ordinal-v4prQcuq.js} +1 -1
- package/dist/assets/{otel-BNGM50C-.js → otel-D1LswXpM.js} +1 -1
- package/dist/assets/packet-7NZHBO7P-BKQkXRtk.js +1 -0
- package/dist/assets/{pegDiagram-2B236MQR-Cm1kPRC2.js → pegDiagram-2B236MQR-CX824Kd0.js} +1 -1
- package/dist/assets/{pi-ai-Cr3rpCXT.js → pi-ai-DAJlO9ZB.js} +2 -2
- package/dist/assets/{pi-web-ui-DoRGtREc.js → pi-web-ui-B-RJSxjR.js} +1 -1
- package/dist/assets/pie-RZYD4A2V-BTiTN5Ge.js +1 -0
- package/dist/assets/{pieDiagram-ENE6RG2P-Df05wjjo.js → pieDiagram-ENE6RG2P-BT04VWPQ.js} +1 -1
- package/dist/assets/{quadrantDiagram-ABIIQ3AL-BjCwGxJC.js → quadrantDiagram-ABIIQ3AL-BvOZxkBr.js} +1 -1
- package/dist/assets/radar-I7S5WNFK-BU-oVjKM.js +1 -0
- package/dist/assets/railroad-3IZDKUUU-7H2hxNbL.js +1 -0
- package/dist/assets/railroad-abnf-AHOZXSZD-Mx6wf6XQ.js +1 -0
- package/dist/assets/railroad-ebnf-EBAXGLYW-BgXSKhYy.js +1 -0
- package/dist/assets/railroad-peg-LSFZ7HO6-DTEl2rAC.js +1 -0
- package/dist/assets/{railroadDiagram-RFXS5EU6-CTUvpKkv.js → railroadDiagram-RFXS5EU6-DnTU--BV.js} +1 -1
- package/dist/assets/{react-vendor-Dr5xvL-e.js → react-vendor-eWH0QhNU.js} +1 -1
- package/dist/assets/{requirementDiagram-TGXJPOKE-BU1kvEku.js → requirementDiagram-TGXJPOKE--MZX_yEv.js} +1 -1
- package/dist/assets/{sankeyDiagram-HTMAVEWB-BHmvxVqH.js → sankeyDiagram-HTMAVEWB-SEZkHhYn.js} +1 -1
- package/dist/assets/{sequenceDiagram-DBY2YBRQ-CTpwICgg.js → sequenceDiagram-DBY2YBRQ-BhC2OHiz.js} +1 -1
- package/dist/assets/{sizeCapture-X5ZJPWSS-BbLhGaa4.js → sizeCapture-X5ZJPWSS-Ci5LeToV.js} +1 -1
- package/dist/assets/{skills-dialog-REBeTFSH.js → skills-dialog-DDh1h8eH.js} +3 -1
- package/dist/assets/{src-B4Tvg3gT.js → src-CovulcRC.js} +1 -1
- package/dist/assets/{stateDiagram-2N3HPSRC-BxuDwIgT.js → stateDiagram-2N3HPSRC-DKK5tFT4.js} +1 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-D8x3mkni.js +1 -0
- package/dist/assets/{swimlanes-5IMT3BWC-EkZsiylV.js → swimlanes-5IMT3BWC-DxxGCk67.js} +2 -2
- package/dist/assets/swimlanesDiagram-G3AALYLV-C4nOBNp8.js +8 -0
- package/dist/assets/{timeline-definition-FHXFAJF6-C9ewOCTa.js → timeline-definition-FHXFAJF6-BPXB3Sue.js} +1 -1
- package/dist/assets/treeView-QDETBFTQ-DOE6NSdf.js +1 -0
- package/dist/assets/treemap-6X3UGDF4-Ca7QD_b4.js +1 -0
- package/dist/assets/{vennDiagram-L72KCM5P-CR49Y4Lp.js → vennDiagram-L72KCM5P-CxcBCKye.js} +1 -1
- package/dist/assets/wardley-OPB4EBWU-D9O4RKRm.js +1 -0
- package/dist/assets/{wardleyDiagram-EHGQE667-Cn0GgwWi.js → wardleyDiagram-EHGQE667-DEL6Yes5.js} +1 -1
- package/dist/assets/web-RgX7H-OH.js +1 -0
- package/dist/assets/{xychartDiagram-FW5EYKEG-DlmPNAvd.js → xychartDiagram-FW5EYKEG-N8cPbcjC.js} +1 -1
- package/dist/index.html +12 -11
- package/dist/mobile-error.html +24 -0
- package/package.json +4 -1
- package/server/acp/server.mjs +14 -9
- package/server/agent-manager.mjs +215 -20
- package/server/ai-http-logger.mjs +68 -11
- package/server/ai-provider-options.mjs +3 -0
- package/server/channels/channel-logs.mjs +13 -0
- package/server/channels/event-relay.mjs +33 -0
- package/server/channels/process-channel.mjs +29 -0
- package/server/channels/providers/wechat.mjs +9 -3
- package/server/channels/registry.mjs +5 -1
- package/server/index.mjs +36 -23
- package/server/lan-access-store.mjs +93 -3
- package/server/network-proxy.mjs +68 -3
- package/server/plugins/registry.mjs +64 -4
- package/server/public-api.mjs +6 -2
- package/server/routes/agent-profiles.mjs +2 -2
- package/server/routes/agent.mjs +28 -0
- package/server/routes/channels.mjs +47 -0
- package/server/routes/lan-access.mjs +246 -21
- package/server/routes/models.mjs +6 -3
- package/server/routes/project.mjs +19 -1
- package/server/routes/scheduled-tasks.mjs +2 -2
- package/server/routes/static.mjs +26 -1
- package/server/routes/system.mjs +11 -0
- package/server/routes/terminal.mjs +7 -2
- package/server/routes/workspace.mjs +60 -9
- package/server/session-utils.mjs +2 -2
- package/server/subagents.mjs +1 -1
- package/server/terminal/terminal-manager.mjs +2 -4
- package/server/tools/definitions.mjs +2 -2
- package/server/tools/index.mjs +5 -3
- package/server/utils/package-update.mjs +70 -47
- package/server/utils/process-env.mjs +7 -0
- package/server/utils/response.mjs +2 -2
- package/dist/assets/AgentProfilesPage-D7pbg8nm.js +0 -1
- package/dist/assets/SettingsWorkspacePage-BtJZMIsZ.js +0 -1576
- package/dist/assets/SharedConversationPage-Ce3KoVZt.js +0 -1
- package/dist/assets/TerminalDock-4eUuXP7X.js +0 -2
- package/dist/assets/WorkspaceInspector-kM3BRPjY.js +0 -13
- package/dist/assets/architecture-TIHT7OUA-BgP-IMeo.js +0 -1
- package/dist/assets/channel-Rz20dKTK.js +0 -1
- package/dist/assets/chunk-2Q5K7J3B-Cb14ZF_k.js +0 -1
- package/dist/assets/chunk-VAUOI2AC-BOZvd2Sn.js +0 -1
- package/dist/assets/chunk-XXDRQBXY-CD_EGCtT.js +0 -1
- package/dist/assets/classDiagram-OUVF2IWQ-C_ozTKCt.js +0 -1
- package/dist/assets/classDiagram-v2-EOCWNBFH-FOfFbbZF.js +0 -1
- package/dist/assets/cynefin-VYW2F7L2-BzPhLtd5.js +0 -1
- package/dist/assets/eventmodeling-45OFAUF4-BcgGbVJ-.js +0 -1
- package/dist/assets/flowDiagram-23GEKE2U-dtkzcC8E.js +0 -1
- package/dist/assets/gitGraph-TEB2WS4Q-VByWboBU.js +0 -1
- package/dist/assets/icons-BP8YOS-Z.js +0 -1
- package/dist/assets/index-C6k5taeb.js +0 -66
- package/dist/assets/index-CzN8NSKC.css +0 -3
- package/dist/assets/info-DKCQHKI2-CZeDLZxx.js +0 -1
- package/dist/assets/packet-7NZHBO7P-decrrxyX.js +0 -1
- package/dist/assets/pie-RZYD4A2V-J1CasQZl.js +0 -1
- package/dist/assets/radar-I7S5WNFK-B-sZytUA.js +0 -1
- package/dist/assets/railroad-3IZDKUUU-BSaqNPm8.js +0 -1
- package/dist/assets/railroad-abnf-AHOZXSZD-lzZR7PxT.js +0 -1
- package/dist/assets/railroad-ebnf-EBAXGLYW-DQtz1Fh9.js +0 -1
- package/dist/assets/railroad-peg-LSFZ7HO6-CpMsuGY3.js +0 -1
- package/dist/assets/stateDiagram-v2-6OUMAXLB-BGLshxcY.js +0 -1
- package/dist/assets/swimlanesDiagram-G3AALYLV-CqdqxA-b.js +0 -8
- package/dist/assets/treeView-QDETBFTQ-Byb71heW.js +0 -1
- package/dist/assets/treemap-6X3UGDF4-CMV1SJsq.js +0 -1
- package/dist/assets/wardley-OPB4EBWU-DtCHtr2V.js +0 -1
- /package/dist/assets/{array-CYkMkqnU.js → array-DqLCdDFv.js} +0 -0
- /package/dist/assets/{chunk-KEIR6QF5-77hsebd7.js → chunk-KEIR6QF5-s7Qq-R3i.js} +0 -0
- /package/dist/assets/{chunk-Y2CYZVJY-CQltPwYk.js → chunk-Y2CYZVJY-BgISNSiw.js} +0 -0
- /package/dist/assets/{css-utils-rkE68RDy.js → css-utils-31qzCXsk.js} +0 -0
- /package/dist/assets/{cytoscape.esm-DwdZnGOm.js → cytoscape.esm-iekjSZ2n.js} +0 -0
- /package/dist/assets/{defaultLocale-Beh6XjaL.js → defaultLocale-CrJzLgRD.js} +0 -0
- /package/dist/assets/{dist-DelZBZpK.js → dist-zzfqk5hx.js} +0 -0
- /package/dist/assets/{graphlib-CAISHZh4.js → graphlib-CIz_CfxW.js} +0 -0
- /package/dist/assets/{init-Rr1s_RiX.js → init-C0r9Gk5G.js} +0 -0
- /package/dist/assets/{lit-vendor-Dr3cpBGF.js → lit-vendor-DvaQX_UQ.js} +0 -0
- /package/dist/assets/{logger-B65Akg8A.js → logger-8REuLPGK.js} +0 -0
- /package/dist/assets/{path-BAQ3hXlG.js → path-DIKpVbHL.js} +0 -0
- /package/dist/assets/{plugin-api-BbUkYm3Y.js → plugin-api-C8hMT5W6.js} +0 -0
- /package/dist/assets/{rough.esm-Djo4Abte.js → rough.esm-BMOtDaaS.js} +0 -0
- /package/dist/assets/{xterm-CGiQzDiR.js → xterm-BFzZ1FH4.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
3
|
import { spawn } from 'node:child_process'
|
|
4
|
-
import {
|
|
4
|
+
import { streamSimpleWithAiHttpLogging } from '../ai-http-logger.mjs'
|
|
5
5
|
import { DEFAULT_AI_MAX_RETRIES } from '../ai-provider-options.mjs'
|
|
6
6
|
import { sendJson, readJsonBody } from '../utils/response.mjs'
|
|
7
7
|
import { projectContextFromId } from '../project-config.mjs'
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
|
|
18
18
|
const MAX_PREVIEW_BYTES = 50 * 1024 * 1024
|
|
19
19
|
const MAX_STATIC_PREVIEW_BYTES = 50 * 1024 * 1024
|
|
20
|
+
const DEFAULT_GIT_TIMEOUT_MS = 2 * 60 * 1000
|
|
20
21
|
const MAX_GIT_LINE_COUNT_FILES = 100
|
|
21
22
|
const MAX_GIT_LINE_COUNT_FILE_BYTES = 1024 * 1024
|
|
22
23
|
const MAX_GIT_LINE_COUNT_TOTAL_BYTES = 10 * 1024 * 1024
|
|
@@ -29,7 +30,7 @@ const extensionLanguageMap = new Map([
|
|
|
29
30
|
['ts', 'typescript'], ['tsx', 'typescript'], ['js', 'javascript'], ['jsx', 'javascript'],
|
|
30
31
|
['mjs', 'javascript'], ['cjs', 'javascript'], ['json', 'json'], ['jsonc', 'json'],
|
|
31
32
|
['css', 'css'], ['scss', 'scss'], ['less', 'less'], ['html', 'html'], ['htm', 'html'],
|
|
32
|
-
['md', 'markdown'], ['markdown', 'markdown'], ['py', 'python'], ['rb', 'ruby'], ['go', 'go'],
|
|
33
|
+
['md', 'markdown'], ['mdx', 'markdown'], ['markdown', 'markdown'], ['py', 'python'], ['rb', 'ruby'], ['go', 'go'],
|
|
33
34
|
['rs', 'rust'], ['java', 'java'], ['c', 'c'], ['h', 'c'], ['cpp', 'cpp'], ['cc', 'cpp'],
|
|
34
35
|
['cxx', 'cpp'], ['hpp', 'cpp'], ['cs', 'csharp'], ['php', 'php'], ['swift', 'swift'],
|
|
35
36
|
['kt', 'kotlin'], ['kts', 'kotlin'], ['sh', 'shell'], ['bash', 'shell'], ['zsh', 'shell'],
|
|
@@ -76,20 +77,65 @@ async function projectContextFromUrl(url) {
|
|
|
76
77
|
return projectContextFromId(projectId)
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
function
|
|
80
|
+
function killProcessTree(child) {
|
|
81
|
+
if (!child?.pid) return
|
|
82
|
+
if (process.platform === 'win32') {
|
|
83
|
+
const killer = spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], {
|
|
84
|
+
stdio: 'ignore',
|
|
85
|
+
windowsHide: true,
|
|
86
|
+
})
|
|
87
|
+
killer.on('error', () => {
|
|
88
|
+
try { child.kill('SIGKILL') } catch { /* ignore */ }
|
|
89
|
+
})
|
|
90
|
+
return
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
process.kill(-child.pid, 'SIGKILL')
|
|
94
|
+
} catch {
|
|
95
|
+
try { child.kill('SIGKILL') } catch { /* ignore */ }
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function git(args, cwd, options = {}) {
|
|
80
100
|
return new Promise((resolve, reject) => {
|
|
101
|
+
const timeoutMs = Number.isFinite(options.timeoutMs) ? Math.max(1, options.timeoutMs) : DEFAULT_GIT_TIMEOUT_MS
|
|
81
102
|
const child = spawn('git', args, {
|
|
82
103
|
cwd,
|
|
83
104
|
shell: false,
|
|
84
105
|
windowsHide: true,
|
|
85
|
-
|
|
106
|
+
detached: process.platform !== 'win32',
|
|
107
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
108
|
+
env: {
|
|
109
|
+
...process.env,
|
|
110
|
+
GIT_OPTIONAL_LOCKS: '0',
|
|
111
|
+
GIT_TERMINAL_PROMPT: '0',
|
|
112
|
+
GCM_INTERACTIVE: 'Never',
|
|
113
|
+
},
|
|
86
114
|
})
|
|
87
115
|
const stdout = []
|
|
88
116
|
const stderr = []
|
|
117
|
+
let settled = false
|
|
118
|
+
const finish = (callback) => {
|
|
119
|
+
if (settled) return
|
|
120
|
+
settled = true
|
|
121
|
+
clearTimeout(timeout)
|
|
122
|
+
callback()
|
|
123
|
+
}
|
|
124
|
+
const timeout = setTimeout(() => {
|
|
125
|
+
killProcessTree(child)
|
|
126
|
+
finish(() => {
|
|
127
|
+
const error = new Error(`git ${args.join(' ')} timed out after ${timeoutMs}ms`)
|
|
128
|
+
error.statusCode = 504
|
|
129
|
+
error.code = 'GIT_TIMEOUT'
|
|
130
|
+
reject(error)
|
|
131
|
+
})
|
|
132
|
+
}, timeoutMs)
|
|
133
|
+
timeout.unref?.()
|
|
134
|
+
|
|
89
135
|
child.stdout.on('data', (chunk) => stdout.push(chunk))
|
|
90
136
|
child.stderr.on('data', (chunk) => stderr.push(chunk))
|
|
91
|
-
child.once('error', reject)
|
|
92
|
-
child.once('close', (code) => {
|
|
137
|
+
child.once('error', (error) => finish(() => reject(error)))
|
|
138
|
+
child.once('close', (code) => finish(() => {
|
|
93
139
|
const out = Buffer.concat(stdout)
|
|
94
140
|
const err = Buffer.concat(stderr).toString('utf8').trim()
|
|
95
141
|
if (code === 0 || options.allowFailure) {
|
|
@@ -99,7 +145,7 @@ function git(args, cwd, options = {}) {
|
|
|
99
145
|
error.statusCode = 400
|
|
100
146
|
reject(error)
|
|
101
147
|
}
|
|
102
|
-
})
|
|
148
|
+
}))
|
|
103
149
|
})
|
|
104
150
|
}
|
|
105
151
|
|
|
@@ -619,7 +665,7 @@ Unstaged diff:
|
|
|
619
665
|
${trimForPrompt(worktreeDiff)}`
|
|
620
666
|
|
|
621
667
|
try {
|
|
622
|
-
const stream =
|
|
668
|
+
const stream = streamSimpleWithAiHttpLogging(
|
|
623
669
|
model,
|
|
624
670
|
{
|
|
625
671
|
systemPrompt,
|
|
@@ -1100,7 +1146,7 @@ async function handleGitCommitAndPush(req, res) {
|
|
|
1100
1146
|
sendJson(res, 200, await commitAndPushGitChanges(context, body?.message, Boolean(body?.includeUnstaged)))
|
|
1101
1147
|
}
|
|
1102
1148
|
|
|
1103
|
-
export async function handleWorkspaceApi(req, res, url) {
|
|
1149
|
+
export async function handleWorkspaceApi(req, res, url, requestContext = {}) {
|
|
1104
1150
|
if (req.method === 'GET' && url.pathname === '/api/workspace/tree') {
|
|
1105
1151
|
await handleWorkspaceTree(req, res, url)
|
|
1106
1152
|
return
|
|
@@ -1118,6 +1164,11 @@ export async function handleWorkspaceApi(req, res, url) {
|
|
|
1118
1164
|
return
|
|
1119
1165
|
}
|
|
1120
1166
|
if (req.method === 'POST' && url.pathname === '/api/workspace/open-external') {
|
|
1167
|
+
if (requestContext.isLocalRequest !== true) {
|
|
1168
|
+
const error = new Error('Opening applications is only allowed from this computer')
|
|
1169
|
+
error.statusCode = 403
|
|
1170
|
+
throw error
|
|
1171
|
+
}
|
|
1121
1172
|
await handleWorkspaceOpenExternal(req, res)
|
|
1122
1173
|
return
|
|
1123
1174
|
}
|
package/server/session-utils.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { streamSimpleWithAiHttpLogging } from './ai-http-logger.mjs'
|
|
2
2
|
import { DEFAULT_AI_MAX_RETRIES } from './ai-provider-options.mjs'
|
|
3
3
|
import { buildInstructionsPayload, projectContextFromId } from './project-config.mjs'
|
|
4
4
|
import { composeSystemPrompt } from './system-prompt.mjs'
|
|
@@ -88,7 +88,7 @@ export async function generateAiTitle(messages, model, thinkingLevel, getApiKey)
|
|
|
88
88
|
|
|
89
89
|
try {
|
|
90
90
|
const apiKey = getApiKey ? await getApiKey(model.provider) : undefined
|
|
91
|
-
const stream =
|
|
91
|
+
const stream = streamSimpleWithAiHttpLogging(
|
|
92
92
|
model,
|
|
93
93
|
{
|
|
94
94
|
systemPrompt: '你是对话标题生成器。请用和用户相同的语言,根据对话主题生成 3 到 5 个词的短标题。只输出标题,不要解释,不要标点。',
|
package/server/subagents.mjs
CHANGED
|
@@ -48,7 +48,7 @@ export const subagentDefinitions = [
|
|
|
48
48
|
allowFileMutations: false,
|
|
49
49
|
maxRuntimeMs: 30 * 60 * 1000,
|
|
50
50
|
maxToolCalls: 300,
|
|
51
|
-
systemPrompt: `You are Explore, the preferred read-only repository
|
|
51
|
+
systemPrompt: `You are Explore, the preferred read-only repository research subagent. Investigate the delegated question using read_file, grep_files, and safe read-only run_command calls, and report only findings grounded in repository evidence. Do not design solutions or propose implementation, architecture, refactoring, or code changes. Cite relevant file paths, symbols, and line ranges when practical. Clearly separate verified facts, reasonable inferences, and unknowns, and never present an inference as a verified fact. Unless the parent Agent explicitly requests them, do not provide an implementation plan, recommendations, or suggested next steps. You cannot modify files.`,
|
|
52
52
|
},
|
|
53
53
|
]
|
|
54
54
|
|
|
@@ -7,8 +7,7 @@ import { logger } from '../utils/logger.mjs'
|
|
|
7
7
|
const require = createRequire(import.meta.url)
|
|
8
8
|
const MAX_SESSIONS = Math.max(1, Number(process.env.QUICKFORGE_MAX_TERMINALS || 6))
|
|
9
9
|
const TERMINAL_DISABLED = process.env.QUICKFORGE_TERMINAL === '0'
|
|
10
|
-
const RECONNECT_GRACE_MS = Number(process.env.QUICKFORGE_TERMINAL_RECONNECT_MS ||
|
|
11
|
-
const IDLE_TIMEOUT_MS = Number(process.env.QUICKFORGE_TERMINAL_IDLE_MS || 30 * 60 * 1000)
|
|
10
|
+
const RECONNECT_GRACE_MS = Number(process.env.QUICKFORGE_TERMINAL_RECONNECT_MS || 30 * 60 * 1000)
|
|
12
11
|
|
|
13
12
|
const sessions = new Map()
|
|
14
13
|
let cleanupTimer = null
|
|
@@ -85,8 +84,7 @@ function scheduleCleanup() {
|
|
|
85
84
|
const now = Date.now()
|
|
86
85
|
for (const session of sessions.values()) {
|
|
87
86
|
const disconnectedTooLong = session.clients.size === 0 && now - session.disconnectedAt > RECONNECT_GRACE_MS
|
|
88
|
-
|
|
89
|
-
if (session.exited || disconnectedTooLong || idleTooLong) {
|
|
87
|
+
if (session.exited || disconnectedTooLong) {
|
|
90
88
|
destroyTerminalSession(session.id)
|
|
91
89
|
}
|
|
92
90
|
}
|
|
@@ -129,7 +129,7 @@ export const workspaceTools = [
|
|
|
129
129
|
{
|
|
130
130
|
name: 'present_files',
|
|
131
131
|
label: 'Present files',
|
|
132
|
-
description: '
|
|
132
|
+
description: 'Present one or more AI-produced artifact files only when the user is likely to benefit from inspecting the actual deliverable directly. Use it for visual outputs, reports, documents, generated assets, or when the user explicitly asks to view or review a file. Source code and configuration files should only be presented when they are themselves the requested deliverable or the user asks to inspect them. Do not present routine implementation changes, test files, supporting code, or large sets of modified files merely because they were edited. Prefer a small, relevant selection. HTML and supported images open in Browser; Markdown, code, configuration, and text files open in Reader. Unsupported files remain available in the artifact list.',
|
|
133
133
|
parameters: Type.Object({
|
|
134
134
|
files: Type.Array(Type.Union([
|
|
135
135
|
Type.String({ description: 'File path relative to the workspace root.' }),
|
|
@@ -138,7 +138,7 @@ export const workspaceTools = [
|
|
|
138
138
|
title: Type.Optional(Type.String({ description: 'Optional display title.' })),
|
|
139
139
|
description: Type.Optional(Type.String({ description: 'Optional short description shown in artifact lists.' })),
|
|
140
140
|
kind: Type.Optional(Type.String({ description: 'Optional file kind hint, such as html, image, markdown, or code.' })),
|
|
141
|
-
preview: Type.Optional(Type.Boolean({ description: 'Whether this file
|
|
141
|
+
preview: Type.Optional(Type.Boolean({ description: 'Whether this file may be opened automatically. Set false to list it without opening it.' })),
|
|
142
142
|
}),
|
|
143
143
|
]), { description: 'Artifact files to present.' }),
|
|
144
144
|
defaultPreview: Type.Optional(Type.String({ description: 'File path to open as the default preview when multiple files are presented.' })),
|
package/server/tools/index.mjs
CHANGED
|
@@ -624,10 +624,12 @@ export async function toolReadSkillResource(params, context) {
|
|
|
624
624
|
// --- present_files ---
|
|
625
625
|
function inferPresentedFileKind(relativePath) {
|
|
626
626
|
const lower = String(relativePath || '').toLowerCase()
|
|
627
|
+
const fileName = lower.replace(/\\/g, '/').split('/').pop() || lower
|
|
627
628
|
if (lower.endsWith('.html') || lower.endsWith('.htm')) return 'html'
|
|
628
|
-
if (/\.(svg|png|jpe?g|webp|gif|
|
|
629
|
-
if (
|
|
630
|
-
if (
|
|
629
|
+
if (/\.(svg|png|jpe?g|webp|gif|ico)$/.test(lower)) return 'image'
|
|
630
|
+
if (/\.(md|mdx|markdown)$/.test(lower)) return 'markdown'
|
|
631
|
+
if (fileName === 'dockerfile' || fileName.endsWith('.dockerfile') || fileName === 'makefile') return 'code'
|
|
632
|
+
if (/\.(ts|tsx|js|jsx|mjs|cjs|css|scss|less|json|jsonc|txt|csv|tsv|log|sql|xml|yml|yaml|toml|ini|py|rb|go|rs|java|swift|kt|kts|c|h|cpp|hpp|cs|php|sh|bash|zsh|ps1)$/.test(lower)) return 'code'
|
|
631
633
|
return 'unknown'
|
|
632
634
|
}
|
|
633
635
|
|
|
@@ -5,6 +5,25 @@ import path from 'node:path'
|
|
|
5
5
|
const QUICKFORGE_RELEASES_URL = 'https://github.com/shawnstack/quickforge/releases/latest'
|
|
6
6
|
const QUICKFORGE_LATEST_RELEASE_API_URL = 'https://api.github.com/repos/shawnstack/quickforge/releases/latest'
|
|
7
7
|
|
|
8
|
+
// 外部更新检查(npm registry / GitHub Releases)是应用中最慢的调用。
|
|
9
|
+
// 增加进程内冷却缓存:并发调用共享同一 Promise,TTL 内重复调用复用结果;
|
|
10
|
+
// 失败不缓存,下次调用立即重试。
|
|
11
|
+
const UPDATE_CHECK_COOLDOWN_MS = 5 * 60 * 1000
|
|
12
|
+
const updateCheckCooldowns = new Map() // key -> { at, promise }
|
|
13
|
+
|
|
14
|
+
function cooldownLoad(key, loader) {
|
|
15
|
+
const now = Date.now()
|
|
16
|
+
const entry = updateCheckCooldowns.get(key)
|
|
17
|
+
if (entry && now - entry.at < UPDATE_CHECK_COOLDOWN_MS) return entry.promise
|
|
18
|
+
|
|
19
|
+
const promise = Promise.resolve().then(loader)
|
|
20
|
+
updateCheckCooldowns.set(key, { at: now, promise })
|
|
21
|
+
promise.catch(() => {
|
|
22
|
+
if (updateCheckCooldowns.get(key)?.promise === promise) updateCheckCooldowns.delete(key)
|
|
23
|
+
})
|
|
24
|
+
return promise
|
|
25
|
+
}
|
|
26
|
+
|
|
8
27
|
function normalizeRepositoryUrl(value) {
|
|
9
28
|
if (!value || typeof value !== 'string') return ''
|
|
10
29
|
return value
|
|
@@ -119,61 +138,65 @@ export async function fetchLatestVersion(packageName) {
|
|
|
119
138
|
}
|
|
120
139
|
}
|
|
121
140
|
|
|
122
|
-
export
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return {
|
|
127
|
-
...pkg,
|
|
128
|
-
channel: 'npm-runtime',
|
|
129
|
-
distribution: 'npm',
|
|
130
|
-
currentVersion: pkg.version,
|
|
131
|
-
latestVersion,
|
|
132
|
-
updateAvailable: comparison < 0,
|
|
133
|
-
localVersionIsNewer: comparison > 0,
|
|
134
|
-
installCommand: `npm install -g ${pkg.name}@latest`,
|
|
135
|
-
releaseUrl: QUICKFORGE_RELEASES_URL,
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export async function checkDesktopRelease(projectRoot) {
|
|
140
|
-
const pkg = await getPackageInfo(projectRoot)
|
|
141
|
-
const controller = new AbortController()
|
|
142
|
-
const timeout = setTimeout(() => controller.abort(), 5000)
|
|
143
|
-
|
|
144
|
-
try {
|
|
145
|
-
const response = await fetch(QUICKFORGE_LATEST_RELEASE_API_URL, {
|
|
146
|
-
headers: {
|
|
147
|
-
accept: 'application/vnd.github+json',
|
|
148
|
-
'user-agent': `${pkg.name || 'quickforge'}-desktop-update-check`,
|
|
149
|
-
},
|
|
150
|
-
signal: controller.signal,
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
if (!response.ok) throw new Error(`GitHub releases returned HTTP ${response.status}`)
|
|
154
|
-
|
|
155
|
-
const release = await response.json()
|
|
156
|
-
const latestVersion = release?.tag_name || release?.name
|
|
157
|
-
if (!latestVersion || typeof latestVersion !== 'string') throw new Error('latest release version not found in GitHub response')
|
|
158
|
-
|
|
141
|
+
export function checkForUpdates(projectRoot) {
|
|
142
|
+
return cooldownLoad(`npm:${projectRoot}`, async () => {
|
|
143
|
+
const pkg = await getPackageInfo(projectRoot)
|
|
144
|
+
const latestVersion = await fetchLatestVersion(pkg.name)
|
|
159
145
|
const comparison = compareVersions(pkg.version, latestVersion)
|
|
160
146
|
return {
|
|
161
147
|
...pkg,
|
|
162
|
-
channel: '
|
|
163
|
-
distribution: '
|
|
148
|
+
channel: 'npm-runtime',
|
|
149
|
+
distribution: 'npm',
|
|
164
150
|
currentVersion: pkg.version,
|
|
165
151
|
latestVersion,
|
|
166
152
|
updateAvailable: comparison < 0,
|
|
167
153
|
localVersionIsNewer: comparison > 0,
|
|
168
|
-
|
|
169
|
-
|
|
154
|
+
installCommand: `npm install -g ${pkg.name}@latest`,
|
|
155
|
+
releaseUrl: QUICKFORGE_RELEASES_URL,
|
|
170
156
|
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export function checkDesktopRelease(projectRoot) {
|
|
161
|
+
return cooldownLoad(`desktop:${projectRoot}`, async () => {
|
|
162
|
+
const pkg = await getPackageInfo(projectRoot)
|
|
163
|
+
const controller = new AbortController()
|
|
164
|
+
const timeout = setTimeout(() => controller.abort(), 5000)
|
|
165
|
+
|
|
166
|
+
try {
|
|
167
|
+
const response = await fetch(QUICKFORGE_LATEST_RELEASE_API_URL, {
|
|
168
|
+
headers: {
|
|
169
|
+
accept: 'application/vnd.github+json',
|
|
170
|
+
'user-agent': `${pkg.name || 'quickforge'}-desktop-update-check`,
|
|
171
|
+
},
|
|
172
|
+
signal: controller.signal,
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
if (!response.ok) throw new Error(`GitHub releases returned HTTP ${response.status}`)
|
|
176
|
+
|
|
177
|
+
const release = await response.json()
|
|
178
|
+
const latestVersion = release?.tag_name || release?.name
|
|
179
|
+
if (!latestVersion || typeof latestVersion !== 'string') throw new Error('latest release version not found in GitHub response')
|
|
180
|
+
|
|
181
|
+
const comparison = compareVersions(pkg.version, latestVersion)
|
|
182
|
+
return {
|
|
183
|
+
...pkg,
|
|
184
|
+
channel: 'desktop-app',
|
|
185
|
+
distribution: 'github-releases',
|
|
186
|
+
currentVersion: pkg.version,
|
|
187
|
+
latestVersion,
|
|
188
|
+
updateAvailable: comparison < 0,
|
|
189
|
+
localVersionIsNewer: comparison > 0,
|
|
190
|
+
releaseUrl: release?.html_url || QUICKFORGE_RELEASES_URL,
|
|
191
|
+
installable: false,
|
|
192
|
+
}
|
|
193
|
+
} catch (error) {
|
|
194
|
+
if (error.name === 'AbortError') throw new Error('request timeout', { cause: error })
|
|
195
|
+
throw error
|
|
196
|
+
} finally {
|
|
197
|
+
clearTimeout(timeout)
|
|
198
|
+
}
|
|
199
|
+
})
|
|
177
200
|
}
|
|
178
201
|
|
|
179
202
|
function getNpmCommand() {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function createNodeProcessEnv(source = process.env, overrides = {}, versions = process.versions) {
|
|
2
|
+
const env = { ...source, ...overrides }
|
|
3
|
+
delete env.ELECTRON_RUN_AS_NODE
|
|
4
|
+
delete env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
|
5
|
+
if (versions.electron) env.ELECTRON_RUN_AS_NODE = '1'
|
|
6
|
+
return env
|
|
7
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
const DEFAULT_MAX_BODY_BYTES = Number(process.env.QUICKFORGE_MAX_BODY_BYTES || 50 * 1024 * 1024)
|
|
2
2
|
|
|
3
|
-
export function sendJson(res, status, value) {
|
|
3
|
+
export function sendJson(res, status, value, cacheControl) {
|
|
4
4
|
const body = JSON.stringify(value)
|
|
5
5
|
res.writeHead(status, {
|
|
6
6
|
'content-type': 'application/json; charset=utf-8',
|
|
7
|
-
'cache-control': 'no-store',
|
|
7
|
+
'cache-control': cacheControl || 'no-store',
|
|
8
8
|
})
|
|
9
9
|
res.end(body)
|
|
10
10
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{i as e}from"./rolldown-runtime-DWdDZTNf.js";import{Dt as t,E as n,Pt as r,a as i,c as a,it as ee,jt as o}from"./icons-BP8YOS-Z.js";import{i as s,n as c}from"./react-vendor-Dr5xvL-e.js";import{Ct as l,Ot as u,V as te,dt as d,ft as ne,ht as re,mt as ie,pt as ae,xt as f}from"./index-C6k5taeb.js";var p=e(r(),1),oe=s(),m=c(),h=144,g=82,_=4,v=8;function y(e){return JSON.stringify({provider:e.provider,modelId:e.id,api:e.api,baseUrl:e.baseUrl})}function b(e){if(!e)return{mode:`inherit`};try{let t=JSON.parse(e);return{mode:`fixed`,provider:String(t.provider||``),modelId:String(t.modelId||``),api:t.api?String(t.api):void 0,baseUrl:t.baseUrl?String(t.baseUrl):void 0}}catch{return{mode:`inherit`}}}function x(e){return!e||e.mode!==`fixed`?``:JSON.stringify({provider:e.provider,modelId:e.modelId,api:e.api,baseUrl:e.baseUrl})}function se(e){return e.name||`${e.provider}/${e.id}`}function S(){return{name:``,label:``,description:``,systemPrompt:``,allowedTools:[`read_file`,`grep_files`],maxRuntimeMs:`1800000`,maxToolCalls:`300`,enabledAsSubagent:!0,modelMode:`inherit`,fixedModelValue:``,thinkingLevel:`inherit`}}function ce(e){return{name:e.name,label:e.label,description:e.description??``,systemPrompt:e.systemPrompt??``,allowedTools:e.allowedTools??[],maxRuntimeMs:String(e.maxRuntimeMs??18e5),maxToolCalls:String(e.maxToolCalls??300),enabledAsSubagent:e.enabledAsSubagent,modelMode:e.model?.mode===`fixed`?`fixed`:`inherit`,fixedModelValue:x(e.model),thinkingLevel:e.thinkingLevel??`inherit`}}function le(e){return{name:e.name.trim().toLowerCase(),label:e.label.trim(),description:e.description.trim(),systemPrompt:e.systemPrompt.trim(),allowedTools:e.allowedTools,maxRuntimeMs:Number(e.maxRuntimeMs||18e5),maxToolCalls:Number(e.maxToolCalls||300),enabledAsSubagent:e.enabledAsSubagent,model:e.modelMode===`fixed`?b(e.fixedModelValue):{mode:`inherit`},thinkingLevel:e.thinkingLevel}}function C(e){return!!(e.name.trim()&&e.label.trim()&&e.allowedTools.length>0)}async function w(e,t){let n=await fetch(e,{...t,headers:{"content-type":`application/json`,...t?.headers}}),r=await n.json().catch(()=>null);if(!n.ok)throw Error(r?.error||`请求失败`);return r}function T(){let[e,r]=(0,p.useState)([]),[s,c]=(0,p.useState)([]),[x,T]=(0,p.useState)(!1),[E,D]=(0,p.useState)(null),[O,k]=(0,p.useState)(()=>S()),[A,j]=(0,p.useState)(!1),[M,N]=(0,p.useState)(``),[P,F]=(0,p.useState)(!1),[I,ue]=(0,p.useState)(),[L,de]=(0,p.useState)([]),[fe,pe]=(0,p.useState)(`off`),[R,z]=(0,p.useState)(``),[B,V]=(0,p.useState)(null),[H,U]=(0,p.useState)(null);async function W(){let[e,t]=await Promise.all([w(`/api/agent-profiles`),w(`/api/agent-profiles/available-tools`)]);r(e.agents),c(t.tools)}(0,p.useEffect)(()=>{let e=!1;async function t(){try{let[t,n]=await Promise.all([w(`/api/agent-profiles`),w(`/api/agent-profiles/available-tools`)]);if(e)return;r(t.agents),c(n.tools)}catch(t){e||z(t instanceof Error?t.message:u(`requestFailed`))}}return t(),()=>{e=!0}},[]),(0,p.useEffect)(()=>{let e=!1;async function t(){try{let t=await ae(),n=await ne(t);de(n);let r=await ie(t),i=r.model??await re(t)??n[0];if(e)return;ue(i),pe(r.thinkingLevel??d(i))}catch{}}return t(),()=>{e=!0}},[]),(0,p.useEffect)(()=>{if(!B)return;let e=()=>{V(null),U(null)},t=t=>{t.key===`Escape`&&e()};return window.addEventListener(`click`,e),window.addEventListener(`blur`,e),window.addEventListener(`resize`,e),window.addEventListener(`scroll`,e,!0),document.addEventListener(`keydown`,t),()=>{window.removeEventListener(`click`,e),window.removeEventListener(`blur`,e),window.removeEventListener(`resize`,e),window.removeEventListener(`scroll`,e,!0),document.removeEventListener(`keydown`,t)}},[B]);let G=(0,p.useMemo)(()=>e.find(e=>e.id===E)??null,[e,E]),K=(0,p.useMemo)(()=>e.find(e=>e.id===B)??null,[e,B]),q=!!G?.readonly,J=!!(G?.readonly&&!G?.builtin),Y=(0,p.useMemo)(()=>L.find(e=>y(e)===O.fixedModelValue),[O.fixedModelValue,L]),X=O.modelMode===`fixed`&&!!Y&&Y?.reasoning!==!0;function me(e,t){if(e.stopPropagation(),B===t){V(null),U(null);return}let n=e.currentTarget.getBoundingClientRect(),r=Math.max(v,Math.min(n.right-h,window.innerWidth-h-v)),i=n.bottom+_,a=n.top-_-g;U({left:r,top:i+g<=window.innerHeight-v?i:Math.max(v,a)}),V(t)}function Z(e,t){k(n=>({...n,[e]:t}))}function he(e){k(t=>({...t,allowedTools:t.allowedTools.includes(e)?t.allowedTools.filter(t=>t!==e):[...t.allowedTools,e]}))}function ge(){D(null),k(S()),N(``),z(``),T(!0)}function Q(e){D(e.id),k(ce(e)),N(``),z(``),T(!0)}function $(){A||P||(T(!1),D(null),k(S()),N(``))}async function _e(){let e=M.trim();if(!e){z(u(`aiFillAgentInputRequired`));return}if(!I){z(u(`aiFillAgentNoModel`));return}F(!0),z(``);try{let t=await w(`/api/agent-profiles/ai-fill`,{method:`POST`,body:JSON.stringify({instruction:e,model:I,thinkingLevel:fe})});k(e=>({...e,name:t.agent.name,label:t.agent.label,description:t.agent.description,systemPrompt:t.agent.systemPrompt}))}catch(e){z(e instanceof Error?e.message:u(`aiFillAgentFailed`))}finally{F(!1)}}async function ve(){if(C(O)){j(!0),z(``);try{let e=G?.builtin?{model:O.modelMode===`fixed`?b(O.fixedModelValue):{mode:`inherit`}}:le({...O,thinkingLevel:X?`off`:O.thinkingLevel});E?await w(`/api/agent-profiles/${encodeURIComponent(E)}`,{method:`PATCH`,body:JSON.stringify(e)}):await w(`/api/agent-profiles`,{method:`POST`,body:JSON.stringify(e)}),$(),await W()}catch(e){z(e instanceof Error?e.message:u(`requestFailed`))}finally{j(!1)}}}async function ye(e){if(e.builtin||e.readonly)return;let t=!e.enabledAsSubagent,n=e.enabledAsSubagent;r(n=>n.map(n=>n.id===e.id?{...n,enabledAsSubagent:t}:n)),V(null);try{await w(`/api/agent-profiles/${encodeURIComponent(e.id)}`,{method:`PATCH`,body:JSON.stringify({enabledAsSubagent:t})})}catch(t){r(t=>t.map(t=>t.id===e.id?{...t,enabledAsSubagent:n}:t)),z(t instanceof Error?t.message:u(`requestFailed`))}}async function be(e){if(!(e.builtin||e.readonly)&&await te({description:u(`confirmDeleteAgent`),confirmLabel:u(`confirmDelete`),cancelLabel:u(`cancel`),variant:`destructive`})){z(``);try{await w(`/api/agent-profiles/${encodeURIComponent(e.id)}`,{method:`DELETE`}),await W()}catch(e){z(e instanceof Error?e.message:u(`requestFailed`))}}}return x?(0,m.jsxs)(`div`,{className:`quickforge-settings-stack`,children:[(0,m.jsx)(`div`,{className:`quickforge-settings-heading`,children:(0,m.jsxs)(`h3`,{className:`quickforge-settings-title`,children:[G?.builtin?u(`builtinAgentModelSettings`):u(G?`editAgent`:`createAgent`),(0,m.jsx)(f,{label:G?.builtin?u(`builtinAgentModelOnly`):G?.readonly?u(`readonlyAgentDescription`):u(`agentsDescription`)})]})}),(0,m.jsxs)(`section`,{className:`quickforge-settings-section`,"aria-label":u(G?`editAgent`:`createAgent`),children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`button`,{className:`quickforge-settings-button quickforge-settings-button-secondary`,type:`button`,onClick:$,disabled:A||P,children:[(0,m.jsx)(o,{className:`mr-2 size-4`}),u(`back`)]}),(0,m.jsxs)(`div`,{className:`quickforge-settings-row-main`,children:[(0,m.jsx)(`div`,{className:`quickforge-settings-row-title`,children:G?.builtin?u(`builtinAgentModelSettings`):u(G?`editAgent`:`createAgent`)}),G?.builtin?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:u(`builtinAgentModelOnly`)}):G?.readonly?(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:u(`readonlyAgentDescription`)}):null]})]}),(0,m.jsx)(`div`,{className:`px-5 py-4`,children:(0,m.jsxs)(`div`,{className:`space-y-4`,children:[(0,m.jsxs)(`div`,{className:`rounded-2xl border border-border bg-muted/20 p-3`,children:[(0,m.jsxs)(`div`,{className:`mb-2 flex items-center gap-2 text-sm font-medium text-foreground`,children:[(0,m.jsx)(a,{className:`size-4 text-primary`}),u(`aiFillAgent`),(0,m.jsx)(f,{label:u(`aiFillAgentDescription`)})]}),(0,m.jsx)(`textarea`,{className:`min-h-20 w-full resize-y rounded-xl border border-input bg-background px-3 py-2 text-sm outline-none transition-colors placeholder:text-muted-foreground/65 focus:border-ring disabled:opacity-60`,value:M,disabled:q||P,onChange:e=>N(e.target.value),placeholder:u(`aiFillAgentPlaceholder`)}),(0,m.jsx)(`div`,{className:`mt-2 flex justify-end`,children:(0,m.jsxs)(l,{variant:`outline`,size:`sm`,onClick:()=>void _e(),disabled:q||P||!M.trim(),children:[(0,m.jsx)(a,{className:`mr-1 size-3.5`}),u(P?`aiFillAgentLoading`:`aiFillAgent`)]})})]}),(0,m.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentName`),(0,m.jsx)(`input`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.name,disabled:q,onChange:e=>Z(`name`,e.target.value),placeholder:`reviewer`})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentLabel`),(0,m.jsx)(`input`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.label,disabled:q,onChange:e=>Z(`label`,e.target.value),placeholder:u(`agentLabelPlaceholder`)})]})]}),G?(0,m.jsxs)(`div`,{className:`rounded-xl border border-border bg-muted/20 px-3 py-2 text-sm`,children:[(0,m.jsx)(`div`,{className:`text-xs font-medium text-muted-foreground`,children:u(`agentSourcePath`)}),(0,m.jsx)(`div`,{className:`mt-1 truncate font-mono text-xs text-foreground`,title:G.source?`${G.source}${G.relativePath?` · ${G.relativePath}`:``}`:void 0,children:G.source?`${G.source}${G.relativePath?` · ${G.relativePath}`:``}`:G.builtin?u(`builtinAgent`):`-`})]}):null,(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentDescription`),(0,m.jsx)(`input`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.description,disabled:q,onChange:e=>Z(`description`,e.target.value)})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentSystemPrompt`),(0,m.jsx)(`textarea`,{className:`mt-1 min-h-36 w-full resize-y rounded-xl border border-input bg-background px-3 py-2 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.systemPrompt,disabled:q,onChange:e=>Z(`systemPrompt`,e.target.value)})]}),(0,m.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentModelMode`),(0,m.jsxs)(`select`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.modelMode,disabled:J,onChange:e=>Z(`modelMode`,e.target.value),children:[(0,m.jsx)(`option`,{value:`inherit`,children:u(`agentModelInherit`)}),(0,m.jsx)(`option`,{value:`fixed`,children:u(`agentModelFixed`)})]})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentFixedModel`),(0,m.jsxs)(`select`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.fixedModelValue,disabled:J||O.modelMode!==`fixed`,onChange:e=>Z(`fixedModelValue`,e.target.value),children:[(0,m.jsx)(`option`,{value:``,children:u(`agentModelInherit`)}),L.map(e=>(0,m.jsx)(`option`,{value:y(e),children:se(e)},y(e)))]})]})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`agentThinkingLevel`),(0,m.jsxs)(`select`,{className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:X&&O.thinkingLevel!==`inherit`?`off`:O.thinkingLevel,disabled:q||X,onChange:e=>Z(`thinkingLevel`,e.target.value),children:[(0,m.jsx)(`option`,{value:`inherit`,children:u(`agentThinkingInherit`)}),(0,m.jsx)(`option`,{value:`off`,children:u(`thinkingOff`)}),(0,m.jsx)(`option`,{value:`low`,children:u(`thinkingLow`)}),(0,m.jsx)(`option`,{value:`medium`,children:u(`thinkingMedium`)}),(0,m.jsx)(`option`,{value:`high`,children:u(`thinkingHigh`)}),(0,m.jsx)(`option`,{value:`xhigh`,children:u(`thinkingXHigh`)})]}),(0,m.jsx)(`span`,{className:`mt-1 block text-xs text-muted-foreground`,children:u(X?`agentThinkingUnsupported`:`agentThinkingDescription`)})]}),(0,m.jsxs)(`div`,{children:[(0,m.jsx)(`div`,{className:`mb-2 text-sm font-medium text-foreground`,children:u(`allowedTools`)}),(0,m.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2`,children:s.map(e=>(0,m.jsxs)(`label`,{className:`flex items-start gap-2 rounded-xl border border-border bg-muted/20 p-3 text-sm disabled:opacity-60`,children:[(0,m.jsx)(`input`,{type:`checkbox`,className:`mt-1`,disabled:q,checked:O.allowedTools.includes(e.name),onChange:()=>he(e.name)}),(0,m.jsxs)(`span`,{children:[(0,m.jsx)(`span`,{className:`font-medium text-foreground`,children:e.label}),(0,m.jsx)(`span`,{className:`ml-2 font-mono text-xs text-muted-foreground`,children:e.name}),e.riskLevel===`dangerous`?(0,m.jsx)(`span`,{className:`ml-2 rounded-full bg-amber-500/10 px-2 py-0.5 text-xs text-amber-700`,children:u(`highRiskTool`)}):null,(0,m.jsx)(`span`,{className:`mt-1 block text-xs text-muted-foreground`,children:e.description})]})]},e.name))})]}),(0,m.jsxs)(`div`,{className:`grid gap-3 sm:grid-cols-2`,children:[(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`maxRuntimeMs`),(0,m.jsx)(`input`,{type:`number`,className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.maxRuntimeMs,disabled:q,onChange:e=>Z(`maxRuntimeMs`,e.target.value)})]}),(0,m.jsxs)(`label`,{className:`block text-sm font-medium text-foreground`,children:[u(`maxToolCalls`),(0,m.jsx)(`input`,{type:`number`,className:`mt-1 h-10 w-full rounded-md border border-input bg-background px-3 text-sm outline-none focus:border-ring disabled:opacity-60`,value:O.maxToolCalls,disabled:q,onChange:e=>Z(`maxToolCalls`,e.target.value)})]})]}),(0,m.jsxs)(`label`,{className:`flex items-center gap-2 text-sm text-foreground`,children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:O.enabledAsSubagent,disabled:q,onChange:e=>Z(`enabledAsSubagent`,e.target.checked)}),u(`enabledAsSubagent`)]}),R?(0,m.jsx)(`div`,{className:`rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive`,children:R}):null]})}),(0,m.jsxs)(`div`,{className:`quickforge-settings-divider flex justify-end gap-2 px-5 py-4`,children:[(0,m.jsx)(l,{variant:`outline`,onClick:$,disabled:A||P,children:u(`cancel`)}),(0,m.jsx)(l,{onClick:ve,disabled:A||P||J||!G?.builtin&&!C(O)||O.modelMode===`fixed`&&!O.fixedModelValue,children:u(`save`)})]})]})]}):(0,m.jsxs)(`div`,{className:`quickforge-settings-stack`,children:[(0,m.jsxs)(`section`,{className:`quickforge-settings-section`,"aria-label":u(`agentsTab`),children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-toolbar`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-main`,children:[(0,m.jsxs)(`div`,{className:`quickforge-settings-row-title`,children:[(0,m.jsx)(t,{className:`size-4 text-primary`}),u(`agentsTab`)]}),(0,m.jsx)(`div`,{className:`quickforge-settings-row-description`,children:u(`agentsDescription`)})]}),(0,m.jsx)(`button`,{className:`quickforge-settings-button quickforge-settings-button-primary`,type:`button`,onClick:ge,children:u(`createAgent`)})]}),R?(0,m.jsx)(`div`,{className:`quickforge-settings-alert quickforge-settings-warning-attached`,children:R}):null,e.length===0?(0,m.jsx)(`div`,{className:`quickforge-settings-empty-row`,children:u(`loading`)}):e.map(e=>(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item quickforge-agent-profile-row`,role:`button`,tabIndex:0,onClick:()=>Q(e),onKeyDown:t=>{t.target===t.currentTarget&&(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),Q(e))},children:[(0,m.jsx)(`div`,{className:`quickforge-settings-list-item-main quickforge-agent-profile-row-main`,children:(0,m.jsxs)(`div`,{className:`quickforge-agent-profile-summary`,children:[(0,m.jsx)(`span`,{className:`quickforge-agent-profile-label`,title:e.label,children:e.label}),e.description?(0,m.jsx)(`span`,{className:`quickforge-agent-profile-description`,title:e.description,children:e.description}):null]})}),(0,m.jsxs)(`div`,{className:`quickforge-settings-list-item-actions`,onClick:e=>e.stopPropagation(),children:[(0,m.jsxs)(`label`,{className:`quickforge-settings-switch`,"aria-disabled":e.builtin||e.readonly?`true`:`false`,title:e.enabledAsSubagent?u(`disableAsSubagent`):u(`enableAsSubagent`),children:[(0,m.jsx)(`input`,{type:`checkbox`,checked:e.enabledAsSubagent,disabled:e.builtin||e.readonly,onChange:()=>void ye(e)}),(0,m.jsx)(`span`,{"aria-hidden":`true`})]}),(0,m.jsx)(`button`,{className:`quickforge-settings-icon-action`,type:`button`,onClick:t=>me(t,e.id),title:u(`moreActions`),"aria-label":u(`moreActions`),"aria-haspopup":`menu`,"aria-expanded":B===e.id,children:(0,m.jsx)(ee,{className:`size-4`})})]})]},e.id))]}),K&&H?(0,oe.createPortal)((0,m.jsxs)(`div`,{className:`fixed z-50 w-36 overflow-hidden rounded-xl border border-border bg-popover py-1 text-sm shadow-quickforge`,style:{left:H.left,top:H.top},role:`menu`,"aria-label":u(`moreActions`),onClick:e=>e.stopPropagation(),children:[(0,m.jsxs)(`button`,{className:`flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50`,type:`button`,role:`menuitem`,disabled:K.readonly&&!K.builtin,onClick:()=>{V(null),U(null),Q(K)},children:[(0,m.jsx)(n,{className:`size-3.5`}),K.builtin?u(`builtinAgentModelSettings`):u(`editTask`)]}),(0,m.jsxs)(`button`,{className:`flex w-full items-center gap-2 px-3 py-2 text-left text-destructive hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50`,type:`button`,role:`menuitem`,disabled:K.builtin||K.readonly,onClick:()=>{V(null),U(null),be(K)},children:[(0,m.jsx)(i,{className:`size-3.5`}),u(`delete`)]})]}),document.body):null]})}export{T as AgentProfilesPage};
|