zyflow 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (705) hide show
  1. package/.claude-flow/metrics/agent-metrics.json +1 -0
  2. package/.claude-flow/metrics/performance.json +87 -0
  3. package/.claude-flow/metrics/system-metrics.json +4370 -0
  4. package/.claude-flow/metrics/task-metrics.json +10 -0
  5. package/.claude-plugin/marketplace.json +18 -0
  6. package/.claude-plugin/plugin.json +17 -0
  7. package/.gitleaks.toml +69 -0
  8. package/.hive-mind/config/queens.json +59 -0
  9. package/.hive-mind/config/workers.json +72 -0
  10. package/.hive-mind/config.json +111 -0
  11. package/.hive-mind/hive.db +0 -0
  12. package/.hive-mind/hive.db-shm +0 -0
  13. package/.hive-mind/hive.db-wal +0 -0
  14. package/.leann/indexes/zyflow/documents.ids.txt +2078 -0
  15. package/.leann/indexes/zyflow/documents.index +0 -0
  16. package/.leann/indexes/zyflow/documents.leann.meta.json +25 -0
  17. package/.leann/indexes/zyflow/documents.leann.passages.idx +0 -0
  18. package/.leann/indexes/zyflow/documents.leann.passages.jsonl +2078 -0
  19. package/.mcp.json +41 -0
  20. package/.moai-backups/20260126_231508/.mcp.json +11 -0
  21. package/.moai-backups/20260126_231508/backup_metadata.json +34 -0
  22. package/.moai-backups/20260129_145438/.mcp.json +41 -0
  23. package/.moai-backups/20260129_145438/backup_metadata.json +53 -0
  24. package/.moai-backups/20260129_145504/.mcp.json +41 -0
  25. package/.moai-backups/20260129_145504/backup_metadata.json +20 -0
  26. package/.moai-backups/20260201_140004/.mcp.json +41 -0
  27. package/.moai-backups/20260201_140004/backup_metadata.json +51 -0
  28. package/.moai-backups/backup/.mcp.json +12 -0
  29. package/.moai-backups/settings-backup/settings.local.json +61 -0
  30. package/.pre-commit-config.yaml +74 -0
  31. package/.prettierignore +3 -0
  32. package/.prettierrc +7 -0
  33. package/.scannerwork/.sonar_lock +0 -0
  34. package/.scannerwork/report-task.txt +6 -0
  35. package/.serena/project.yml +105 -0
  36. package/.shadcn-admin-ref/.env.example +1 -0
  37. package/.shadcn-admin-ref/.prettierignore +18 -0
  38. package/.shadcn-admin-ref/.prettierrc +50 -0
  39. package/.shadcn-admin-ref/LICENSE +21 -0
  40. package/.shadcn-admin-ref/components.json +21 -0
  41. package/.shadcn-admin-ref/cz.yaml +7 -0
  42. package/.shadcn-admin-ref/eslint.config.js +59 -0
  43. package/.shadcn-admin-ref/index.html +80 -0
  44. package/.shadcn-admin-ref/knip.config.ts +8 -0
  45. package/.shadcn-admin-ref/netlify.toml +4 -0
  46. package/.shadcn-admin-ref/package.json +83 -0
  47. package/.shadcn-admin-ref/public/images/favicon.png +0 -0
  48. package/.shadcn-admin-ref/public/images/favicon.svg +4 -0
  49. package/.shadcn-admin-ref/public/images/favicon_light.png +0 -0
  50. package/.shadcn-admin-ref/public/images/favicon_light.svg +1 -0
  51. package/.shadcn-admin-ref/public/images/shadcn-admin.png +0 -0
  52. package/.shadcn-admin-ref/src/assets/brand-icons/icon-discord.tsx +28 -0
  53. package/.shadcn-admin-ref/src/assets/brand-icons/icon-docker.tsx +33 -0
  54. package/.shadcn-admin-ref/src/assets/brand-icons/icon-facebook.tsx +25 -0
  55. package/.shadcn-admin-ref/src/assets/brand-icons/icon-figma.tsx +27 -0
  56. package/.shadcn-admin-ref/src/assets/brand-icons/icon-github.tsx +25 -0
  57. package/.shadcn-admin-ref/src/assets/brand-icons/icon-gitlab.tsx +25 -0
  58. package/.shadcn-admin-ref/src/assets/brand-icons/icon-gmail.tsx +28 -0
  59. package/.shadcn-admin-ref/src/assets/brand-icons/icon-medium.tsx +30 -0
  60. package/.shadcn-admin-ref/src/assets/brand-icons/icon-notion.tsx +28 -0
  61. package/.shadcn-admin-ref/src/assets/brand-icons/icon-skype.tsx +26 -0
  62. package/.shadcn-admin-ref/src/assets/brand-icons/icon-slack.tsx +28 -0
  63. package/.shadcn-admin-ref/src/assets/brand-icons/icon-stripe.tsx +25 -0
  64. package/.shadcn-admin-ref/src/assets/brand-icons/icon-telegram.tsx +25 -0
  65. package/.shadcn-admin-ref/src/assets/brand-icons/icon-trello.tsx +27 -0
  66. package/.shadcn-admin-ref/src/assets/brand-icons/icon-whatsapp.tsx +26 -0
  67. package/.shadcn-admin-ref/src/assets/brand-icons/icon-zoom.tsx +26 -0
  68. package/.shadcn-admin-ref/src/assets/brand-icons/index.ts +16 -0
  69. package/.shadcn-admin-ref/src/assets/clerk-full-logo.tsx +41 -0
  70. package/.shadcn-admin-ref/src/assets/clerk-logo.tsx +23 -0
  71. package/.shadcn-admin-ref/src/assets/custom/icon-dir.tsx +110 -0
  72. package/.shadcn-admin-ref/src/assets/custom/icon-layout-compact.tsx +131 -0
  73. package/.shadcn-admin-ref/src/assets/custom/icon-layout-default.tsx +124 -0
  74. package/.shadcn-admin-ref/src/assets/custom/icon-layout-full.tsx +100 -0
  75. package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-floating.tsx +82 -0
  76. package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-inset.tsx +58 -0
  77. package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-sidebar.tsx +53 -0
  78. package/.shadcn-admin-ref/src/assets/custom/icon-theme-dark.tsx +79 -0
  79. package/.shadcn-admin-ref/src/assets/custom/icon-theme-light.tsx +78 -0
  80. package/.shadcn-admin-ref/src/assets/custom/icon-theme-system.tsx +116 -0
  81. package/.shadcn-admin-ref/src/assets/logo.tsx +24 -0
  82. package/.shadcn-admin-ref/src/components/coming-soon.tsx +16 -0
  83. package/.shadcn-admin-ref/src/components/command-menu.tsx +91 -0
  84. package/.shadcn-admin-ref/src/components/config-drawer.tsx +354 -0
  85. package/.shadcn-admin-ref/src/components/confirm-dialog.tsx +67 -0
  86. package/.shadcn-admin-ref/src/components/data-table/bulk-actions.tsx +213 -0
  87. package/.shadcn-admin-ref/src/components/data-table/column-header.tsx +74 -0
  88. package/.shadcn-admin-ref/src/components/data-table/faceted-filter.tsx +146 -0
  89. package/.shadcn-admin-ref/src/components/data-table/index.ts +6 -0
  90. package/.shadcn-admin-ref/src/components/data-table/pagination.tsx +130 -0
  91. package/.shadcn-admin-ref/src/components/data-table/toolbar.tsx +85 -0
  92. package/.shadcn-admin-ref/src/components/data-table/view-options.tsx +56 -0
  93. package/.shadcn-admin-ref/src/components/date-picker.tsx +51 -0
  94. package/.shadcn-admin-ref/src/components/layout/app-sidebar.tsx +37 -0
  95. package/.shadcn-admin-ref/src/components/layout/app-title.tsx +64 -0
  96. package/.shadcn-admin-ref/src/components/layout/authenticated-layout.tsx +42 -0
  97. package/.shadcn-admin-ref/src/components/layout/data/sidebar-data.ts +205 -0
  98. package/.shadcn-admin-ref/src/components/layout/header.tsx +50 -0
  99. package/.shadcn-admin-ref/src/components/layout/main.tsx +27 -0
  100. package/.shadcn-admin-ref/src/components/layout/nav-group.tsx +185 -0
  101. package/.shadcn-admin-ref/src/components/layout/nav-user.tsx +124 -0
  102. package/.shadcn-admin-ref/src/components/layout/team-switcher.tsx +86 -0
  103. package/.shadcn-admin-ref/src/components/layout/top-nav.tsx +67 -0
  104. package/.shadcn-admin-ref/src/components/layout/types.ts +44 -0
  105. package/.shadcn-admin-ref/src/components/learn-more.tsx +44 -0
  106. package/.shadcn-admin-ref/src/components/long-text.tsx +84 -0
  107. package/.shadcn-admin-ref/src/components/navigation-progress.tsx +25 -0
  108. package/.shadcn-admin-ref/src/components/password-input.tsx +42 -0
  109. package/.shadcn-admin-ref/src/components/profile-dropdown.tsx +75 -0
  110. package/.shadcn-admin-ref/src/components/search.tsx +37 -0
  111. package/.shadcn-admin-ref/src/components/select-dropdown.tsx +62 -0
  112. package/.shadcn-admin-ref/src/components/sign-out-dialog.tsx +38 -0
  113. package/.shadcn-admin-ref/src/components/skip-to-main.tsx +10 -0
  114. package/.shadcn-admin-ref/src/components/theme-switch.tsx +58 -0
  115. package/.shadcn-admin-ref/src/components/ui/alert-dialog.tsx +154 -0
  116. package/.shadcn-admin-ref/src/components/ui/alert.tsx +65 -0
  117. package/.shadcn-admin-ref/src/components/ui/avatar.tsx +50 -0
  118. package/.shadcn-admin-ref/src/components/ui/badge.tsx +45 -0
  119. package/.shadcn-admin-ref/src/components/ui/button.tsx +58 -0
  120. package/.shadcn-admin-ref/src/components/ui/calendar.tsx +210 -0
  121. package/.shadcn-admin-ref/src/components/ui/card.tsx +91 -0
  122. package/.shadcn-admin-ref/src/components/ui/checkbox.tsx +29 -0
  123. package/.shadcn-admin-ref/src/components/ui/collapsible.tsx +31 -0
  124. package/.shadcn-admin-ref/src/components/ui/command.tsx +181 -0
  125. package/.shadcn-admin-ref/src/components/ui/dialog.tsx +142 -0
  126. package/.shadcn-admin-ref/src/components/ui/dropdown-menu.tsx +254 -0
  127. package/.shadcn-admin-ref/src/components/ui/form.tsx +164 -0
  128. package/.shadcn-admin-ref/src/components/ui/input-otp.tsx +74 -0
  129. package/.shadcn-admin-ref/src/components/ui/input.tsx +20 -0
  130. package/.shadcn-admin-ref/src/components/ui/label.tsx +23 -0
  131. package/.shadcn-admin-ref/src/components/ui/popover.tsx +45 -0
  132. package/.shadcn-admin-ref/src/components/ui/radio-group.tsx +42 -0
  133. package/.shadcn-admin-ref/src/components/ui/scroll-area.tsx +65 -0
  134. package/.shadcn-admin-ref/src/components/ui/select.tsx +182 -0
  135. package/.shadcn-admin-ref/src/components/ui/separator.tsx +25 -0
  136. package/.shadcn-admin-ref/src/components/ui/sheet.tsx +136 -0
  137. package/.shadcn-admin-ref/src/components/ui/sidebar.tsx +728 -0
  138. package/.shadcn-admin-ref/src/components/ui/skeleton.tsx +13 -0
  139. package/.shadcn-admin-ref/src/components/ui/sonner.tsx +21 -0
  140. package/.shadcn-admin-ref/src/components/ui/switch.tsx +28 -0
  141. package/.shadcn-admin-ref/src/components/ui/table.tsx +113 -0
  142. package/.shadcn-admin-ref/src/components/ui/tabs.tsx +63 -0
  143. package/.shadcn-admin-ref/src/components/ui/textarea.tsx +17 -0
  144. package/.shadcn-admin-ref/src/components/ui/tooltip.tsx +60 -0
  145. package/.shadcn-admin-ref/src/config/fonts.ts +19 -0
  146. package/.shadcn-admin-ref/src/context/direction-provider.tsx +61 -0
  147. package/.shadcn-admin-ref/src/context/font-provider.tsx +58 -0
  148. package/.shadcn-admin-ref/src/context/layout-provider.tsx +85 -0
  149. package/.shadcn-admin-ref/src/context/search-provider.tsx +46 -0
  150. package/.shadcn-admin-ref/src/context/theme-provider.tsx +110 -0
  151. package/.shadcn-admin-ref/src/features/apps/data/apps.tsx +110 -0
  152. package/.shadcn-admin-ref/src/features/apps/index.tsx +179 -0
  153. package/.shadcn-admin-ref/src/features/auth/auth-layout.tsx +19 -0
  154. package/.shadcn-admin-ref/src/features/auth/forgot-password/components/forgot-password-form.tsx +82 -0
  155. package/.shadcn-admin-ref/src/features/auth/forgot-password/index.tsx +44 -0
  156. package/.shadcn-admin-ref/src/features/auth/otp/components/otp-form.tsx +100 -0
  157. package/.shadcn-admin-ref/src/features/auth/otp/index.tsx +44 -0
  158. package/.shadcn-admin-ref/src/features/auth/sign-in/assets/dashboard-dark.png +0 -0
  159. package/.shadcn-admin-ref/src/features/auth/sign-in/assets/dashboard-light.png +0 -0
  160. package/.shadcn-admin-ref/src/features/auth/sign-in/components/user-auth-form.tsx +150 -0
  161. package/.shadcn-admin-ref/src/features/auth/sign-in/index.tsx +51 -0
  162. package/.shadcn-admin-ref/src/features/auth/sign-in/sign-in-2.tsx +69 -0
  163. package/.shadcn-admin-ref/src/features/auth/sign-up/components/sign-up-form.tsx +143 -0
  164. package/.shadcn-admin-ref/src/features/auth/sign-up/index.tsx +57 -0
  165. package/.shadcn-admin-ref/src/features/chats/components/new-chat.tsx +127 -0
  166. package/.shadcn-admin-ref/src/features/chats/data/chat-types.ts +4 -0
  167. package/.shadcn-admin-ref/src/features/chats/data/convo.json +309 -0
  168. package/.shadcn-admin-ref/src/features/chats/index.tsx +349 -0
  169. package/.shadcn-admin-ref/src/features/dashboard/components/analytics-chart.tsx +77 -0
  170. package/.shadcn-admin-ref/src/features/dashboard/components/analytics.tsx +189 -0
  171. package/.shadcn-admin-ref/src/features/dashboard/components/overview.tsx +82 -0
  172. package/.shadcn-admin-ref/src/features/dashboard/components/recent-sales.tsx +83 -0
  173. package/.shadcn-admin-ref/src/features/dashboard/index.tsx +220 -0
  174. package/.shadcn-admin-ref/src/features/errors/forbidden.tsx +25 -0
  175. package/.shadcn-admin-ref/src/features/errors/general-error.tsx +36 -0
  176. package/.shadcn-admin-ref/src/features/errors/maintenance-error.tsx +19 -0
  177. package/.shadcn-admin-ref/src/features/errors/not-found-error.tsx +25 -0
  178. package/.shadcn-admin-ref/src/features/errors/unauthorized-error.tsx +25 -0
  179. package/.shadcn-admin-ref/src/features/settings/account/account-form.tsx +173 -0
  180. package/.shadcn-admin-ref/src/features/settings/account/index.tsx +14 -0
  181. package/.shadcn-admin-ref/src/features/settings/appearance/appearance-form.tsx +162 -0
  182. package/.shadcn-admin-ref/src/features/settings/appearance/index.tsx +14 -0
  183. package/.shadcn-admin-ref/src/features/settings/components/content-section.tsx +22 -0
  184. package/.shadcn-admin-ref/src/features/settings/components/sidebar-nav.tsx +84 -0
  185. package/.shadcn-admin-ref/src/features/settings/display/display-form.tsx +121 -0
  186. package/.shadcn-admin-ref/src/features/settings/display/index.tsx +13 -0
  187. package/.shadcn-admin-ref/src/features/settings/index.tsx +74 -0
  188. package/.shadcn-admin-ref/src/features/settings/notifications/index.tsx +13 -0
  189. package/.shadcn-admin-ref/src/features/settings/notifications/notifications-form.tsx +220 -0
  190. package/.shadcn-admin-ref/src/features/settings/profile/index.tsx +13 -0
  191. package/.shadcn-admin-ref/src/features/settings/profile/profile-form.tsx +177 -0
  192. package/.shadcn-admin-ref/src/features/tasks/components/data-table-bulk-actions.tsx +193 -0
  193. package/.shadcn-admin-ref/src/features/tasks/components/data-table-row-actions.tsx +83 -0
  194. package/.shadcn-admin-ref/src/features/tasks/components/tasks-columns.tsx +123 -0
  195. package/.shadcn-admin-ref/src/features/tasks/components/tasks-dialogs.tsx +72 -0
  196. package/.shadcn-admin-ref/src/features/tasks/components/tasks-import-dialog.tsx +110 -0
  197. package/.shadcn-admin-ref/src/features/tasks/components/tasks-multi-delete-dialog.tsx +95 -0
  198. package/.shadcn-admin-ref/src/features/tasks/components/tasks-mutate-drawer.tsx +212 -0
  199. package/.shadcn-admin-ref/src/features/tasks/components/tasks-primary-buttons.tsx +21 -0
  200. package/.shadcn-admin-ref/src/features/tasks/components/tasks-provider.tsx +36 -0
  201. package/.shadcn-admin-ref/src/features/tasks/components/tasks-table.tsx +197 -0
  202. package/.shadcn-admin-ref/src/features/tasks/data/data.tsx +77 -0
  203. package/.shadcn-admin-ref/src/features/tasks/data/schema.ts +13 -0
  204. package/.shadcn-admin-ref/src/features/tasks/data/tasks.ts +29 -0
  205. package/.shadcn-admin-ref/src/features/tasks/index.tsx +41 -0
  206. package/.shadcn-admin-ref/src/features/users/components/data-table-bulk-actions.tsx +139 -0
  207. package/.shadcn-admin-ref/src/features/users/components/data-table-row-actions.tsx +63 -0
  208. package/.shadcn-admin-ref/src/features/users/components/users-action-dialog.tsx +326 -0
  209. package/.shadcn-admin-ref/src/features/users/components/users-columns.tsx +138 -0
  210. package/.shadcn-admin-ref/src/features/users/components/users-delete-dialog.tsx +81 -0
  211. package/.shadcn-admin-ref/src/features/users/components/users-dialogs.tsx +51 -0
  212. package/.shadcn-admin-ref/src/features/users/components/users-invite-dialog.tsx +150 -0
  213. package/.shadcn-admin-ref/src/features/users/components/users-multi-delete-dialog.tsx +95 -0
  214. package/.shadcn-admin-ref/src/features/users/components/users-primary-buttons.tsx +21 -0
  215. package/.shadcn-admin-ref/src/features/users/components/users-provider.tsx +36 -0
  216. package/.shadcn-admin-ref/src/features/users/components/users-table.tsx +194 -0
  217. package/.shadcn-admin-ref/src/features/users/data/data.ts +35 -0
  218. package/.shadcn-admin-ref/src/features/users/data/schema.ts +32 -0
  219. package/.shadcn-admin-ref/src/features/users/data/users.ts +33 -0
  220. package/.shadcn-admin-ref/src/features/users/index.tsx +47 -0
  221. package/.shadcn-admin-ref/src/hooks/use-dialog-state.tsx +18 -0
  222. package/.shadcn-admin-ref/src/hooks/use-mobile.tsx +19 -0
  223. package/.shadcn-admin-ref/src/hooks/use-table-url-state.ts +219 -0
  224. package/.shadcn-admin-ref/src/lib/cookies.ts +43 -0
  225. package/.shadcn-admin-ref/src/lib/handle-server-error.ts +24 -0
  226. package/.shadcn-admin-ref/src/lib/show-submitted-data.tsx +15 -0
  227. package/.shadcn-admin-ref/src/lib/utils.ts +60 -0
  228. package/.shadcn-admin-ref/src/main.tsx +107 -0
  229. package/.shadcn-admin-ref/src/routeTree.gen.ts +719 -0
  230. package/.shadcn-admin-ref/src/routes/(auth)/forgot-password.tsx +6 -0
  231. package/.shadcn-admin-ref/src/routes/(auth)/otp.tsx +6 -0
  232. package/.shadcn-admin-ref/src/routes/(auth)/sign-in-2.tsx +6 -0
  233. package/.shadcn-admin-ref/src/routes/(auth)/sign-in.tsx +12 -0
  234. package/.shadcn-admin-ref/src/routes/(auth)/sign-up.tsx +6 -0
  235. package/.shadcn-admin-ref/src/routes/(errors)/401.tsx +6 -0
  236. package/.shadcn-admin-ref/src/routes/(errors)/403.tsx +6 -0
  237. package/.shadcn-admin-ref/src/routes/(errors)/404.tsx +6 -0
  238. package/.shadcn-admin-ref/src/routes/(errors)/500.tsx +6 -0
  239. package/.shadcn-admin-ref/src/routes/(errors)/503.tsx +6 -0
  240. package/.shadcn-admin-ref/src/routes/__root.tsx +30 -0
  241. package/.shadcn-admin-ref/src/routes/_authenticated/apps/index.tsx +17 -0
  242. package/.shadcn-admin-ref/src/routes/_authenticated/chats/index.tsx +6 -0
  243. package/.shadcn-admin-ref/src/routes/_authenticated/errors/$error.tsx +45 -0
  244. package/.shadcn-admin-ref/src/routes/_authenticated/help-center/index.tsx +6 -0
  245. package/.shadcn-admin-ref/src/routes/_authenticated/index.tsx +6 -0
  246. package/.shadcn-admin-ref/src/routes/_authenticated/route.tsx +6 -0
  247. package/.shadcn-admin-ref/src/routes/_authenticated/settings/account.tsx +6 -0
  248. package/.shadcn-admin-ref/src/routes/_authenticated/settings/appearance.tsx +6 -0
  249. package/.shadcn-admin-ref/src/routes/_authenticated/settings/display.tsx +6 -0
  250. package/.shadcn-admin-ref/src/routes/_authenticated/settings/index.tsx +6 -0
  251. package/.shadcn-admin-ref/src/routes/_authenticated/settings/notifications.tsx +6 -0
  252. package/.shadcn-admin-ref/src/routes/_authenticated/settings/route.tsx +6 -0
  253. package/.shadcn-admin-ref/src/routes/_authenticated/tasks/index.tsx +23 -0
  254. package/.shadcn-admin-ref/src/routes/_authenticated/users/index.tsx +32 -0
  255. package/.shadcn-admin-ref/src/routes/clerk/(auth)/route.tsx +60 -0
  256. package/.shadcn-admin-ref/src/routes/clerk/(auth)/sign-in.tsx +14 -0
  257. package/.shadcn-admin-ref/src/routes/clerk/(auth)/sign-up.tsx +9 -0
  258. package/.shadcn-admin-ref/src/routes/clerk/_authenticated/route.tsx +6 -0
  259. package/.shadcn-admin-ref/src/routes/clerk/_authenticated/user-management.tsx +184 -0
  260. package/.shadcn-admin-ref/src/routes/clerk/route.tsx +135 -0
  261. package/.shadcn-admin-ref/src/stores/auth-store.ts +53 -0
  262. package/.shadcn-admin-ref/src/styles/index.css +87 -0
  263. package/.shadcn-admin-ref/src/styles/theme.css +102 -0
  264. package/.shadcn-admin-ref/src/tanstack-table.d.ts +10 -0
  265. package/.shadcn-admin-ref/src/vite-env.d.ts +1 -0
  266. package/.swarm/memory.db +0 -0
  267. package/.swarm/memory.db-shm +0 -0
  268. package/.swarm/memory.db-wal +0 -0
  269. package/.zyflow/cli-settings.json +30 -0
  270. package/.zyflow/db.sqlite +0 -0
  271. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491505852.json +10 -0
  272. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491622627.json +10 -0
  273. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491794652.json +10 -0
  274. package/.zyflow/logs/add-gitdiagram-integration/1633-1765491890392.json +10 -0
  275. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494002879.json +10 -0
  276. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494183887.json +10 -0
  277. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494342052.json +10 -0
  278. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494387244.json +10 -0
  279. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494387245.json +10 -0
  280. package/.zyflow/logs/add-gitdiagram-integration/1633-1765494606176.json +10 -0
  281. package/.zyflow/logs/add-gitdiagram-integration/1633-1765495967542.json +16 -0
  282. package/.zyflow/logs/add-gitdiagram-integration/1633-1765495967629.json +16 -0
  283. package/.zyflow/logs/add-gitdiagram-integration/1633-1765497861143.json +16 -0
  284. package/.zyflow/logs/add-gitdiagram-integration/1633-1765497861870.json +20 -0
  285. package/.zyflow/logs/add-gitdiagram-integration/1633-1765498021377.json +18 -0
  286. package/.zyflow/logs/add-gitdiagram-integration/1633-1765498021660.json +18 -0
  287. package/.zyflow/logs/add-gitdiagram-integration/1633-1765503255525.json +13 -0
  288. package/.zyflow/logs/add-gitdiagram-integration/1633-1765503256018.json +13 -0
  289. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504009102.json +16 -0
  290. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504492051.json +18 -0
  291. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504946437.json +16 -0
  292. package/.zyflow/logs/add-gitdiagram-integration/1633-1765504946640.json +16 -0
  293. package/.zyflow/logs/add-gitdiagram-integration/1634-1765505950215.json +16 -0
  294. package/.zyflow/logs/add-gitdiagram-integration/1634-1765505950948.json +18 -0
  295. package/.zyflow/logs/add-gitdiagram-integration/1635-1765505971712.json +18 -0
  296. package/.zyflow/logs/add-gitdiagram-integration/1635-1765505971976.json +18 -0
  297. package/.zyflow/logs/add-gitdiagram-integration/1636-1765505986208.json +18 -0
  298. package/.zyflow/logs/add-gitdiagram-integration/1636-1765505986620.json +16 -0
  299. package/.zyflow/logs/integrate-claude-flow/3580-1765996816612.json +10 -0
  300. package/.zyflow/logs/integrate-claude-flow/3580-1766014825819.json +10 -0
  301. package/.zyflow/logs/integrate-claude-flow/3580-1766015183794.json +12 -0
  302. package/.zyflow/logs/integrate-claude-flow/3580-1766015474608.json +12 -0
  303. package/.zyflow/logs/integrate-claude-flow/3581-1766016502824.json +63 -0
  304. package/.zyflow/logs/integrate-claude-flow/3581-1766016576008.json +60 -0
  305. package/.zyflow/logs/integrate-claude-flow/3582-1766022737754.json +110 -0
  306. package/.zyflow/logs/integrate-claude-flow/3582-1766022809327.json +135 -0
  307. package/.zyflow/sessions.json +242 -0
  308. package/.zyflow/settings.json +6 -0
  309. package/.zyflow/tasks.db +0 -0
  310. package/.zyflow/tasks.db-shm +0 -0
  311. package/.zyflow/tasks.db-wal +0 -0
  312. package/.zyflow/zyflow.sqlite +0 -0
  313. package/Dockerfile +82 -0
  314. package/LICENSE +21 -0
  315. package/README.md +506 -0
  316. package/claude-flow +34 -0
  317. package/components.json +21 -0
  318. package/config/ports.ts +28 -0
  319. package/docker-compose.yml +52 -0
  320. package/eslint.config.js +34 -0
  321. package/index.html +19 -0
  322. package/logs/mcp-error.log +55 -0
  323. package/logs/mcp-out.log +0 -0
  324. package/logs/pm2-error.log +0 -0
  325. package/logs/pm2-out.log +265 -0
  326. package/logs/py-error.log +22 -0
  327. package/logs/py-out.log +0 -0
  328. package/logs/server-error.log +11000 -0
  329. package/logs/server-out.log +8117 -0
  330. package/logs/vite-error.log +404 -0
  331. package/logs/vite-out.log +311 -0
  332. package/mcp-server/agent-tools.ts +375 -0
  333. package/mcp-server/cli-models.ts +193 -0
  334. package/mcp-server/context.ts +110 -0
  335. package/mcp-server/diagram-tools.ts +341 -0
  336. package/mcp-server/index.ts +2014 -0
  337. package/mcp-server/integration-tools.ts +909 -0
  338. package/mcp-server/moai-spec-tools.ts +416 -0
  339. package/mcp-server/parser.ts +422 -0
  340. package/mcp-server/post-task-runner.ts +253 -0
  341. package/mcp-server/post-task-types.ts +426 -0
  342. package/mcp-server/quarantine-manager.ts +479 -0
  343. package/mcp-server/report-generator.ts +386 -0
  344. package/mcp-server/task-tools.ts +619 -0
  345. package/mcp-server/trigger-config.ts +288 -0
  346. package/mcp-server/trigger-router.ts +305 -0
  347. package/mcp-server/triggers/event-listener.ts +331 -0
  348. package/mcp-server/triggers/git-hooks.ts +283 -0
  349. package/mcp-server/triggers/scheduler.ts +289 -0
  350. package/mcp-server/types.ts +55 -0
  351. package/memory/claude-flow@alpha-data.json +5 -0
  352. package/nginx/zyflow.conf +144 -0
  353. package/openspec/config.yaml +78 -0
  354. package/openspec-backup.tar.gz +0 -0
  355. package/package.json +154 -0
  356. package/packages/gitdiagram-core/.claude-flow/metrics/agent-metrics.json +1 -0
  357. package/packages/gitdiagram-core/.claude-flow/metrics/performance.json +87 -0
  358. package/packages/gitdiagram-core/.claude-flow/metrics/task-metrics.json +10 -0
  359. package/packages/gitdiagram-core/package.json +41 -0
  360. package/packages/gitdiagram-core/src/file-tree.ts +272 -0
  361. package/packages/gitdiagram-core/src/generator.ts +283 -0
  362. package/packages/gitdiagram-core/src/index.ts +78 -0
  363. package/packages/gitdiagram-core/src/llm-adapter.ts +235 -0
  364. package/packages/gitdiagram-core/src/mermaid-utils.ts +304 -0
  365. package/packages/gitdiagram-core/src/prompts.ts +281 -0
  366. package/packages/zyflow-parser/package.json +34 -0
  367. package/packages/zyflow-parser/src/index.ts +26 -0
  368. package/packages/zyflow-parser/src/moai-parser.ts +603 -0
  369. package/packages/zyflow-parser/src/moai-types.ts +110 -0
  370. package/packages/zyflow-remote-plugin/.claude-flow/metrics/agent-metrics.json +1 -0
  371. package/packages/zyflow-remote-plugin/.claude-flow/metrics/performance.json +87 -0
  372. package/packages/zyflow-remote-plugin/.claude-flow/metrics/task-metrics.json +10 -0
  373. package/packages/zyflow-remote-plugin/package.json +31 -0
  374. package/packages/zyflow-remote-plugin/src/index.ts +71 -0
  375. package/packages/zyflow-remote-plugin/src/remote-config.ts +232 -0
  376. package/packages/zyflow-remote-plugin/src/router.ts +535 -0
  377. package/packages/zyflow-remote-plugin/src/ssh-config-parser.ts +123 -0
  378. package/packages/zyflow-remote-plugin/src/ssh-manager.ts +598 -0
  379. package/packages/zyflow-remote-plugin/src/types.ts +149 -0
  380. package/plugin/manifest.json +26 -0
  381. package/plugin/package.json +13 -0
  382. package/public/favicon.svg +4 -0
  383. package/server/adk/agents/error-analyzer.ts +223 -0
  384. package/server/adk/agents/fix-generator.ts +187 -0
  385. package/server/adk/agents/pr-agent.ts +264 -0
  386. package/server/adk/agents/validator.ts +187 -0
  387. package/server/adk/config.ts +43 -0
  388. package/server/adk/index.ts +69 -0
  389. package/server/adk/integration.ts +297 -0
  390. package/server/adk/orchestrator.ts +405 -0
  391. package/server/adk/tools/build-tools.ts +290 -0
  392. package/server/adk/tools/file-tools.ts +351 -0
  393. package/server/adk/tools/git-tools.ts +280 -0
  394. package/server/adk/tools/github-tools.ts +249 -0
  395. package/server/agents/agent-monitor.ts +416 -0
  396. package/server/agents/alert-integration.ts +312 -0
  397. package/server/agents/error-analyzer.ts +472 -0
  398. package/server/agents/error-detector.ts +442 -0
  399. package/server/agents/fix-generator.ts +421 -0
  400. package/server/agents/fix-validator.ts +428 -0
  401. package/server/agents/merge-policy.ts +362 -0
  402. package/server/agents/pr-workflow.ts +476 -0
  403. package/server/agents/prompts/error-analysis.ts +393 -0
  404. package/server/ai/gemini-client.ts +499 -0
  405. package/server/ai/index.ts +317 -0
  406. package/server/ai/types.ts +137 -0
  407. package/server/app.ts +3693 -0
  408. package/server/archive-manager.ts +604 -0
  409. package/server/backlog/index.ts +7 -0
  410. package/server/backlog/migration.ts +331 -0
  411. package/server/backlog/parser.ts +323 -0
  412. package/server/backlog/sync.ts +325 -0
  413. package/server/change-log.ts +868 -0
  414. package/server/claude-flow/index.ts +12 -0
  415. package/server/claude-flow/prompt-builder.ts +407 -0
  416. package/server/claude-flow/types.ts +33 -0
  417. package/server/cli-adapter/index.ts +11 -0
  418. package/server/cli-adapter/process-manager.ts +612 -0
  419. package/server/cli-adapter/profile-manager.ts +286 -0
  420. package/server/cli-adapter/routes.ts +561 -0
  421. package/server/cli-adapter/types.ts +226 -0
  422. package/server/config.d.ts +18 -0
  423. package/server/config.js +79 -0
  424. package/server/config.ts +262 -0
  425. package/server/flow-sync.ts +543 -0
  426. package/server/git/change-workflow.ts +446 -0
  427. package/server/git/commands.ts +370 -0
  428. package/server/git/github.ts +247 -0
  429. package/server/git/index.ts +1202 -0
  430. package/server/git/status.ts +322 -0
  431. package/server/index.ts +136 -0
  432. package/server/integrations/crypto.ts +142 -0
  433. package/server/integrations/db/client.ts +169 -0
  434. package/server/integrations/db/schema.ts +167 -0
  435. package/server/integrations/env-parser.ts +365 -0
  436. package/server/integrations/index.ts +101 -0
  437. package/server/integrations/keychain.ts +239 -0
  438. package/server/integrations/local/file-utils.ts +383 -0
  439. package/server/integrations/local/index.ts +64 -0
  440. package/server/integrations/local/resolver.ts +439 -0
  441. package/server/integrations/local/types.ts +122 -0
  442. package/server/integrations/routes.ts +1100 -0
  443. package/server/integrations/service-patterns.ts +771 -0
  444. package/server/integrations/services/accounts.ts +356 -0
  445. package/server/integrations/services/env-import.ts +279 -0
  446. package/server/integrations/services/projects.ts +552 -0
  447. package/server/integrations/services/system-import.ts +1110 -0
  448. package/server/migrations/ears-generator.ts +491 -0
  449. package/server/migrations/gherkin-generator.ts +605 -0
  450. package/server/migrations/index.ts +73 -0
  451. package/server/migrations/migrate-spec-format.ts +492 -0
  452. package/server/migrations/openspec-parser.ts +542 -0
  453. package/server/migrations/tag-generator.ts +474 -0
  454. package/server/moai-specs.ts +487 -0
  455. package/server/moai-watcher.ts +145 -0
  456. package/server/parser-debug.ts +37 -0
  457. package/server/parser-utils.ts +316 -0
  458. package/server/parser.d.ts +17 -0
  459. package/server/parser.js +221 -0
  460. package/server/parser.ts +342 -0
  461. package/server/remote-watcher.ts +367 -0
  462. package/server/replay-engine.ts +915 -0
  463. package/server/routes/alerts.ts +1028 -0
  464. package/server/routes/changes.ts +812 -0
  465. package/server/routes/docs.ts +898 -0
  466. package/server/routes/flow.ts +2814 -0
  467. package/server/routes/global-chat.ts +162 -0
  468. package/server/routes/leann.ts +327 -0
  469. package/server/routes/projects.ts +1282 -0
  470. package/server/routes/search.ts +266 -0
  471. package/server/routes/specs.ts +482 -0
  472. package/server/routes/webhooks.ts +579 -0
  473. package/server/server/parser.js +265 -0
  474. package/server/services/githubActionsPoller.ts +797 -0
  475. package/server/services/slackNotifier.ts +476 -0
  476. package/server/src/types/index.js +1 -0
  477. package/server/sync-tasks.ts +741 -0
  478. package/server/tasks/cli/commands.ts +269 -0
  479. package/server/tasks/cli/index.ts +152 -0
  480. package/server/tasks/core/search.ts +81 -0
  481. package/server/tasks/core/task.ts +307 -0
  482. package/server/tasks/db/client.ts +1008 -0
  483. package/server/tasks/db/schema.ts +572 -0
  484. package/server/tasks/index.ts +24 -0
  485. package/server/tasks.db +0 -0
  486. package/server/types/archive.ts +136 -0
  487. package/server/types/change-log.ts +643 -0
  488. package/server/types/spec.ts +188 -0
  489. package/server/unified-spec-scanner.ts +753 -0
  490. package/server/utils/crypto.ts +179 -0
  491. package/server/utils/webhook-verify.ts +216 -0
  492. package/server/watcher.ts +132 -0
  493. package/server/websocket.ts +99 -0
  494. package/server-output.log +6 -0
  495. package/sonar-project.properties +18 -0
  496. package/src/App.tsx +386 -0
  497. package/src/api/client.ts +346 -0
  498. package/src/api/error-interceptor.ts +366 -0
  499. package/src/api/errors.ts +123 -0
  500. package/src/api/flow.ts +233 -0
  501. package/src/api/offline-queue.ts +351 -0
  502. package/src/api/retry-logic.ts +233 -0
  503. package/src/components/OfflineModeBanner.tsx +159 -0
  504. package/src/components/SSEStatusIndicator.tsx +194 -0
  505. package/src/components/agent/AgentChat.tsx +243 -0
  506. package/src/components/agent/AgentPage.tsx +182 -0
  507. package/src/components/agent/AgentSidebar.tsx +231 -0
  508. package/src/components/agent/index.ts +7 -0
  509. package/src/components/alerts/AlertCenter.tsx +239 -0
  510. package/src/components/alerts/AlertDashboard.tsx +211 -0
  511. package/src/components/alerts/AlertDetail.tsx +474 -0
  512. package/src/components/alerts/AlertList.tsx +113 -0
  513. package/src/components/alerts/AlertSettings.tsx +336 -0
  514. package/src/components/alerts/index.ts +5 -0
  515. package/src/components/chat/ChatPanel.tsx +642 -0
  516. package/src/components/chat/index.ts +1 -0
  517. package/src/components/cli/AddCustomCLIDialog.tsx +210 -0
  518. package/src/components/cli/CLISelector.tsx +187 -0
  519. package/src/components/cli/index.ts +8 -0
  520. package/src/components/dashboard/ArchivedChangeList.tsx +102 -0
  521. package/src/components/dashboard/ArchivedChangeViewer.tsx +184 -0
  522. package/src/components/dashboard/ArchivedChangesPage.tsx +31 -0
  523. package/src/components/dashboard/ChangeList.tsx +86 -0
  524. package/src/components/dashboard/ThemeToggle.tsx +33 -0
  525. package/src/components/diagram/DiagramViewer.tsx +256 -0
  526. package/src/components/diagram/MermaidRenderer.tsx +163 -0
  527. package/src/components/diagram/ProjectDiagramTab.tsx +161 -0
  528. package/src/components/diagram/index.ts +13 -0
  529. package/src/components/errors/ErrorBoundary.tsx +276 -0
  530. package/src/components/errors/ErrorFallback.tsx +198 -0
  531. package/src/components/errors/ErrorToast.tsx +221 -0
  532. package/src/components/flow/BacklogView.tsx +1142 -0
  533. package/src/components/flow/ChangeDetail.tsx +475 -0
  534. package/src/components/flow/ChangeItem.tsx +230 -0
  535. package/src/components/flow/ChangeList.tsx +92 -0
  536. package/src/components/flow/ExecutionHistoryDialog.tsx +224 -0
  537. package/src/components/flow/FlowContent.tsx +212 -0
  538. package/src/components/flow/FlowPage.tsx +9 -0
  539. package/src/components/flow/PipelineBar.tsx +214 -0
  540. package/src/components/flow/ProjectDashboard.tsx +222 -0
  541. package/src/components/flow/SpecDetail.tsx +138 -0
  542. package/src/components/flow/SpecDetailTabs.tsx +176 -0
  543. package/src/components/flow/SpecItem.tsx +93 -0
  544. package/src/components/flow/SpecProgressBar.tsx +47 -0
  545. package/src/components/flow/StageContent.tsx +620 -0
  546. package/src/components/flow/StandaloneTasks.tsx +960 -0
  547. package/src/components/flow/TaskExecutionDialog.tsx +1204 -0
  548. package/src/components/flow/index.ts +9 -0
  549. package/src/components/flow/task-execution/AgentSlider.tsx +37 -0
  550. package/src/components/flow/task-execution/ConsensusSettings.tsx +129 -0
  551. package/src/components/flow/task-execution/ExecutionOutput.tsx +398 -0
  552. package/src/components/flow/task-execution/ModelSelector.tsx +134 -0
  553. package/src/components/flow/task-execution/ProviderSelector.tsx +137 -0
  554. package/src/components/flow/task-execution/RecommendationBanner.tsx +71 -0
  555. package/src/components/flow/task-execution/StatusBadge.tsx +43 -0
  556. package/src/components/flow/task-execution/StrategySelector.tsx +48 -0
  557. package/src/components/flow/task-execution/SwarmSummary.tsx +55 -0
  558. package/src/components/flow/task-execution/index.ts +14 -0
  559. package/src/components/flow/task-execution/types.ts +56 -0
  560. package/src/components/git/ChangeWorkflowDialog.tsx +582 -0
  561. package/src/components/git/ConflictResolutionDialog.tsx +398 -0
  562. package/src/components/git/GitBranchSelector.tsx +212 -0
  563. package/src/components/git/GitCommitDialog.tsx +254 -0
  564. package/src/components/git/GitStatusBadge.tsx +148 -0
  565. package/src/components/git/GitSyncButton.tsx +128 -0
  566. package/src/components/git/RemoteStatusBanner.tsx +143 -0
  567. package/src/components/git/index.ts +9 -0
  568. package/src/components/integrations/EnvImportDialog.tsx +524 -0
  569. package/src/components/integrations/EnvironmentDialog.tsx +227 -0
  570. package/src/components/integrations/IntegrationBadges.tsx +91 -0
  571. package/src/components/integrations/IntegrationsSettings.tsx +55 -0
  572. package/src/components/integrations/ProjectIntegrations.tsx +481 -0
  573. package/src/components/integrations/ServiceAccountDialog.tsx +422 -0
  574. package/src/components/integrations/ServiceAccountList.tsx +305 -0
  575. package/src/components/integrations/SystemImportDialog.tsx +436 -0
  576. package/src/components/integrations/TestAccountDialog.tsx +162 -0
  577. package/src/components/integrations/index.ts +6 -0
  578. package/src/components/layout/AppSidebar.tsx +284 -0
  579. package/src/components/layout/FlowSidebar.tsx +435 -0
  580. package/src/components/layout/GlobalCommandPalette.tsx +410 -0
  581. package/src/components/layout/MenuBar.tsx +227 -0
  582. package/src/components/layout/StatusBar.tsx +226 -0
  583. package/src/components/monitoring/ErrorDashboard.tsx +274 -0
  584. package/src/components/monitoring/ErrorDetailPanel.tsx +200 -0
  585. package/src/components/monitoring/ErrorFilters.tsx +219 -0
  586. package/src/components/monitoring/ErrorHistoryList.tsx +141 -0
  587. package/src/components/monitoring/ErrorStats.tsx +249 -0
  588. package/src/components/remote/RemoteFileBrowser.tsx +249 -0
  589. package/src/components/remote/RemoteServerDialog.tsx +234 -0
  590. package/src/components/remote/RemoteServerList.tsx +366 -0
  591. package/src/components/remote/index.ts +7 -0
  592. package/src/components/settings/CLISettings.tsx +522 -0
  593. package/src/components/settings/CustomCLIDialog.tsx +548 -0
  594. package/src/components/settings/IntegrationsSettings.tsx +51 -0
  595. package/src/components/settings/ProjectSettings.tsx +441 -0
  596. package/src/components/settings/ProjectsSettings.tsx +541 -0
  597. package/src/components/settings/SearchSettings.tsx +272 -0
  598. package/src/components/settings/SettingsPage.tsx +68 -0
  599. package/src/components/settings/index.ts +5 -0
  600. package/src/components/swarm/ExecutionPanel.tsx +284 -0
  601. package/src/components/swarm/LogViewer.tsx +196 -0
  602. package/src/components/swarm/ProgressIndicator.tsx +111 -0
  603. package/src/components/swarm/index.ts +3 -0
  604. package/src/components/tasks/ArchiveTable.tsx +203 -0
  605. package/src/components/tasks/KanbanBoard.tsx +264 -0
  606. package/src/components/tasks/TaskCard.tsx +138 -0
  607. package/src/components/tasks/TaskColumn.tsx +81 -0
  608. package/src/components/tasks/TaskDialog.tsx +274 -0
  609. package/src/components/tasks/index.ts +5 -0
  610. package/src/components/tasks/types.ts +43 -0
  611. package/src/components/ui/alert-dialog.tsx +154 -0
  612. package/src/components/ui/alert.tsx +65 -0
  613. package/src/components/ui/badge.tsx +45 -0
  614. package/src/components/ui/button.tsx +58 -0
  615. package/src/components/ui/card.tsx +91 -0
  616. package/src/components/ui/checkbox.tsx +29 -0
  617. package/src/components/ui/collapsible.tsx +31 -0
  618. package/src/components/ui/command.tsx +184 -0
  619. package/src/components/ui/confirm-dialog.tsx +55 -0
  620. package/src/components/ui/dialog.tsx +142 -0
  621. package/src/components/ui/dropdown-menu.tsx +254 -0
  622. package/src/components/ui/input.tsx +20 -0
  623. package/src/components/ui/label.tsx +22 -0
  624. package/src/components/ui/markdown.tsx +100 -0
  625. package/src/components/ui/progress.tsx +27 -0
  626. package/src/components/ui/resizable-sidebar.tsx +156 -0
  627. package/src/components/ui/resizable.tsx +54 -0
  628. package/src/components/ui/right-resizable-sidebar.tsx +158 -0
  629. package/src/components/ui/scroll-area.tsx +64 -0
  630. package/src/components/ui/select.tsx +185 -0
  631. package/src/components/ui/separator.tsx +25 -0
  632. package/src/components/ui/sheet.tsx +136 -0
  633. package/src/components/ui/sidebar.tsx +726 -0
  634. package/src/components/ui/skeleton.tsx +13 -0
  635. package/src/components/ui/slider.tsx +56 -0
  636. package/src/components/ui/switch.tsx +29 -0
  637. package/src/components/ui/table.tsx +113 -0
  638. package/src/components/ui/tabs.tsx +63 -0
  639. package/src/components/ui/textarea.tsx +17 -0
  640. package/src/components/ui/tooltip.tsx +60 -0
  641. package/src/config/api.ts +83 -0
  642. package/src/constants/error-codes.ts +255 -0
  643. package/src/constants/stages.ts +27 -0
  644. package/src/context/ErrorContext.tsx +185 -0
  645. package/src/context/theme-provider.tsx +63 -0
  646. package/src/hooks/use-mobile.tsx +19 -0
  647. package/src/hooks/useAI.ts +206 -0
  648. package/src/hooks/useAgentSession.ts +431 -0
  649. package/src/hooks/useAlerts.ts +935 -0
  650. package/src/hooks/useArchivedChanges.ts +39 -0
  651. package/src/hooks/useAsyncError.ts +45 -0
  652. package/src/hooks/useChangeGit.ts +727 -0
  653. package/src/hooks/useChanges.ts +20 -0
  654. package/src/hooks/useClaude.ts +130 -0
  655. package/src/hooks/useDocs.ts +182 -0
  656. package/src/hooks/useErrorDashboard.ts +243 -0
  657. package/src/hooks/useErrorHandler.ts +150 -0
  658. package/src/hooks/useExecutionHistory.ts +55 -0
  659. package/src/hooks/useFlowChanges.ts +850 -0
  660. package/src/hooks/useFlowItems.ts +205 -0
  661. package/src/hooks/useGit.ts +427 -0
  662. package/src/hooks/useHideCompletedSpecs.ts +15 -0
  663. package/src/hooks/useInstance.ts +40 -0
  664. package/src/hooks/useIntegrations.ts +737 -0
  665. package/src/hooks/useLeannStatus.ts +93 -0
  666. package/src/hooks/useNetworkStatus.ts +167 -0
  667. package/src/hooks/useProjects.ts +353 -0
  668. package/src/hooks/useRemoteServers.ts +383 -0
  669. package/src/hooks/useSSEConnection.ts +346 -0
  670. package/src/hooks/useSpecs.ts +39 -0
  671. package/src/hooks/useSwarm.ts +462 -0
  672. package/src/hooks/useTasks.ts +137 -0
  673. package/src/hooks/useURLSync.ts +122 -0
  674. package/src/hooks/useWebSocket.ts +262 -0
  675. package/src/lib/utils.ts +121 -0
  676. package/src/main.tsx +22 -0
  677. package/src/stores/errorStore.ts +301 -0
  678. package/src/stores/offlineStore.ts +266 -0
  679. package/src/stores/sseStore.ts +247 -0
  680. package/src/stores/useHideCompletedStore.ts +21 -0
  681. package/src/styles/index.css +87 -0
  682. package/src/styles/theme.css +102 -0
  683. package/src/types/ai.ts +191 -0
  684. package/src/types/errors.ts +253 -0
  685. package/src/types/flow.ts +382 -0
  686. package/src/types/index.ts +614 -0
  687. package/src/utils/error-logger.ts +399 -0
  688. package/src/utils/error-statistics.ts +305 -0
  689. package/src/utils/logger.ts +280 -0
  690. package/src/utils/task-routing.ts +795 -0
  691. package/src/vite-env.d.ts +1 -0
  692. package/test-results/.last-run.json +4 -0
  693. package/tmp/check-docker-final.ts +48 -0
  694. package/tmp/check-docker-tasks.ts +58 -0
  695. package/tmp/check-docker-tasks2.ts +48 -0
  696. package/tmp/check-docker-tasks3.ts +42 -0
  697. package/tmp/check-mobile-tasks.ts +57 -0
  698. package/tmp/check-zywiki-tasks.ts +49 -0
  699. package/tmp/sync-mobile.ts +11 -0
  700. package/tmp/sync-zywiki.ts +68 -0
  701. package/tmp/test-docker-parser.ts +15 -0
  702. package/tmp/test-mobile-parser.ts +28 -0
  703. package/tmp/test-parser.ts +27 -0
  704. package/tmp/test-unnumbered.ts +35 -0
  705. package/zyflow.db +0 -0
