@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.
Files changed (403) hide show
  1. package/dist/bin/openflow.d.ts +2 -0
  2. package/dist/bin/openflow.js +8 -0
  3. package/dist/bin/openflow.js.map +1 -0
  4. package/dist/commands/config.d.ts +2 -0
  5. package/dist/commands/config.js +38 -0
  6. package/dist/commands/config.js.map +1 -0
  7. package/dist/commands/flow.d.ts +1 -0
  8. package/dist/commands/flow.js +119 -0
  9. package/dist/commands/flow.js.map +1 -0
  10. package/dist/commands/init.d.ts +2 -0
  11. package/dist/commands/init.js +1082 -0
  12. package/dist/commands/init.js.map +1 -0
  13. package/dist/commands/iteration.d.ts +1 -0
  14. package/dist/commands/iteration.js +131 -0
  15. package/dist/commands/iteration.js.map +1 -0
  16. package/dist/commands/mcp.d.ts +1 -0
  17. package/dist/commands/mcp.js +12 -0
  18. package/dist/commands/mcp.js.map +1 -0
  19. package/dist/commands/module.d.ts +1 -0
  20. package/dist/commands/module.js +137 -0
  21. package/dist/commands/module.js.map +1 -0
  22. package/dist/commands/plan.d.ts +1 -0
  23. package/dist/commands/plan.js +111 -0
  24. package/dist/commands/plan.js.map +1 -0
  25. package/dist/commands/plugin.d.ts +1 -0
  26. package/dist/commands/plugin.js +246 -0
  27. package/dist/commands/plugin.js.map +1 -0
  28. package/dist/commands/preflight.d.ts +8 -0
  29. package/dist/commands/preflight.js +57 -0
  30. package/dist/commands/preflight.js.map +1 -0
  31. package/dist/commands/review.d.ts +1 -0
  32. package/dist/commands/review.js +145 -0
  33. package/dist/commands/review.js.map +1 -0
  34. package/dist/commands/state.d.ts +1 -0
  35. package/dist/commands/state.js +28 -0
  36. package/dist/commands/state.js.map +1 -0
  37. package/dist/commands/validate.d.ts +1 -0
  38. package/dist/commands/validate.js +310 -0
  39. package/dist/commands/validate.js.map +1 -0
  40. package/dist/core/artifacts.d.ts +140 -0
  41. package/dist/core/artifacts.js +809 -0
  42. package/dist/core/artifacts.js.map +1 -0
  43. package/dist/core/index.d.ts +12 -0
  44. package/dist/core/index.js +27 -0
  45. package/dist/core/index.js.map +1 -0
  46. package/dist/core-artifacts/marketplace.json +14 -0
  47. package/dist/core-artifacts/modules.json +20 -0
  48. package/dist/core-artifacts/openflow/.claude-plugin/plugin.json +8 -0
  49. package/dist/core-artifacts/openflow/.mcp.json +9 -0
  50. package/dist/core-artifacts/openflow/agents/openflow-artifact-reviewer.md +308 -0
  51. package/dist/core-artifacts/openflow/agents/openflow-code-reviewer.md +177 -0
  52. package/dist/core-artifacts/openflow/agents/openflow-executor-deep.md +119 -0
  53. package/dist/core-artifacts/openflow/agents/openflow-executor-general.md +104 -0
  54. package/dist/core-artifacts/openflow/agents/openflow-executor-quick.md +93 -0
  55. package/dist/core-artifacts/openflow/agents/openflow-explorer.md +69 -0
  56. package/dist/core-artifacts/openflow/agents/openflow-knowledge-curator.md +89 -0
  57. package/dist/core-artifacts/openflow/commands/knowledge.md +102 -0
  58. package/dist/core-artifacts/openflow/hooks/hooks.json +33 -0
  59. package/dist/core-artifacts/openflow/scripts/openflow-drift-guard.cjs +54 -0
  60. package/dist/core-artifacts/openflow/scripts/openflow-evidence-reminder.cjs +64 -0
  61. package/dist/core-artifacts/openflow/scripts/openflow-mcp-review.cjs +27 -0
  62. package/dist/core-artifacts/openflow/scripts/openflow-write-guard.cjs +27 -0
  63. package/dist/core-artifacts/openflow/scripts/session-start.cjs +12 -0
  64. package/dist/core-artifacts/openflow/skills/brainstorm/SKILL.md +131 -0
  65. package/dist/core-artifacts/openflow/skills/cli-reference/SKILL.md +196 -0
  66. package/dist/core-artifacts/openflow/skills/finalize/SKILL.md +109 -0
  67. package/dist/core-artifacts/openflow/skills/finalize/references/summary-template.md +39 -0
  68. package/dist/core-artifacts/openflow/skills/implement/SKILL.md +296 -0
  69. package/dist/core-artifacts/openflow/skills/implement/references/working-memory.md +49 -0
  70. package/dist/core-artifacts/openflow/skills/knowledge-retrieval/SKILL.md +78 -0
  71. package/dist/core-artifacts/openflow/skills/prd/SKILL.md +173 -0
  72. package/dist/core-artifacts/openflow/skills/prd/references/level-routing.md +94 -0
  73. package/dist/core-artifacts/openflow/skills/prd/references/prd-template.md +187 -0
  74. package/dist/core-artifacts/openflow/skills/prd/references/wireframe-template.html +122 -0
  75. package/dist/core-artifacts/openflow/skills/spec/SKILL.md +341 -0
  76. package/dist/core-artifacts/openflow/skills/spec/references/context-template.md +38 -0
  77. package/dist/core-artifacts/openflow/skills/spec/references/plan-template.md +61 -0
  78. package/dist/core-artifacts/openflow/skills/spec/references/spec-template.md +187 -0
  79. package/dist/core-artifacts/openflow/skills/spec/references/tasks-template.md +99 -0
  80. package/dist/core-artifacts/openflow/skills/workflow-governance/SKILL.md +384 -0
  81. package/dist/core-artifacts/openflow/skills/workflow-governance/references/knowledge-schema.md +241 -0
  82. package/dist/core-artifacts/openflow/skills/workflow-governance/references/state-files.md +148 -0
  83. package/dist/core-artifacts/openflow/skills/workflow-governance/references/workflow.md +119 -0
  84. package/dist/core-artifacts/templates/.gitkeep +0 -0
  85. package/dist/index.d.ts +4 -0
  86. package/dist/index.js +5 -0
  87. package/dist/index.js.map +1 -0
  88. package/dist/mcp/review-mcp-server.d.ts +1 -0
  89. package/dist/mcp/review-mcp-server.js +191 -0
  90. package/dist/mcp/review-mcp-server.js.map +1 -0
  91. package/dist/mcp/review-server.d.ts +33 -0
  92. package/dist/mcp/review-server.js +340 -0
  93. package/dist/mcp/review-server.js.map +1 -0
  94. package/dist/mcp/review-ui/assets/arc-DH58vMfF.js +1 -0
  95. package/dist/mcp/review-ui/assets/architecture-YZFGNWBL-CW8o5JQi.js +1 -0
  96. package/dist/mcp/review-ui/assets/architectureDiagram-Q4EWVU46-CH35GquJ.js +36 -0
  97. package/dist/mcp/review-ui/assets/array-BCJ35G43.js +1 -0
  98. package/dist/mcp/review-ui/assets/blockDiagram-DXYQGD6D-B1JZnKG_.js +132 -0
  99. package/dist/mcp/review-ui/assets/c4Diagram-AHTNJAMY-DCAtnxWd.js +10 -0
  100. package/dist/mcp/review-ui/assets/channel-BgHR4NPf.js +1 -0
  101. package/dist/mcp/review-ui/assets/chunk-2KRD3SAO-BkEfK915.js +1 -0
  102. package/dist/mcp/review-ui/assets/chunk-4BX2VUAB-Dn9kswJO.js +1 -0
  103. package/dist/mcp/review-ui/assets/chunk-4TB4RGXK-DbeI3ZO6.js +206 -0
  104. package/dist/mcp/review-ui/assets/chunk-55IACEB6-CLBoivXU.js +1 -0
  105. package/dist/mcp/review-ui/assets/chunk-5FUZZQ4R-DU7La6QA.js +62 -0
  106. package/dist/mcp/review-ui/assets/chunk-5PVQY5BW-Dy3eUu9a.js +2 -0
  107. package/dist/mcp/review-ui/assets/chunk-67CJDMHE-BKQ4iYAM.js +1 -0
  108. package/dist/mcp/review-ui/assets/chunk-7N4EOEYR-CUngSlME.js +1 -0
  109. package/dist/mcp/review-ui/assets/chunk-AA7GKIK3-BClDbXxt.js +1 -0
  110. package/dist/mcp/review-ui/assets/chunk-BSJP7CBP-BlpmbHL-.js +1 -0
  111. package/dist/mcp/review-ui/assets/chunk-CIAEETIT-THpBXcoN.js +1 -0
  112. package/dist/mcp/review-ui/assets/chunk-Dlc7tRH4.js +1 -0
  113. package/dist/mcp/review-ui/assets/chunk-EDXVE4YY-DNUlHz7M.js +1 -0
  114. package/dist/mcp/review-ui/assets/chunk-ENJZ2VHE-fwEKj0pQ.js +10 -0
  115. package/dist/mcp/review-ui/assets/chunk-FMBD7UC4-Cj8B2TLo.js +15 -0
  116. package/dist/mcp/review-ui/assets/chunk-FOC6F5B3-BtR_JW_A.js +1 -0
  117. package/dist/mcp/review-ui/assets/chunk-ICPOFSXX-WTr3HDYE.js +122 -0
  118. package/dist/mcp/review-ui/assets/chunk-K5T4RW27-vtP3ehR7.js +94 -0
  119. package/dist/mcp/review-ui/assets/chunk-KGLVRYIC-Di2tkB7O.js +1 -0
  120. package/dist/mcp/review-ui/assets/chunk-LIHQZDEY-DoHl9hYE.js +1 -0
  121. package/dist/mcp/review-ui/assets/chunk-ORNJ4GCN-Bff-Vc2X.js +1 -0
  122. package/dist/mcp/review-ui/assets/chunk-OYMX7WX6-Djey8TrX.js +231 -0
  123. package/dist/mcp/review-ui/assets/chunk-QZHKN3VN-C4w1Z4n9.js +1 -0
  124. package/dist/mcp/review-ui/assets/chunk-U2HBQHQK-D8HUikvJ.js +70 -0
  125. package/dist/mcp/review-ui/assets/chunk-X2U36JSP-CuZ-SN2r.js +1 -0
  126. package/dist/mcp/review-ui/assets/chunk-YZCP3GAM-D0-dHF3G.js +1 -0
  127. package/dist/mcp/review-ui/assets/chunk-ZZ45TVLE-C1aIZGDA.js +1 -0
  128. package/dist/mcp/review-ui/assets/classDiagram-6PBFFD2Q-DHrSK7zx.js +1 -0
  129. package/dist/mcp/review-ui/assets/classDiagram-v2-HSJHXN6E-ftN8ECVk.js +1 -0
  130. package/dist/mcp/review-ui/assets/clone-C3rjhi9V.js +1 -0
  131. package/dist/mcp/review-ui/assets/cose-bilkent-S5V4N54A-szpqu_3d.js +1 -0
  132. package/dist/mcp/review-ui/assets/cytoscape.esm-DZ22BVwz.js +321 -0
  133. package/dist/mcp/review-ui/assets/dagre-B4oIQbi5.js +1 -0
  134. package/dist/mcp/review-ui/assets/dagre-KV5264BT-zDsxU5-B.js +4 -0
  135. package/dist/mcp/review-ui/assets/defaultLocale-CIS5GEjP.js +1 -0
  136. package/dist/mcp/review-ui/assets/diagram-5BDNPKRD-UgfFjZ4o.js +10 -0
  137. package/dist/mcp/review-ui/assets/diagram-G4DWMVQ6-Wh9VCn50.js +24 -0
  138. package/dist/mcp/review-ui/assets/diagram-MMDJMWI5-xVD3G7_9.js +43 -0
  139. package/dist/mcp/review-ui/assets/diagram-TYMM5635-AUD291P2.js +24 -0
  140. package/dist/mcp/review-ui/assets/dist-B51l2n-9.js +1 -0
  141. package/dist/mcp/review-ui/assets/erDiagram-SMLLAGMA-B83D6NXm.js +85 -0
  142. package/dist/mcp/review-ui/assets/flatten-B80WBwOJ.js +1 -0
  143. package/dist/mcp/review-ui/assets/flowDiagram-DWJPFMVM-D3lXOeHD.js +162 -0
  144. package/dist/mcp/review-ui/assets/ganttDiagram-T4ZO3ILL-CFAN903o.js +292 -0
  145. package/dist/mcp/review-ui/assets/gitGraph-7Q5UKJZL-BfgkNWmC.js +1 -0
  146. package/dist/mcp/review-ui/assets/gitGraphDiagram-UUTBAWPF-DxqTOi4I.js +106 -0
  147. package/dist/mcp/review-ui/assets/graphlib-De-foo_H.js +1 -0
  148. package/dist/mcp/review-ui/assets/identity-CWMh0UL-.js +1 -0
  149. package/dist/mcp/review-ui/assets/index-Do0fBEfH.css +2 -0
  150. package/dist/mcp/review-ui/assets/index-uPMLqduV.js +123 -0
  151. package/dist/mcp/review-ui/assets/info-OMHHGYJF-DE18zZ5Z.js +1 -0
  152. package/dist/mcp/review-ui/assets/infoDiagram-42DDH7IO-Bnco1OGr.js +2 -0
  153. package/dist/mcp/review-ui/assets/init-BMBYmmUa.js +1 -0
  154. package/dist/mcp/review-ui/assets/ishikawaDiagram-UXIWVN3A-B89fugr9.js +70 -0
  155. package/dist/mcp/review-ui/assets/journeyDiagram-VCZTEJTY-CMx2w_is.js +139 -0
  156. package/dist/mcp/review-ui/assets/kanban-definition-6JOO6SKY-YvTOD1Vd.js +89 -0
  157. package/dist/mcp/review-ui/assets/katex-8mXVa4k3.js +257 -0
  158. package/dist/mcp/review-ui/assets/line-BCdBO-oK.js +1 -0
  159. package/dist/mcp/review-ui/assets/linear-d7UHSQqm.js +1 -0
  160. package/dist/mcp/review-ui/assets/mermaid-parser.core-DI1-3xL2.js +4 -0
  161. package/dist/mcp/review-ui/assets/mindmap-definition-QFDTVHPH-E_mV-_Fs.js +96 -0
  162. package/dist/mcp/review-ui/assets/ordinal-BDTCIhXR.js +1 -0
  163. package/dist/mcp/review-ui/assets/packet-4T2RLAQJ-BLPGKWDX.js +1 -0
  164. package/dist/mcp/review-ui/assets/path-CIRGLb_6.js +1 -0
  165. package/dist/mcp/review-ui/assets/pie-ZZUOXDRM-DVV6Yua9.js +1 -0
  166. package/dist/mcp/review-ui/assets/pieDiagram-DEJITSTG-Ct4JvywP.js +30 -0
  167. package/dist/mcp/review-ui/assets/quadrantDiagram-34T5L4WZ-BSFYvc1U.js +7 -0
  168. package/dist/mcp/review-ui/assets/radar-PYXPWWZC-BMkQDLKp.js +1 -0
  169. package/dist/mcp/review-ui/assets/reduce-C80XcylQ.js +1 -0
  170. package/dist/mcp/review-ui/assets/requirementDiagram-MS252O5E-Bp7uSYEK.js +84 -0
  171. package/dist/mcp/review-ui/assets/rough.esm-DtEqI08j.js +1 -0
  172. package/dist/mcp/review-ui/assets/sankeyDiagram-XADWPNL6-CV38ZpSv.js +10 -0
  173. package/dist/mcp/review-ui/assets/sequenceDiagram-FGHM5R23-BXN9jl1N.js +157 -0
  174. package/dist/mcp/review-ui/assets/src-Cxc1bu7b.js +1 -0
  175. package/dist/mcp/review-ui/assets/stateDiagram-FHFEXIEX-DZduDkIw.js +1 -0
  176. package/dist/mcp/review-ui/assets/stateDiagram-v2-QKLJ7IA2-xAWOcxSi.js +1 -0
  177. package/dist/mcp/review-ui/assets/timeline-definition-GMOUNBTQ-CLqXzNm8.js +120 -0
  178. package/dist/mcp/review-ui/assets/treeView-SZITEDCU-tPcANHUc.js +1 -0
  179. package/dist/mcp/review-ui/assets/treemap-W4RFUUIX-BGbXISSk.js +1 -0
  180. package/dist/mcp/review-ui/assets/vennDiagram-DHZGUBPP-gCnd0IYN.js +34 -0
  181. package/dist/mcp/review-ui/assets/wardley-RL74JXVD-CK3EfklM.js +1 -0
  182. package/dist/mcp/review-ui/assets/wardleyDiagram-NUSXRM2D-Dd7qMlPS.js +20 -0
  183. package/dist/mcp/review-ui/assets/xychartDiagram-5P7HB3ND-DXHXO8Zm.js +7 -0
  184. package/dist/mcp/review-ui/index.html +29 -0
  185. package/dist/mcp/studio/assets/arc-DH58vMfF.js +1 -0
  186. package/dist/mcp/studio/assets/architecture-YZFGNWBL-8xrwD39F.js +1 -0
  187. package/dist/mcp/studio/assets/architectureDiagram-Q4EWVU46-VmcLZTJf.js +36 -0
  188. package/dist/mcp/studio/assets/array-BCJ35G43.js +1 -0
  189. package/dist/mcp/studio/assets/blockDiagram-DXYQGD6D-D-1mlLYy.js +132 -0
  190. package/dist/mcp/studio/assets/c4Diagram-AHTNJAMY-DCAtnxWd.js +10 -0
  191. package/dist/mcp/studio/assets/channel-BgHR4NPf.js +1 -0
  192. package/dist/mcp/studio/assets/chunk-2KRD3SAO-CMDQx2WD.js +1 -0
  193. package/dist/mcp/studio/assets/chunk-4BX2VUAB-Dn9kswJO.js +1 -0
  194. package/dist/mcp/studio/assets/chunk-4TB4RGXK-aFEYGDkJ.js +206 -0
  195. package/dist/mcp/studio/assets/chunk-55IACEB6-CLBoivXU.js +1 -0
  196. package/dist/mcp/studio/assets/chunk-5FUZZQ4R-DU7La6QA.js +62 -0
  197. package/dist/mcp/studio/assets/chunk-5PVQY5BW-Dy3eUu9a.js +2 -0
  198. package/dist/mcp/studio/assets/chunk-67CJDMHE-DnkyJt7A.js +1 -0
  199. package/dist/mcp/studio/assets/chunk-7N4EOEYR-cnJ9dWSC.js +1 -0
  200. package/dist/mcp/studio/assets/chunk-AA7GKIK3-DjCZnyrT.js +1 -0
  201. package/dist/mcp/studio/assets/chunk-BSJP7CBP-BlpmbHL-.js +1 -0
  202. package/dist/mcp/studio/assets/chunk-CIAEETIT-CtvXSBsf.js +1 -0
  203. package/dist/mcp/studio/assets/chunk-Dlc7tRH4.js +1 -0
  204. package/dist/mcp/studio/assets/chunk-EDXVE4YY-DNUlHz7M.js +1 -0
  205. package/dist/mcp/studio/assets/chunk-ENJZ2VHE-fwEKj0pQ.js +10 -0
  206. package/dist/mcp/studio/assets/chunk-FMBD7UC4-Cj8B2TLo.js +15 -0
  207. package/dist/mcp/studio/assets/chunk-FOC6F5B3-Ca28VADd.js +1 -0
  208. package/dist/mcp/studio/assets/chunk-ICPOFSXX-WTr3HDYE.js +122 -0
  209. package/dist/mcp/studio/assets/chunk-K5T4RW27-pqiOLnBn.js +94 -0
  210. package/dist/mcp/studio/assets/chunk-KGLVRYIC-DZfGlR-G.js +1 -0
  211. package/dist/mcp/studio/assets/chunk-LIHQZDEY-6Ygb8Kwt.js +1 -0
  212. package/dist/mcp/studio/assets/chunk-ORNJ4GCN-DSlr7oSO.js +1 -0
  213. package/dist/mcp/studio/assets/chunk-OYMX7WX6-8z_2lCb3.js +231 -0
  214. package/dist/mcp/studio/assets/chunk-QZHKN3VN-C4w1Z4n9.js +1 -0
  215. package/dist/mcp/studio/assets/chunk-U2HBQHQK-D8HUikvJ.js +70 -0
  216. package/dist/mcp/studio/assets/chunk-X2U36JSP-CuZ-SN2r.js +1 -0
  217. package/dist/mcp/studio/assets/chunk-YZCP3GAM-D0-dHF3G.js +1 -0
  218. package/dist/mcp/studio/assets/chunk-ZZ45TVLE-C1aIZGDA.js +1 -0
  219. package/dist/mcp/studio/assets/classDiagram-6PBFFD2Q-IZXxqxqM.js +1 -0
  220. package/dist/mcp/studio/assets/classDiagram-v2-HSJHXN6E-BiJKwTXT.js +1 -0
  221. package/dist/mcp/studio/assets/clone-g4CuF1Hf.js +1 -0
  222. package/dist/mcp/studio/assets/cose-bilkent-S5V4N54A-szpqu_3d.js +1 -0
  223. package/dist/mcp/studio/assets/cytoscape.esm-DZ22BVwz.js +321 -0
  224. package/dist/mcp/studio/assets/dagre-Be9o0OzC.js +1 -0
  225. package/dist/mcp/studio/assets/dagre-KV5264BT-iB6PnHLr.js +4 -0
  226. package/dist/mcp/studio/assets/defaultLocale-CIS5GEjP.js +1 -0
  227. package/dist/mcp/studio/assets/diagram-5BDNPKRD-BLfWbiEB.js +10 -0
  228. package/dist/mcp/studio/assets/diagram-G4DWMVQ6-CgcnwgVO.js +24 -0
  229. package/dist/mcp/studio/assets/diagram-MMDJMWI5-CpkXvs2p.js +43 -0
  230. package/dist/mcp/studio/assets/diagram-TYMM5635-guxqmxjJ.js +24 -0
  231. package/dist/mcp/studio/assets/dist-B51l2n-9.js +1 -0
  232. package/dist/mcp/studio/assets/erDiagram-SMLLAGMA-Lwv-cC2Y.js +85 -0
  233. package/dist/mcp/studio/assets/flatten-Dv3Z_7XJ.js +1 -0
  234. package/dist/mcp/studio/assets/flowDiagram-DWJPFMVM-BKnaFfFR.js +162 -0
  235. package/dist/mcp/studio/assets/ganttDiagram-T4ZO3ILL-CFAN903o.js +292 -0
  236. package/dist/mcp/studio/assets/gitGraph-7Q5UKJZL-BSdEZNVc.js +1 -0
  237. package/dist/mcp/studio/assets/gitGraphDiagram-UUTBAWPF-D4z4QWni.js +106 -0
  238. package/dist/mcp/studio/assets/graphlib-C1IZi4Cg.js +1 -0
  239. package/dist/mcp/studio/assets/identity-CWMh0UL-.js +1 -0
  240. package/dist/mcp/studio/assets/index-CyBqHDpB.js +109 -0
  241. package/dist/mcp/studio/assets/index-Dn_Ujmba.css +2 -0
  242. package/dist/mcp/studio/assets/info-OMHHGYJF-CoTx64p3.js +1 -0
  243. package/dist/mcp/studio/assets/infoDiagram-42DDH7IO-QEji23sQ.js +2 -0
  244. package/dist/mcp/studio/assets/init-BMBYmmUa.js +1 -0
  245. package/dist/mcp/studio/assets/ishikawaDiagram-UXIWVN3A-lMurmqul.js +70 -0
  246. package/dist/mcp/studio/assets/journeyDiagram-VCZTEJTY-CMx2w_is.js +139 -0
  247. package/dist/mcp/studio/assets/kanban-definition-6JOO6SKY-DsOybLrS.js +89 -0
  248. package/dist/mcp/studio/assets/katex-8mXVa4k3.js +257 -0
  249. package/dist/mcp/studio/assets/line-BCdBO-oK.js +1 -0
  250. package/dist/mcp/studio/assets/linear-d7UHSQqm.js +1 -0
  251. package/dist/mcp/studio/assets/mermaid-parser.core-BZtTt4qJ.js +4 -0
  252. package/dist/mcp/studio/assets/mindmap-definition-QFDTVHPH-B2yfABR9.js +96 -0
  253. package/dist/mcp/studio/assets/ordinal-BDTCIhXR.js +1 -0
  254. package/dist/mcp/studio/assets/packet-4T2RLAQJ-Bi4IG7s8.js +1 -0
  255. package/dist/mcp/studio/assets/path-CIRGLb_6.js +1 -0
  256. package/dist/mcp/studio/assets/pie-ZZUOXDRM-DsJRjVcu.js +1 -0
  257. package/dist/mcp/studio/assets/pieDiagram-DEJITSTG-JeKGFs3r.js +30 -0
  258. package/dist/mcp/studio/assets/quadrantDiagram-34T5L4WZ-BSFYvc1U.js +7 -0
  259. package/dist/mcp/studio/assets/radar-PYXPWWZC-cUDYP2Ic.js +1 -0
  260. package/dist/mcp/studio/assets/reduce-x-wchVXY.js +1 -0
  261. package/dist/mcp/studio/assets/requirementDiagram-MS252O5E-CGeLKQyn.js +84 -0
  262. package/dist/mcp/studio/assets/rough.esm-DtEqI08j.js +1 -0
  263. package/dist/mcp/studio/assets/sankeyDiagram-XADWPNL6-CV38ZpSv.js +10 -0
  264. package/dist/mcp/studio/assets/sequenceDiagram-FGHM5R23-BbHPv3l1.js +157 -0
  265. package/dist/mcp/studio/assets/src-Cxc1bu7b.js +1 -0
  266. package/dist/mcp/studio/assets/stateDiagram-FHFEXIEX-BuBuguzn.js +1 -0
  267. package/dist/mcp/studio/assets/stateDiagram-v2-QKLJ7IA2-PQA-rl9o.js +1 -0
  268. package/dist/mcp/studio/assets/timeline-definition-GMOUNBTQ-D5xtyNE9.js +120 -0
  269. package/dist/mcp/studio/assets/treeView-SZITEDCU-DhRx0eaI.js +1 -0
  270. package/dist/mcp/studio/assets/treemap-W4RFUUIX-Btsj9DUH.js +1 -0
  271. package/dist/mcp/studio/assets/vennDiagram-DHZGUBPP-W4g15SMY.js +34 -0
  272. package/dist/mcp/studio/assets/wardley-RL74JXVD-BTpKsgl7.js +1 -0
  273. package/dist/mcp/studio/assets/wardleyDiagram-NUSXRM2D-f7wgXdwe.js +20 -0
  274. package/dist/mcp/studio/assets/xychartDiagram-5P7HB3ND-BWx9swPf.js +7 -0
  275. package/dist/mcp/studio/index.html +29 -0
  276. package/dist/review-mcp-server.d.ts +1 -0
  277. package/dist/review-mcp-server.js +178 -0
  278. package/dist/review-mcp-server.js.map +1 -0
  279. package/dist/review-server.d.ts +17 -0
  280. package/dist/review-server.js +223 -0
  281. package/dist/review-server.js.map +1 -0
  282. package/dist/review-ui/assets/arc-DH58vMfF.js +1 -0
  283. package/dist/review-ui/assets/architecture-YZFGNWBL-ChakYgFO.js +1 -0
  284. package/dist/review-ui/assets/architectureDiagram-Q4EWVU46-CcJOZCOb.js +36 -0
  285. package/dist/review-ui/assets/array-BCJ35G43.js +1 -0
  286. package/dist/review-ui/assets/blockDiagram-DXYQGD6D-H7mMv5Tv.js +132 -0
  287. package/dist/review-ui/assets/c4Diagram-AHTNJAMY-DCAtnxWd.js +10 -0
  288. package/dist/review-ui/assets/channel-BgHR4NPf.js +1 -0
  289. package/dist/review-ui/assets/chunk-2KRD3SAO-BfA3IkPQ.js +1 -0
  290. package/dist/review-ui/assets/chunk-4BX2VUAB-Dn9kswJO.js +1 -0
  291. package/dist/review-ui/assets/chunk-4TB4RGXK-CvTeZi33.js +206 -0
  292. package/dist/review-ui/assets/chunk-55IACEB6-CLBoivXU.js +1 -0
  293. package/dist/review-ui/assets/chunk-5FUZZQ4R-DU7La6QA.js +62 -0
  294. package/dist/review-ui/assets/chunk-5PVQY5BW-Dy3eUu9a.js +2 -0
  295. package/dist/review-ui/assets/chunk-67CJDMHE-BQ1xNHFx.js +1 -0
  296. package/dist/review-ui/assets/chunk-7N4EOEYR-B1ORNLQP.js +1 -0
  297. package/dist/review-ui/assets/chunk-AA7GKIK3-D3pS3mnx.js +1 -0
  298. package/dist/review-ui/assets/chunk-BSJP7CBP-BlpmbHL-.js +1 -0
  299. package/dist/review-ui/assets/chunk-CIAEETIT-BDZkAY47.js +1 -0
  300. package/dist/review-ui/assets/chunk-Dlc7tRH4.js +1 -0
  301. package/dist/review-ui/assets/chunk-EDXVE4YY-DNUlHz7M.js +1 -0
  302. package/dist/review-ui/assets/chunk-ENJZ2VHE-fwEKj0pQ.js +10 -0
  303. package/dist/review-ui/assets/chunk-FMBD7UC4-Cj8B2TLo.js +15 -0
  304. package/dist/review-ui/assets/chunk-FOC6F5B3-DGtCX5Ra.js +1 -0
  305. package/dist/review-ui/assets/chunk-ICPOFSXX-WTr3HDYE.js +122 -0
  306. package/dist/review-ui/assets/chunk-K5T4RW27-CWpdECLF.js +94 -0
  307. package/dist/review-ui/assets/chunk-KGLVRYIC-oI2XKaPz.js +1 -0
  308. package/dist/review-ui/assets/chunk-LIHQZDEY-Dzp3G35O.js +1 -0
  309. package/dist/review-ui/assets/chunk-ORNJ4GCN-DsHuVbPU.js +1 -0
  310. package/dist/review-ui/assets/chunk-OYMX7WX6-fgjoXAXJ.js +231 -0
  311. package/dist/review-ui/assets/chunk-QZHKN3VN-C4w1Z4n9.js +1 -0
  312. package/dist/review-ui/assets/chunk-U2HBQHQK-D8HUikvJ.js +70 -0
  313. package/dist/review-ui/assets/chunk-X2U36JSP-CuZ-SN2r.js +1 -0
  314. package/dist/review-ui/assets/chunk-YZCP3GAM-D0-dHF3G.js +1 -0
  315. package/dist/review-ui/assets/chunk-ZZ45TVLE-C1aIZGDA.js +1 -0
  316. package/dist/review-ui/assets/classDiagram-6PBFFD2Q-D_3LhkJc.js +1 -0
  317. package/dist/review-ui/assets/classDiagram-v2-HSJHXN6E-DQRUREh5.js +1 -0
  318. package/dist/review-ui/assets/clone-BZMtGzbS.js +1 -0
  319. package/dist/review-ui/assets/cose-bilkent-S5V4N54A-szpqu_3d.js +1 -0
  320. package/dist/review-ui/assets/cytoscape.esm-DZ22BVwz.js +321 -0
  321. package/dist/review-ui/assets/dagre-BfNtd34y.js +1 -0
  322. package/dist/review-ui/assets/dagre-KV5264BT-D6PbxORW.js +4 -0
  323. package/dist/review-ui/assets/defaultLocale-CIS5GEjP.js +1 -0
  324. package/dist/review-ui/assets/diagram-5BDNPKRD-BNAXBDig.js +10 -0
  325. package/dist/review-ui/assets/diagram-G4DWMVQ6-CIGS_5yQ.js +24 -0
  326. package/dist/review-ui/assets/diagram-MMDJMWI5-DJmcU2xZ.js +43 -0
  327. package/dist/review-ui/assets/diagram-TYMM5635-DW8XzrAz.js +24 -0
  328. package/dist/review-ui/assets/dist-B51l2n-9.js +1 -0
  329. package/dist/review-ui/assets/erDiagram-SMLLAGMA-BfUNH8zz.js +85 -0
  330. package/dist/review-ui/assets/flatten-BHh95bpO.js +1 -0
  331. package/dist/review-ui/assets/flowDiagram-DWJPFMVM-qgnlSvEC.js +162 -0
  332. package/dist/review-ui/assets/ganttDiagram-T4ZO3ILL-CFAN903o.js +292 -0
  333. package/dist/review-ui/assets/gitGraph-7Q5UKJZL-Dn47XunR.js +1 -0
  334. package/dist/review-ui/assets/gitGraphDiagram-UUTBAWPF-BcG6fDsE.js +106 -0
  335. package/dist/review-ui/assets/graphlib-Cie4kcbC.js +1 -0
  336. package/dist/review-ui/assets/identity-CWMh0UL-.js +1 -0
  337. package/dist/review-ui/assets/index-ByplNhhd.css +2 -0
  338. package/dist/review-ui/assets/index-S7nbpFp2.js +123 -0
  339. package/dist/review-ui/assets/info-OMHHGYJF-hAukP1xW.js +1 -0
  340. package/dist/review-ui/assets/infoDiagram-42DDH7IO-FblTAfC3.js +2 -0
  341. package/dist/review-ui/assets/init-BMBYmmUa.js +1 -0
  342. package/dist/review-ui/assets/ishikawaDiagram-UXIWVN3A-BA7dJd-J.js +70 -0
  343. package/dist/review-ui/assets/journeyDiagram-VCZTEJTY-CMx2w_is.js +139 -0
  344. package/dist/review-ui/assets/kanban-definition-6JOO6SKY-CFiOZCrT.js +89 -0
  345. package/dist/review-ui/assets/katex-8mXVa4k3.js +257 -0
  346. package/dist/review-ui/assets/line-BCdBO-oK.js +1 -0
  347. package/dist/review-ui/assets/linear-d7UHSQqm.js +1 -0
  348. package/dist/review-ui/assets/mermaid-parser.core-BHMXLuNx.js +4 -0
  349. package/dist/review-ui/assets/mindmap-definition-QFDTVHPH-CWO7vDqu.js +96 -0
  350. package/dist/review-ui/assets/ordinal-BDTCIhXR.js +1 -0
  351. package/dist/review-ui/assets/packet-4T2RLAQJ-Btz3ryW7.js +1 -0
  352. package/dist/review-ui/assets/path-CIRGLb_6.js +1 -0
  353. package/dist/review-ui/assets/pie-ZZUOXDRM-CreBtuDj.js +1 -0
  354. package/dist/review-ui/assets/pieDiagram-DEJITSTG-X2mFk5I3.js +30 -0
  355. package/dist/review-ui/assets/quadrantDiagram-34T5L4WZ-BSFYvc1U.js +7 -0
  356. package/dist/review-ui/assets/radar-PYXPWWZC-BcAPYMpV.js +1 -0
  357. package/dist/review-ui/assets/reduce-14YNCNxn.js +1 -0
  358. package/dist/review-ui/assets/requirementDiagram-MS252O5E-CDv1lxdq.js +84 -0
  359. package/dist/review-ui/assets/rough.esm-DtEqI08j.js +1 -0
  360. package/dist/review-ui/assets/sankeyDiagram-XADWPNL6-CV38ZpSv.js +10 -0
  361. package/dist/review-ui/assets/sequenceDiagram-FGHM5R23-DCuV_bhx.js +157 -0
  362. package/dist/review-ui/assets/src-Cxc1bu7b.js +1 -0
  363. package/dist/review-ui/assets/stateDiagram-FHFEXIEX-BfE_bGUQ.js +1 -0
  364. package/dist/review-ui/assets/stateDiagram-v2-QKLJ7IA2-u1yKXWoz.js +1 -0
  365. package/dist/review-ui/assets/timeline-definition-GMOUNBTQ-Ci0uFxaT.js +120 -0
  366. package/dist/review-ui/assets/treeView-SZITEDCU-BXg6-7zY.js +1 -0
  367. package/dist/review-ui/assets/treemap-W4RFUUIX-BToYbgol.js +1 -0
  368. package/dist/review-ui/assets/vennDiagram-DHZGUBPP-DvOuThac.js +34 -0
  369. package/dist/review-ui/assets/wardley-RL74JXVD-BAYzkcK-.js +1 -0
  370. package/dist/review-ui/assets/wardleyDiagram-NUSXRM2D-YxTu6WZw.js +20 -0
  371. package/dist/review-ui/assets/xychartDiagram-5P7HB3ND-V9j-Dl7t.js +7 -0
  372. package/dist/review-ui/index.html +29 -0
  373. package/dist/run-openflow-cli.d.ts +1 -0
  374. package/dist/run-openflow-cli.js +41 -0
  375. package/dist/run-openflow-cli.js.map +1 -0
  376. package/dist/shared/args.d.ts +3 -0
  377. package/dist/shared/args.js +27 -0
  378. package/dist/shared/args.js.map +1 -0
  379. package/dist/shared/browser.d.ts +4 -0
  380. package/dist/shared/browser.js +17 -0
  381. package/dist/shared/browser.js.map +1 -0
  382. package/dist/shared/fs.d.ts +15 -0
  383. package/dist/shared/fs.js +48 -0
  384. package/dist/shared/fs.js.map +1 -0
  385. package/dist/shared/i18n.d.ts +5 -0
  386. package/dist/shared/i18n.js +65 -0
  387. package/dist/shared/i18n.js.map +1 -0
  388. package/dist/shared/locales/en-US.json +88 -0
  389. package/dist/shared/locales/zh-CN.json +88 -0
  390. package/dist/shared/plugin-registry.d.ts +36 -0
  391. package/dist/shared/plugin-registry.js +51 -0
  392. package/dist/shared/plugin-registry.js.map +1 -0
  393. package/dist/shared/project-state.d.ts +17 -0
  394. package/dist/shared/project-state.js +75 -0
  395. package/dist/shared/project-state.js.map +1 -0
  396. package/dist/shared/terminal.d.ts +10 -0
  397. package/dist/shared/terminal.js +110 -0
  398. package/dist/shared/terminal.js.map +1 -0
  399. package/package.json +28 -0
  400. package/templates/archive/.gitkeep +1 -0
  401. package/templates/config.json +11 -0
  402. package/templates/current.json +3 -0
  403. 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