@openflowjs/cli 0.2.0
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/dist/bin/openflow.d.ts +2 -0
- package/dist/bin/openflow.js +8 -0
- package/dist/bin/openflow.js.map +1 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +38 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/flow.d.ts +1 -0
- package/dist/commands/flow.js +119 -0
- package/dist/commands/flow.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.js +1082 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/iteration.d.ts +1 -0
- package/dist/commands/iteration.js +131 -0
- package/dist/commands/iteration.js.map +1 -0
- package/dist/commands/mcp.d.ts +1 -0
- package/dist/commands/mcp.js +12 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/module.d.ts +1 -0
- package/dist/commands/module.js +137 -0
- package/dist/commands/module.js.map +1 -0
- package/dist/commands/plan.d.ts +1 -0
- package/dist/commands/plan.js +111 -0
- package/dist/commands/plan.js.map +1 -0
- package/dist/commands/plugin.d.ts +1 -0
- package/dist/commands/plugin.js +246 -0
- package/dist/commands/plugin.js.map +1 -0
- package/dist/commands/preflight.d.ts +8 -0
- package/dist/commands/preflight.js +57 -0
- package/dist/commands/preflight.js.map +1 -0
- package/dist/commands/review.d.ts +1 -0
- package/dist/commands/review.js +145 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/state.d.ts +1 -0
- package/dist/commands/state.js +28 -0
- package/dist/commands/state.js.map +1 -0
- package/dist/commands/validate.d.ts +1 -0
- package/dist/commands/validate.js +310 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/core/artifacts.d.ts +140 -0
- package/dist/core/artifacts.js +809 -0
- package/dist/core/artifacts.js.map +1 -0
- package/dist/core/index.d.ts +12 -0
- package/dist/core/index.js +27 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core-artifacts/marketplace.json +14 -0
- package/dist/core-artifacts/modules.json +20 -0
- package/dist/core-artifacts/openflow/.claude-plugin/plugin.json +8 -0
- package/dist/core-artifacts/openflow/.mcp.json +9 -0
- package/dist/core-artifacts/openflow/agents/openflow-artifact-reviewer.md +308 -0
- package/dist/core-artifacts/openflow/agents/openflow-code-reviewer.md +177 -0
- package/dist/core-artifacts/openflow/agents/openflow-executor-deep.md +119 -0
- package/dist/core-artifacts/openflow/agents/openflow-executor-general.md +104 -0
- package/dist/core-artifacts/openflow/agents/openflow-executor-quick.md +93 -0
- package/dist/core-artifacts/openflow/agents/openflow-explorer.md +69 -0
- package/dist/core-artifacts/openflow/agents/openflow-knowledge-curator.md +89 -0
- package/dist/core-artifacts/openflow/commands/knowledge.md +102 -0
- package/dist/core-artifacts/openflow/hooks/hooks.json +33 -0
- package/dist/core-artifacts/openflow/scripts/openflow-drift-guard.cjs +54 -0
- package/dist/core-artifacts/openflow/scripts/openflow-evidence-reminder.cjs +64 -0
- package/dist/core-artifacts/openflow/scripts/openflow-mcp-review.cjs +27 -0
- package/dist/core-artifacts/openflow/scripts/openflow-write-guard.cjs +27 -0
- package/dist/core-artifacts/openflow/scripts/session-start.cjs +12 -0
- package/dist/core-artifacts/openflow/skills/brainstorm/SKILL.md +131 -0
- package/dist/core-artifacts/openflow/skills/cli-reference/SKILL.md +196 -0
- package/dist/core-artifacts/openflow/skills/finalize/SKILL.md +109 -0
- package/dist/core-artifacts/openflow/skills/finalize/references/summary-template.md +39 -0
- package/dist/core-artifacts/openflow/skills/implement/SKILL.md +296 -0
- package/dist/core-artifacts/openflow/skills/implement/references/working-memory.md +49 -0
- package/dist/core-artifacts/openflow/skills/knowledge-retrieval/SKILL.md +78 -0
- package/dist/core-artifacts/openflow/skills/prd/SKILL.md +173 -0
- package/dist/core-artifacts/openflow/skills/prd/references/level-routing.md +94 -0
- package/dist/core-artifacts/openflow/skills/prd/references/prd-template.md +187 -0
- package/dist/core-artifacts/openflow/skills/prd/references/wireframe-template.html +122 -0
- package/dist/core-artifacts/openflow/skills/spec/SKILL.md +341 -0
- package/dist/core-artifacts/openflow/skills/spec/references/context-template.md +38 -0
- package/dist/core-artifacts/openflow/skills/spec/references/plan-template.md +61 -0
- package/dist/core-artifacts/openflow/skills/spec/references/spec-template.md +187 -0
- package/dist/core-artifacts/openflow/skills/spec/references/tasks-template.md +99 -0
- package/dist/core-artifacts/openflow/skills/workflow-governance/SKILL.md +384 -0
- package/dist/core-artifacts/openflow/skills/workflow-governance/references/knowledge-schema.md +241 -0
- package/dist/core-artifacts/openflow/skills/workflow-governance/references/state-files.md +148 -0
- package/dist/core-artifacts/openflow/skills/workflow-governance/references/workflow.md +119 -0
- package/dist/core-artifacts/templates/.gitkeep +0 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/review-mcp-server.d.ts +1 -0
- package/dist/mcp/review-mcp-server.js +191 -0
- package/dist/mcp/review-mcp-server.js.map +1 -0
- package/dist/mcp/review-server.d.ts +33 -0
- package/dist/mcp/review-server.js +340 -0
- package/dist/mcp/review-server.js.map +1 -0
- package/dist/mcp/review-ui/assets/arc-DH58vMfF.js +1 -0
- package/dist/mcp/review-ui/assets/architecture-YZFGNWBL-CW8o5JQi.js +1 -0
- package/dist/mcp/review-ui/assets/architectureDiagram-Q4EWVU46-CH35GquJ.js +36 -0
- package/dist/mcp/review-ui/assets/array-BCJ35G43.js +1 -0
- package/dist/mcp/review-ui/assets/blockDiagram-DXYQGD6D-B1JZnKG_.js +132 -0
- package/dist/mcp/review-ui/assets/c4Diagram-AHTNJAMY-DCAtnxWd.js +10 -0
- package/dist/mcp/review-ui/assets/channel-BgHR4NPf.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-2KRD3SAO-BkEfK915.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-4BX2VUAB-Dn9kswJO.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-4TB4RGXK-DbeI3ZO6.js +206 -0
- package/dist/mcp/review-ui/assets/chunk-55IACEB6-CLBoivXU.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-5FUZZQ4R-DU7La6QA.js +62 -0
- package/dist/mcp/review-ui/assets/chunk-5PVQY5BW-Dy3eUu9a.js +2 -0
- package/dist/mcp/review-ui/assets/chunk-67CJDMHE-BKQ4iYAM.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-7N4EOEYR-CUngSlME.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-AA7GKIK3-BClDbXxt.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-BSJP7CBP-BlpmbHL-.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-CIAEETIT-THpBXcoN.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-Dlc7tRH4.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-EDXVE4YY-DNUlHz7M.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-ENJZ2VHE-fwEKj0pQ.js +10 -0
- package/dist/mcp/review-ui/assets/chunk-FMBD7UC4-Cj8B2TLo.js +15 -0
- package/dist/mcp/review-ui/assets/chunk-FOC6F5B3-BtR_JW_A.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-ICPOFSXX-WTr3HDYE.js +122 -0
- package/dist/mcp/review-ui/assets/chunk-K5T4RW27-vtP3ehR7.js +94 -0
- package/dist/mcp/review-ui/assets/chunk-KGLVRYIC-Di2tkB7O.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-LIHQZDEY-DoHl9hYE.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-ORNJ4GCN-Bff-Vc2X.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-OYMX7WX6-Djey8TrX.js +231 -0
- package/dist/mcp/review-ui/assets/chunk-QZHKN3VN-C4w1Z4n9.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-U2HBQHQK-D8HUikvJ.js +70 -0
- package/dist/mcp/review-ui/assets/chunk-X2U36JSP-CuZ-SN2r.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-YZCP3GAM-D0-dHF3G.js +1 -0
- package/dist/mcp/review-ui/assets/chunk-ZZ45TVLE-C1aIZGDA.js +1 -0
- package/dist/mcp/review-ui/assets/classDiagram-6PBFFD2Q-DHrSK7zx.js +1 -0
- package/dist/mcp/review-ui/assets/classDiagram-v2-HSJHXN6E-ftN8ECVk.js +1 -0
- package/dist/mcp/review-ui/assets/clone-C3rjhi9V.js +1 -0
- package/dist/mcp/review-ui/assets/cose-bilkent-S5V4N54A-szpqu_3d.js +1 -0
- package/dist/mcp/review-ui/assets/cytoscape.esm-DZ22BVwz.js +321 -0
- package/dist/mcp/review-ui/assets/dagre-B4oIQbi5.js +1 -0
- package/dist/mcp/review-ui/assets/dagre-KV5264BT-zDsxU5-B.js +4 -0
- package/dist/mcp/review-ui/assets/defaultLocale-CIS5GEjP.js +1 -0
- package/dist/mcp/review-ui/assets/diagram-5BDNPKRD-UgfFjZ4o.js +10 -0
- package/dist/mcp/review-ui/assets/diagram-G4DWMVQ6-Wh9VCn50.js +24 -0
- package/dist/mcp/review-ui/assets/diagram-MMDJMWI5-xVD3G7_9.js +43 -0
- package/dist/mcp/review-ui/assets/diagram-TYMM5635-AUD291P2.js +24 -0
- package/dist/mcp/review-ui/assets/dist-B51l2n-9.js +1 -0
- package/dist/mcp/review-ui/assets/erDiagram-SMLLAGMA-B83D6NXm.js +85 -0
- package/dist/mcp/review-ui/assets/flatten-B80WBwOJ.js +1 -0
- package/dist/mcp/review-ui/assets/flowDiagram-DWJPFMVM-D3lXOeHD.js +162 -0
- package/dist/mcp/review-ui/assets/ganttDiagram-T4ZO3ILL-CFAN903o.js +292 -0
- package/dist/mcp/review-ui/assets/gitGraph-7Q5UKJZL-BfgkNWmC.js +1 -0
- package/dist/mcp/review-ui/assets/gitGraphDiagram-UUTBAWPF-DxqTOi4I.js +106 -0
- package/dist/mcp/review-ui/assets/graphlib-De-foo_H.js +1 -0
- package/dist/mcp/review-ui/assets/identity-CWMh0UL-.js +1 -0
- package/dist/mcp/review-ui/assets/index-Do0fBEfH.css +2 -0
- package/dist/mcp/review-ui/assets/index-uPMLqduV.js +123 -0
- package/dist/mcp/review-ui/assets/info-OMHHGYJF-DE18zZ5Z.js +1 -0
- package/dist/mcp/review-ui/assets/infoDiagram-42DDH7IO-Bnco1OGr.js +2 -0
- package/dist/mcp/review-ui/assets/init-BMBYmmUa.js +1 -0
- package/dist/mcp/review-ui/assets/ishikawaDiagram-UXIWVN3A-B89fugr9.js +70 -0
- package/dist/mcp/review-ui/assets/journeyDiagram-VCZTEJTY-CMx2w_is.js +139 -0
- package/dist/mcp/review-ui/assets/kanban-definition-6JOO6SKY-YvTOD1Vd.js +89 -0
- package/dist/mcp/review-ui/assets/katex-8mXVa4k3.js +257 -0
- package/dist/mcp/review-ui/assets/line-BCdBO-oK.js +1 -0
- package/dist/mcp/review-ui/assets/linear-d7UHSQqm.js +1 -0
- package/dist/mcp/review-ui/assets/mermaid-parser.core-DI1-3xL2.js +4 -0
- package/dist/mcp/review-ui/assets/mindmap-definition-QFDTVHPH-E_mV-_Fs.js +96 -0
- package/dist/mcp/review-ui/assets/ordinal-BDTCIhXR.js +1 -0
- package/dist/mcp/review-ui/assets/packet-4T2RLAQJ-BLPGKWDX.js +1 -0
- package/dist/mcp/review-ui/assets/path-CIRGLb_6.js +1 -0
- package/dist/mcp/review-ui/assets/pie-ZZUOXDRM-DVV6Yua9.js +1 -0
- package/dist/mcp/review-ui/assets/pieDiagram-DEJITSTG-Ct4JvywP.js +30 -0
- package/dist/mcp/review-ui/assets/quadrantDiagram-34T5L4WZ-BSFYvc1U.js +7 -0
- package/dist/mcp/review-ui/assets/radar-PYXPWWZC-BMkQDLKp.js +1 -0
- package/dist/mcp/review-ui/assets/reduce-C80XcylQ.js +1 -0
- package/dist/mcp/review-ui/assets/requirementDiagram-MS252O5E-Bp7uSYEK.js +84 -0
- package/dist/mcp/review-ui/assets/rough.esm-DtEqI08j.js +1 -0
- package/dist/mcp/review-ui/assets/sankeyDiagram-XADWPNL6-CV38ZpSv.js +10 -0
- package/dist/mcp/review-ui/assets/sequenceDiagram-FGHM5R23-BXN9jl1N.js +157 -0
- package/dist/mcp/review-ui/assets/src-Cxc1bu7b.js +1 -0
- package/dist/mcp/review-ui/assets/stateDiagram-FHFEXIEX-DZduDkIw.js +1 -0
- package/dist/mcp/review-ui/assets/stateDiagram-v2-QKLJ7IA2-xAWOcxSi.js +1 -0
- package/dist/mcp/review-ui/assets/timeline-definition-GMOUNBTQ-CLqXzNm8.js +120 -0
- package/dist/mcp/review-ui/assets/treeView-SZITEDCU-tPcANHUc.js +1 -0
- package/dist/mcp/review-ui/assets/treemap-W4RFUUIX-BGbXISSk.js +1 -0
- package/dist/mcp/review-ui/assets/vennDiagram-DHZGUBPP-gCnd0IYN.js +34 -0
- package/dist/mcp/review-ui/assets/wardley-RL74JXVD-CK3EfklM.js +1 -0
- package/dist/mcp/review-ui/assets/wardleyDiagram-NUSXRM2D-Dd7qMlPS.js +20 -0
- package/dist/mcp/review-ui/assets/xychartDiagram-5P7HB3ND-DXHXO8Zm.js +7 -0
- package/dist/mcp/review-ui/index.html +29 -0
- package/dist/mcp/studio/assets/arc-DH58vMfF.js +1 -0
- package/dist/mcp/studio/assets/architecture-YZFGNWBL-8xrwD39F.js +1 -0
- package/dist/mcp/studio/assets/architectureDiagram-Q4EWVU46-VmcLZTJf.js +36 -0
- package/dist/mcp/studio/assets/array-BCJ35G43.js +1 -0
- package/dist/mcp/studio/assets/blockDiagram-DXYQGD6D-D-1mlLYy.js +132 -0
- package/dist/mcp/studio/assets/c4Diagram-AHTNJAMY-DCAtnxWd.js +10 -0
- package/dist/mcp/studio/assets/channel-BgHR4NPf.js +1 -0
- package/dist/mcp/studio/assets/chunk-2KRD3SAO-CMDQx2WD.js +1 -0
- package/dist/mcp/studio/assets/chunk-4BX2VUAB-Dn9kswJO.js +1 -0
- package/dist/mcp/studio/assets/chunk-4TB4RGXK-aFEYGDkJ.js +206 -0
- package/dist/mcp/studio/assets/chunk-55IACEB6-CLBoivXU.js +1 -0
- package/dist/mcp/studio/assets/chunk-5FUZZQ4R-DU7La6QA.js +62 -0
- package/dist/mcp/studio/assets/chunk-5PVQY5BW-Dy3eUu9a.js +2 -0
- package/dist/mcp/studio/assets/chunk-67CJDMHE-DnkyJt7A.js +1 -0
- package/dist/mcp/studio/assets/chunk-7N4EOEYR-cnJ9dWSC.js +1 -0
- package/dist/mcp/studio/assets/chunk-AA7GKIK3-DjCZnyrT.js +1 -0
- package/dist/mcp/studio/assets/chunk-BSJP7CBP-BlpmbHL-.js +1 -0
- package/dist/mcp/studio/assets/chunk-CIAEETIT-CtvXSBsf.js +1 -0
- package/dist/mcp/studio/assets/chunk-Dlc7tRH4.js +1 -0
- package/dist/mcp/studio/assets/chunk-EDXVE4YY-DNUlHz7M.js +1 -0
- package/dist/mcp/studio/assets/chunk-ENJZ2VHE-fwEKj0pQ.js +10 -0
- package/dist/mcp/studio/assets/chunk-FMBD7UC4-Cj8B2TLo.js +15 -0
- package/dist/mcp/studio/assets/chunk-FOC6F5B3-Ca28VADd.js +1 -0
- package/dist/mcp/studio/assets/chunk-ICPOFSXX-WTr3HDYE.js +122 -0
- package/dist/mcp/studio/assets/chunk-K5T4RW27-pqiOLnBn.js +94 -0
- package/dist/mcp/studio/assets/chunk-KGLVRYIC-DZfGlR-G.js +1 -0
- package/dist/mcp/studio/assets/chunk-LIHQZDEY-6Ygb8Kwt.js +1 -0
- package/dist/mcp/studio/assets/chunk-ORNJ4GCN-DSlr7oSO.js +1 -0
- package/dist/mcp/studio/assets/chunk-OYMX7WX6-8z_2lCb3.js +231 -0
- package/dist/mcp/studio/assets/chunk-QZHKN3VN-C4w1Z4n9.js +1 -0
- package/dist/mcp/studio/assets/chunk-U2HBQHQK-D8HUikvJ.js +70 -0
- package/dist/mcp/studio/assets/chunk-X2U36JSP-CuZ-SN2r.js +1 -0
- package/dist/mcp/studio/assets/chunk-YZCP3GAM-D0-dHF3G.js +1 -0
- package/dist/mcp/studio/assets/chunk-ZZ45TVLE-C1aIZGDA.js +1 -0
- package/dist/mcp/studio/assets/classDiagram-6PBFFD2Q-IZXxqxqM.js +1 -0
- package/dist/mcp/studio/assets/classDiagram-v2-HSJHXN6E-BiJKwTXT.js +1 -0
- package/dist/mcp/studio/assets/clone-g4CuF1Hf.js +1 -0
- package/dist/mcp/studio/assets/cose-bilkent-S5V4N54A-szpqu_3d.js +1 -0
- package/dist/mcp/studio/assets/cytoscape.esm-DZ22BVwz.js +321 -0
- package/dist/mcp/studio/assets/dagre-Be9o0OzC.js +1 -0
- package/dist/mcp/studio/assets/dagre-KV5264BT-iB6PnHLr.js +4 -0
- package/dist/mcp/studio/assets/defaultLocale-CIS5GEjP.js +1 -0
- package/dist/mcp/studio/assets/diagram-5BDNPKRD-BLfWbiEB.js +10 -0
- package/dist/mcp/studio/assets/diagram-G4DWMVQ6-CgcnwgVO.js +24 -0
- package/dist/mcp/studio/assets/diagram-MMDJMWI5-CpkXvs2p.js +43 -0
- package/dist/mcp/studio/assets/diagram-TYMM5635-guxqmxjJ.js +24 -0
- package/dist/mcp/studio/assets/dist-B51l2n-9.js +1 -0
- package/dist/mcp/studio/assets/erDiagram-SMLLAGMA-Lwv-cC2Y.js +85 -0
- package/dist/mcp/studio/assets/flatten-Dv3Z_7XJ.js +1 -0
- package/dist/mcp/studio/assets/flowDiagram-DWJPFMVM-BKnaFfFR.js +162 -0
- package/dist/mcp/studio/assets/ganttDiagram-T4ZO3ILL-CFAN903o.js +292 -0
- package/dist/mcp/studio/assets/gitGraph-7Q5UKJZL-BSdEZNVc.js +1 -0
- package/dist/mcp/studio/assets/gitGraphDiagram-UUTBAWPF-D4z4QWni.js +106 -0
- package/dist/mcp/studio/assets/graphlib-C1IZi4Cg.js +1 -0
- package/dist/mcp/studio/assets/identity-CWMh0UL-.js +1 -0
- package/dist/mcp/studio/assets/index-CyBqHDpB.js +109 -0
- package/dist/mcp/studio/assets/index-Dn_Ujmba.css +2 -0
- package/dist/mcp/studio/assets/info-OMHHGYJF-CoTx64p3.js +1 -0
- package/dist/mcp/studio/assets/infoDiagram-42DDH7IO-QEji23sQ.js +2 -0
- package/dist/mcp/studio/assets/init-BMBYmmUa.js +1 -0
- package/dist/mcp/studio/assets/ishikawaDiagram-UXIWVN3A-lMurmqul.js +70 -0
- package/dist/mcp/studio/assets/journeyDiagram-VCZTEJTY-CMx2w_is.js +139 -0
- package/dist/mcp/studio/assets/kanban-definition-6JOO6SKY-DsOybLrS.js +89 -0
- package/dist/mcp/studio/assets/katex-8mXVa4k3.js +257 -0
- package/dist/mcp/studio/assets/line-BCdBO-oK.js +1 -0
- package/dist/mcp/studio/assets/linear-d7UHSQqm.js +1 -0
- package/dist/mcp/studio/assets/mermaid-parser.core-BZtTt4qJ.js +4 -0
- package/dist/mcp/studio/assets/mindmap-definition-QFDTVHPH-B2yfABR9.js +96 -0
- package/dist/mcp/studio/assets/ordinal-BDTCIhXR.js +1 -0
- package/dist/mcp/studio/assets/packet-4T2RLAQJ-Bi4IG7s8.js +1 -0
- package/dist/mcp/studio/assets/path-CIRGLb_6.js +1 -0
- package/dist/mcp/studio/assets/pie-ZZUOXDRM-DsJRjVcu.js +1 -0
- package/dist/mcp/studio/assets/pieDiagram-DEJITSTG-JeKGFs3r.js +30 -0
- package/dist/mcp/studio/assets/quadrantDiagram-34T5L4WZ-BSFYvc1U.js +7 -0
- package/dist/mcp/studio/assets/radar-PYXPWWZC-cUDYP2Ic.js +1 -0
- package/dist/mcp/studio/assets/reduce-x-wchVXY.js +1 -0
- package/dist/mcp/studio/assets/requirementDiagram-MS252O5E-CGeLKQyn.js +84 -0
- package/dist/mcp/studio/assets/rough.esm-DtEqI08j.js +1 -0
- package/dist/mcp/studio/assets/sankeyDiagram-XADWPNL6-CV38ZpSv.js +10 -0
- package/dist/mcp/studio/assets/sequenceDiagram-FGHM5R23-BbHPv3l1.js +157 -0
- package/dist/mcp/studio/assets/src-Cxc1bu7b.js +1 -0
- package/dist/mcp/studio/assets/stateDiagram-FHFEXIEX-BuBuguzn.js +1 -0
- package/dist/mcp/studio/assets/stateDiagram-v2-QKLJ7IA2-PQA-rl9o.js +1 -0
- package/dist/mcp/studio/assets/timeline-definition-GMOUNBTQ-D5xtyNE9.js +120 -0
- package/dist/mcp/studio/assets/treeView-SZITEDCU-DhRx0eaI.js +1 -0
- package/dist/mcp/studio/assets/treemap-W4RFUUIX-Btsj9DUH.js +1 -0
- package/dist/mcp/studio/assets/vennDiagram-DHZGUBPP-W4g15SMY.js +34 -0
- package/dist/mcp/studio/assets/wardley-RL74JXVD-BTpKsgl7.js +1 -0
- package/dist/mcp/studio/assets/wardleyDiagram-NUSXRM2D-f7wgXdwe.js +20 -0
- package/dist/mcp/studio/assets/xychartDiagram-5P7HB3ND-BWx9swPf.js +7 -0
- package/dist/mcp/studio/index.html +29 -0
- package/dist/review-mcp-server.d.ts +1 -0
- package/dist/review-mcp-server.js +178 -0
- package/dist/review-mcp-server.js.map +1 -0
- package/dist/review-server.d.ts +17 -0
- package/dist/review-server.js +223 -0
- package/dist/review-server.js.map +1 -0
- package/dist/review-ui/assets/arc-DH58vMfF.js +1 -0
- package/dist/review-ui/assets/architecture-YZFGNWBL-ChakYgFO.js +1 -0
- package/dist/review-ui/assets/architectureDiagram-Q4EWVU46-CcJOZCOb.js +36 -0
- package/dist/review-ui/assets/array-BCJ35G43.js +1 -0
- package/dist/review-ui/assets/blockDiagram-DXYQGD6D-H7mMv5Tv.js +132 -0
- package/dist/review-ui/assets/c4Diagram-AHTNJAMY-DCAtnxWd.js +10 -0
- package/dist/review-ui/assets/channel-BgHR4NPf.js +1 -0
- package/dist/review-ui/assets/chunk-2KRD3SAO-BfA3IkPQ.js +1 -0
- package/dist/review-ui/assets/chunk-4BX2VUAB-Dn9kswJO.js +1 -0
- package/dist/review-ui/assets/chunk-4TB4RGXK-CvTeZi33.js +206 -0
- package/dist/review-ui/assets/chunk-55IACEB6-CLBoivXU.js +1 -0
- package/dist/review-ui/assets/chunk-5FUZZQ4R-DU7La6QA.js +62 -0
- package/dist/review-ui/assets/chunk-5PVQY5BW-Dy3eUu9a.js +2 -0
- package/dist/review-ui/assets/chunk-67CJDMHE-BQ1xNHFx.js +1 -0
- package/dist/review-ui/assets/chunk-7N4EOEYR-B1ORNLQP.js +1 -0
- package/dist/review-ui/assets/chunk-AA7GKIK3-D3pS3mnx.js +1 -0
- package/dist/review-ui/assets/chunk-BSJP7CBP-BlpmbHL-.js +1 -0
- package/dist/review-ui/assets/chunk-CIAEETIT-BDZkAY47.js +1 -0
- package/dist/review-ui/assets/chunk-Dlc7tRH4.js +1 -0
- package/dist/review-ui/assets/chunk-EDXVE4YY-DNUlHz7M.js +1 -0
- package/dist/review-ui/assets/chunk-ENJZ2VHE-fwEKj0pQ.js +10 -0
- package/dist/review-ui/assets/chunk-FMBD7UC4-Cj8B2TLo.js +15 -0
- package/dist/review-ui/assets/chunk-FOC6F5B3-DGtCX5Ra.js +1 -0
- package/dist/review-ui/assets/chunk-ICPOFSXX-WTr3HDYE.js +122 -0
- package/dist/review-ui/assets/chunk-K5T4RW27-CWpdECLF.js +94 -0
- package/dist/review-ui/assets/chunk-KGLVRYIC-oI2XKaPz.js +1 -0
- package/dist/review-ui/assets/chunk-LIHQZDEY-Dzp3G35O.js +1 -0
- package/dist/review-ui/assets/chunk-ORNJ4GCN-DsHuVbPU.js +1 -0
- package/dist/review-ui/assets/chunk-OYMX7WX6-fgjoXAXJ.js +231 -0
- package/dist/review-ui/assets/chunk-QZHKN3VN-C4w1Z4n9.js +1 -0
- package/dist/review-ui/assets/chunk-U2HBQHQK-D8HUikvJ.js +70 -0
- package/dist/review-ui/assets/chunk-X2U36JSP-CuZ-SN2r.js +1 -0
- package/dist/review-ui/assets/chunk-YZCP3GAM-D0-dHF3G.js +1 -0
- package/dist/review-ui/assets/chunk-ZZ45TVLE-C1aIZGDA.js +1 -0
- package/dist/review-ui/assets/classDiagram-6PBFFD2Q-D_3LhkJc.js +1 -0
- package/dist/review-ui/assets/classDiagram-v2-HSJHXN6E-DQRUREh5.js +1 -0
- package/dist/review-ui/assets/clone-BZMtGzbS.js +1 -0
- package/dist/review-ui/assets/cose-bilkent-S5V4N54A-szpqu_3d.js +1 -0
- package/dist/review-ui/assets/cytoscape.esm-DZ22BVwz.js +321 -0
- package/dist/review-ui/assets/dagre-BfNtd34y.js +1 -0
- package/dist/review-ui/assets/dagre-KV5264BT-D6PbxORW.js +4 -0
- package/dist/review-ui/assets/defaultLocale-CIS5GEjP.js +1 -0
- package/dist/review-ui/assets/diagram-5BDNPKRD-BNAXBDig.js +10 -0
- package/dist/review-ui/assets/diagram-G4DWMVQ6-CIGS_5yQ.js +24 -0
- package/dist/review-ui/assets/diagram-MMDJMWI5-DJmcU2xZ.js +43 -0
- package/dist/review-ui/assets/diagram-TYMM5635-DW8XzrAz.js +24 -0
- package/dist/review-ui/assets/dist-B51l2n-9.js +1 -0
- package/dist/review-ui/assets/erDiagram-SMLLAGMA-BfUNH8zz.js +85 -0
- package/dist/review-ui/assets/flatten-BHh95bpO.js +1 -0
- package/dist/review-ui/assets/flowDiagram-DWJPFMVM-qgnlSvEC.js +162 -0
- package/dist/review-ui/assets/ganttDiagram-T4ZO3ILL-CFAN903o.js +292 -0
- package/dist/review-ui/assets/gitGraph-7Q5UKJZL-Dn47XunR.js +1 -0
- package/dist/review-ui/assets/gitGraphDiagram-UUTBAWPF-BcG6fDsE.js +106 -0
- package/dist/review-ui/assets/graphlib-Cie4kcbC.js +1 -0
- package/dist/review-ui/assets/identity-CWMh0UL-.js +1 -0
- package/dist/review-ui/assets/index-ByplNhhd.css +2 -0
- package/dist/review-ui/assets/index-S7nbpFp2.js +123 -0
- package/dist/review-ui/assets/info-OMHHGYJF-hAukP1xW.js +1 -0
- package/dist/review-ui/assets/infoDiagram-42DDH7IO-FblTAfC3.js +2 -0
- package/dist/review-ui/assets/init-BMBYmmUa.js +1 -0
- package/dist/review-ui/assets/ishikawaDiagram-UXIWVN3A-BA7dJd-J.js +70 -0
- package/dist/review-ui/assets/journeyDiagram-VCZTEJTY-CMx2w_is.js +139 -0
- package/dist/review-ui/assets/kanban-definition-6JOO6SKY-CFiOZCrT.js +89 -0
- package/dist/review-ui/assets/katex-8mXVa4k3.js +257 -0
- package/dist/review-ui/assets/line-BCdBO-oK.js +1 -0
- package/dist/review-ui/assets/linear-d7UHSQqm.js +1 -0
- package/dist/review-ui/assets/mermaid-parser.core-BHMXLuNx.js +4 -0
- package/dist/review-ui/assets/mindmap-definition-QFDTVHPH-CWO7vDqu.js +96 -0
- package/dist/review-ui/assets/ordinal-BDTCIhXR.js +1 -0
- package/dist/review-ui/assets/packet-4T2RLAQJ-Btz3ryW7.js +1 -0
- package/dist/review-ui/assets/path-CIRGLb_6.js +1 -0
- package/dist/review-ui/assets/pie-ZZUOXDRM-CreBtuDj.js +1 -0
- package/dist/review-ui/assets/pieDiagram-DEJITSTG-X2mFk5I3.js +30 -0
- package/dist/review-ui/assets/quadrantDiagram-34T5L4WZ-BSFYvc1U.js +7 -0
- package/dist/review-ui/assets/radar-PYXPWWZC-BcAPYMpV.js +1 -0
- package/dist/review-ui/assets/reduce-14YNCNxn.js +1 -0
- package/dist/review-ui/assets/requirementDiagram-MS252O5E-CDv1lxdq.js +84 -0
- package/dist/review-ui/assets/rough.esm-DtEqI08j.js +1 -0
- package/dist/review-ui/assets/sankeyDiagram-XADWPNL6-CV38ZpSv.js +10 -0
- package/dist/review-ui/assets/sequenceDiagram-FGHM5R23-DCuV_bhx.js +157 -0
- package/dist/review-ui/assets/src-Cxc1bu7b.js +1 -0
- package/dist/review-ui/assets/stateDiagram-FHFEXIEX-BfE_bGUQ.js +1 -0
- package/dist/review-ui/assets/stateDiagram-v2-QKLJ7IA2-u1yKXWoz.js +1 -0
- package/dist/review-ui/assets/timeline-definition-GMOUNBTQ-Ci0uFxaT.js +120 -0
- package/dist/review-ui/assets/treeView-SZITEDCU-BXg6-7zY.js +1 -0
- package/dist/review-ui/assets/treemap-W4RFUUIX-BToYbgol.js +1 -0
- package/dist/review-ui/assets/vennDiagram-DHZGUBPP-DvOuThac.js +34 -0
- package/dist/review-ui/assets/wardley-RL74JXVD-BAYzkcK-.js +1 -0
- package/dist/review-ui/assets/wardleyDiagram-NUSXRM2D-YxTu6WZw.js +20 -0
- package/dist/review-ui/assets/xychartDiagram-5P7HB3ND-V9j-Dl7t.js +7 -0
- package/dist/review-ui/index.html +29 -0
- package/dist/run-openflow-cli.d.ts +1 -0
- package/dist/run-openflow-cli.js +41 -0
- package/dist/run-openflow-cli.js.map +1 -0
- package/dist/shared/args.d.ts +3 -0
- package/dist/shared/args.js +27 -0
- package/dist/shared/args.js.map +1 -0
- package/dist/shared/browser.d.ts +4 -0
- package/dist/shared/browser.js +17 -0
- package/dist/shared/browser.js.map +1 -0
- package/dist/shared/fs.d.ts +15 -0
- package/dist/shared/fs.js +48 -0
- package/dist/shared/fs.js.map +1 -0
- package/dist/shared/i18n.d.ts +5 -0
- package/dist/shared/i18n.js +65 -0
- package/dist/shared/i18n.js.map +1 -0
- package/dist/shared/locales/en-US.json +88 -0
- package/dist/shared/locales/zh-CN.json +88 -0
- package/dist/shared/plugin-registry.d.ts +36 -0
- package/dist/shared/plugin-registry.js +51 -0
- package/dist/shared/plugin-registry.js.map +1 -0
- package/dist/shared/project-state.d.ts +17 -0
- package/dist/shared/project-state.js +75 -0
- package/dist/shared/project-state.js.map +1 -0
- package/dist/shared/terminal.d.ts +10 -0
- package/dist/shared/terminal.js +110 -0
- package/dist/shared/terminal.js.map +1 -0
- package/package.json +28 -0
- package/templates/archive/.gitkeep +1 -0
- package/templates/config.json +11 -0
- package/templates/current.json +3 -0
- package/templates/iterations/.gitkeep +1 -0
|
@@ -0,0 +1,1082 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { copyFile, mkdir, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, relative } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { homedir } from "node:os";
|
|
6
|
+
import { clearScreenDown, cursorTo, emitKeypressEvents, moveCursor } from "node:readline";
|
|
7
|
+
import { execFile } from "node:child_process";
|
|
8
|
+
import { promisify } from "node:util";
|
|
9
|
+
import { isRecord, writeJsonAtomic, collectFiles, sha256File, readJsonObjectIfExists } from "../shared/fs.js";
|
|
10
|
+
import { printLogo, printPanel, printFileStatus, formatTitle, colorText, printStep, printSeparator, printKeyValue } from "../shared/terminal.js";
|
|
11
|
+
import { setLocale, t } from "../shared/i18n.js";
|
|
12
|
+
const execFileAsync = promisify(execFile);
|
|
13
|
+
const INIT_LANGUAGE_CHOICES = ["en-US", "zh-CN"];
|
|
14
|
+
const INSTALL_MANIFEST_PATH = ".openflow/install.json";
|
|
15
|
+
const CLAUDE_PROJECT_MCP_SERVER_NAME = "openflow-studio";
|
|
16
|
+
const CLAUDE_BIN_ENV = "OPENFLOW_CLAUDE_BIN";
|
|
17
|
+
const CLAUDE_BIN_ARGS_ENV = "OPENFLOW_CLAUDE_BIN_ARGS";
|
|
18
|
+
export async function runInitCommand(args) {
|
|
19
|
+
printLogo();
|
|
20
|
+
const options = await resolveInitOptions(args);
|
|
21
|
+
const result = options.format === "plugin"
|
|
22
|
+
? await installPlugin(options)
|
|
23
|
+
: await installAdapter(options);
|
|
24
|
+
printInstallResult(result);
|
|
25
|
+
printCompletionMessage();
|
|
26
|
+
}
|
|
27
|
+
function printCompletionMessage() {
|
|
28
|
+
console.log();
|
|
29
|
+
printSeparator();
|
|
30
|
+
console.log();
|
|
31
|
+
console.log(` ${colorText("bold", colorText("green", t("init.ready")))}`);
|
|
32
|
+
console.log(` ${t("init.nextStep")}`);
|
|
33
|
+
console.log();
|
|
34
|
+
}
|
|
35
|
+
export async function runUpdateCommand(args) {
|
|
36
|
+
const options = parseUpdateArgs(args);
|
|
37
|
+
const result = await updateAdapter(options);
|
|
38
|
+
printUpdateResult(result);
|
|
39
|
+
}
|
|
40
|
+
async function resolveInitOptions(args) {
|
|
41
|
+
const state = parseInitArgs(args);
|
|
42
|
+
if (state.scope === "global" && state.targetProvided) {
|
|
43
|
+
throw new Error(t("init.errorCombineGlobalTarget"));
|
|
44
|
+
}
|
|
45
|
+
let step = 0;
|
|
46
|
+
const maxSteps = 4;
|
|
47
|
+
// Step 1: Prompt language first (before any other interaction)
|
|
48
|
+
if (state.language === undefined && process.stdin.isTTY) {
|
|
49
|
+
step += 1;
|
|
50
|
+
printStep(step, maxSteps, t("init.stepLanguage"));
|
|
51
|
+
state.language = await promptLanguage();
|
|
52
|
+
setLocale(state.language);
|
|
53
|
+
}
|
|
54
|
+
else if (state.language) {
|
|
55
|
+
setLocale(state.language);
|
|
56
|
+
}
|
|
57
|
+
// Step 1.5: Prompt module selection
|
|
58
|
+
if (!state.modulesProvided && process.stdin.isTTY) {
|
|
59
|
+
step += 1;
|
|
60
|
+
printStep(step, maxSteps, t("init.stepModules"));
|
|
61
|
+
state.modules = await promptModules();
|
|
62
|
+
}
|
|
63
|
+
// Step 2: Determine adapter type (interactive)
|
|
64
|
+
if (!state.adapterProvided && !state.formatProvided && process.stdin.isTTY) {
|
|
65
|
+
step += 1;
|
|
66
|
+
printStep(step, maxSteps, t("init.stepAdapter"));
|
|
67
|
+
const type = await promptAdapterType();
|
|
68
|
+
if (type === "opencode") {
|
|
69
|
+
throw new Error(t("init.errorOpencode"));
|
|
70
|
+
}
|
|
71
|
+
if (type === "plugin") {
|
|
72
|
+
state.format = "plugin";
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
state.format = "copy";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const adapter = state.adapter ?? "claude-code";
|
|
79
|
+
if (adapter === "opencode") {
|
|
80
|
+
throw new Error(t("init.errorOpencode"));
|
|
81
|
+
}
|
|
82
|
+
const format = state.format ?? "copy";
|
|
83
|
+
// Step 3: Prompt scope (skip for plugin — always global)
|
|
84
|
+
if (format !== "plugin" && !state.scopeProvided && !state.targetProvided && process.stdin.isTTY) {
|
|
85
|
+
step += 1;
|
|
86
|
+
printStep(step, maxSteps, t("init.stepLocation"));
|
|
87
|
+
state.scope = await promptScope();
|
|
88
|
+
}
|
|
89
|
+
return {
|
|
90
|
+
adapter,
|
|
91
|
+
targetPath: state.targetPath,
|
|
92
|
+
force: state.force,
|
|
93
|
+
scope: format === "plugin" ? "global" : (state.scope ?? "project"),
|
|
94
|
+
format,
|
|
95
|
+
language: state.language,
|
|
96
|
+
modules: state.modules
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function parseInitArgs(args) {
|
|
100
|
+
const state = {
|
|
101
|
+
adapterProvided: false,
|
|
102
|
+
targetPath: ".",
|
|
103
|
+
targetProvided: false,
|
|
104
|
+
force: false,
|
|
105
|
+
scopeProvided: false,
|
|
106
|
+
formatProvided: false,
|
|
107
|
+
modulesProvided: false
|
|
108
|
+
};
|
|
109
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
110
|
+
const arg = args[index];
|
|
111
|
+
if (arg === "--adapter") {
|
|
112
|
+
const value = args[index + 1];
|
|
113
|
+
if (value !== "claude-code" && value !== "opencode") {
|
|
114
|
+
throw new Error(t("init.errorAdapterValue"));
|
|
115
|
+
}
|
|
116
|
+
state.adapter = value;
|
|
117
|
+
state.adapterProvided = true;
|
|
118
|
+
index += 1;
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (arg === "--target") {
|
|
122
|
+
const value = args[index + 1];
|
|
123
|
+
if (!value) {
|
|
124
|
+
throw new Error(t("init.errorTargetPath"));
|
|
125
|
+
}
|
|
126
|
+
state.targetPath = value;
|
|
127
|
+
state.targetProvided = true;
|
|
128
|
+
index += 1;
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (arg === "--global") {
|
|
132
|
+
state.scope = "global";
|
|
133
|
+
state.scopeProvided = true;
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (arg === "--scope") {
|
|
137
|
+
const value = args[index + 1];
|
|
138
|
+
if (value !== "project" && value !== "global") {
|
|
139
|
+
throw new Error(t("init.errorScopeValue"));
|
|
140
|
+
}
|
|
141
|
+
state.scope = value;
|
|
142
|
+
state.scopeProvided = true;
|
|
143
|
+
index += 1;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
if (arg === "--force") {
|
|
147
|
+
state.force = true;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
if (arg === "--format") {
|
|
151
|
+
const value = args[index + 1];
|
|
152
|
+
if (value !== "copy" && value !== "plugin") {
|
|
153
|
+
throw new Error(t("init.errorFormatValue"));
|
|
154
|
+
}
|
|
155
|
+
state.format = value;
|
|
156
|
+
state.formatProvided = true;
|
|
157
|
+
index += 1;
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (arg === "--language") {
|
|
161
|
+
const value = args[index + 1];
|
|
162
|
+
const language = normalizeInitLanguage(value);
|
|
163
|
+
if (!language) {
|
|
164
|
+
throw new Error(t("init.errorLanguageValue"));
|
|
165
|
+
}
|
|
166
|
+
state.language = language;
|
|
167
|
+
index += 1;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
if (arg === "--module") {
|
|
171
|
+
const value = args[index + 1];
|
|
172
|
+
if (!value) {
|
|
173
|
+
throw new Error("--module requires a value");
|
|
174
|
+
}
|
|
175
|
+
if (!state.modules) {
|
|
176
|
+
state.modules = [];
|
|
177
|
+
}
|
|
178
|
+
state.modules.push(value);
|
|
179
|
+
state.modulesProvided = true;
|
|
180
|
+
index += 1;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
throw new Error(t("init.errorUnknownOption", { option: arg }));
|
|
184
|
+
}
|
|
185
|
+
return state;
|
|
186
|
+
}
|
|
187
|
+
function parseUpdateArgs(args) {
|
|
188
|
+
const options = {
|
|
189
|
+
adapter: "claude-code",
|
|
190
|
+
targetPath: ".",
|
|
191
|
+
force: false,
|
|
192
|
+
dryRun: false
|
|
193
|
+
};
|
|
194
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
195
|
+
const arg = args[index];
|
|
196
|
+
if (arg === "--adapter") {
|
|
197
|
+
const value = args[index + 1];
|
|
198
|
+
if (value !== "claude-code") {
|
|
199
|
+
throw new Error(t("update.errorAdapterValue"));
|
|
200
|
+
}
|
|
201
|
+
options.adapter = value;
|
|
202
|
+
index += 1;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
if (arg === "--target") {
|
|
206
|
+
const value = args[index + 1];
|
|
207
|
+
if (!value) {
|
|
208
|
+
throw new Error(t("update.errorTargetPath"));
|
|
209
|
+
}
|
|
210
|
+
options.targetPath = value;
|
|
211
|
+
index += 1;
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
214
|
+
if (arg === "--force") {
|
|
215
|
+
options.force = true;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (arg === "--dry-run") {
|
|
219
|
+
options.dryRun = true;
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
throw new Error(t("update.errorUnknownOption"));
|
|
223
|
+
}
|
|
224
|
+
return options;
|
|
225
|
+
}
|
|
226
|
+
async function installAdapter(options) {
|
|
227
|
+
const coreDistRoot = getCoreDistRoot();
|
|
228
|
+
const openflowPkgRoot = join(coreDistRoot, "openflow");
|
|
229
|
+
const templateRoot = join(coreDistRoot, "templates");
|
|
230
|
+
const targetRoot = options.scope === "global" ? getClaudeCodeUserRoot() : options.targetPath;
|
|
231
|
+
const files = [];
|
|
232
|
+
const adapterMappings = [
|
|
233
|
+
["commands", "commands"],
|
|
234
|
+
["skills", "skills"],
|
|
235
|
+
["agents", "agents"],
|
|
236
|
+
];
|
|
237
|
+
// Read modules.json and compute allowed file names
|
|
238
|
+
const modulesJsonPath = join(coreDistRoot, "modules.json");
|
|
239
|
+
const allowedFiles = await computeAllowedFiles(modulesJsonPath, options.modules);
|
|
240
|
+
const adapterTargetRoot = options.scope === "global" ? targetRoot : join(targetRoot, ".claude");
|
|
241
|
+
for (const [sourceDir, targetDir] of adapterMappings) {
|
|
242
|
+
const sourceRoot = join(openflowPkgRoot, sourceDir);
|
|
243
|
+
files.push(...(await copyMappedFiles(sourceRoot, join(adapterTargetRoot, targetDir), targetRoot, options.force, allowedFiles.get(sourceDir))));
|
|
244
|
+
}
|
|
245
|
+
if (options.scope === "project") {
|
|
246
|
+
files.push(...(await copyMappedFiles(templateRoot, join(targetRoot, ".openflow"), targetRoot, options.force)));
|
|
247
|
+
// Merge .mcp.json from the plugin package into the project root
|
|
248
|
+
files.push(await mergePluginMcpConfig(openflowPkgRoot, targetRoot, options.force));
|
|
249
|
+
if (options.language) {
|
|
250
|
+
const { updateProjectLanguage } = await import("./config.js");
|
|
251
|
+
await updateProjectLanguage(targetRoot, options.language);
|
|
252
|
+
}
|
|
253
|
+
if (options.modules && options.modules.length > 0) {
|
|
254
|
+
const configPath = join(targetRoot, ".openflow", "config.json");
|
|
255
|
+
if (existsSync(configPath)) {
|
|
256
|
+
const config = JSON.parse(await readFile(configPath, "utf8"));
|
|
257
|
+
config.modules = options.modules;
|
|
258
|
+
await writeJsonAtomic(configPath, config);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
await writeInstallManifest(targetRoot, options.adapter);
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
format: "copy",
|
|
265
|
+
adapter: options.adapter,
|
|
266
|
+
targetPath: targetRoot,
|
|
267
|
+
files,
|
|
268
|
+
modules: options.modules
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function toLocalMarketplacePath(absPath) {
|
|
272
|
+
// Claude CLI requires ./relative format; convert absolute path from process.cwd()
|
|
273
|
+
const rel = relative(process.cwd(), absPath).replace(/\\/g, "/");
|
|
274
|
+
if (rel.startsWith("./") || rel.startsWith("../"))
|
|
275
|
+
return rel;
|
|
276
|
+
// isAbsolute check: cross-drive on Windows makes relative() return absolute
|
|
277
|
+
if (/^[a-zA-Z]:/.test(rel) || rel.startsWith("/"))
|
|
278
|
+
return `./${absPath.replace(/\\/g, "/")}`;
|
|
279
|
+
return `./${rel}`;
|
|
280
|
+
}
|
|
281
|
+
async function assembleMarketplaceDir(coreDistRoot) {
|
|
282
|
+
const marketplaceDir = join(getClaudeCodeUserRoot(), "plugins", "marketplaces", "openflow");
|
|
283
|
+
if (existsSync(marketplaceDir)) {
|
|
284
|
+
await rm(marketplaceDir, { recursive: true, force: true });
|
|
285
|
+
}
|
|
286
|
+
await mkdir(marketplaceDir, { recursive: true });
|
|
287
|
+
// .claude-plugin/marketplace.json at marketplace root
|
|
288
|
+
const mktClaudeDir = join(marketplaceDir, ".claude-plugin");
|
|
289
|
+
await mkdir(mktClaudeDir, { recursive: true });
|
|
290
|
+
await copyFile(join(coreDistRoot, "marketplace.json"), join(mktClaudeDir, "marketplace.json"));
|
|
291
|
+
// openflow/ plugin package
|
|
292
|
+
const openflowSrc = join(coreDistRoot, "openflow");
|
|
293
|
+
const openflowDest = join(marketplaceDir, "openflow");
|
|
294
|
+
const allFiles = await collectFiles(openflowSrc);
|
|
295
|
+
for (const srcFile of allFiles) {
|
|
296
|
+
const relPath = relative(openflowSrc, srcFile);
|
|
297
|
+
const targetFile = join(openflowDest, relPath);
|
|
298
|
+
await mkdir(dirname(targetFile), { recursive: true });
|
|
299
|
+
await copyFile(srcFile, targetFile);
|
|
300
|
+
}
|
|
301
|
+
return marketplaceDir;
|
|
302
|
+
}
|
|
303
|
+
async function createFilteredPluginDir(coreDistRoot, selectedModules) {
|
|
304
|
+
const marketplaceDir = join(getClaudeCodeUserRoot(), "plugins", "marketplaces", "openflow");
|
|
305
|
+
if (existsSync(marketplaceDir)) {
|
|
306
|
+
await rm(marketplaceDir, { recursive: true, force: true });
|
|
307
|
+
}
|
|
308
|
+
await mkdir(marketplaceDir, { recursive: true });
|
|
309
|
+
// .claude-plugin/marketplace.json at marketplace root
|
|
310
|
+
const mktClaudeDir = join(marketplaceDir, ".claude-plugin");
|
|
311
|
+
await mkdir(mktClaudeDir, { recursive: true });
|
|
312
|
+
await copyFile(join(coreDistRoot, "marketplace.json"), join(mktClaudeDir, "marketplace.json"));
|
|
313
|
+
// Filter and copy openflow/ plugin package
|
|
314
|
+
const openflowSrc = join(coreDistRoot, "openflow");
|
|
315
|
+
const openflowDest = join(marketplaceDir, "openflow");
|
|
316
|
+
await mkdir(openflowDest, { recursive: true });
|
|
317
|
+
const modulesJsonPath = join(coreDistRoot, "modules.json");
|
|
318
|
+
const allowedFilesMap = await computeAllowedFiles(modulesJsonPath, selectedModules);
|
|
319
|
+
const filteredDirs = new Set(["skills", "agents", "commands"]);
|
|
320
|
+
const allSourceFiles = await collectFiles(openflowSrc);
|
|
321
|
+
for (const srcFile of allSourceFiles) {
|
|
322
|
+
const relPath = relative(openflowSrc, srcFile);
|
|
323
|
+
const parts = relPath.split(/[/\\]/);
|
|
324
|
+
const topDir = parts[0];
|
|
325
|
+
if (filteredDirs.has(topDir)) {
|
|
326
|
+
const allowed = allowedFilesMap.get(topDir);
|
|
327
|
+
if (allowed !== undefined) {
|
|
328
|
+
const itemName = parts[1]?.replace(/\.(md|cjs|mjs|js|ts)$/, "");
|
|
329
|
+
if (!itemName || !allowed.has(itemName)) {
|
|
330
|
+
continue;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
const targetFile = join(openflowDest, relPath);
|
|
335
|
+
await mkdir(dirname(targetFile), { recursive: true });
|
|
336
|
+
await copyFile(srcFile, targetFile);
|
|
337
|
+
}
|
|
338
|
+
return marketplaceDir;
|
|
339
|
+
}
|
|
340
|
+
async function installPlugin(options) {
|
|
341
|
+
const coreDistRoot = getCoreDistRoot();
|
|
342
|
+
// Build a filtered plugin dir if specific modules were selected, otherwise use dist/ directly
|
|
343
|
+
let marketplaceDir;
|
|
344
|
+
if (options.modules && options.modules.length > 0) {
|
|
345
|
+
marketplaceDir = await createFilteredPluginDir(coreDistRoot, options.modules);
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// Use dist/ directly as marketplace: it has .claude-plugin/marketplace.json (via symlink/copy)
|
|
349
|
+
// We need to assemble a proper marketplace dir with .claude-plugin/marketplace.json + openflow/
|
|
350
|
+
marketplaceDir = await assembleMarketplaceDir(coreDistRoot);
|
|
351
|
+
}
|
|
352
|
+
// Step 1: Register local marketplace — Claude CLI requires ./relative path format
|
|
353
|
+
const marketplaceArg = toLocalMarketplacePath(marketplaceDir);
|
|
354
|
+
console.log(` ${colorText("muted", t("init.stepMarketplace") + "...")}`);
|
|
355
|
+
try {
|
|
356
|
+
await execClaudeAsync(["plugin", "marketplace", "add", marketplaceArg]);
|
|
357
|
+
}
|
|
358
|
+
catch (err) {
|
|
359
|
+
// Only treat ENOENT as "claude not installed"; other errors come from the marketplace command itself
|
|
360
|
+
if (isRecord(err) && err.code === "ENOENT") {
|
|
361
|
+
throw new Error(t("init.errorClaudeCliMissing"));
|
|
362
|
+
}
|
|
363
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
364
|
+
throw new Error(t("init.errorMarketplaceAdd", { message }));
|
|
365
|
+
}
|
|
366
|
+
// Step 2: Install plugin from marketplace
|
|
367
|
+
console.log(` ${colorText("muted", t("init.stepPluginInstall") + "...")}`);
|
|
368
|
+
try {
|
|
369
|
+
await execClaudeAsync(["plugin", "install", "openflow@openflow", "--scope", "user"]);
|
|
370
|
+
}
|
|
371
|
+
catch (err) {
|
|
372
|
+
if (isMissingExecutableError(err)) {
|
|
373
|
+
throw new Error(t("init.errorClaudeCliMissing"));
|
|
374
|
+
}
|
|
375
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
376
|
+
throw new Error(t("init.errorPluginInstall", { message }));
|
|
377
|
+
}
|
|
378
|
+
// Step 3: Verify installation
|
|
379
|
+
console.log(` ${colorText("muted", t("init.stepVerify") + "...")}`);
|
|
380
|
+
await verifyPluginInstall();
|
|
381
|
+
printPanel(t("init.panelPlugin"), [
|
|
382
|
+
["plugin", "openflow"],
|
|
383
|
+
["marketplace", marketplaceDir],
|
|
384
|
+
["scope", "user"]
|
|
385
|
+
]);
|
|
386
|
+
return {
|
|
387
|
+
format: "plugin",
|
|
388
|
+
adapter: options.adapter,
|
|
389
|
+
targetPath: options.targetPath,
|
|
390
|
+
files: [],
|
|
391
|
+
marketplacePath: marketplaceDir,
|
|
392
|
+
pluginId: "openflow@openflow",
|
|
393
|
+
scope: "user"
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
async function verifyPluginInstall() {
|
|
397
|
+
const errors = [];
|
|
398
|
+
try {
|
|
399
|
+
const { stdout } = await execClaudeAsync(["plugin", "list", "--json"], { captureOutput: true });
|
|
400
|
+
const trimmed = stdout.trim();
|
|
401
|
+
// Detect non-JSON output early (e.g. AI chat response from claude CLI)
|
|
402
|
+
if (trimmed.length > 0 && !trimmed.startsWith("[") && !trimmed.startsWith("{")) {
|
|
403
|
+
throw new Error(t("init.errorPluginOutput"));
|
|
404
|
+
}
|
|
405
|
+
const plugins = parseJsonFromClaudeOutput(trimmed);
|
|
406
|
+
if (Array.isArray(plugins) && plugins.some((plugin) => isRecord(plugin) && plugin.id === "openflow@openflow" && plugin.enabled !== false)) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
412
|
+
}
|
|
413
|
+
try {
|
|
414
|
+
const userSettings = await readJsonObjectIfExists(join(getClaudeCodeUserRoot(), "settings.json"));
|
|
415
|
+
if (userSettings.exists &&
|
|
416
|
+
userSettings.valid &&
|
|
417
|
+
isRecord(userSettings.value.enabledPlugins) &&
|
|
418
|
+
userSettings.value.enabledPlugins["openflow@openflow"] === true) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
catch (err) {
|
|
423
|
+
errors.push(err instanceof Error ? err.message : String(err));
|
|
424
|
+
}
|
|
425
|
+
const message = errors.length > 0
|
|
426
|
+
? errors.join("; ")
|
|
427
|
+
: "openflow@openflow was not listed after installation.";
|
|
428
|
+
throw new Error(t("init.errorPluginVerify", { message }));
|
|
429
|
+
}
|
|
430
|
+
function parseJsonFromClaudeOutput(output) {
|
|
431
|
+
const trimmed = output.trim();
|
|
432
|
+
try {
|
|
433
|
+
return JSON.parse(trimmed);
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
const start = trimmed.search(/[\[{]/);
|
|
437
|
+
if (start >= 0) {
|
|
438
|
+
const candidate = trimmed.slice(start);
|
|
439
|
+
try {
|
|
440
|
+
return JSON.parse(candidate);
|
|
441
|
+
}
|
|
442
|
+
catch {
|
|
443
|
+
// Report the original parse error below; the prefix was not the only issue.
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
throw err;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
async function execClaudeAsync(args, options = {}) {
|
|
450
|
+
const commandFromEnv = process.env[CLAUDE_BIN_ENV];
|
|
451
|
+
const command = commandFromEnv ?? "claude";
|
|
452
|
+
const prefixArgs = parseClaudeBinArgs();
|
|
453
|
+
const commandArgs = [...prefixArgs, ...args];
|
|
454
|
+
const execOptions = { timeout: 60_000 };
|
|
455
|
+
if (process.platform === "win32" && (!commandFromEnv || /\.(cmd|bat)$/i.test(command))) {
|
|
456
|
+
const commandLine = [quoteCmdCommand(command), ...commandArgs.map(quoteCmdArg)].join(" ");
|
|
457
|
+
const result = await execFileAsync(process.env.ComSpec ?? "cmd.exe", ["/d", "/c", commandLine], execOptions);
|
|
458
|
+
return options.captureOutput ? result : undefined;
|
|
459
|
+
}
|
|
460
|
+
const result = await execFileAsync(command, commandArgs, execOptions);
|
|
461
|
+
return options.captureOutput ? result : undefined;
|
|
462
|
+
}
|
|
463
|
+
function isMissingExecutableError(error) {
|
|
464
|
+
if (isRecord(error) && error.code === "ENOENT") {
|
|
465
|
+
return true;
|
|
466
|
+
}
|
|
467
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
468
|
+
return /not recognized as an internal or external command|not found|system cannot find|找不到|不是内部或外部命令|系统找不到/.test(message);
|
|
469
|
+
}
|
|
470
|
+
function quoteCmdArg(value) {
|
|
471
|
+
// Only quote arguments that contain spaces or special shell characters.
|
|
472
|
+
// Over-quoting simple args like "plugin" "list" "--json" causes cmd.exe /c
|
|
473
|
+
// to pass them to claude as a prompt string instead of subcommand args.
|
|
474
|
+
if (/^[A-Za-z0-9_.@:/\\-]+$/.test(value)) {
|
|
475
|
+
return value;
|
|
476
|
+
}
|
|
477
|
+
return `"${value.replaceAll("%", "%%").replaceAll('"', '\\"')}"`;
|
|
478
|
+
}
|
|
479
|
+
function quoteCmdCommand(value) {
|
|
480
|
+
return /^[A-Za-z0-9_.-]+$/.test(value) ? value : quoteCmdArg(value);
|
|
481
|
+
}
|
|
482
|
+
function parseClaudeBinArgs() {
|
|
483
|
+
const raw = process.env[CLAUDE_BIN_ARGS_ENV];
|
|
484
|
+
if (!raw) {
|
|
485
|
+
return [];
|
|
486
|
+
}
|
|
487
|
+
const value = JSON.parse(raw);
|
|
488
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
489
|
+
throw new Error(`${CLAUDE_BIN_ARGS_ENV} must be a JSON array of strings.`);
|
|
490
|
+
}
|
|
491
|
+
return value;
|
|
492
|
+
}
|
|
493
|
+
async function updateAdapter(options) {
|
|
494
|
+
const targetRoot = options.targetPath;
|
|
495
|
+
const manifest = await readInstallManifest(targetRoot);
|
|
496
|
+
const files = await updateManagedAdapterFiles(targetRoot, manifest, options);
|
|
497
|
+
files.push(await updateClaudeProjectMcpConfig(targetRoot, options));
|
|
498
|
+
const configStatus = await mergeProjectConfigDefaults(targetRoot, options.dryRun);
|
|
499
|
+
const hasConflicts = files.some((file) => file.status === "conflict" || file.status === "would-conflict");
|
|
500
|
+
if (!options.dryRun && !hasConflicts) {
|
|
501
|
+
await writeInstallManifest(targetRoot, options.adapter);
|
|
502
|
+
}
|
|
503
|
+
return {
|
|
504
|
+
adapter: options.adapter,
|
|
505
|
+
targetPath: targetRoot,
|
|
506
|
+
files,
|
|
507
|
+
configStatus,
|
|
508
|
+
manifestStatus: !options.dryRun && !hasConflicts ? "written" : "skipped"
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Resolves the path to platform-specific artifacts bundled inside this package.
|
|
513
|
+
* Core dist is copied into cli/dist/core during build.
|
|
514
|
+
*/
|
|
515
|
+
function getCoreDistRoot() {
|
|
516
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
517
|
+
return join(thisDir, "..", "core-artifacts");
|
|
518
|
+
}
|
|
519
|
+
async function computeAllowedFiles(modulesJsonPath, selectedModules) {
|
|
520
|
+
if (!selectedModules || selectedModules.length === 0) {
|
|
521
|
+
// No filter — return empty map, allowedFiles.get() returns undefined = allow all
|
|
522
|
+
return new Map();
|
|
523
|
+
}
|
|
524
|
+
const result = new Map();
|
|
525
|
+
result.set("skills", new Set());
|
|
526
|
+
result.set("agents", new Set());
|
|
527
|
+
result.set("commands", new Set());
|
|
528
|
+
result.set("hooks", new Set());
|
|
529
|
+
if (!existsSync(modulesJsonPath)) {
|
|
530
|
+
return result;
|
|
531
|
+
}
|
|
532
|
+
const modulesJson = JSON.parse(await readFile(modulesJsonPath, "utf8"));
|
|
533
|
+
for (const modId of selectedModules) {
|
|
534
|
+
const mod = modulesJson.modules[modId];
|
|
535
|
+
if (!mod)
|
|
536
|
+
continue;
|
|
537
|
+
for (const category of ["skills", "agents", "commands", "hooks"]) {
|
|
538
|
+
const items = mod[category] ?? [];
|
|
539
|
+
const set = result.get(category);
|
|
540
|
+
if (set) {
|
|
541
|
+
for (const item of items) {
|
|
542
|
+
set.add(item);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return result;
|
|
548
|
+
}
|
|
549
|
+
function getCliTemplateRoot() {
|
|
550
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
551
|
+
return join(thisDir, "..", "core-artifacts", "templates");
|
|
552
|
+
}
|
|
553
|
+
function getClaudeCodeUserRoot() {
|
|
554
|
+
return process.env.OPENFLOW_CLAUDE_HOME ?? join(homedir(), ".claude");
|
|
555
|
+
}
|
|
556
|
+
async function copyMappedFiles(sourceRoot, targetRoot, displayRoot, force, allowedFiles) {
|
|
557
|
+
const files = [];
|
|
558
|
+
const sourceFiles = await collectFiles(sourceRoot);
|
|
559
|
+
for (const sourceFile of sourceFiles) {
|
|
560
|
+
const relativeSource = relative(sourceRoot, sourceFile);
|
|
561
|
+
// Filter by allowed files if specified
|
|
562
|
+
if (allowedFiles) {
|
|
563
|
+
// Extract the base directory name (e.g., "brainstorm" from "brainstorm/SKILL.md")
|
|
564
|
+
const parts = relativeSource.split(/[/\\]/);
|
|
565
|
+
const baseName = parts[0].replace(/\.(md|cjs|mjs|js|ts)$/, "");
|
|
566
|
+
if (!allowedFiles.has(baseName)) {
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
const targetFile = join(targetRoot, relativeSource);
|
|
571
|
+
const existed = existsSync(targetFile);
|
|
572
|
+
if (existed && !force) {
|
|
573
|
+
files.push({
|
|
574
|
+
source: relativeSource,
|
|
575
|
+
target: relative(displayRoot, targetFile),
|
|
576
|
+
status: "skipped"
|
|
577
|
+
});
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
await mkdir(dirname(targetFile), { recursive: true });
|
|
581
|
+
await copyFile(sourceFile, targetFile);
|
|
582
|
+
files.push({
|
|
583
|
+
source: relativeSource,
|
|
584
|
+
target: relative(displayRoot, targetFile),
|
|
585
|
+
status: existed ? "overwritten" : "created"
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
return files;
|
|
589
|
+
}
|
|
590
|
+
async function mergePluginMcpConfig(openflowPkgRoot, targetRoot, force) {
|
|
591
|
+
const mcpPath = join(targetRoot, ".mcp.json");
|
|
592
|
+
const target = relative(targetRoot, mcpPath);
|
|
593
|
+
const pluginMcpPath = join(openflowPkgRoot, ".mcp.json");
|
|
594
|
+
// Read plugin's .mcp.json to get the servers to merge
|
|
595
|
+
const pluginMcp = existsSync(pluginMcpPath)
|
|
596
|
+
? JSON.parse(await readFile(pluginMcpPath, "utf8"))
|
|
597
|
+
: null;
|
|
598
|
+
if (!pluginMcp || !isRecord(pluginMcp.mcpServers)) {
|
|
599
|
+
// Fallback: use hardcoded studio server
|
|
600
|
+
const mcpPath = join(targetRoot, ".mcp.json");
|
|
601
|
+
const target = relative(targetRoot, mcpPath);
|
|
602
|
+
const current = await readJsonObjectIfExists(mcpPath);
|
|
603
|
+
if (!current.exists) {
|
|
604
|
+
await writeJsonAtomic(mcpPath, createClaudeProjectMcpConfig());
|
|
605
|
+
return { source: "openflow/.mcp.json", target, status: "created" };
|
|
606
|
+
}
|
|
607
|
+
return { source: "openflow/.mcp.json", target, status: "skipped" };
|
|
608
|
+
}
|
|
609
|
+
// Transform plugin MCP servers: replace ${CLAUDE_PLUGIN_ROOT} with npx invocation
|
|
610
|
+
const servers = {};
|
|
611
|
+
for (const [name, serverDef] of Object.entries(pluginMcp.mcpServers)) {
|
|
612
|
+
if (!isRecord(serverDef))
|
|
613
|
+
continue;
|
|
614
|
+
// For copy mode, use npx-based invocation instead of plugin-relative paths
|
|
615
|
+
servers[name] = createClaudeProjectMcpServer();
|
|
616
|
+
}
|
|
617
|
+
const current = await readJsonObjectIfExists(mcpPath);
|
|
618
|
+
if (!current.exists) {
|
|
619
|
+
await writeJsonAtomic(mcpPath, { mcpServers: servers });
|
|
620
|
+
return { source: "openflow/.mcp.json", target, status: "created" };
|
|
621
|
+
}
|
|
622
|
+
if (!current.valid) {
|
|
623
|
+
return { source: "openflow/.mcp.json", target, status: "skipped" };
|
|
624
|
+
}
|
|
625
|
+
const existingServers = isRecord(current.value.mcpServers) ? current.value.mcpServers : {};
|
|
626
|
+
const hasAllServers = Object.keys(servers).every((k) => mcpServerEquals(existingServers[k], servers[k]));
|
|
627
|
+
if (hasAllServers) {
|
|
628
|
+
return { source: "openflow/.mcp.json", target, status: "skipped" };
|
|
629
|
+
}
|
|
630
|
+
if (!force && Object.keys(servers).some((k) => existingServers[k] !== undefined)) {
|
|
631
|
+
return { source: "openflow/.mcp.json", target, status: "skipped" };
|
|
632
|
+
}
|
|
633
|
+
await writeJsonAtomic(mcpPath, {
|
|
634
|
+
...current.value,
|
|
635
|
+
mcpServers: { ...existingServers, ...servers }
|
|
636
|
+
});
|
|
637
|
+
return { source: "openflow/.mcp.json", target, status: "overwritten" };
|
|
638
|
+
}
|
|
639
|
+
async function updateClaudeProjectMcpConfig(targetRoot, options) {
|
|
640
|
+
const mcpPath = join(targetRoot, ".mcp.json");
|
|
641
|
+
const target = relative(targetRoot, mcpPath);
|
|
642
|
+
const current = await readJsonObjectIfExists(mcpPath);
|
|
643
|
+
if (!current.exists) {
|
|
644
|
+
if (!options.dryRun) {
|
|
645
|
+
await writeJsonAtomic(mcpPath, createClaudeProjectMcpConfig());
|
|
646
|
+
}
|
|
647
|
+
return { source: "claude-code-mcp", target, status: options.dryRun ? "would-create" : "created" };
|
|
648
|
+
}
|
|
649
|
+
if (!current.valid) {
|
|
650
|
+
return { source: "claude-code-mcp", target, status: options.dryRun ? "would-conflict" : "conflict" };
|
|
651
|
+
}
|
|
652
|
+
const existingServer = readMcpServer(current.value, CLAUDE_PROJECT_MCP_SERVER_NAME);
|
|
653
|
+
const server = createClaudeProjectMcpServer();
|
|
654
|
+
if (mcpServerEquals(existingServer, server)) {
|
|
655
|
+
return { source: "claude-code-mcp", target, status: "unchanged" };
|
|
656
|
+
}
|
|
657
|
+
if (existingServer !== undefined && !options.force) {
|
|
658
|
+
return { source: "claude-code-mcp", target, status: options.dryRun ? "would-conflict" : "conflict" };
|
|
659
|
+
}
|
|
660
|
+
if (!options.dryRun) {
|
|
661
|
+
await writeJsonAtomic(mcpPath, mergeClaudeProjectMcpConfig(current.value));
|
|
662
|
+
}
|
|
663
|
+
return { source: "claude-code-mcp", target, status: options.dryRun ? "would-update" : "updated" };
|
|
664
|
+
}
|
|
665
|
+
function createClaudeProjectMcpConfig() {
|
|
666
|
+
return {
|
|
667
|
+
mcpServers: {
|
|
668
|
+
[CLAUDE_PROJECT_MCP_SERVER_NAME]: createClaudeProjectMcpServer()
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
function mergeClaudeProjectMcpConfig(current) {
|
|
673
|
+
const mcpServers = isRecord(current.mcpServers) ? current.mcpServers : {};
|
|
674
|
+
return {
|
|
675
|
+
...current,
|
|
676
|
+
mcpServers: {
|
|
677
|
+
...mcpServers,
|
|
678
|
+
[CLAUDE_PROJECT_MCP_SERVER_NAME]: createClaudeProjectMcpServer()
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
}
|
|
682
|
+
function createClaudeProjectMcpServer() {
|
|
683
|
+
if (process.platform === "win32") {
|
|
684
|
+
return {
|
|
685
|
+
type: "stdio",
|
|
686
|
+
command: "cmd",
|
|
687
|
+
args: ["/c", "npx", "-y", "@openflowjs/cli", "mcp", "review"]
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
return {
|
|
691
|
+
type: "stdio",
|
|
692
|
+
command: "npx",
|
|
693
|
+
args: ["-y", "@openflowjs/cli", "mcp", "review"]
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
function readMcpServer(config, name) {
|
|
697
|
+
return isRecord(config.mcpServers) ? config.mcpServers[name] : undefined;
|
|
698
|
+
}
|
|
699
|
+
function mcpServerEquals(left, right) {
|
|
700
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
701
|
+
}
|
|
702
|
+
async function updateManagedAdapterFiles(targetRoot, manifest, options) {
|
|
703
|
+
const entries = await collectManagedAdapterEntries(targetRoot);
|
|
704
|
+
const files = [];
|
|
705
|
+
for (const entry of entries) {
|
|
706
|
+
const existed = existsSync(entry.targetFile);
|
|
707
|
+
const target = relative(targetRoot, entry.targetFile);
|
|
708
|
+
if (!existed) {
|
|
709
|
+
files.push({
|
|
710
|
+
source: entry.source,
|
|
711
|
+
target,
|
|
712
|
+
status: options.dryRun ? "would-create" : "created"
|
|
713
|
+
});
|
|
714
|
+
if (!options.dryRun) {
|
|
715
|
+
await mkdir(dirname(entry.targetFile), { recursive: true });
|
|
716
|
+
await copyFile(entry.sourceFile, entry.targetFile);
|
|
717
|
+
}
|
|
718
|
+
continue;
|
|
719
|
+
}
|
|
720
|
+
const sourceSha = await sha256File(entry.sourceFile);
|
|
721
|
+
const targetSha = await sha256File(entry.targetFile);
|
|
722
|
+
if (sourceSha === targetSha) {
|
|
723
|
+
files.push({ source: entry.source, target, status: "unchanged" });
|
|
724
|
+
continue;
|
|
725
|
+
}
|
|
726
|
+
const knownSha = manifest?.files[target]?.sha256;
|
|
727
|
+
const canOverwrite = options.force || knownSha === targetSha;
|
|
728
|
+
if (!canOverwrite) {
|
|
729
|
+
files.push({
|
|
730
|
+
source: entry.source,
|
|
731
|
+
target,
|
|
732
|
+
status: options.dryRun ? "would-conflict" : "conflict"
|
|
733
|
+
});
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
files.push({
|
|
737
|
+
source: entry.source,
|
|
738
|
+
target,
|
|
739
|
+
status: options.dryRun ? "would-update" : "updated"
|
|
740
|
+
});
|
|
741
|
+
if (!options.dryRun) {
|
|
742
|
+
await copyFile(entry.sourceFile, entry.targetFile);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
return files;
|
|
746
|
+
}
|
|
747
|
+
async function collectManagedAdapterEntries(targetRoot) {
|
|
748
|
+
const openflowPkgRoot = join(getCoreDistRoot(), "openflow");
|
|
749
|
+
const adapterMappings = [
|
|
750
|
+
["commands", "commands"],
|
|
751
|
+
["skills", "skills"],
|
|
752
|
+
["agents", "agents"],
|
|
753
|
+
];
|
|
754
|
+
const entries = [];
|
|
755
|
+
for (const [sourceDir, targetDir] of adapterMappings) {
|
|
756
|
+
const sourceRoot = join(openflowPkgRoot, sourceDir);
|
|
757
|
+
const sourceFiles = await collectFiles(sourceRoot);
|
|
758
|
+
for (const sourceFile of sourceFiles) {
|
|
759
|
+
const relativeSource = relative(sourceRoot, sourceFile);
|
|
760
|
+
entries.push({
|
|
761
|
+
source: `${sourceDir}/${relativeSource.replace(/\\/g, "/")}`,
|
|
762
|
+
sourceFile,
|
|
763
|
+
targetFile: join(targetRoot, ".claude", targetDir, relativeSource)
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
return entries;
|
|
768
|
+
}
|
|
769
|
+
async function readInstallManifest(targetRoot) {
|
|
770
|
+
const manifestPath = join(targetRoot, INSTALL_MANIFEST_PATH);
|
|
771
|
+
if (!existsSync(manifestPath)) {
|
|
772
|
+
return undefined;
|
|
773
|
+
}
|
|
774
|
+
const value = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
775
|
+
if (!isRecord(value) || value.version !== 1 || value.adapter !== "claude-code" || !isRecord(value.files)) {
|
|
776
|
+
return undefined;
|
|
777
|
+
}
|
|
778
|
+
const files = {};
|
|
779
|
+
for (const [path, entry] of Object.entries(value.files)) {
|
|
780
|
+
if (isRecord(entry) && typeof entry.sha256 === "string") {
|
|
781
|
+
files[path] = { sha256: entry.sha256 };
|
|
782
|
+
}
|
|
783
|
+
}
|
|
784
|
+
return {
|
|
785
|
+
version: 1,
|
|
786
|
+
adapter: "claude-code",
|
|
787
|
+
installedAt: typeof value.installedAt === "string" ? value.installedAt : "",
|
|
788
|
+
files
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
async function writeInstallManifest(targetRoot, adapter) {
|
|
792
|
+
const entries = await collectManagedAdapterEntries(targetRoot);
|
|
793
|
+
const files = {};
|
|
794
|
+
for (const entry of entries) {
|
|
795
|
+
if (!existsSync(entry.targetFile)) {
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
files[relative(targetRoot, entry.targetFile)] = {
|
|
799
|
+
sha256: await sha256File(entry.targetFile)
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
await writeJsonAtomic(join(targetRoot, INSTALL_MANIFEST_PATH), {
|
|
803
|
+
version: 1,
|
|
804
|
+
adapter,
|
|
805
|
+
installedAt: new Date().toISOString(),
|
|
806
|
+
files
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
async function mergeProjectConfigDefaults(targetPath, dryRun) {
|
|
810
|
+
const configPath = join(targetPath, ".openflow", "config.json");
|
|
811
|
+
const template = JSON.parse(await readFile(join(getCliTemplateRoot(), "config.json"), "utf8"));
|
|
812
|
+
if (!existsSync(configPath)) {
|
|
813
|
+
if (!dryRun) {
|
|
814
|
+
await writeJsonAtomic(configPath, template);
|
|
815
|
+
}
|
|
816
|
+
return dryRun ? "would-create" : "created";
|
|
817
|
+
}
|
|
818
|
+
const { readProjectConfig } = await import("./config.js");
|
|
819
|
+
const current = await readProjectConfig(targetPath);
|
|
820
|
+
const merged = mergeMissingConfigDefaults(current, template);
|
|
821
|
+
if (JSON.stringify(current) === JSON.stringify(merged)) {
|
|
822
|
+
return "unchanged";
|
|
823
|
+
}
|
|
824
|
+
if (!dryRun) {
|
|
825
|
+
await writeJsonAtomic(configPath, merged);
|
|
826
|
+
}
|
|
827
|
+
return dryRun ? "would-merge" : "merged";
|
|
828
|
+
}
|
|
829
|
+
function mergeMissingConfigDefaults(current, defaults) {
|
|
830
|
+
const merged = { ...current };
|
|
831
|
+
for (const [key, value] of Object.entries(defaults)) {
|
|
832
|
+
if (!(key in merged)) {
|
|
833
|
+
merged[key] = value;
|
|
834
|
+
continue;
|
|
835
|
+
}
|
|
836
|
+
if (isRecord(merged[key]) && isRecord(value)) {
|
|
837
|
+
merged[key] = mergeMissingConfigDefaults(merged[key], value);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
return merged;
|
|
841
|
+
}
|
|
842
|
+
async function promptAdapterType() {
|
|
843
|
+
const answer = await promptChoice(t("init.adapterType"), [t("init.adapterCopy"), t("init.adapterPlugin"), t("init.adapterOpencode")], "1");
|
|
844
|
+
if (answer === "2")
|
|
845
|
+
return "plugin";
|
|
846
|
+
if (answer === "3")
|
|
847
|
+
return "opencode";
|
|
848
|
+
return "claude-code";
|
|
849
|
+
}
|
|
850
|
+
async function promptScope() {
|
|
851
|
+
const answer = await promptChoice(t("init.installLocation"), [t("init.installLocal"), t("init.installGlobal")], "1");
|
|
852
|
+
return answer === "2" ? "global" : "project";
|
|
853
|
+
}
|
|
854
|
+
async function promptLanguage() {
|
|
855
|
+
const answer = await promptChoice("Interface language", ["English (en-US)", "Chinese (zh-CN)"], "1");
|
|
856
|
+
setLocale(INIT_LANGUAGE_CHOICES[Number(answer) - 1] ?? "en-US");
|
|
857
|
+
return INIT_LANGUAGE_CHOICES[Number(answer) - 1] ?? "en-US";
|
|
858
|
+
}
|
|
859
|
+
async function promptModules() {
|
|
860
|
+
const items = [
|
|
861
|
+
{ id: "core", label: t("init.moduleCore"), desc: t("init.moduleCoreDesc"), checked: true, required: true },
|
|
862
|
+
{ id: "brainstorm-prd", label: t("init.moduleBrainstormPrd"), desc: t("init.moduleBrainstormPrdDesc"), checked: false, required: false },
|
|
863
|
+
];
|
|
864
|
+
const input = process.stdin;
|
|
865
|
+
const output = process.stdout;
|
|
866
|
+
if (!input.isTTY) {
|
|
867
|
+
return items.filter((item) => item.checked).map((item) => item.id);
|
|
868
|
+
}
|
|
869
|
+
let selectedIndex = 0;
|
|
870
|
+
let renderedLines = 0;
|
|
871
|
+
emitKeypressEvents(input);
|
|
872
|
+
const wasRaw = input.isRaw;
|
|
873
|
+
function render(initial = false) {
|
|
874
|
+
if (!initial) {
|
|
875
|
+
moveCursor(output, 0, -renderedLines);
|
|
876
|
+
cursorTo(output, 0);
|
|
877
|
+
clearScreenDown(output);
|
|
878
|
+
}
|
|
879
|
+
const lines = [];
|
|
880
|
+
for (let i = 0; i < items.length; i++) {
|
|
881
|
+
const item = items[i];
|
|
882
|
+
const cursor = i === selectedIndex ? ">" : " ";
|
|
883
|
+
const check = item.checked ? "x" : " ";
|
|
884
|
+
const req = item.required ? ` ${t("init.moduleRequired")}` : "";
|
|
885
|
+
lines.push(`${cursor} [${check}] ${item.label}${req} - ${item.desc}`);
|
|
886
|
+
}
|
|
887
|
+
lines.push(colorText("muted", t("init.moduleCheckboxHint")));
|
|
888
|
+
output.write(`${lines.join("\n")}\n`);
|
|
889
|
+
renderedLines = lines.length;
|
|
890
|
+
}
|
|
891
|
+
try {
|
|
892
|
+
input.setRawMode(true);
|
|
893
|
+
input.resume();
|
|
894
|
+
render(true);
|
|
895
|
+
return await new Promise((resolve, reject) => {
|
|
896
|
+
const onKeypress = (_text, key) => {
|
|
897
|
+
if ((key.ctrl && key.name === "c") || key.name === "escape") {
|
|
898
|
+
cleanup();
|
|
899
|
+
reject(new Error(t("init.cancelled")));
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
if (key.name === "up") {
|
|
903
|
+
selectedIndex = selectedIndex === 0 ? items.length - 1 : selectedIndex - 1;
|
|
904
|
+
render();
|
|
905
|
+
return;
|
|
906
|
+
}
|
|
907
|
+
if (key.name === "down") {
|
|
908
|
+
selectedIndex = selectedIndex === items.length - 1 ? 0 : selectedIndex + 1;
|
|
909
|
+
render();
|
|
910
|
+
return;
|
|
911
|
+
}
|
|
912
|
+
if (key.name === "space") {
|
|
913
|
+
if (!items[selectedIndex].required) {
|
|
914
|
+
items[selectedIndex].checked = !items[selectedIndex].checked;
|
|
915
|
+
render();
|
|
916
|
+
}
|
|
917
|
+
return;
|
|
918
|
+
}
|
|
919
|
+
if (key.name === "return" || key.name === "enter") {
|
|
920
|
+
cleanup();
|
|
921
|
+
output.write("\n");
|
|
922
|
+
resolve(items.filter((item) => item.checked).map((item) => item.id));
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
};
|
|
926
|
+
const cleanup = () => {
|
|
927
|
+
input.off("keypress", onKeypress);
|
|
928
|
+
input.setRawMode(wasRaw);
|
|
929
|
+
if (!wasRaw) {
|
|
930
|
+
input.pause();
|
|
931
|
+
}
|
|
932
|
+
};
|
|
933
|
+
input.on("keypress", onKeypress);
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
finally {
|
|
937
|
+
if (input.isRaw !== wasRaw) {
|
|
938
|
+
input.setRawMode(wasRaw);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
async function promptChoice(title, labels, defaultValue) {
|
|
943
|
+
const defaultIndex = Number(defaultValue) - 1;
|
|
944
|
+
let selectedIndex = Math.min(Math.max(defaultIndex, 0), labels.length - 1);
|
|
945
|
+
let renderedLines = 0;
|
|
946
|
+
const input = process.stdin;
|
|
947
|
+
const output = process.stdout;
|
|
948
|
+
if (!input.isTTY) {
|
|
949
|
+
return String(selectedIndex + 1);
|
|
950
|
+
}
|
|
951
|
+
emitKeypressEvents(input);
|
|
952
|
+
const wasRaw = input.isRaw;
|
|
953
|
+
function render(initial = false) {
|
|
954
|
+
if (!initial) {
|
|
955
|
+
moveCursor(output, 0, -renderedLines);
|
|
956
|
+
cursorTo(output, 0);
|
|
957
|
+
clearScreenDown(output);
|
|
958
|
+
}
|
|
959
|
+
const lines = renderChoiceLines(title, labels, selectedIndex);
|
|
960
|
+
output.write(`${lines.join("\n")}\n`);
|
|
961
|
+
renderedLines = lines.length;
|
|
962
|
+
}
|
|
963
|
+
try {
|
|
964
|
+
input.setRawMode(true);
|
|
965
|
+
input.resume();
|
|
966
|
+
render(true);
|
|
967
|
+
return await new Promise((resolve, reject) => {
|
|
968
|
+
const onKeypress = (_text, key) => {
|
|
969
|
+
if ((key.ctrl && key.name === "c") || key.name === "escape") {
|
|
970
|
+
cleanup();
|
|
971
|
+
reject(new Error(t("init.cancelled")));
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
if (key.name === "up") {
|
|
975
|
+
selectedIndex = selectedIndex === 0 ? labels.length - 1 : selectedIndex - 1;
|
|
976
|
+
render();
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
if (key.name === "down") {
|
|
980
|
+
selectedIndex = selectedIndex === labels.length - 1 ? 0 : selectedIndex + 1;
|
|
981
|
+
render();
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
if (key.name === "return" || key.name === "enter") {
|
|
985
|
+
cleanup();
|
|
986
|
+
output.write("\n");
|
|
987
|
+
resolve(String(selectedIndex + 1));
|
|
988
|
+
return;
|
|
989
|
+
}
|
|
990
|
+
};
|
|
991
|
+
const cleanup = () => {
|
|
992
|
+
input.off("keypress", onKeypress);
|
|
993
|
+
input.setRawMode(wasRaw);
|
|
994
|
+
if (!wasRaw) {
|
|
995
|
+
input.pause();
|
|
996
|
+
}
|
|
997
|
+
};
|
|
998
|
+
input.on("keypress", onKeypress);
|
|
999
|
+
});
|
|
1000
|
+
}
|
|
1001
|
+
finally {
|
|
1002
|
+
if (input.isRaw !== wasRaw) {
|
|
1003
|
+
input.setRawMode(wasRaw);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
function renderChoiceLines(title, labels, selectedIndex) {
|
|
1008
|
+
return [
|
|
1009
|
+
formatTitle(title),
|
|
1010
|
+
...labels.map((label, index) => {
|
|
1011
|
+
const marker = index === selectedIndex ? ">" : " ";
|
|
1012
|
+
const number = `${index + 1}.`;
|
|
1013
|
+
return `${marker} ${number} ${label}`;
|
|
1014
|
+
}),
|
|
1015
|
+
colorText("muted", t("init.promptHint"))
|
|
1016
|
+
];
|
|
1017
|
+
}
|
|
1018
|
+
function normalizeInitLanguage(value) {
|
|
1019
|
+
if (typeof value !== "string") {
|
|
1020
|
+
return undefined;
|
|
1021
|
+
}
|
|
1022
|
+
const normalized = value.trim().toLowerCase();
|
|
1023
|
+
if (normalized === "zh" || normalized === "zh-cn" || normalized === "cn" || normalized === "chinese") {
|
|
1024
|
+
return "zh-CN";
|
|
1025
|
+
}
|
|
1026
|
+
if (normalized === "en" || normalized === "en-us" || normalized === "english") {
|
|
1027
|
+
return "en-US";
|
|
1028
|
+
}
|
|
1029
|
+
return undefined;
|
|
1030
|
+
}
|
|
1031
|
+
function printInstallResult(result) {
|
|
1032
|
+
console.log();
|
|
1033
|
+
console.log(formatTitle(t("init.title")));
|
|
1034
|
+
printKeyValue("adapter", result.adapter);
|
|
1035
|
+
printKeyValue("format", result.format);
|
|
1036
|
+
printKeyValue("target", result.targetPath);
|
|
1037
|
+
if (result.format === "plugin") {
|
|
1038
|
+
printKeyValue("plugin", result.pluginId);
|
|
1039
|
+
printKeyValue("marketplace", result.marketplacePath);
|
|
1040
|
+
printKeyValue("scope", result.scope);
|
|
1041
|
+
}
|
|
1042
|
+
if (result.format === "copy" && result.modules && result.modules.length > 0) {
|
|
1043
|
+
printKeyValue("modules", result.modules.join(", "));
|
|
1044
|
+
}
|
|
1045
|
+
console.log();
|
|
1046
|
+
for (const file of result.files) {
|
|
1047
|
+
printFileStatus(file.status, file.target);
|
|
1048
|
+
}
|
|
1049
|
+
const totalCount = result.files.length;
|
|
1050
|
+
if (totalCount > 0) {
|
|
1051
|
+
console.log();
|
|
1052
|
+
console.log(` ${colorText("muted", t("init.filesInstalled", { count: String(totalCount) }))}`);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
function printUpdateResult(result) {
|
|
1056
|
+
const counts = result.files.reduce((accumulator, file) => {
|
|
1057
|
+
accumulator[file.status] += 1;
|
|
1058
|
+
return accumulator;
|
|
1059
|
+
}, {
|
|
1060
|
+
created: 0,
|
|
1061
|
+
updated: 0,
|
|
1062
|
+
unchanged: 0,
|
|
1063
|
+
conflict: 0,
|
|
1064
|
+
"would-create": 0,
|
|
1065
|
+
"would-update": 0,
|
|
1066
|
+
"would-conflict": 0
|
|
1067
|
+
});
|
|
1068
|
+
printPanel(t("update.title"), [
|
|
1069
|
+
["adapter", result.adapter],
|
|
1070
|
+
["target", result.targetPath],
|
|
1071
|
+
[
|
|
1072
|
+
"summary",
|
|
1073
|
+
`created=${counts.created} updated=${counts.updated} unchanged=${counts.unchanged} conflict=${counts.conflict} ` +
|
|
1074
|
+
`would-create=${counts["would-create"]} would-update=${counts["would-update"]} would-conflict=${counts["would-conflict"]}`
|
|
1075
|
+
],
|
|
1076
|
+
["state", `config=${result.configStatus} manifest=${result.manifestStatus}`]
|
|
1077
|
+
]);
|
|
1078
|
+
for (const file of result.files) {
|
|
1079
|
+
printFileStatus(file.status, file.target);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
//# sourceMappingURL=init.js.map
|