@shawnstack/quickforge 1.7.2 → 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 -0
- package/bin/quickforge.mjs +2 -21
- package/dist/assets/AgentProfilesPage-B84w-r9S.js +1 -0
- package/dist/assets/{ChatPanelHost-Cld9HcVz.js → ChatPanelHost-CyO8fEoj.js} +98 -98
- package/dist/assets/{PluginsPage-DEMqwhOA.js → PluginsPage-D2862wul.js} +1 -1
- package/dist/assets/{ScheduledTasksPage-DTP_gedp.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-Bp6kbIup.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-DiJAUfvW.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 +7 -1
- package/server/acp/server.mjs +14 -9
- package/server/agent-manager.mjs +215 -20
- package/server/ai-http-logger.mjs +69 -12
- package/server/ai-provider-options.mjs +11 -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 +43 -25
- package/server/lan-access-store.mjs +93 -3
- package/server/network-proxy.mjs +449 -0
- package/server/plugins/registry.mjs +64 -4
- package/server/public-api.mjs +10 -2
- package/server/routes/agent-profiles.mjs +4 -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 +7 -3
- package/server/routes/project.mjs +19 -1
- package/server/routes/scheduled-tasks.mjs +4 -2
- package/server/routes/static.mjs +26 -1
- package/server/routes/system.mjs +37 -0
- package/server/routes/terminal.mjs +7 -2
- package/server/routes/workspace.mjs +62 -9
- package/server/session-utils.mjs +4 -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-BFgyFa5e.js +0 -1
- package/dist/assets/SettingsWorkspacePage-Dr9zT5Bs.js +0 -1495
- package/dist/assets/SharedConversationPage-op3DRwcw.js +0 -1
- package/dist/assets/TerminalDock-BL_UovwU.js +0 -2
- package/dist/assets/WorkspaceInspector-73dhAime.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-Cu2bBHLv.css +0 -3
- package/dist/assets/index-yV1wtqTr.js +0 -66
- 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
|
@@ -4,6 +4,7 @@ import { promises as fs } from 'node:fs'
|
|
|
4
4
|
import path from 'node:path'
|
|
5
5
|
import { ProcessChannelProvider } from '../process-channel.mjs'
|
|
6
6
|
import { getDefaultWorkspaceRoot, readProjectConfig } from '../../project-config.mjs'
|
|
7
|
+
import { createNodeProcessEnv } from '../../utils/process-env.mjs'
|
|
7
8
|
|
|
8
9
|
const WEIXIN_ACP_PACKAGE = 'weixin-acp'
|
|
9
10
|
const MIN_NODE_MAJOR = 22
|
|
@@ -134,7 +135,7 @@ function runCommand(command, args, options = {}) {
|
|
|
134
135
|
}
|
|
135
136
|
|
|
136
137
|
export class WechatChannelProvider extends ProcessChannelProvider {
|
|
137
|
-
constructor({ projectRoot }) {
|
|
138
|
+
constructor({ projectRoot, channelEventsUrl, logsDir }) {
|
|
138
139
|
super({
|
|
139
140
|
id: 'wechat',
|
|
140
141
|
name: '微信',
|
|
@@ -149,8 +150,9 @@ export class WechatChannelProvider extends ProcessChannelProvider {
|
|
|
149
150
|
{ id: 'relogin', label: '重新登录' },
|
|
150
151
|
],
|
|
151
152
|
requirements: [`Node.js >= ${MIN_NODE_MAJOR}`, 'npm/npx 可用', '首次启动需要微信扫码登录'],
|
|
152
|
-
})
|
|
153
|
+
}, { logsDir })
|
|
153
154
|
this.projectRoot = projectRoot
|
|
155
|
+
this.channelEventsUrl = channelEventsUrl
|
|
154
156
|
this.launchWorkspace = null
|
|
155
157
|
}
|
|
156
158
|
|
|
@@ -179,7 +181,11 @@ export class WechatChannelProvider extends ProcessChannelProvider {
|
|
|
179
181
|
command: npxCommand(),
|
|
180
182
|
args: ['-y', WEIXIN_ACP_PACKAGE, 'start', '--', acpCommand, ...acpArgs],
|
|
181
183
|
cwd: this.launchWorkspace?.path || getDefaultWorkspaceRoot() || this.projectRoot,
|
|
182
|
-
env: process.env,
|
|
184
|
+
env: createNodeProcessEnv(process.env, {
|
|
185
|
+
QUICKFORGE_ACP_CHANNEL_ID: this.definition.id,
|
|
186
|
+
QUICKFORGE_ACP_CHANNEL_NAME: this.definition.name,
|
|
187
|
+
...(this.channelEventsUrl ? { QUICKFORGE_CHANNEL_EVENTS_URL: this.channelEventsUrl } : {}),
|
|
188
|
+
}),
|
|
183
189
|
shell: shouldUseShellForNpx(),
|
|
184
190
|
}
|
|
185
191
|
}
|
|
@@ -16,7 +16,11 @@ function attachProvider(provider) {
|
|
|
16
16
|
export function initializeChannels(options = {}) {
|
|
17
17
|
if (initialized) return
|
|
18
18
|
initialized = true
|
|
19
|
-
attachProvider(createWechatChannelProvider({
|
|
19
|
+
attachProvider(createWechatChannelProvider({
|
|
20
|
+
projectRoot: options.projectRoot,
|
|
21
|
+
channelEventsUrl: options.channelEventsUrl,
|
|
22
|
+
logsDir: options.logsDir,
|
|
23
|
+
}))
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
function requireProvider(id) {
|
package/server/index.mjs
CHANGED
|
@@ -5,8 +5,9 @@ import path from 'node:path'
|
|
|
5
5
|
import { randomUUID } from 'node:crypto'
|
|
6
6
|
import { fileURLToPath } from 'node:url'
|
|
7
7
|
import { sendJson, sendError } from './utils/response.mjs'
|
|
8
|
-
import { openBrowser } from './utils/platform.mjs'
|
|
8
|
+
import { openBrowser, openPathInFileManager } from './utils/platform.mjs'
|
|
9
9
|
import { ensureStorage, dataDir, configDir, storageDir, cacheDir, logsDir } from './storage.mjs'
|
|
10
|
+
import { getNetworkProxyConfig, initializeNetworkProxy, refreshSystemProxy, updateNetworkProxyConfig } from './network-proxy.mjs'
|
|
10
11
|
import { setDefaultWorkspaceRoot, initializeActiveProject, readProjectConfig, getActiveProject, readTerminalShellSetting, updateTerminalShellSetting, readTerminalShellConfig, updateTerminalShellConfig } from './project-config.mjs'
|
|
11
12
|
import { getWorkspaceRoot } from './utils/workspace.mjs'
|
|
12
13
|
import { handleStorageApi } from './routes/storage.mjs'
|
|
@@ -43,6 +44,7 @@ import { shutdown as shutdownAgentManager, resetStaleTaskStatuses } from './agen
|
|
|
43
44
|
import { initializeChannels, shutdownChannels } from './channels/registry.mjs'
|
|
44
45
|
import { shutdownMcpConnections } from './mcp/registry.mjs'
|
|
45
46
|
import { shutdownTerminalSessions } from './terminal/terminal-manager.mjs'
|
|
47
|
+
import { createNodeProcessEnv } from './utils/process-env.mjs'
|
|
46
48
|
|
|
47
49
|
const __filename = fileURLToPath(import.meta.url)
|
|
48
50
|
const __dirname = path.dirname(__filename)
|
|
@@ -65,16 +67,16 @@ let restartInProgress = false
|
|
|
65
67
|
let updateInProgress = false
|
|
66
68
|
|
|
67
69
|
setDefaultWorkspaceRoot(process.env.QUICKFORGE_WORKSPACE_DIR || path.join(dataDir, 'workspace'))
|
|
68
|
-
installAiHttpLogger()
|
|
69
70
|
|
|
70
71
|
function getRestartSupport() {
|
|
71
72
|
return { supported: true, reason: null }
|
|
72
73
|
}
|
|
73
74
|
|
|
74
|
-
async function getSystemStatus() {
|
|
75
|
+
async function getSystemStatus({ isLocalRequest = true } = {}) {
|
|
75
76
|
const config = await readProjectConfig()
|
|
76
77
|
const restartSupport = getRestartSupport()
|
|
77
78
|
const packageInfo = await getPackageInfo(projectRoot)
|
|
79
|
+
const restartSupported = isLocalRequest && restartSupport.supported
|
|
78
80
|
return {
|
|
79
81
|
ok: true,
|
|
80
82
|
mode: isDev ? 'development' : 'production',
|
|
@@ -83,8 +85,14 @@ async function getSystemStatus() {
|
|
|
83
85
|
startedAt,
|
|
84
86
|
version: packageInfo.version,
|
|
85
87
|
package: packageInfo,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
isLocalRequest,
|
|
89
|
+
capabilities: {
|
|
90
|
+
restart: restartSupported,
|
|
91
|
+
openLocalApps: isLocalRequest,
|
|
92
|
+
terminal: isLocalRequest,
|
|
93
|
+
},
|
|
94
|
+
restartSupported,
|
|
95
|
+
restartUnsupportedReason: isLocalRequest ? restartSupport.reason : 'Restart is only allowed from this computer',
|
|
88
96
|
dataDir,
|
|
89
97
|
configDir,
|
|
90
98
|
storageDir,
|
|
@@ -113,10 +121,9 @@ function spawnRestartSupervisor() {
|
|
|
113
121
|
stdio: 'ignore',
|
|
114
122
|
windowsHide: true,
|
|
115
123
|
shell: false,
|
|
116
|
-
env: {
|
|
117
|
-
...process.env,
|
|
124
|
+
env: createNodeProcessEnv(process.env, {
|
|
118
125
|
QUICKFORGE_NO_OPEN: '1',
|
|
119
|
-
},
|
|
126
|
+
}),
|
|
120
127
|
})
|
|
121
128
|
|
|
122
129
|
child.once('error', reject)
|
|
@@ -206,10 +213,9 @@ function spawnUpdateSupervisor(update) {
|
|
|
206
213
|
stdio: 'ignore',
|
|
207
214
|
windowsHide: true,
|
|
208
215
|
shell: false,
|
|
209
|
-
env: {
|
|
210
|
-
...process.env,
|
|
216
|
+
env: createNodeProcessEnv(process.env, {
|
|
211
217
|
QUICKFORGE_NO_OPEN: '1',
|
|
212
|
-
},
|
|
218
|
+
}),
|
|
213
219
|
})
|
|
214
220
|
|
|
215
221
|
child.once('error', reject)
|
|
@@ -277,7 +283,7 @@ async function updateQuickForge() {
|
|
|
277
283
|
}
|
|
278
284
|
|
|
279
285
|
// --- Route dispatching ---
|
|
280
|
-
async function handleApi(req, res, url) {
|
|
286
|
+
async function handleApi(req, res, url, requestContext = {}) {
|
|
281
287
|
const pathname = url.pathname
|
|
282
288
|
const parts = pathname.split('/').filter(Boolean)
|
|
283
289
|
|
|
@@ -297,22 +303,22 @@ async function handleApi(req, res, url) {
|
|
|
297
303
|
return
|
|
298
304
|
}
|
|
299
305
|
|
|
300
|
-
if (pathname
|
|
306
|
+
if (pathname.startsWith('/api/lan-access/')) {
|
|
301
307
|
await handleLanAccessApi(req, res, url, {
|
|
302
308
|
port,
|
|
303
|
-
isLocalRequest:
|
|
309
|
+
isLocalRequest: requestContext.isLocalRequest === true,
|
|
304
310
|
})
|
|
305
311
|
return
|
|
306
312
|
}
|
|
307
313
|
|
|
308
314
|
// Health check
|
|
309
315
|
if (req.method === 'GET' && pathname === '/api/health') {
|
|
310
|
-
sendJson(res, 200, await getSystemStatus())
|
|
316
|
+
sendJson(res, 200, await getSystemStatus(requestContext))
|
|
311
317
|
return
|
|
312
318
|
}
|
|
313
319
|
|
|
314
320
|
if (req.method === 'GET' && pathname === '/api/project/commands') {
|
|
315
|
-
await handleProjectApi(req, res, url)
|
|
321
|
+
await handleProjectApi(req, res, url, requestContext)
|
|
316
322
|
return
|
|
317
323
|
}
|
|
318
324
|
|
|
@@ -355,7 +361,9 @@ async function handleApi(req, res, url) {
|
|
|
355
361
|
// Channels
|
|
356
362
|
if (pathname === '/api/channels' || pathname.startsWith('/api/channels/')) {
|
|
357
363
|
await handleChannelsApi(req, res, url, {
|
|
358
|
-
isLocalRequest:
|
|
364
|
+
isLocalRequest: requestContext.isLocalRequest === true,
|
|
365
|
+
logsDir,
|
|
366
|
+
openPathInFileManager,
|
|
359
367
|
})
|
|
360
368
|
return
|
|
361
369
|
}
|
|
@@ -368,13 +376,13 @@ async function handleApi(req, res, url) {
|
|
|
368
376
|
|
|
369
377
|
// Project routes
|
|
370
378
|
if (pathname === '/api/project' || pathname.startsWith('/api/project/')) {
|
|
371
|
-
await handleProjectApi(req, res, url)
|
|
379
|
+
await handleProjectApi(req, res, url, requestContext)
|
|
372
380
|
return
|
|
373
381
|
}
|
|
374
382
|
|
|
375
383
|
// Project workspace inspector routes
|
|
376
384
|
if (pathname === '/api/workspace/tree' || pathname === '/api/workspace/file' || pathname === '/api/workspace/resolve-path' || pathname === '/api/workspace/open-external' || pathname.startsWith('/api/workspace/preview/')) {
|
|
377
|
-
await handleWorkspaceApi(req, res, url)
|
|
385
|
+
await handleWorkspaceApi(req, res, url, requestContext)
|
|
378
386
|
return
|
|
379
387
|
}
|
|
380
388
|
|
|
@@ -420,19 +428,22 @@ async function handleApi(req, res, url) {
|
|
|
420
428
|
}
|
|
421
429
|
|
|
422
430
|
// System routes
|
|
423
|
-
if (pathname === '/api/system/status' || pathname === '/api/system/restart' || pathname === '/api/system/network' || pathname === '/api/system/terminal-shell' || pathname === '/api/system/about' || pathname === '/api/system/update/check' || pathname === '/api/system/update/desktop' || pathname === '/api/system/update') {
|
|
431
|
+
if (pathname === '/api/system/status' || pathname === '/api/system/restart' || pathname === '/api/system/network' || pathname === '/api/system/network-proxy' || pathname === '/api/system/network-proxy/refresh' || pathname === '/api/system/terminal-shell' || pathname === '/api/system/about' || pathname === '/api/system/update/check' || pathname === '/api/system/update/desktop' || pathname === '/api/system/update') {
|
|
424
432
|
await handleSystemApi(req, res, url, {
|
|
425
|
-
getSystemStatus,
|
|
433
|
+
getSystemStatus: () => getSystemStatus(requestContext),
|
|
426
434
|
requestRestart,
|
|
427
435
|
getPackageInfo: () => getPackageInfo(projectRoot),
|
|
428
436
|
checkForUpdates: () => checkForUpdates(projectRoot),
|
|
429
437
|
checkDesktopRelease: () => checkDesktopRelease(projectRoot),
|
|
430
438
|
updateQuickForge,
|
|
431
|
-
isLocalRequest:
|
|
439
|
+
isLocalRequest: requestContext.isLocalRequest === true,
|
|
432
440
|
getTerminalShellSetting: readTerminalShellSetting,
|
|
433
441
|
updateTerminalShellSetting,
|
|
434
442
|
getTerminalShellConfig: readTerminalShellConfig,
|
|
435
443
|
updateTerminalShellConfig,
|
|
444
|
+
getNetworkProxyConfig,
|
|
445
|
+
updateNetworkProxyConfig,
|
|
446
|
+
refreshSystemProxy,
|
|
436
447
|
host,
|
|
437
448
|
port,
|
|
438
449
|
remoteEnabled: host !== '127.0.0.1' && host !== 'localhost',
|
|
@@ -443,7 +454,7 @@ async function handleApi(req, res, url) {
|
|
|
443
454
|
// Terminal routes (local-only; real shell access)
|
|
444
455
|
if (pathname === '/api/terminal/capabilities' || pathname === '/api/terminal/sessions' || pathname.startsWith('/api/terminal/sessions/')) {
|
|
445
456
|
await handleTerminalApi(req, res, url, {
|
|
446
|
-
isLocalRequest:
|
|
457
|
+
isLocalRequest: requestContext.isLocalRequest === true,
|
|
447
458
|
})
|
|
448
459
|
return
|
|
449
460
|
}
|
|
@@ -529,6 +540,7 @@ function isLanAccessBootstrapPath(pathname) {
|
|
|
529
540
|
|
|
530
541
|
function isStaticAssetPath(pathname) {
|
|
531
542
|
return pathname.startsWith('/assets/')
|
|
543
|
+
|| pathname.startsWith('/downloads/')
|
|
532
544
|
|| pathname === '/favicon.svg'
|
|
533
545
|
|| pathname === '/vite.svg'
|
|
534
546
|
|| pathname === '/manifest.webmanifest'
|
|
@@ -607,7 +619,7 @@ const server = createServer(async (req, res) => {
|
|
|
607
619
|
}
|
|
608
620
|
|
|
609
621
|
if (url.pathname.startsWith('/api/')) {
|
|
610
|
-
await handleApi(req, res, url)
|
|
622
|
+
await handleApi(req, res, url, { isLocalRequest: !isRemoteRequest })
|
|
611
623
|
return
|
|
612
624
|
}
|
|
613
625
|
|
|
@@ -669,7 +681,13 @@ server.on('upgrade', (req, socket, head) => {
|
|
|
669
681
|
})
|
|
670
682
|
|
|
671
683
|
await ensureStorage()
|
|
672
|
-
|
|
684
|
+
await initializeNetworkProxy()
|
|
685
|
+
installAiHttpLogger()
|
|
686
|
+
initializeChannels({
|
|
687
|
+
projectRoot,
|
|
688
|
+
channelEventsUrl: `http://127.0.0.1:${port}/api/channels/events`,
|
|
689
|
+
logsDir,
|
|
690
|
+
})
|
|
673
691
|
await resetStaleTaskStatuses()
|
|
674
692
|
await initializeActiveProject()
|
|
675
693
|
setActiveWorkspaceRootForFilesystem(getWorkspaceRoot())
|
|
@@ -80,13 +80,41 @@ async function writeLanAccessFile(config) {
|
|
|
80
80
|
await fs.writeFile(LAN_ACCESS_FILE, `${JSON.stringify(normalizeConfig(config), null, 2)}\n`, 'utf8')
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
function normalizeText(value, maxLength) {
|
|
84
|
+
if (typeof value !== 'string') return undefined
|
|
85
|
+
const text = value.trim()
|
|
86
|
+
return text ? text.slice(0, maxLength) : undefined
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function normalizeRemoteAddress(value) {
|
|
90
|
+
const address = normalizeText(value, 128)
|
|
91
|
+
return address?.startsWith('::ffff:') ? address.slice(7) : address
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function tokenRecordId(tokenRecord) {
|
|
95
|
+
const id = normalizeText(tokenRecord?.id, 128)
|
|
96
|
+
return id || `legacy_${sha256Base64Url(tokenRecord?.tokenHash || '').slice(0, 24)}`
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function publicTokenRecord(tokenRecord) {
|
|
100
|
+
return {
|
|
101
|
+
id: tokenRecordId(tokenRecord),
|
|
102
|
+
address: normalizeRemoteAddress(tokenRecord.remoteAddress),
|
|
103
|
+
userAgent: normalizeText(tokenRecord.userAgent, 300),
|
|
104
|
+
issuedAt: tokenRecord.issuedAt,
|
|
105
|
+
expiresAt: tokenRecord.expiresAt,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
83
109
|
function publicStatus(config) {
|
|
110
|
+
const activeTokens = pruneTokens(config.tokens)
|
|
84
111
|
return {
|
|
85
112
|
enabled: Boolean(config.enabled),
|
|
86
113
|
hasPassword: Boolean(config.passwordHash),
|
|
87
114
|
sessionTtlHours: config.sessionTtlHours,
|
|
88
115
|
authVersion: config.authVersion || 1,
|
|
89
|
-
activeTokenCount:
|
|
116
|
+
activeTokenCount: activeTokens.length,
|
|
117
|
+
activeDevices: activeTokens.map(publicTokenRecord),
|
|
90
118
|
updatedAt: config.updatedAt,
|
|
91
119
|
}
|
|
92
120
|
}
|
|
@@ -98,6 +126,12 @@ function pruneTokens(tokens, now = Date.now()) {
|
|
|
98
126
|
if (!tokenRecord.expiresAt) return true
|
|
99
127
|
return Date.parse(tokenRecord.expiresAt) > now
|
|
100
128
|
})
|
|
129
|
+
.map((tokenRecord) => ({
|
|
130
|
+
...tokenRecord,
|
|
131
|
+
id: tokenRecordId(tokenRecord),
|
|
132
|
+
remoteAddress: normalizeRemoteAddress(tokenRecord.remoteAddress),
|
|
133
|
+
userAgent: normalizeText(tokenRecord.userAgent, 300),
|
|
134
|
+
}))
|
|
101
135
|
.slice(-LAN_TOKEN_MAX_COUNT)
|
|
102
136
|
}
|
|
103
137
|
|
|
@@ -162,11 +196,58 @@ export async function revokeLanAccessTokens() {
|
|
|
162
196
|
})
|
|
163
197
|
}
|
|
164
198
|
|
|
199
|
+
export async function revokeLanAccessTokenById(id) {
|
|
200
|
+
const normalizedId = normalizeText(id, 128)
|
|
201
|
+
if (!normalizedId) {
|
|
202
|
+
const error = new Error('LAN access session id is required.')
|
|
203
|
+
error.statusCode = 400
|
|
204
|
+
throw error
|
|
205
|
+
}
|
|
206
|
+
return enqueueWrite(writeQueueName, async () => {
|
|
207
|
+
const current = await readLanAccessFile()
|
|
208
|
+
const tokens = pruneTokens(current.tokens)
|
|
209
|
+
const nextTokens = tokens.filter((tokenRecord) => tokenRecordId(tokenRecord) !== normalizedId)
|
|
210
|
+
if (nextTokens.length === tokens.length) {
|
|
211
|
+
const error = new Error('LAN access session not found.')
|
|
212
|
+
error.statusCode = 404
|
|
213
|
+
throw error
|
|
214
|
+
}
|
|
215
|
+
const next = normalizeConfig({
|
|
216
|
+
...current,
|
|
217
|
+
tokens: nextTokens,
|
|
218
|
+
updatedAt: new Date().toISOString(),
|
|
219
|
+
})
|
|
220
|
+
await writeLanAccessFile(next)
|
|
221
|
+
return publicStatus(next)
|
|
222
|
+
})
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export async function revokeLanAccessToken(token) {
|
|
226
|
+
if (!token || typeof token !== 'string') return false
|
|
227
|
+
const [versionText, secret] = token.split('.')
|
|
228
|
+
if (!secret) return false
|
|
229
|
+
const actualHash = sha256Base64Url(secret)
|
|
230
|
+
return enqueueWrite(writeQueueName, async () => {
|
|
231
|
+
const current = await readLanAccessFile()
|
|
232
|
+
if (Number(versionText) !== (current.authVersion || 1)) return false
|
|
233
|
+
const tokens = pruneTokens(current.tokens)
|
|
234
|
+
const nextTokens = tokens.filter((tokenRecord) => !safeHashEqual(tokenRecord.tokenHash, actualHash))
|
|
235
|
+
if (nextTokens.length === tokens.length) return false
|
|
236
|
+
const next = normalizeConfig({
|
|
237
|
+
...current,
|
|
238
|
+
tokens: nextTokens,
|
|
239
|
+
updatedAt: new Date().toISOString(),
|
|
240
|
+
})
|
|
241
|
+
await writeLanAccessFile(next)
|
|
242
|
+
return true
|
|
243
|
+
})
|
|
244
|
+
}
|
|
245
|
+
|
|
165
246
|
export function lanAccessCookieName() {
|
|
166
247
|
return 'qf_lan_access'
|
|
167
248
|
}
|
|
168
249
|
|
|
169
|
-
export async function issueLanAccessToken(password) {
|
|
250
|
+
export async function issueLanAccessToken(password, metadata = {}) {
|
|
170
251
|
return enqueueWrite(writeQueueName, async () => {
|
|
171
252
|
const current = await readLanAccessFile()
|
|
172
253
|
if (!current.enabled || !current.passwordHash) {
|
|
@@ -185,11 +266,20 @@ export async function issueLanAccessToken(password) {
|
|
|
185
266
|
const issuedAt = new Date().toISOString()
|
|
186
267
|
const ttlMs = normalizeSessionTtlHours(current.sessionTtlHours) * 60 * 60 * 1000
|
|
187
268
|
const expiresAt = new Date(Date.now() + ttlMs).toISOString()
|
|
269
|
+
const tokenRecord = {
|
|
270
|
+
id: createRandomToken(18),
|
|
271
|
+
tokenHash,
|
|
272
|
+
issuedAt,
|
|
273
|
+
expiresAt,
|
|
274
|
+
authVersion: current.authVersion || 1,
|
|
275
|
+
remoteAddress: normalizeRemoteAddress(metadata.remoteAddress),
|
|
276
|
+
userAgent: normalizeText(metadata.userAgent, 300),
|
|
277
|
+
}
|
|
188
278
|
const next = normalizeConfig({
|
|
189
279
|
...current,
|
|
190
280
|
tokens: [
|
|
191
281
|
...pruneTokens(current.tokens),
|
|
192
|
-
|
|
282
|
+
tokenRecord,
|
|
193
283
|
].slice(-LAN_TOKEN_MAX_COUNT),
|
|
194
284
|
updatedAt: issuedAt,
|
|
195
285
|
})
|