@@ -0,0 +1,2014 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js'
4
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
5
+ import {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ ErrorCode,
9
+ McpError,
10
+ } from '@modelcontextprotocol/sdk/types.js'
11
+ import { readFile, writeFile, readdir } from 'fs/promises'
12
+ import { join } from 'path'
13
+ import matter from 'gray-matter'
14
+
15
+ import { parseTasksFile, setTaskStatus } from './parser.js'
16
+ import { buildTaskContext, readDesign } from './context.js'
17
+ import {
18
+ validateChange,
19
+ archiveChange,
20
+ getInstructions,
21
+ getChangeStatus,
22
+ isOpenSpecAvailable,
23
+ } from '../server/cli-adapter/openspec.js'
24
+ import type { Change, Task, TasksFile, NextTaskResponse } from './types.js'
25
+ import {
26
+ scanMoaiSpecs,
27
+ getMoaiSpecContext,
28
+ getNextMoaiTag,
29
+ getMoaiTag,
30
+ updateMoaiTagStatus,
31
+ updateMoaiTagInDatabase,
32
+ syncSpecStatusFromTags,
33
+ isMoaiSpec,
34
+ isMoaiTag,
35
+ type MoaiSpecSummary,
36
+ } from './moai-spec-tools.js'
37
+ import {
38
+ taskToolDefinitions,
39
+ initTaskDb,
40
+ handleTaskList,
41
+ handleTaskCreate,
42
+ handleTaskUpdate,
43
+ handleTaskSearch,
44
+ handleTaskDelete,
45
+ handleTaskView,
46
+ handleTaskArchive,
47
+ handleTaskUnarchive,
48
+ } from './task-tools.js'
49
+
50
+ // Integration Hub imports
51
+ import {
52
+ integrationToolDefinitions,
53
+ handleIntegrationContext,
54
+ handleListAccounts,
55
+ handleGetEnv,
56
+ handleApplyGit,
57
+ handleGetTestAccount,
58
+ handleScanEnv,
59
+ handleImportEnv,
60
+ // 새로운 로컬 설정 도구
61
+ handleInitLocal,
62
+ handleExportToLocal,
63
+ } from './integration-tools.js'
64
+
65
+ // Agent Tools imports
66
+ import {
67
+ agentToolDefinitions,
68
+ handleExecuteChange,
69
+ handleGetAgentStatus,
70
+ handleStopAgent,
71
+ handleResumeAgent,
72
+ handleListAgentSessions,
73
+ handleGetAgentLogs,
74
+ handleDeleteAgentSession,
75
+ } from './agent-tools.js'
76
+
77
+
78
+ // Change Log & Replay imports
79
+ import { getChangeLogManager } from '../server/change-log.js'
80
+ import { getReplayEngine } from '../server/replay-engine.js'
81
+ import type { EventFilter, ReplayOptions, EventType, EventSeverity, EventSource } from '../server/types/change-log.js'
82
+
83
+ // RAG 기능 삭제됨 - LEANN 외부 MCP 서버로 대체 (leann-server)
84
+
85
+ // MCP Handler Argument Types
86
+ interface GetEventsArgs {
87
+ event_types?: EventType[];
88
+ severities?: EventSeverity[];
89
+ sources?: EventSource[];
90
+ project_ids?: string[];
91
+ change_ids?: string[];
92
+ time_range?: { start: string; end: string };
93
+ limit?: number;
94
+ offset?: number;
95
+ sort_by?: { field: string; direction: 'ASC' | 'DESC' };
96
+ }
97
+
98
+ interface GetEventStatisticsArgs {
99
+ event_types?: EventType[];
100
+ time_range?: { start: string; end: string };
101
+ }
102
+
103
+ interface SearchEventsArgs {
104
+ query: string;
105
+ event_types?: EventType[];
106
+ time_range?: { start: string; end: string };
107
+ }
108
+
109
+ interface ExportEventsArgs {
110
+ filter?: EventFilter;
111
+ format?: 'JSON' | 'CSV' | 'SQL';
112
+ }
113
+
114
+ interface CreateReplaySessionArgs {
115
+ name: string;
116
+ description?: string;
117
+ filter?: EventFilter;
118
+ mode?: 'SAFE' | 'FAST' | 'VERBOSE' | 'DRY_RUN';
119
+ strategy?: 'SEQUENTIAL' | 'PARALLEL' | 'DEPENDENCY_AWARE' | 'SELECTIVE';
120
+ stop_on_error?: boolean;
121
+ enable_validation?: boolean;
122
+ enable_rollback?: boolean;
123
+ max_concurrency?: number;
124
+ skip_events?: string[];
125
+ include_events?: string[];
126
+ }
127
+
128
+ interface StartReplayArgs {
129
+ session_id: string;
130
+ }
131
+
132
+ interface GetReplayProgressArgs {
133
+ session_id: string;
134
+ }
135
+
136
+ // Get project path from environment or use current directory
137
+ const PROJECT_PATH = process.env.ZYFLOW_PROJECT || process.cwd()
138
+
139
+ /**
140
+ * List all changes in both openspec/changes and .moai/specs directories
141
+ */
142
+ async function listChanges(projectPath?: string): Promise<(Change | MoaiSpecSummary)[]> {
143
+ const basePath = projectPath || PROJECT_PATH
144
+ const changes: (Change | MoaiSpecSummary)[] = []
145
+
146
+ // Scan OpenSpec changes (legacy)
147
+ const changesDir = join(basePath, 'openspec', 'changes')
148
+ try {
149
+ const entries = await readdir(changesDir, { withFileTypes: true })
150
+
151
+ for (const entry of entries) {
152
+ if (!entry.isDirectory() || entry.name === 'archive') continue
153
+
154
+ const changeId = entry.name
155
+ const tasksPath = join(changesDir, changeId, 'tasks.md')
156
+ const proposalPath = join(changesDir, changeId, 'proposal.md')
157
+
158
+ try {
159
+ // Read tasks.md
160
+ const tasksContent = await readFile(tasksPath, 'utf-8')
161
+ const tasksFile = parseTasksFile(changeId, tasksContent)
162
+
163
+ // Calculate progress
164
+ const allTasks = tasksFile.groups.flatMap(g => g.tasks)
165
+ const completedTasks = allTasks.filter(t => t.completed).length
166
+ const totalTasks = allTasks.length
167
+ const progress = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0
168
+
169
+ // Read proposal for title
170
+ let title = changeId
171
+ let description = ''
172
+ try {
173
+ const proposalContent = await readFile(proposalPath, 'utf-8')
174
+ const { data, content } = matter(proposalContent)
175
+ title = data.title || changeId
176
+ // Extract first paragraph as description
177
+ const firstPara = content.split('\n\n')[0]?.replace(/^#.*\n/, '').trim()
178
+ description = firstPara || ''
179
+ } catch {
180
+ // Use changeId as title
181
+ }
182
+
183
+ changes.push({
184
+ id: changeId,
185
+ title,
186
+ description,
187
+ progress,
188
+ totalTasks,
189
+ completedTasks,
190
+ })
191
+ } catch {
192
+ // Skip changes without valid tasks.md
193
+ }
194
+ }
195
+ } catch {
196
+ // openspec/changes directory doesn't exist
197
+ }
198
+
199
+ // Scan MoAI SPECs
200
+ const moaiSpecs = await scanMoaiSpecs(basePath)
201
+ changes.push(...moaiSpecs)
202
+
203
+ return changes.sort((a, b) => b.progress - a.progress)
204
+ }
205
+
206
+ /**
207
+ * Get tasks for a specific change (OpenSpec) or TAG chain for MoAI SPEC
208
+ */
209
+ async function getTasks(changeId: string, projectPath?: string): Promise<TasksFile> {
210
+ const basePath = projectPath || PROJECT_PATH
211
+
212
+ // Check if this is a MoAI SPEC
213
+ if (isMoaiSpec(changeId)) {
214
+ // Get MoAI SPEC TAG chain
215
+ const context = await getMoaiSpecContext(changeId, basePath)
216
+ const tags = context.plan.tags || []
217
+
218
+ // Convert TAGs to TasksFile format for compatibility
219
+ // Each TAG becomes a "group" with one task
220
+ const groups = tags.map((tag, index) => ({
221
+ id: `moai-group-${index + 1}`,
222
+ title: tag.id,
223
+ tasks: [
224
+ {
225
+ id: tag.id,
226
+ title: tag.title,
227
+ completed: tag.completed,
228
+ groupId: `moai-group-${index + 1}`,
229
+ lineNumber: index + 1,
230
+ displayId: tag.id,
231
+ indent: 0,
232
+ },
233
+ ],
234
+ }))
235
+
236
+ return {
237
+ changeId,
238
+ groups,
239
+ }
240
+ }
241
+
242
+ // OpenSpec format (legacy)
243
+ const tasksPath = join(basePath, 'openspec', 'changes', changeId, 'tasks.md')
244
+ const content = await readFile(tasksPath, 'utf-8')
245
+ return parseTasksFile(changeId, content)
246
+ }
247
+
248
+ /**
249
+ * Get the next incomplete task (OpenSpec) or TAG (MoAI SPEC) with context
250
+ */
251
+ async function getNextTask(changeId: string, projectPath?: string): Promise<NextTaskResponse | Record<string, unknown>> {
252
+ const basePath = projectPath || PROJECT_PATH
253
+
254
+ // Check if this is a MoAI SPEC
255
+ if (isMoaiSpec(changeId)) {
256
+ // Get next MoAI TAG respecting dependencies
257
+ const nextTag = await getNextMoaiTag(changeId, basePath)
258
+
259
+ // Convert TAG to Task format
260
+ let nextTask: Task | null = null
261
+ if (nextTag) {
262
+ nextTask = {
263
+ id: nextTag.id,
264
+ title: nextTag.title,
265
+ completed: nextTag.completed,
266
+ groupId: '',
267
+ lineNumber: 0,
268
+ displayId: nextTag.id,
269
+ }
270
+ }
271
+
272
+ // Get full context
273
+ const moaiContext = await getMoaiSpecContext(changeId, basePath)
274
+
275
+ return {
276
+ task: nextTask,
277
+ context: {
278
+ spec: moaiContext.spec,
279
+ plan: moaiContext.plan,
280
+ acceptance: moaiContext.acceptance,
281
+ } as unknown,
282
+ group: 'MoAI SPEC',
283
+ }
284
+ }
285
+
286
+ // OpenSpec format (legacy)
287
+ const tasksFile = await getTasks(changeId, basePath)
288
+
289
+ // Find first incomplete task
290
+ let nextTask: Task | null = null
291
+ let taskGroup = ''
292
+
293
+ for (const group of tasksFile.groups) {
294
+ for (const task of group.tasks) {
295
+ if (!task.completed) {
296
+ nextTask = task
297
+ taskGroup = group.title
298
+ break
299
+ }
300
+ }
301
+ if (nextTask) break
302
+ }
303
+
304
+ // Build context even if no task found
305
+ const context = await buildTaskContext(
306
+ basePath,
307
+ changeId,
308
+ tasksFile,
309
+ nextTask || { id: '', title: '', completed: false, groupId: '', lineNumber: 0 }
310
+ )
311
+
312
+ return {
313
+ task: nextTask,
314
+ context,
315
+ group: taskGroup,
316
+ }
317
+ }
318
+
319
+ /**
320
+ * Get detailed context for a specific task (OpenSpec) or TAG (MoAI SPEC)
321
+ * Returns full SPEC context for MoAI SPECs (spec.md + plan.md + acceptance.md)
322
+ */
323
+ async function getTaskContext(changeId: string, taskId: string, projectPath?: string) {
324
+ const basePath = projectPath || PROJECT_PATH
325
+
326
+ // Check if this is a MoAI SPEC
327
+ if (isMoaiSpec(changeId)) {
328
+ // Get full MoAI SPEC context
329
+ const moaiContext = await getMoaiSpecContext(changeId, basePath)
330
+
331
+ // Find the TAG
332
+ const tag = moaiContext.plan.tags.find(t => t.id === taskId)
333
+ if (!tag) {
334
+ throw new Error(`TAG not found: ${taskId}`)
335
+ }
336
+
337
+ // Convert TAG to Task format for compatibility
338
+ const task: Task = {
339
+ id: tag.id,
340
+ title: tag.title,
341
+ completed: tag.completed,
342
+ groupId: '',
343
+ lineNumber: 0,
344
+ displayId: tag.id,
345
+ }
346
+
347
+ // Return MoAI SPEC context as unknown (will be JSON stringified)
348
+ return {
349
+ task,
350
+ context: {
351
+ spec: moaiContext.spec,
352
+ plan: moaiContext.plan,
353
+ acceptance: moaiContext.acceptance,
354
+ } as unknown,
355
+ group: 'MoAI SPEC',
356
+ isMoaiSpec: true,
357
+ }
358
+ }
359
+
360
+ // OpenSpec format (legacy)
361
+ const tasksFile = await getTasks(changeId, basePath)
362
+
363
+ // Find the task
364
+ let targetTask: Task | null = null
365
+ let taskGroup = ''
366
+
367
+ for (const group of tasksFile.groups) {
368
+ const task = group.tasks.find(t => t.id === taskId)
369
+ if (task) {
370
+ targetTask = task
371
+ taskGroup = group.title
372
+ break
373
+ }
374
+ }
375
+
376
+ if (!targetTask) {
377
+ throw new Error(`Task not found: ${taskId}`)
378
+ }
379
+
380
+ const context = await buildTaskContext(basePath, changeId, tasksFile, targetTask)
381
+ const design = await readDesign(basePath, changeId)
382
+
383
+ // OpenSpec 1.0: 동적 인스트럭션 조회 (CLI가 있는 경우)
384
+ let instructions: unknown = null
385
+ let artifactStatus: unknown = null
386
+ try {
387
+ if (await isOpenSpecAvailable()) {
388
+ // apply 아티팩트의 인스트럭션 조회 (태스크 실행 시 필요)
389
+ const instructionsResult = await getInstructions('apply', { cwd: basePath, change: changeId })
390
+ if (instructionsResult.success) {
391
+ instructions = instructionsResult.data
392
+ }
393
+
394
+ // 아티팩트 상태 조회
395
+ const statusResult = await getChangeStatus({ cwd: basePath, change: changeId })
396
+ if (statusResult.success) {
397
+ artifactStatus = statusResult.data
398
+ }
399
+ }
400
+ } catch (err) {
401
+ // 인스트럭션 조회 실패는 무시 (선택적 기능)
402
+ console.warn('Failed to get dynamic instructions:', err)
403
+ }
404
+
405
+ return {
406
+ task: targetTask,
407
+ context: {
408
+ ...context,
409
+ design,
410
+ instructions,
411
+ artifactStatus,
412
+ },
413
+ group: taskGroup,
414
+ }
415
+ }
416
+
417
+ /**
418
+ * Mark a task as complete (OpenSpec) or TAG as complete (MoAI SPEC)
419
+ */
420
+ async function markComplete(changeId: string, taskId: string, projectPath?: string): Promise<Task> {
421
+ const basePath = projectPath || PROJECT_PATH
422
+
423
+ // Check if this is a MoAI SPEC
424
+ if (isMoaiSpec(changeId)) {
425
+ // Update plan.md for MoAI SPEC
426
+ await updateMoaiTagStatus(changeId, taskId, true, basePath)
427
+
428
+ // Also update database for dual-origin tracking
429
+ await updateMoaiTagInDatabase(changeId, taskId, true)
430
+
431
+ // Sync SPEC status if all TAGs are completed
432
+ const syncResult = await syncSpecStatusFromTags(changeId, basePath)
433
+ if (syncResult.statusChanged) {
434
+ console.log(`[MoAI] SPEC ${changeId} status updated to ${syncResult.newStatus}`)
435
+ }
436
+
437
+ // Get the updated TAG to return
438
+ const tag = await getMoaiTag(changeId, taskId, basePath)
439
+
440
+ // Return in Task format for compatibility
441
+ return {
442
+ id: tag.id,
443
+ title: tag.title,
444
+ completed: tag.completed,
445
+ groupId: '',
446
+ lineNumber: 0,
447
+ displayId: tag.id,
448
+ }
449
+ }
450
+
451
+ // OpenSpec format (legacy)
452
+ const tasksPath = join(basePath, 'openspec', 'changes', changeId, 'tasks.md')
453
+ const content = await readFile(tasksPath, 'utf-8')
454
+
455
+ const { newContent, task } = setTaskStatus(content, taskId, true)
456
+ await writeFile(tasksPath, newContent, 'utf-8')
457
+
458
+ return task
459
+ }
460
+
461
+ /**
462
+ * Mark a task as incomplete (OpenSpec) or TAG as incomplete (MoAI SPEC)
463
+ */
464
+ async function markIncomplete(changeId: string, taskId: string, projectPath?: string): Promise<Task> {
465
+ const basePath = projectPath || PROJECT_PATH
466
+
467
+ // Check if this is a MoAI SPEC
468
+ if (isMoaiSpec(changeId)) {
469
+ // Update plan.md for MoAI SPEC
470
+ await updateMoaiTagStatus(changeId, taskId, false, basePath)
471
+
472
+ // Also update database for dual-origin tracking
473
+ await updateMoaiTagInDatabase(changeId, taskId, false)
474
+
475
+ // Sync SPEC status (will revert to 'active' if it was 'completed')
476
+ const syncResult = await syncSpecStatusFromTags(changeId, basePath)
477
+ if (syncResult.statusChanged) {
478
+ console.log(`[MoAI] SPEC ${changeId} status updated to ${syncResult.newStatus}`)
479
+ }
480
+
481
+ // Get the updated TAG to return
482
+ const tag = await getMoaiTag(changeId, taskId, basePath)
483
+
484
+ // Return in Task format for compatibility
485
+ return {
486
+ id: tag.id,
487
+ title: tag.title,
488
+ completed: tag.completed,
489
+ groupId: '',
490
+ lineNumber: 0,
491
+ displayId: tag.id,
492
+ }
493
+ }
494
+
495
+ // OpenSpec format (legacy)
496
+ const tasksPath = join(basePath, 'openspec', 'changes', changeId, 'tasks.md')
497
+ const content = await readFile(tasksPath, 'utf-8')
498
+
499
+ const { newContent, task } = setTaskStatus(content, taskId, false)
500
+ await writeFile(tasksPath, newContent, 'utf-8')
501
+
502
+ return task
503
+ }
504
+
505
+ // Create server
506
+ const server = new Server(
507
+ {
508
+ name: 'zyflow',
509
+ version: '1.0.0',
510
+ },
511
+ {
512
+ capabilities: {
513
+ tools: {},
514
+ },
515
+ }
516
+ )
517
+
518
+ // List available tools
519
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
520
+ return {
521
+ tools: [
522
+ {
523
+ name: 'zyflow_global_search',
524
+ description: '모든 프로젝트에서 Changes를 검색합니다. 제목, ID, 프로젝트명으로 검색합니다.',
525
+ inputSchema: {
526
+ type: 'object' as const,
527
+ properties: {
528
+ query: {
529
+ type: 'string',
530
+ description: '검색어 (제목, ID, 프로젝트명에서 검색)',
531
+ },
532
+ limit: {
533
+ type: 'number',
534
+ description: '반환할 최대 결과 수 (기본: 10)',
535
+ },
536
+ },
537
+ required: ['query'],
538
+ },
539
+ },
540
+ {
541
+ name: 'zyflow_list_changes',
542
+ description: '현재 프로젝트의 OpenSpec 변경 제안과 MoAI SPEC 목록을 조회합니다. 각 항목의 ID, 제목, 진행률, 완료/전체 태스크 또는 TAG 수를 반환합니다.',
543
+ inputSchema: {
544
+ type: 'object' as const,
545
+ properties: {
546
+ projectPath: {
547
+ type: 'string',
548
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
549
+ },
550
+ },
551
+ required: [],
552
+ },
553
+ },
554
+ {
555
+ name: 'zyflow_get_tasks',
556
+ description: '특정 변경 제안의 전체 태스크 목록(OpenSpec) 또는 TAG 체인(MoAI SPEC)을 그룹별로 조회합니다.',
557
+ inputSchema: {
558
+ type: 'object' as const,
559
+ properties: {
560
+ changeId: {
561
+ type: 'string',
562
+ description: '변경 제안 ID (예: add-payment-method-registry) 또는 MoAI SPEC ID (예: SPEC-MIGR-001)',
563
+ },
564
+ projectPath: {
565
+ type: 'string',
566
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
567
+ },
568
+ },
569
+ required: ['changeId'],
570
+ },
571
+ },
572
+ {
573
+ name: 'zyflow_get_next_task',
574
+ description: '다음 미완료 태스크(OpenSpec) 또는 TAG(MoAI SPEC)와 실행에 필요한 컨텍스트를 조회합니다. MoAI SPEC의 경우 TAG 의존성을 고려합니다.',
575
+ inputSchema: {
576
+ type: 'object' as const,
577
+ properties: {
578
+ changeId: {
579
+ type: 'string',
580
+ description: '변경 제안 ID',
581
+ },
582
+ projectPath: {
583
+ type: 'string',
584
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
585
+ },
586
+ },
587
+ required: ['changeId'],
588
+ },
589
+ },
590
+ {
591
+ name: 'zyflow_get_task_context',
592
+ description: '특정 태스크(OpenSpec) 또는 TAG(MoAI SPEC)의 상세 컨텍스트를 조회합니다. OpenSpec의 경우 proposal/spec/design 문서, MoAI SPEC의 경우 spec.md/plan.md/acceptance.md를 포함합니다.',
593
+ inputSchema: {
594
+ type: 'object' as const,
595
+ properties: {
596
+ changeId: {
597
+ type: 'string',
598
+ description: '변경 제안 ID 또는 MoAI SPEC ID',
599
+ },
600
+ taskId: {
601
+ type: 'string',
602
+ description: '태스크 ID (예: task-1-1) 또는 TAG ID (예: TAG-001)',
603
+ },
604
+ projectPath: {
605
+ type: 'string',
606
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
607
+ },
608
+ },
609
+ required: ['changeId', 'taskId'],
610
+ },
611
+ },
612
+ {
613
+ name: 'zyflow_mark_complete',
614
+ description: '태스크(OpenSpec) 또는 TAG(MoAI SPEC)를 완료로 표시합니다. tasks.md 또는 plan.md 파일이 자동으로 업데이트됩니다.',
615
+ inputSchema: {
616
+ type: 'object' as const,
617
+ properties: {
618
+ changeId: {
619
+ type: 'string',
620
+ description: '변경 제안 ID 또는 MoAI SPEC ID',
621
+ },
622
+ taskId: {
623
+ type: 'string',
624
+ description: '태스크 ID 또는 TAG ID',
625
+ },
626
+ projectPath: {
627
+ type: 'string',
628
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
629
+ },
630
+ },
631
+ required: ['changeId', 'taskId'],
632
+ },
633
+ },
634
+ {
635
+ name: 'zyflow_mark_incomplete',
636
+ description: '태스크를 미완료로 되돌립니다. 잘못 완료 표시한 경우 사용합니다.',
637
+ inputSchema: {
638
+ type: 'object' as const,
639
+ properties: {
640
+ changeId: {
641
+ type: 'string',
642
+ description: '변경 제안 ID',
643
+ },
644
+ taskId: {
645
+ type: 'string',
646
+ description: '태스크 ID',
647
+ },
648
+ projectPath: {
649
+ type: 'string',
650
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
651
+ },
652
+ },
653
+ required: ['changeId', 'taskId'],
654
+ },
655
+ },
656
+ {
657
+ name: 'zyflow_unified_context',
658
+ description: '통합 컨텍스트 검색입니다. OpenSpec의 Changes/Tasks 정보와 claude-mem의 Memory(이전 작업 기록, 결정사항)를 함께 검색합니다.',
659
+ inputSchema: {
660
+ type: 'object' as const,
661
+ properties: {
662
+ query: {
663
+ type: 'string',
664
+ description: '검색어',
665
+ },
666
+ includeChanges: {
667
+ type: 'boolean',
668
+ description: 'OpenSpec Changes 포함 여부 (기본: true)',
669
+ },
670
+ includeMemory: {
671
+ type: 'boolean',
672
+ description: 'claude-mem Memory 포함 여부 (기본: true)',
673
+ },
674
+ limit: {
675
+ type: 'number',
676
+ description: '각 카테고리별 최대 결과 수 (기본: 5)',
677
+ },
678
+ },
679
+ required: ['query'],
680
+ },
681
+ },
682
+ // OpenSpec 1.0 CLI Integration Tools
683
+ {
684
+ name: 'zyflow_validate_change',
685
+ description: 'OpenSpec 변경을 검증합니다. 아티팩트의 무결성과 스키마 준수 여부를 확인합니다.',
686
+ inputSchema: {
687
+ type: 'object' as const,
688
+ properties: {
689
+ changeId: {
690
+ type: 'string',
691
+ description: '검증할 변경 제안 ID (선택, 없으면 현재 활성 변경)',
692
+ },
693
+ strict: {
694
+ type: 'boolean',
695
+ description: '엄격 모드 활성화 (경고도 오류로 처리)',
696
+ },
697
+ projectPath: {
698
+ type: 'string',
699
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
700
+ },
701
+ },
702
+ required: [],
703
+ },
704
+ },
705
+ {
706
+ name: 'zyflow_archive_change',
707
+ description: '완료된 변경을 아카이브합니다. 메인 스펙으로 동기화하고 변경 디렉토리를 archive로 이동합니다.',
708
+ inputSchema: {
709
+ type: 'object' as const,
710
+ properties: {
711
+ changeId: {
712
+ type: 'string',
713
+ description: '아카이브할 변경 제안 ID',
714
+ },
715
+ syncSpecs: {
716
+ type: 'boolean',
717
+ description: '메인 스펙으로 동기화 여부 (기본: true)',
718
+ },
719
+ projectPath: {
720
+ type: 'string',
721
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
722
+ },
723
+ },
724
+ required: ['changeId'],
725
+ },
726
+ },
727
+ {
728
+ name: 'zyflow_get_instructions',
729
+ description: 'OpenSpec 동적 인스트럭션을 조회합니다. 아티팩트 생성 또는 태스크 적용을 위한 컨텍스트 기반 지침을 제공합니다.',
730
+ inputSchema: {
731
+ type: 'object' as const,
732
+ properties: {
733
+ artifact: {
734
+ type: 'string',
735
+ description: '아티팩트 유형 (proposal, design, tasks, apply 등)',
736
+ },
737
+ changeId: {
738
+ type: 'string',
739
+ description: '변경 제안 ID (선택)',
740
+ },
741
+ projectPath: {
742
+ type: 'string',
743
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
744
+ },
745
+ },
746
+ required: ['artifact'],
747
+ },
748
+ },
749
+ {
750
+ name: 'zyflow_get_status',
751
+ description: 'OpenSpec 변경의 아티팩트 완료 상태를 조회합니다. 전체 진행률과 각 아티팩트 상태를 반환합니다.',
752
+ inputSchema: {
753
+ type: 'object' as const,
754
+ properties: {
755
+ changeId: {
756
+ type: 'string',
757
+ description: '변경 제안 ID (선택)',
758
+ },
759
+ projectPath: {
760
+ type: 'string',
761
+ description: '프로젝트 경로 (선택, 기본값: 현재 디렉토리)',
762
+ },
763
+ },
764
+ required: [],
765
+ },
766
+ },
767
+ // Task management tools (SQLite-based)
768
+ ...taskToolDefinitions,
769
+
770
+ // Integration Hub Tools
771
+ ...integrationToolDefinitions,
772
+
773
+ // Agent Tools
774
+ ...agentToolDefinitions,
775
+
776
+ // Change Log Tools
777
+ {
778
+ name: 'get_events',
779
+ description: 'Get change events with optional filtering',
780
+ inputSchema: {
781
+ type: 'object',
782
+ properties: {
783
+ event_types: {
784
+ type: 'array',
785
+ items: { type: 'string' },
786
+ description: 'Filter by event types (optional)',
787
+ },
788
+ severities: {
789
+ type: 'array',
790
+ items: { type: 'string' },
791
+ description: 'Filter by severity levels (optional)',
792
+ },
793
+ sources: {
794
+ type: 'array',
795
+ items: { type: 'string' },
796
+ description: 'Filter by event sources (optional)',
797
+ },
798
+ project_ids: {
799
+ type: 'array',
800
+ items: { type: 'string' },
801
+ description: 'Filter by project IDs (optional)',
802
+ },
803
+ change_ids: {
804
+ type: 'array',
805
+ items: { type: 'string' },
806
+ description: 'Filter by change IDs (optional)',
807
+ },
808
+ time_range: {
809
+ type: 'object',
810
+ properties: {
811
+ start: { type: 'string', description: 'Start date (ISO format)' },
812
+ end: { type: 'string', description: 'End date (ISO format)' },
813
+ },
814
+ description: 'Filter by time range (optional)',
815
+ },
816
+ limit: {
817
+ type: 'number',
818
+ description: 'Maximum number of events to return (optional)',
819
+ },
820
+ offset: {
821
+ type: 'number',
822
+ description: 'Number of events to skip (optional)',
823
+ },
824
+ sort_by: {
825
+ type: 'object',
826
+ properties: {
827
+ field: { type: 'string', description: 'Field to sort by' },
828
+ direction: { type: 'string', enum: ['ASC', 'DESC'], description: 'Sort direction' },
829
+ },
830
+ description: 'Sort options (optional)',
831
+ },
832
+ },
833
+ },
834
+ },
835
+ {
836
+ name: 'get_event_statistics',
837
+ description: 'Get event statistics',
838
+ inputSchema: {
839
+ type: 'object',
840
+ properties: {
841
+ event_types: {
842
+ type: 'array',
843
+ items: { type: 'string' },
844
+ description: 'Filter by event types (optional)',
845
+ },
846
+ time_range: {
847
+ type: 'object',
848
+ properties: {
849
+ start: { type: 'string', description: 'Start date (ISO format)' },
850
+ end: { type: 'string', description: 'End date (ISO format)' },
851
+ },
852
+ description: 'Filter by time range (optional)',
853
+ },
854
+ },
855
+ },
856
+ },
857
+ {
858
+ name: 'search_events',
859
+ description: 'Search events by text query',
860
+ inputSchema: {
861
+ type: 'object',
862
+ properties: {
863
+ query: {
864
+ type: 'string',
865
+ description: 'Search query',
866
+ },
867
+ event_types: {
868
+ type: 'array',
869
+ items: { type: 'string' },
870
+ description: 'Filter by event types (optional)',
871
+ },
872
+ time_range: {
873
+ type: 'object',
874
+ properties: {
875
+ start: { type: 'string', description: 'Start date (ISO format)' },
876
+ end: { type: 'string', description: 'End date (ISO format)' },
877
+ },
878
+ description: 'Filter by time range (optional)',
879
+ },
880
+ },
881
+ required: ['query'],
882
+ },
883
+ },
884
+ {
885
+ name: 'export_events',
886
+ description: 'Export events in various formats',
887
+ inputSchema: {
888
+ type: 'object',
889
+ properties: {
890
+ filter: {
891
+ type: 'object',
892
+ description: 'Event filter (same as get_events)',
893
+ },
894
+ format: {
895
+ type: 'string',
896
+ enum: ['JSON', 'CSV', 'SQL'],
897
+ description: 'Export format',
898
+ default: 'JSON',
899
+ },
900
+ },
901
+ },
902
+ },
903
+
904
+ // Replay Tools
905
+ {
906
+ name: 'create_replay_session',
907
+ description: 'Create a replay session',
908
+ inputSchema: {
909
+ type: 'object',
910
+ properties: {
911
+ name: {
912
+ type: 'string',
913
+ description: 'Session name',
914
+ },
915
+ description: {
916
+ type: 'string',
917
+ description: 'Session description (optional)',
918
+ },
919
+ filter: {
920
+ type: 'object',
921
+ description: 'Event filter for replay',
922
+ },
923
+ mode: {
924
+ type: 'string',
925
+ enum: ['SAFE', 'FAST', 'VERBOSE', 'DRY_RUN'],
926
+ description: 'Replay mode',
927
+ default: 'SAFE',
928
+ },
929
+ strategy: {
930
+ type: 'string',
931
+ enum: ['SEQUENTIAL', 'PARALLEL', 'DEPENDENCY_AWARE', 'SELECTIVE'],
932
+ description: 'Replay strategy',
933
+ default: 'SEQUENTIAL',
934
+ },
935
+ stop_on_error: {
936
+ type: 'boolean',
937
+ description: 'Stop on error',
938
+ default: true,
939
+ },
940
+ enable_validation: {
941
+ type: 'boolean',
942
+ description: 'Enable validation',
943
+ default: true,
944
+ },
945
+ enable_rollback: {
946
+ type: 'boolean',
947
+ description: 'Enable rollback',
948
+ default: false,
949
+ },
950
+ max_concurrency: {
951
+ type: 'number',
952
+ description: 'Maximum concurrency for parallel replay',
953
+ },
954
+ skip_events: {
955
+ type: 'array',
956
+ items: { type: 'string' },
957
+ description: 'Event IDs to skip',
958
+ },
959
+ include_events: {
960
+ type: 'array',
961
+ items: { type: 'string' },
962
+ description: 'Event IDs to include',
963
+ },
964
+ },
965
+ required: ['name'],
966
+ },
967
+ },
968
+ {
969
+ name: 'start_replay',
970
+ description: 'Start a replay session',
971
+ inputSchema: {
972
+ type: 'object',
973
+ properties: {
974
+ session_id: {
975
+ type: 'string',
976
+ description: 'Replay session ID',
977
+ },
978
+ },
979
+ required: ['session_id'],
980
+ },
981
+ },
982
+ {
983
+ name: 'get_replay_progress',
984
+ description: 'Get replay session progress',
985
+ inputSchema: {
986
+ type: 'object',
987
+ properties: {
988
+ session_id: {
989
+ type: 'string',
990
+ description: 'Replay session ID',
991
+ },
992
+ },
993
+ required: ['session_id'],
994
+ },
995
+ },
996
+
997
+ // RAG 기능 삭제됨 - LEANN 외부 MCP 서버(leann-server) 사용
998
+ ],
999
+ }
1000
+ })
1001
+
1002
+ // Handle tool calls
1003
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1004
+ const { name, arguments: args } = request.params
1005
+
1006
+ try {
1007
+ switch (name) {
1008
+ case 'zyflow_global_search': {
1009
+ const { query, limit = 10 } = args as { query: string; limit?: number }
1010
+
1011
+ // Fetch all projects data from the API
1012
+ const API_BASE = process.env.ZYFLOW_API_BASE || 'http://localhost:3200'
1013
+
1014
+ let allProjects: Record<string, unknown>[] = []
1015
+
1016
+ try {
1017
+ const response = await fetch(`${API_BASE}/api/projects/all-data`)
1018
+ if (response.ok) {
1019
+ const json = await response.json() as { data?: { projects?: Record<string, unknown>[] } }
1020
+ allProjects = json.data?.projects || []
1021
+ }
1022
+ } catch (_err) {
1023
+ // API not available, fall back to local project only
1024
+ const localChanges = await listChanges()
1025
+ allProjects = [{
1026
+ id: 'local',
1027
+ name: 'Current Project',
1028
+ path: PROJECT_PATH,
1029
+ changes: localChanges,
1030
+ }]
1031
+ }
1032
+
1033
+ // Collect all changes with project info
1034
+ const allChanges: Record<string, unknown>[] = []
1035
+ for (const project of allProjects) {
1036
+ if (project.changes) {
1037
+ for (const change of project.changes) {
1038
+ allChanges.push({
1039
+ id: change.id,
1040
+ title: change.title,
1041
+ progress: change.progress || 0,
1042
+ totalTasks: change.totalTasks || 0,
1043
+ completedTasks: change.completedTasks || 0,
1044
+ projectId: project.id,
1045
+ projectName: project.name,
1046
+ projectPath: project.path,
1047
+ })
1048
+ }
1049
+ }
1050
+ }
1051
+
1052
+ // Search
1053
+ const queryLower = query.toLowerCase()
1054
+ const results = allChanges.filter(c =>
1055
+ c.title.toLowerCase().includes(queryLower) ||
1056
+ c.id.toLowerCase().includes(queryLower) ||
1057
+ c.projectName.toLowerCase().includes(queryLower)
1058
+ ).slice(0, limit)
1059
+
1060
+ return {
1061
+ content: [
1062
+ {
1063
+ type: 'text' as const,
1064
+ text: JSON.stringify({
1065
+ query,
1066
+ totalResults: results.length,
1067
+ results,
1068
+ }, null, 2),
1069
+ },
1070
+ ],
1071
+ }
1072
+ }
1073
+
1074
+ case 'zyflow_list_changes': {
1075
+ const { projectPath } = args as { projectPath?: string }
1076
+ const changes = await listChanges(projectPath)
1077
+ return {
1078
+ content: [
1079
+ {
1080
+ type: 'text' as const,
1081
+ text: JSON.stringify({ changes, projectPath: projectPath || PROJECT_PATH }, null, 2),
1082
+ },
1083
+ ],
1084
+ }
1085
+ }
1086
+
1087
+ case 'zyflow_get_tasks': {
1088
+ const { changeId, projectPath } = args as { changeId: string; projectPath?: string }
1089
+ const tasksFile = await getTasks(changeId, projectPath)
1090
+ return {
1091
+ content: [
1092
+ {
1093
+ type: 'text' as const,
1094
+ text: JSON.stringify(tasksFile, null, 2),
1095
+ },
1096
+ ],
1097
+ }
1098
+ }
1099
+
1100
+ case 'zyflow_get_next_task': {
1101
+ const { changeId, projectPath } = args as { changeId: string; projectPath?: string }
1102
+ const result = await getNextTask(changeId, projectPath)
1103
+ return {
1104
+ content: [
1105
+ {
1106
+ type: 'text' as const,
1107
+ text: JSON.stringify(result, null, 2),
1108
+ },
1109
+ ],
1110
+ }
1111
+ }
1112
+
1113
+ case 'zyflow_get_task_context': {
1114
+ const { changeId, taskId, projectPath } = args as { changeId: string; taskId: string; projectPath?: string }
1115
+ const result = await getTaskContext(changeId, taskId, projectPath)
1116
+ return {
1117
+ content: [
1118
+ {
1119
+ type: 'text' as const,
1120
+ text: JSON.stringify(result, null, 2),
1121
+ },
1122
+ ],
1123
+ }
1124
+ }
1125
+
1126
+ case 'zyflow_mark_complete': {
1127
+ const { changeId, taskId, projectPath } = args as { changeId: string; taskId: string; projectPath?: string }
1128
+ const task = await markComplete(changeId, taskId, projectPath)
1129
+
1130
+ // Get updated progress
1131
+ const tasksFile = await getTasks(changeId, projectPath)
1132
+ const allTasks = tasksFile.groups.flatMap(g => g.tasks)
1133
+ const completed = allTasks.filter(t => t.completed).length
1134
+ const total = allTasks.length
1135
+
1136
+ return {
1137
+ content: [
1138
+ {
1139
+ type: 'text' as const,
1140
+ text: JSON.stringify({
1141
+ success: true,
1142
+ task,
1143
+ progress: `${completed}/${total}`,
1144
+ message: `태스크 "${task.title}"를 완료로 표시했습니다.`,
1145
+ }, null, 2),
1146
+ },
1147
+ ],
1148
+ }
1149
+ }
1150
+
1151
+ case 'zyflow_mark_incomplete': {
1152
+ const { changeId, taskId, projectPath } = args as { changeId: string; taskId: string; projectPath?: string }
1153
+ const task = await markIncomplete(changeId, taskId, projectPath)
1154
+
1155
+ // Get updated progress
1156
+ const tasksFile = await getTasks(changeId, projectPath)
1157
+ const allTasks = tasksFile.groups.flatMap(g => g.tasks)
1158
+ const completed = allTasks.filter(t => t.completed).length
1159
+ const total = allTasks.length
1160
+
1161
+ return {
1162
+ content: [
1163
+ {
1164
+ type: 'text' as const,
1165
+ text: JSON.stringify({
1166
+ success: true,
1167
+ task,
1168
+ progress: `${completed}/${total}`,
1169
+ message: `태스크 "${task.title}"를 미완료로 되돌렸습니다.`,
1170
+ }, null, 2),
1171
+ },
1172
+ ],
1173
+ }
1174
+ }
1175
+
1176
+ case 'zyflow_unified_context': {
1177
+ const { query, includeChanges = true, includeMemory = true, limit = 5 } = args as {
1178
+ query: string
1179
+ includeChanges?: boolean
1180
+ includeMemory?: boolean
1181
+ limit?: number
1182
+ }
1183
+
1184
+ const results: {
1185
+ changes?: Record<string, unknown>[]
1186
+ memory?: Record<string, unknown>[]
1187
+ } = {}
1188
+
1189
+ // 1. Changes/Tasks 검색
1190
+ if (includeChanges) {
1191
+ const API_BASE = process.env.ZYFLOW_API_BASE || 'http://localhost:3200'
1192
+ try {
1193
+ const response = await fetch(`${API_BASE}/api/projects/all-data`)
1194
+ if (response.ok) {
1195
+ const json = await response.json() as { data?: { projects?: Record<string, unknown>[] } }
1196
+ const allProjects = json.data?.projects || []
1197
+ const allChanges: Record<string, unknown>[] = []
1198
+
1199
+ for (const project of allProjects) {
1200
+ if (project.changes) {
1201
+ for (const change of project.changes) {
1202
+ allChanges.push({
1203
+ id: change.id,
1204
+ title: change.title,
1205
+ progress: change.progress || 0,
1206
+ projectId: project.id,
1207
+ projectName: project.name,
1208
+ })
1209
+ }
1210
+ }
1211
+ }
1212
+
1213
+ const queryLower = query.toLowerCase()
1214
+ results.changes = allChanges.filter(c =>
1215
+ c.title.toLowerCase().includes(queryLower) ||
1216
+ c.id.toLowerCase().includes(queryLower)
1217
+ ).slice(0, limit)
1218
+ }
1219
+ } catch {
1220
+ // API not available
1221
+ results.changes = []
1222
+ }
1223
+ }
1224
+
1225
+ // 2. claude-mem Memory 검색
1226
+ if (includeMemory) {
1227
+ const homedir = process.env.HOME || process.env.USERPROFILE || ''
1228
+ const memDbPath = `${homedir}/.claude-mem/memory.db`
1229
+
1230
+ try {
1231
+ const fs = await import('fs')
1232
+ if (fs.existsSync(memDbPath)) {
1233
+ const Database = (await import('better-sqlite3')).default
1234
+ const db = new Database(memDbPath, { readonly: true })
1235
+
1236
+ const searchPattern = `%${query}%`
1237
+ const stmt = db.prepare(`
1238
+ SELECT id, type, title, subtitle
1239
+ FROM observations
1240
+ WHERE title LIKE ? OR subtitle LIKE ? OR facts LIKE ? OR narrative LIKE ?
1241
+ ORDER BY created_at DESC
1242
+ LIMIT ?
1243
+ `)
1244
+ const rows = stmt.all(searchPattern, searchPattern, searchPattern, searchPattern, limit) as Array<{
1245
+ id: number
1246
+ type: string
1247
+ title: string
1248
+ subtitle: string | null
1249
+ }>
1250
+
1251
+ results.memory = rows.map(row => ({
1252
+ id: row.id,
1253
+ type: row.type || 'unknown',
1254
+ title: row.title || 'Untitled',
1255
+ subtitle: row.subtitle || undefined,
1256
+ }))
1257
+
1258
+ db.close()
1259
+ } else {
1260
+ results.memory = []
1261
+ }
1262
+ } catch {
1263
+ results.memory = []
1264
+ }
1265
+ }
1266
+
1267
+ return {
1268
+ content: [
1269
+ {
1270
+ type: 'text' as const,
1271
+ text: JSON.stringify({
1272
+ success: true,
1273
+ query,
1274
+ results,
1275
+ message: `통합 검색 결과: Changes ${results.changes?.length || 0}개, Memory ${results.memory?.length || 0}개`,
1276
+ }, null, 2),
1277
+ },
1278
+ ],
1279
+ }
1280
+ }
1281
+
1282
+ // OpenSpec 1.0 CLI Integration Tools
1283
+ case 'zyflow_validate_change': {
1284
+ const { changeId, strict, projectPath } = args as {
1285
+ changeId?: string
1286
+ strict?: boolean
1287
+ projectPath?: string
1288
+ }
1289
+ const cwd = projectPath || PROJECT_PATH
1290
+
1291
+ // Check if OpenSpec CLI is available
1292
+ const available = await isOpenSpecAvailable()
1293
+ if (!available) {
1294
+ return {
1295
+ content: [{
1296
+ type: 'text' as const,
1297
+ text: JSON.stringify({
1298
+ success: false,
1299
+ error: 'OpenSpec CLI가 설치되어 있지 않습니다. npm install -g openspec 으로 설치해주세요.',
1300
+ }, null, 2),
1301
+ }],
1302
+ isError: true,
1303
+ }
1304
+ }
1305
+
1306
+ const result = await validateChange(changeId, { cwd, strict })
1307
+ return {
1308
+ content: [{
1309
+ type: 'text' as const,
1310
+ text: JSON.stringify({
1311
+ success: result.success,
1312
+ validation: result.data,
1313
+ error: result.error,
1314
+ message: result.success
1315
+ ? '변경 검증이 완료되었습니다.'
1316
+ : `검증 실패: ${result.error}`,
1317
+ }, null, 2),
1318
+ }],
1319
+ isError: !result.success,
1320
+ }
1321
+ }
1322
+
1323
+ case 'zyflow_archive_change': {
1324
+ const { changeId, syncSpecs = true, projectPath } = args as {
1325
+ changeId: string
1326
+ syncSpecs?: boolean
1327
+ projectPath?: string
1328
+ }
1329
+ const cwd = projectPath || PROJECT_PATH
1330
+
1331
+ const available = await isOpenSpecAvailable()
1332
+ if (!available) {
1333
+ return {
1334
+ content: [{
1335
+ type: 'text' as const,
1336
+ text: JSON.stringify({
1337
+ success: false,
1338
+ error: 'OpenSpec CLI가 설치되어 있지 않습니다.',
1339
+ }, null, 2),
1340
+ }],
1341
+ isError: true,
1342
+ }
1343
+ }
1344
+
1345
+ const result = await archiveChange(changeId, { cwd, syncSpecs })
1346
+ return {
1347
+ content: [{
1348
+ type: 'text' as const,
1349
+ text: JSON.stringify({
1350
+ success: result.success,
1351
+ data: result.data,
1352
+ error: result.error,
1353
+ message: result.success
1354
+ ? `변경 "${changeId}"가 성공적으로 아카이브되었습니다.`
1355
+ : `아카이브 실패: ${result.error}`,
1356
+ }, null, 2),
1357
+ }],
1358
+ isError: !result.success,
1359
+ }
1360
+ }
1361
+
1362
+ case 'zyflow_get_instructions': {
1363
+ const { artifact, changeId, projectPath } = args as {
1364
+ artifact: string
1365
+ changeId?: string
1366
+ projectPath?: string
1367
+ }
1368
+ const cwd = projectPath || PROJECT_PATH
1369
+
1370
+ const available = await isOpenSpecAvailable()
1371
+ if (!available) {
1372
+ return {
1373
+ content: [{
1374
+ type: 'text' as const,
1375
+ text: JSON.stringify({
1376
+ success: false,
1377
+ error: 'OpenSpec CLI가 설치되어 있지 않습니다.',
1378
+ }, null, 2),
1379
+ }],
1380
+ isError: true,
1381
+ }
1382
+ }
1383
+
1384
+ const result = await getInstructions(artifact, { cwd, change: changeId })
1385
+ return {
1386
+ content: [{
1387
+ type: 'text' as const,
1388
+ text: JSON.stringify({
1389
+ success: result.success,
1390
+ instructions: result.data,
1391
+ error: result.error,
1392
+ message: result.success
1393
+ ? `${artifact} 아티팩트 인스트럭션을 조회했습니다.`
1394
+ : `인스트럭션 조회 실패: ${result.error}`,
1395
+ }, null, 2),
1396
+ }],
1397
+ isError: !result.success,
1398
+ }
1399
+ }
1400
+
1401
+ case 'zyflow_get_status': {
1402
+ const { changeId, projectPath } = args as {
1403
+ changeId?: string
1404
+ projectPath?: string
1405
+ }
1406
+ const cwd = projectPath || PROJECT_PATH
1407
+
1408
+ const available = await isOpenSpecAvailable()
1409
+ if (!available) {
1410
+ return {
1411
+ content: [{
1412
+ type: 'text' as const,
1413
+ text: JSON.stringify({
1414
+ success: false,
1415
+ error: 'OpenSpec CLI가 설치되어 있지 않습니다.',
1416
+ }, null, 2),
1417
+ }],
1418
+ isError: true,
1419
+ }
1420
+ }
1421
+
1422
+ const result = await getChangeStatus({ cwd, change: changeId })
1423
+ return {
1424
+ content: [{
1425
+ type: 'text' as const,
1426
+ text: JSON.stringify({
1427
+ success: result.success,
1428
+ status: result.data,
1429
+ error: result.error,
1430
+ message: result.success
1431
+ ? '변경 상태를 조회했습니다.'
1432
+ : `상태 조회 실패: ${result.error}`,
1433
+ }, null, 2),
1434
+ }],
1435
+ isError: !result.success,
1436
+ }
1437
+ }
1438
+
1439
+ // Task management tools (SQLite-based)
1440
+ case 'task_list': {
1441
+ const { projectPath, ...restArgs } = args as { projectPath?: string } & Parameters<typeof handleTaskList>[0]
1442
+ const effectivePath = projectPath || PROJECT_PATH
1443
+ initTaskDb(effectivePath)
1444
+ const result = handleTaskList(restArgs, effectivePath)
1445
+ return {
1446
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1447
+ isError: !result.success,
1448
+ }
1449
+ }
1450
+
1451
+ case 'task_create': {
1452
+ const { projectPath, ...restArgs } = args as { projectPath?: string } & Parameters<typeof handleTaskCreate>[0]
1453
+ const effectivePath = projectPath || PROJECT_PATH
1454
+ initTaskDb(effectivePath)
1455
+ const result = handleTaskCreate(restArgs, effectivePath)
1456
+ return {
1457
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1458
+ isError: !result.success,
1459
+ }
1460
+ }
1461
+
1462
+ case 'task_update': {
1463
+ const { projectPath, ...restArgs } = args as { projectPath?: string } & Parameters<typeof handleTaskUpdate>[0]
1464
+ const effectivePath = projectPath || PROJECT_PATH
1465
+ initTaskDb(effectivePath)
1466
+ const result = handleTaskUpdate(restArgs, effectivePath)
1467
+ return {
1468
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1469
+ isError: !result.success,
1470
+ }
1471
+ }
1472
+
1473
+ case 'task_search': {
1474
+ const { projectPath, ...restArgs } = args as { projectPath?: string } & Parameters<typeof handleTaskSearch>[0]
1475
+ const effectivePath = projectPath || PROJECT_PATH
1476
+ initTaskDb(effectivePath)
1477
+ const result = handleTaskSearch(restArgs, effectivePath)
1478
+ return {
1479
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1480
+ isError: !result.success,
1481
+ }
1482
+ }
1483
+
1484
+ case 'task_delete': {
1485
+ const { projectPath, id } = args as { projectPath?: string; id: string }
1486
+ const effectivePath = projectPath || PROJECT_PATH
1487
+ initTaskDb(effectivePath)
1488
+ const result = handleTaskDelete({ id }, effectivePath)
1489
+ return {
1490
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1491
+ isError: !result.success,
1492
+ }
1493
+ }
1494
+
1495
+ case 'task_view': {
1496
+ const { projectPath, id } = args as { projectPath?: string; id: string }
1497
+ const effectivePath = projectPath || PROJECT_PATH
1498
+ initTaskDb(effectivePath)
1499
+ const result = handleTaskView({ id }, effectivePath)
1500
+ return {
1501
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1502
+ isError: !result.success,
1503
+ }
1504
+ }
1505
+
1506
+ case 'task_archive': {
1507
+ const { projectPath, id } = args as { projectPath?: string; id: string }
1508
+ const effectivePath = projectPath || PROJECT_PATH
1509
+ initTaskDb(effectivePath)
1510
+ const result = handleTaskArchive({ id }, effectivePath)
1511
+ return {
1512
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1513
+ isError: !result.success,
1514
+ }
1515
+ }
1516
+
1517
+ case 'task_unarchive': {
1518
+ const { projectPath, id } = args as { projectPath?: string; id: string }
1519
+ const effectivePath = projectPath || PROJECT_PATH
1520
+ initTaskDb(effectivePath)
1521
+ const result = handleTaskUnarchive({ id }, effectivePath)
1522
+ return {
1523
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1524
+ isError: !result.success,
1525
+ }
1526
+ }
1527
+
1528
+ // Integration Hub Tools
1529
+ case 'integration_context': {
1530
+ const result = await handleIntegrationContext(args as { projectId: string })
1531
+ return {
1532
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1533
+ isError: !result.success,
1534
+ }
1535
+ }
1536
+
1537
+ case 'integration_list_accounts': {
1538
+ const result = await handleListAccounts(args as { type?: 'github' | 'supabase' | 'vercel' | 'sentry' | 'custom' })
1539
+ return {
1540
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1541
+ isError: !result.success,
1542
+ }
1543
+ }
1544
+
1545
+ case 'integration_get_env': {
1546
+ const result = await handleGetEnv(args as { projectId: string; envId?: string })
1547
+ return {
1548
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1549
+ isError: !result.success,
1550
+ }
1551
+ }
1552
+
1553
+ case 'integration_apply_git': {
1554
+ const result = await handleApplyGit(args as { projectId: string; scope?: 'local' | 'global' }, PROJECT_PATH)
1555
+ return {
1556
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1557
+ isError: !result.success,
1558
+ }
1559
+ }
1560
+
1561
+ case 'integration_get_test_account': {
1562
+ const result = await handleGetTestAccount(args as { projectId: string; role?: string })
1563
+ return {
1564
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1565
+ isError: !result.success,
1566
+ }
1567
+ }
1568
+
1569
+ case 'integration_scan_env': {
1570
+ const result = await handleScanEnv(args as { projectPath: string })
1571
+ return {
1572
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1573
+ isError: !result.success,
1574
+ }
1575
+ }
1576
+
1577
+ case 'integration_import_env': {
1578
+ const result = await handleImportEnv(args as { projectPath: string; services: Array<{ type: string; name: string }> })
1579
+ return {
1580
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1581
+ isError: !result.success,
1582
+ }
1583
+ }
1584
+
1585
+ // 새로운 로컬 설정 도구
1586
+ case 'integration_init_local': {
1587
+ const result = await handleInitLocal(args as { projectPath: string })
1588
+ return {
1589
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1590
+ isError: !result.success,
1591
+ }
1592
+ }
1593
+
1594
+ case 'integration_export_to_local': {
1595
+ const result = await handleExportToLocal(args as {
1596
+ projectPath: string
1597
+ projectId: string
1598
+ includeEnvironments?: boolean
1599
+ includeTestAccounts?: boolean
1600
+ })
1601
+ return {
1602
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1603
+ isError: !result.success,
1604
+ }
1605
+ }
1606
+
1607
+ // Agent Tools
1608
+ case 'zyflow_execute_change': {
1609
+ const result = await handleExecuteChange(
1610
+ args as { changeId: string; projectPath?: string; model?: 'claude-sonnet' | 'claude-haiku' | 'claude-opus' },
1611
+ PROJECT_PATH
1612
+ )
1613
+ return {
1614
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1615
+ isError: !result.success,
1616
+ }
1617
+ }
1618
+
1619
+ case 'zyflow_get_agent_status': {
1620
+ const result = await handleGetAgentStatus(args as { sessionId: string })
1621
+ return {
1622
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1623
+ isError: !result.success,
1624
+ }
1625
+ }
1626
+
1627
+ case 'zyflow_stop_agent': {
1628
+ const result = await handleStopAgent(args as { sessionId: string })
1629
+ return {
1630
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1631
+ isError: !result.success,
1632
+ }
1633
+ }
1634
+
1635
+ case 'zyflow_resume_agent': {
1636
+ const result = await handleResumeAgent(args as { sessionId: string })
1637
+ return {
1638
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1639
+ isError: !result.success,
1640
+ }
1641
+ }
1642
+
1643
+ case 'zyflow_list_agent_sessions': {
1644
+ const result = await handleListAgentSessions(args as { status?: string })
1645
+ return {
1646
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1647
+ isError: !result.success,
1648
+ }
1649
+ }
1650
+
1651
+ case 'zyflow_get_agent_logs': {
1652
+ const result = await handleGetAgentLogs(args as { sessionId: string })
1653
+ return {
1654
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1655
+ isError: !result.success,
1656
+ }
1657
+ }
1658
+
1659
+ case 'zyflow_delete_agent_session': {
1660
+ const result = await handleDeleteAgentSession(args as { sessionId: string })
1661
+ return {
1662
+ content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }],
1663
+ isError: !result.success,
1664
+ }
1665
+ }
1666
+
1667
+ // Change Log Tools
1668
+ case 'get_events':
1669
+ return await handleGetEvents((args || {}) as GetEventsArgs);
1670
+ case 'get_event_statistics':
1671
+ return await handleGetEventStatistics((args || {}) as GetEventStatisticsArgs);
1672
+ case 'search_events':
1673
+ return await handleSearchEvents(args as unknown as SearchEventsArgs);
1674
+ case 'export_events':
1675
+ return await handleExportEvents((args || {}) as ExportEventsArgs);
1676
+
1677
+ // Replay Tools
1678
+ case 'create_replay_session':
1679
+ return await handleCreateReplaySession(args as unknown as CreateReplaySessionArgs);
1680
+ case 'start_replay':
1681
+ return await handleStartReplay(args as unknown as StartReplayArgs);
1682
+ case 'get_replay_progress':
1683
+ return await handleGetReplayProgress(args as unknown as GetReplayProgressArgs);
1684
+
1685
+ default:
1686
+ throw new Error(`Unknown tool: ${name}`)
1687
+ }
1688
+ } catch (error) {
1689
+ const message = error instanceof Error ? error.message : String(error)
1690
+ return {
1691
+ content: [
1692
+ {
1693
+ type: 'text' as const,
1694
+ text: JSON.stringify({ error: message }, null, 2),
1695
+ },
1696
+ ],
1697
+ isError: true,
1698
+ }
1699
+ }
1700
+ })
1701
+
1702
+ // =============================================
1703
+ // Change Log & Replay Tool Handlers
1704
+ // =============================================
1705
+
1706
+ async function handleGetEvents(args: GetEventsArgs) {
1707
+ const changeLogManager = getChangeLogManager();
1708
+
1709
+ try {
1710
+ const filter: EventFilter = {};
1711
+
1712
+ if (args.event_types) {
1713
+ filter.eventTypes = args.event_types;
1714
+ }
1715
+
1716
+ if (args.severities) {
1717
+ filter.severities = args.severities;
1718
+ }
1719
+
1720
+ if (args.sources) {
1721
+ filter.sources = args.sources;
1722
+ }
1723
+
1724
+ if (args.project_ids) {
1725
+ filter.projectIds = args.project_ids;
1726
+ }
1727
+
1728
+ if (args.change_ids) {
1729
+ filter.changeIds = args.change_ids;
1730
+ }
1731
+
1732
+ if (args.time_range) {
1733
+ filter.timeRange = {
1734
+ start: new Date(args.time_range.start).getTime(),
1735
+ end: new Date(args.time_range.end).getTime()
1736
+ };
1737
+ }
1738
+
1739
+ if (args.limit) {
1740
+ filter.pagination = {
1741
+ offset: args.offset || 0,
1742
+ limit: args.limit
1743
+ };
1744
+ }
1745
+
1746
+ if (args.sort_by) {
1747
+ filter.sortBy = {
1748
+ field: args.sort_by.field || 'timestamp',
1749
+ direction: args.sort_by.direction || 'DESC'
1750
+ };
1751
+ }
1752
+
1753
+ const events = await changeLogManager.getEvents(filter);
1754
+
1755
+ return {
1756
+ content: [
1757
+ {
1758
+ type: 'text' as const,
1759
+ text: `Found ${events.length} events matching the filter criteria.`,
1760
+ },
1761
+ {
1762
+ type: 'text' as const,
1763
+ text: JSON.stringify(events, null, 2),
1764
+ },
1765
+ ],
1766
+ };
1767
+ } catch (error) {
1768
+ throw new McpError(
1769
+ ErrorCode.InternalError,
1770
+ `Failed to get events: ${(error as Error).message}`
1771
+ );
1772
+ }
1773
+ }
1774
+
1775
+ async function handleGetEventStatistics(args: GetEventStatisticsArgs) {
1776
+ const changeLogManager = getChangeLogManager();
1777
+
1778
+ try {
1779
+ const filter: EventFilter = {};
1780
+
1781
+ if (args.event_types) {
1782
+ filter.eventTypes = args.event_types;
1783
+ }
1784
+
1785
+ if (args.time_range) {
1786
+ filter.timeRange = {
1787
+ start: new Date(args.time_range.start).getTime(),
1788
+ end: new Date(args.time_range.end).getTime()
1789
+ };
1790
+ }
1791
+
1792
+ const statistics = await changeLogManager.getStatistics(filter);
1793
+
1794
+ return {
1795
+ content: [
1796
+ {
1797
+ type: 'text' as const,
1798
+ text: 'Event Statistics:',
1799
+ },
1800
+ {
1801
+ type: 'text' as const,
1802
+ text: JSON.stringify(statistics, null, 2),
1803
+ },
1804
+ ],
1805
+ };
1806
+ } catch (error) {
1807
+ throw new McpError(
1808
+ ErrorCode.InternalError,
1809
+ `Failed to get event statistics: ${(error as Error).message}`
1810
+ );
1811
+ }
1812
+ }
1813
+
1814
+ async function handleSearchEvents(args: SearchEventsArgs) {
1815
+ const changeLogManager = getChangeLogManager();
1816
+
1817
+ try {
1818
+ const { query, ...filterArgs } = args;
1819
+
1820
+ const filter: EventFilter = {};
1821
+
1822
+ if (filterArgs.event_types) {
1823
+ filter.eventTypes = filterArgs.event_types;
1824
+ }
1825
+
1826
+ if (filterArgs.time_range) {
1827
+ filter.timeRange = {
1828
+ start: new Date(filterArgs.time_range.start).getTime(),
1829
+ end: new Date(filterArgs.time_range.end).getTime()
1830
+ };
1831
+ }
1832
+
1833
+ const events = await changeLogManager.searchEvents(query, filter);
1834
+
1835
+ return {
1836
+ content: [
1837
+ {
1838
+ type: 'text' as const,
1839
+ text: `Found ${events.length} events matching query: "${query}"`,
1840
+ },
1841
+ {
1842
+ type: 'text' as const,
1843
+ text: JSON.stringify(events, null, 2),
1844
+ },
1845
+ ],
1846
+ };
1847
+ } catch (error) {
1848
+ throw new McpError(
1849
+ ErrorCode.InternalError,
1850
+ `Failed to search events: ${(error as Error).message}`
1851
+ );
1852
+ }
1853
+ }
1854
+
1855
+ async function handleExportEvents(args: ExportEventsArgs) {
1856
+ const changeLogManager = getChangeLogManager();
1857
+
1858
+ try {
1859
+ const filter: EventFilter = args.filter || {};
1860
+ const format = args.format || 'JSON';
1861
+
1862
+ const exportedData = await changeLogManager.exportData(filter, format);
1863
+
1864
+ return {
1865
+ content: [
1866
+ {
1867
+ type: 'text' as const,
1868
+ text: `Exported events in ${format} format:`,
1869
+ },
1870
+ {
1871
+ type: 'text' as const,
1872
+ text: exportedData,
1873
+ },
1874
+ ],
1875
+ };
1876
+ } catch (error) {
1877
+ throw new McpError(
1878
+ ErrorCode.InternalError,
1879
+ `Failed to export events: ${(error as Error).message}`
1880
+ );
1881
+ }
1882
+ }
1883
+
1884
+ async function handleCreateReplaySession(args: CreateReplaySessionArgs) {
1885
+ try {
1886
+ const replayEngine = getReplayEngine();
1887
+
1888
+ const filter: EventFilter = args.filter || {};
1889
+ const options: ReplayOptions = {
1890
+ mode: args.mode || 'SAFE',
1891
+ strategy: args.strategy || 'SEQUENTIAL',
1892
+ stopOnError: args.stop_on_error !== undefined ? args.stop_on_error : true,
1893
+ enableValidation: args.enable_validation !== undefined ? args.enable_validation : true,
1894
+ enableRollback: args.enable_rollback !== undefined ? args.enable_rollback : false
1895
+ };
1896
+
1897
+ if (args.max_concurrency) {
1898
+ options.maxConcurrency = args.max_concurrency;
1899
+ }
1900
+
1901
+ if (args.skip_events) {
1902
+ options.skipEvents = args.skip_events;
1903
+ }
1904
+
1905
+ if (args.include_events) {
1906
+ options.includeEvents = args.include_events;
1907
+ }
1908
+
1909
+ const sessionId = await replayEngine.createSession(
1910
+ args.name,
1911
+ filter,
1912
+ options,
1913
+ args.description
1914
+ );
1915
+
1916
+ return {
1917
+ content: [
1918
+ {
1919
+ type: 'text' as const,
1920
+ text: `Created replay session: ${sessionId}`,
1921
+ },
1922
+ {
1923
+ type: 'text' as const,
1924
+ text: JSON.stringify({ sessionId }, null, 2),
1925
+ },
1926
+ ],
1927
+ };
1928
+ } catch (error) {
1929
+ throw new McpError(
1930
+ ErrorCode.InternalError,
1931
+ `Failed to create replay session: ${(error as Error).message}`
1932
+ );
1933
+ }
1934
+ }
1935
+
1936
+ async function handleStartReplay(args: StartReplayArgs) {
1937
+ try {
1938
+ const replayEngine = getReplayEngine();
1939
+ await replayEngine.startReplay(args.session_id);
1940
+
1941
+ return {
1942
+ content: [
1943
+ {
1944
+ type: 'text' as const,
1945
+ text: `Started replay session: ${args.session_id}`,
1946
+ },
1947
+ ],
1948
+ };
1949
+ } catch (error) {
1950
+ throw new McpError(
1951
+ ErrorCode.InternalError,
1952
+ `Failed to start replay: ${(error as Error).message}`
1953
+ );
1954
+ }
1955
+ }
1956
+
1957
+ async function handleGetReplayProgress(args: GetReplayProgressArgs) {
1958
+ try {
1959
+ const replayEngine = getReplayEngine();
1960
+ const progress = await replayEngine.getReplayProgress(args.session_id);
1961
+
1962
+ return {
1963
+ content: [
1964
+ {
1965
+ type: 'text' as const,
1966
+ text: `Replay progress for session: ${args.session_id}`,
1967
+ },
1968
+ {
1969
+ type: 'text' as const,
1970
+ text: JSON.stringify(progress, null, 2),
1971
+ },
1972
+ ],
1973
+ };
1974
+ } catch (error) {
1975
+ throw new McpError(
1976
+ ErrorCode.InternalError,
1977
+ `Failed to get replay progress: ${(error as Error).message}`
1978
+ );
1979
+ }
1980
+ }
1981
+
1982
+ // Start server
1983
+ async function main() {
1984
+ const transport = new StdioServerTransport()
1985
+
1986
+ await server.connect(transport)
1987
+ console.error('ZyFlow MCP Server started')
1988
+ console.error(`Project path: ${PROJECT_PATH}`)
1989
+
1990
+ // Handle process termination signals
1991
+ process.on('SIGINT', () => {
1992
+ console.error('Received SIGINT, shutting down...')
1993
+ process.exit(0)
1994
+ })
1995
+
1996
+ process.on('SIGTERM', () => {
1997
+ console.error('Received SIGTERM, shutting down...')
1998
+ process.exit(0)
1999
+ })
2000
+
2001
+ // Handle stdin close - MCP client disconnection
2002
+ process.stdin.on('end', () => {
2003
+ console.error('stdin ended, shutting down...')
2004
+ process.exit(0)
2005
+ })
2006
+
2007
+ // Keep the process alive
2008
+ process.stdin.resume()
2009
+ }
2010
+
2011
+ main().catch((error) => {
2012
+ console.error('Failed to start MCP server:', error)
2013
+ process.exit(1)
2014
+ })