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,1028 @@
1
+ /**
2
+ * Alerts Router (Simplified)
3
+ *
4
+ * 간소화된 Alert System API 라우터
5
+ * - GitHub Actions 실패 알림 조회
6
+ * - Alert 기본 CRUD
7
+ * - 프로젝트별 Alert 필터링
8
+ */
9
+
10
+ import { Router } from 'express'
11
+ import { randomUUID } from 'crypto'
12
+ import { getSqlite } from '../tasks/db/client.js'
13
+ import {
14
+ checkGhAuth,
15
+ syncRepoWorkflows,
16
+ syncAllRepos,
17
+ getCurrentRepo,
18
+ getPollerConfig,
19
+ updatePollerConfig,
20
+ startBackgroundPoller,
21
+ stopBackgroundPoller,
22
+ isPollerRunning,
23
+ } from '../services/githubActionsPoller.js'
24
+ import { getProjectById, getActiveProject } from '../config.js'
25
+ import { encrypt, safeDecrypt, maskUrl, generateSecret } from '../utils/crypto.js'
26
+ import { sendTestNotification } from '../services/slackNotifier.js'
27
+ import { processAlertForAutoFix, getRunningJobs, getAgentStats, type Alert } from '../agents/alert-integration.js'
28
+
29
+ // WebSocket broadcast 함수 (app.ts에서 주입)
30
+ let broadcastAlert: ((alert: unknown) => void) | null = null
31
+
32
+ export function setBroadcastAlert(fn: (alert: unknown) => void): void {
33
+ broadcastAlert = fn
34
+ }
35
+
36
+ export const alertsRouter = Router()
37
+
38
+ // =============================================
39
+ // Helper Functions
40
+ // =============================================
41
+
42
+ // Activity log 생성 헬퍼
43
+ function createActivityLog(
44
+ alertId: string | null,
45
+ actor: 'system' | 'agent' | 'user',
46
+ action: string,
47
+ description: string,
48
+ metadata?: Record<string, unknown>
49
+ ): void {
50
+ const sqlite = getSqlite()
51
+ const now = Date.now()
52
+
53
+ sqlite.prepare(`
54
+ INSERT INTO activity_logs (id, alert_id, actor, action, description, metadata, created_at)
55
+ VALUES (?, ?, ?, ?, ?, ?, ?)
56
+ `).run(
57
+ randomUUID(),
58
+ alertId,
59
+ actor,
60
+ action,
61
+ description,
62
+ metadata ? JSON.stringify(metadata) : null,
63
+ now
64
+ )
65
+ }
66
+
67
+ // =============================================
68
+ // Alert CRUD Endpoints
69
+ // =============================================
70
+
71
+ // GET /alerts - List alerts
72
+ alertsRouter.get('/', async (req, res) => {
73
+ try {
74
+ const sqlite = getSqlite()
75
+ const { source, severity, status, projectId, limit = '50', offset = '0' } = req.query
76
+ const now = Date.now()
77
+
78
+ let whereClause = 'WHERE expires_at > ?'
79
+ const params: (string | number | null)[] = [now]
80
+
81
+ if (projectId) {
82
+ whereClause += ' AND project_id = ?'
83
+ params.push(projectId as string)
84
+ }
85
+
86
+ if (source) {
87
+ whereClause += ' AND source = ?'
88
+ params.push(source as string)
89
+ }
90
+ if (severity) {
91
+ whereClause += ' AND severity = ?'
92
+ params.push(severity as string)
93
+ }
94
+ if (status) {
95
+ whereClause += ' AND status = ?'
96
+ params.push(status as string)
97
+ }
98
+
99
+ const countResult = sqlite.prepare(`
100
+ SELECT COUNT(*) as total FROM alerts ${whereClause}
101
+ `).get(...params) as { total: number }
102
+
103
+ const alerts = sqlite.prepare(`
104
+ SELECT * FROM alerts
105
+ ${whereClause}
106
+ ORDER BY created_at DESC
107
+ LIMIT ? OFFSET ?
108
+ `).all(...params, parseInt(limit as string), parseInt(offset as string))
109
+
110
+ res.json({
111
+ success: true,
112
+ data: {
113
+ alerts,
114
+ total: countResult.total,
115
+ limit: parseInt(limit as string),
116
+ offset: parseInt(offset as string),
117
+ },
118
+ })
119
+ } catch (error) {
120
+ console.error('Error listing alerts:', error)
121
+ res.status(500).json({ success: false, error: 'Failed to list alerts' })
122
+ }
123
+ })
124
+
125
+ // GET /alerts/stats - Get alert statistics
126
+ alertsRouter.get('/stats', async (req, res) => {
127
+ try {
128
+ const sqlite = getSqlite()
129
+ const now = Date.now()
130
+ const { projectId } = req.query
131
+
132
+ const projectFilter = projectId ? ' AND project_id = ?' : ''
133
+ const params = projectId ? [now, projectId as string] : [now]
134
+
135
+ const total = sqlite.prepare(`
136
+ SELECT COUNT(*) as count FROM alerts WHERE expires_at > ?${projectFilter}
137
+ `).get(...params) as { count: number }
138
+
139
+ const bySeverity = sqlite.prepare(`
140
+ SELECT severity, COUNT(*) as count FROM alerts WHERE expires_at > ?${projectFilter} GROUP BY severity
141
+ `).all(...params) as { severity: string; count: number }[]
142
+
143
+ const bySource = sqlite.prepare(`
144
+ SELECT source, COUNT(*) as count FROM alerts WHERE expires_at > ?${projectFilter} GROUP BY source
145
+ `).all(...params) as { source: string; count: number }[]
146
+
147
+ const byStatus = sqlite.prepare(`
148
+ SELECT status, COUNT(*) as count FROM alerts WHERE expires_at > ?${projectFilter} GROUP BY status
149
+ `).all(...params) as { status: string; count: number }[]
150
+
151
+ res.json({
152
+ success: true,
153
+ data: {
154
+ total: total.count,
155
+ bySeverity: Object.fromEntries(bySeverity.map(r => [r.severity, r.count])),
156
+ bySource: Object.fromEntries(bySource.map(r => [r.source, r.count])),
157
+ byStatus: Object.fromEntries(byStatus.map(r => [r.status, r.count])),
158
+ },
159
+ })
160
+ } catch (error) {
161
+ console.error('Error getting alert stats:', error)
162
+ res.status(500).json({ success: false, error: 'Failed to get stats' })
163
+ }
164
+ })
165
+
166
+ // GET /activities - List activity logs
167
+ alertsRouter.get('/activities', async (req, res) => {
168
+ try {
169
+ const sqlite = getSqlite()
170
+ const { alertId, actor, limit = '50', offset = '0' } = req.query
171
+
172
+ let whereClause = 'WHERE 1=1'
173
+ const params: (string | number)[] = []
174
+
175
+ if (alertId) {
176
+ whereClause += ' AND alert_id = ?'
177
+ params.push(alertId as string)
178
+ }
179
+ if (actor) {
180
+ whereClause += ' AND actor = ?'
181
+ params.push(actor as string)
182
+ }
183
+
184
+ const activities = sqlite.prepare(`
185
+ SELECT * FROM activity_logs
186
+ ${whereClause}
187
+ ORDER BY created_at DESC
188
+ LIMIT ? OFFSET ?
189
+ `).all(...params, parseInt(limit as string), parseInt(offset as string))
190
+
191
+ res.json({ success: true, data: activities })
192
+ } catch (error) {
193
+ console.error('Error listing activities:', error)
194
+ res.status(500).json({ success: false, error: 'Failed to list activities' })
195
+ }
196
+ })
197
+
198
+ // GET /dashboard-stats - Get dashboard stats
199
+ alertsRouter.get('/dashboard-stats', async (_req, res) => {
200
+ try {
201
+ const sqlite = getSqlite()
202
+ const now = Date.now()
203
+ const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000
204
+
205
+ const todayStart = new Date()
206
+ todayStart.setHours(0, 0, 0, 0)
207
+
208
+ const todayAlerts = sqlite.prepare(`
209
+ SELECT COUNT(*) as count FROM alerts WHERE created_at >= ?
210
+ `).get(todayStart.getTime()) as { count: number }
211
+
212
+ const pendingAlerts = sqlite.prepare(`
213
+ SELECT COUNT(*) as count FROM alerts WHERE status = 'pending' AND expires_at > ?
214
+ `).get(now) as { count: number }
215
+
216
+ const totalLast7Days = sqlite.prepare(`
217
+ SELECT COUNT(*) as count FROM alerts WHERE created_at >= ?
218
+ `).get(sevenDaysAgo) as { count: number }
219
+
220
+ const resolvedLast7Days = sqlite.prepare(`
221
+ SELECT COUNT(*) as count FROM alerts WHERE status = 'resolved' AND created_at >= ?
222
+ `).get(sevenDaysAgo) as { count: number }
223
+
224
+ const resolutionRate = totalLast7Days.count > 0
225
+ ? Math.round((resolvedLast7Days.count / totalLast7Days.count) * 100)
226
+ : 0
227
+
228
+ const criticalToday = sqlite.prepare(`
229
+ SELECT COUNT(*) as count FROM alerts WHERE severity = 'critical' AND created_at >= ?
230
+ `).get(todayStart.getTime()) as { count: number }
231
+
232
+ res.json({
233
+ success: true,
234
+ data: {
235
+ todayAlerts: todayAlerts.count,
236
+ pendingAlerts: pendingAlerts.count,
237
+ resolutionRate,
238
+ criticalToday: criticalToday.count,
239
+ },
240
+ })
241
+ } catch (error) {
242
+ console.error('Error getting dashboard stats:', error)
243
+ res.status(500).json({ success: false, error: 'Failed to get dashboard stats' })
244
+ }
245
+ })
246
+
247
+ // GET /alerts/:id - Get single alert (UUID format only)
248
+ alertsRouter.get('/:id([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})', async (req, res) => {
249
+ try {
250
+ const sqlite = getSqlite()
251
+ const alert = sqlite.prepare('SELECT * FROM alerts WHERE id = ?').get(req.params.id)
252
+
253
+ if (!alert) {
254
+ return res.status(404).json({ success: false, error: 'Alert not found' })
255
+ }
256
+
257
+ res.json({ success: true, data: alert })
258
+ } catch (error) {
259
+ console.error('Error getting alert:', error)
260
+ res.status(500).json({ success: false, error: 'Failed to get alert' })
261
+ }
262
+ })
263
+
264
+ // PATCH /alerts/:id - Update alert status (UUID format only)
265
+ alertsRouter.patch('/:id([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})', async (req, res) => {
266
+ try {
267
+ const sqlite = getSqlite()
268
+ const { status } = req.body
269
+ const alertId = req.params.id
270
+
271
+ if (!['pending', 'processing', 'resolved', 'ignored'].includes(status)) {
272
+ return res.status(400).json({ success: false, error: 'Invalid status' })
273
+ }
274
+
275
+ const now = Date.now()
276
+ const resolvedAt = status === 'resolved' || status === 'ignored' ? now : null
277
+
278
+ sqlite.prepare(`
279
+ UPDATE alerts SET status = ?, updated_at = ?, resolved_at = ? WHERE id = ?
280
+ `).run(status, now, resolvedAt, alertId)
281
+
282
+ createActivityLog(alertId, 'user', 'status.changed', `Alert status changed to ${status}`)
283
+
284
+ const alert = sqlite.prepare('SELECT * FROM alerts WHERE id = ?').get(alertId)
285
+ res.json({ success: true, data: alert })
286
+ } catch (error) {
287
+ console.error('Error updating alert:', error)
288
+ res.status(500).json({ success: false, error: 'Failed to update alert' })
289
+ }
290
+ })
291
+
292
+ // POST /alerts/:id/ignore - Mark alert as ignored (UUID format only)
293
+ alertsRouter.post('/:id([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/ignore', async (req, res) => {
294
+ try {
295
+ const sqlite = getSqlite()
296
+ const alertId = req.params.id
297
+ const now = Date.now()
298
+
299
+ sqlite.prepare(`
300
+ UPDATE alerts SET status = 'ignored', updated_at = ?, resolved_at = ? WHERE id = ?
301
+ `).run(now, now, alertId)
302
+
303
+ createActivityLog(alertId, 'user', 'alert.ignored', 'Alert marked as ignored')
304
+
305
+ const alert = sqlite.prepare('SELECT * FROM alerts WHERE id = ?').get(alertId)
306
+ res.json({ success: true, data: alert })
307
+ } catch (error) {
308
+ console.error('Error ignoring alert:', error)
309
+ res.status(500).json({ success: false, error: 'Failed to ignore alert' })
310
+ }
311
+ })
312
+
313
+ // POST /cleanup - Delete expired alerts
314
+ alertsRouter.post('/cleanup', async (_req, res) => {
315
+ try {
316
+ const sqlite = getSqlite()
317
+ const now = Date.now()
318
+
319
+ const result = sqlite.prepare('DELETE FROM alerts WHERE expires_at < ?').run(now)
320
+
321
+ createActivityLog(null, 'system', 'cleanup.completed', `Deleted ${result.changes} expired alerts`)
322
+
323
+ res.json({ success: true, deleted: result.changes })
324
+ } catch (error) {
325
+ console.error('Error cleaning up alerts:', error)
326
+ res.status(500).json({ success: false, error: 'Failed to cleanup' })
327
+ }
328
+ })
329
+
330
+ // =============================================
331
+ // GitHub Actions Poller Endpoints
332
+ // =============================================
333
+
334
+ // projectId로 실제 경로를 조회하는 헬퍼 함수
335
+ async function getProjectPath(projectId: string): Promise<string | null> {
336
+ if (!projectId) return null
337
+ try {
338
+ const project = await getProjectById(projectId)
339
+ return project?.path || null
340
+ } catch (error) {
341
+ console.error('Error getting project path:', error)
342
+ return null
343
+ }
344
+ }
345
+
346
+ // GET /github/auth-status - Check gh CLI authentication status
347
+ alertsRouter.get('/github/auth-status', async (_req, res) => {
348
+ try {
349
+ const result = await checkGhAuth()
350
+ res.json({ success: true, data: result })
351
+ } catch (error) {
352
+ console.error('Error checking gh auth:', error)
353
+ res.status(500).json({ success: false, error: 'Failed to check gh auth' })
354
+ }
355
+ })
356
+
357
+ // POST /github/sync - Sync GitHub Actions failures for a repository
358
+ alertsRouter.post('/github/sync', async (req, res) => {
359
+ try {
360
+ const { repo, limit = 20, projectId } = req.body
361
+
362
+ let targetRepo = repo
363
+ if (!targetRepo) {
364
+ const projectPath = projectId ? await getProjectPath(projectId) : null
365
+ targetRepo = await getCurrentRepo(projectPath || undefined)
366
+ if (!targetRepo) {
367
+ return res.status(400).json({
368
+ success: false,
369
+ error: 'Repository not specified and could not detect current repository',
370
+ })
371
+ }
372
+ }
373
+
374
+ const result = await syncRepoWorkflows(targetRepo, {
375
+ limit,
376
+ projectId,
377
+ broadcastAlert: broadcastAlert || undefined,
378
+ })
379
+
380
+ createActivityLog(null, 'user', 'github.synced', `Synced GitHub Actions for ${targetRepo}`, {
381
+ repo: targetRepo,
382
+ projectId,
383
+ newAlerts: result.newAlerts,
384
+ skipped: result.skipped,
385
+ })
386
+
387
+ res.json({ success: true, data: result })
388
+ } catch (error) {
389
+ console.error('Error syncing GitHub Actions:', error)
390
+ res.status(500).json({ success: false, error: 'Failed to sync GitHub Actions' })
391
+ }
392
+ })
393
+
394
+ // POST /github/sync-all - Sync GitHub Actions failures for all configured repositories
395
+ alertsRouter.post('/github/sync-all', async (req, res) => {
396
+ try {
397
+ const { repos, projectId } = req.body
398
+
399
+ let targetRepos = repos
400
+ if (!targetRepos || targetRepos.length === 0) {
401
+ const config = getPollerConfig()
402
+ targetRepos = config.repos
403
+
404
+ if (!targetRepos || targetRepos.length === 0) {
405
+ const projectPath = projectId ? await getProjectPath(projectId) : null
406
+ const currentRepo = await getCurrentRepo(projectPath || undefined)
407
+ if (currentRepo) {
408
+ targetRepos = [currentRepo]
409
+ } else {
410
+ return res.status(400).json({
411
+ success: false,
412
+ error: 'No repositories configured and could not detect current repository',
413
+ })
414
+ }
415
+ }
416
+ }
417
+
418
+ const result = await syncAllRepos(targetRepos, {
419
+ projectId,
420
+ broadcastAlert: broadcastAlert || undefined,
421
+ })
422
+
423
+ createActivityLog(null, 'user', 'github.synced_all', `Synced GitHub Actions for ${targetRepos.length} repos`, {
424
+ repos: targetRepos,
425
+ projectId,
426
+ totalNew: result.totalNew,
427
+ totalSkipped: result.totalSkipped,
428
+ })
429
+
430
+ res.json({ success: true, data: result })
431
+ } catch (error) {
432
+ console.error('Error syncing all repos:', error)
433
+ res.status(500).json({ success: false, error: 'Failed to sync all repos' })
434
+ }
435
+ })
436
+
437
+ // GET /github/poller-config - Get poller configuration
438
+ alertsRouter.get('/github/poller-config', async (_req, res) => {
439
+ try {
440
+ const config = getPollerConfig()
441
+ res.json({
442
+ success: true,
443
+ data: {
444
+ ...config,
445
+ isRunning: isPollerRunning(),
446
+ },
447
+ })
448
+ } catch (error) {
449
+ console.error('Error getting poller config:', error)
450
+ res.status(500).json({ success: false, error: 'Failed to get poller config' })
451
+ }
452
+ })
453
+
454
+ // PATCH /github/poller-config - Update poller configuration
455
+ alertsRouter.patch('/github/poller-config', async (req, res) => {
456
+ try {
457
+ const { enabled, intervalMs, repos } = req.body
458
+
459
+ updatePollerConfig({
460
+ enabled: enabled !== undefined ? enabled : undefined,
461
+ intervalMs: intervalMs !== undefined ? intervalMs : undefined,
462
+ repos: repos !== undefined ? repos : undefined,
463
+ })
464
+
465
+ const config = getPollerConfig()
466
+
467
+ if (enabled === true) {
468
+ startBackgroundPoller(broadcastAlert || undefined)
469
+ } else if (enabled === false) {
470
+ stopBackgroundPoller()
471
+ }
472
+
473
+ createActivityLog(null, 'user', 'poller.updated', 'GitHub Actions poller config updated', {
474
+ enabled: config.enabled,
475
+ intervalMs: config.intervalMs,
476
+ repoCount: config.repos.length,
477
+ })
478
+
479
+ res.json({
480
+ success: true,
481
+ data: {
482
+ ...config,
483
+ isRunning: isPollerRunning(),
484
+ },
485
+ })
486
+ } catch (error) {
487
+ console.error('Error updating poller config:', error)
488
+ res.status(500).json({ success: false, error: 'Failed to update poller config' })
489
+ }
490
+ })
491
+
492
+ // POST /github/poller/start - Start background poller
493
+ alertsRouter.post('/github/poller/start', async (_req, res) => {
494
+ try {
495
+ startBackgroundPoller(broadcastAlert || undefined)
496
+ createActivityLog(null, 'user', 'poller.started', 'GitHub Actions poller started')
497
+ res.json({ success: true, message: 'Poller started', isRunning: isPollerRunning() })
498
+ } catch (error) {
499
+ console.error('Error starting poller:', error)
500
+ res.status(500).json({ success: false, error: 'Failed to start poller' })
501
+ }
502
+ })
503
+
504
+ // POST /github/poller/stop - Stop background poller
505
+ alertsRouter.post('/github/poller/stop', async (_req, res) => {
506
+ try {
507
+ stopBackgroundPoller()
508
+ createActivityLog(null, 'user', 'poller.stopped', 'GitHub Actions poller stopped')
509
+ res.json({ success: true, message: 'Poller stopped', isRunning: isPollerRunning() })
510
+ } catch (error) {
511
+ console.error('Error stopping poller:', error)
512
+ res.status(500).json({ success: false, error: 'Failed to stop poller' })
513
+ }
514
+ })
515
+
516
+ // =============================================
517
+ // Notification Config Endpoints
518
+ // =============================================
519
+
520
+ // GET /notification-config - 알림 설정 조회
521
+ alertsRouter.get('/notification-config', async (_req, res) => {
522
+ try {
523
+ const sqlite = getSqlite()
524
+
525
+ // 기본 설정 생성 (없으면)
526
+ const existing = sqlite.prepare('SELECT * FROM notification_config WHERE id = ?').get('default')
527
+ if (!existing) {
528
+ const now = Date.now()
529
+ sqlite.prepare(`
530
+ INSERT INTO notification_config (id, slack_enabled, rule_on_critical, rule_on_autofix, rule_on_all, created_at, updated_at)
531
+ VALUES (?, ?, ?, ?, ?, ?, ?)
532
+ `).run('default', 0, 1, 1, 0, now, now)
533
+ }
534
+
535
+ const config = sqlite.prepare('SELECT * FROM notification_config WHERE id = ?').get('default') as {
536
+ id: string
537
+ slack_webhook_url: string | null
538
+ slack_channel: string | null
539
+ slack_enabled: number
540
+ rule_on_critical: number
541
+ rule_on_autofix: number
542
+ rule_on_all: number
543
+ created_at: number
544
+ updated_at: number
545
+ }
546
+
547
+ // 프론트엔드가 기대하는 중첩 형식으로 변환
548
+ res.json({
549
+ success: true,
550
+ data: {
551
+ slack: {
552
+ webhookUrl: config.slack_webhook_url ? maskUrl(safeDecrypt(config.slack_webhook_url)) : undefined,
553
+ channel: config.slack_channel || undefined,
554
+ enabled: Boolean(config.slack_enabled),
555
+ },
556
+ rules: {
557
+ onCritical: Boolean(config.rule_on_critical),
558
+ onAutofix: Boolean(config.rule_on_autofix),
559
+ onAll: Boolean(config.rule_on_all),
560
+ },
561
+ },
562
+ })
563
+ } catch (error) {
564
+ console.error('Error getting notification config:', error)
565
+ res.status(500).json({ success: false, error: 'Failed to get notification config' })
566
+ }
567
+ })
568
+
569
+ // PATCH /notification-config - 알림 설정 수정
570
+ // 프론트엔드 형식: { slack: { webhookUrl, channel, enabled }, rules: { onCritical, onAutofix, onAll } }
571
+ alertsRouter.patch('/notification-config', async (req, res) => {
572
+ try {
573
+ const sqlite = getSqlite()
574
+ const { slack, rules } = req.body as {
575
+ slack?: { webhookUrl?: string; channel?: string; enabled?: boolean }
576
+ rules?: { onCritical?: boolean; onAutofix?: boolean; onAll?: boolean }
577
+ }
578
+ const now = Date.now()
579
+
580
+ // 현재 설정 조회/생성
581
+ const existing = sqlite.prepare('SELECT id FROM notification_config WHERE id = ?').get('default')
582
+ if (!existing) {
583
+ sqlite.prepare(`
584
+ INSERT INTO notification_config (id, slack_enabled, rule_on_critical, rule_on_autofix, rule_on_all, created_at, updated_at)
585
+ VALUES (?, ?, ?, ?, ?, ?, ?)
586
+ `).run('default', 0, 1, 1, 0, now, now)
587
+ }
588
+
589
+ const updates: string[] = []
590
+ const params: (string | number | null)[] = []
591
+
592
+ // Slack 설정
593
+ if (slack?.webhookUrl !== undefined) {
594
+ updates.push('slack_webhook_url = ?')
595
+ params.push(slack.webhookUrl ? encrypt(slack.webhookUrl) : null)
596
+ }
597
+ if (slack?.channel !== undefined) {
598
+ updates.push('slack_channel = ?')
599
+ params.push(slack.channel || null)
600
+ }
601
+ if (slack?.enabled !== undefined) {
602
+ updates.push('slack_enabled = ?')
603
+ params.push(slack.enabled ? 1 : 0)
604
+ }
605
+
606
+ // 알림 규칙
607
+ if (rules?.onCritical !== undefined) {
608
+ updates.push('rule_on_critical = ?')
609
+ params.push(rules.onCritical ? 1 : 0)
610
+ }
611
+ if (rules?.onAutofix !== undefined) {
612
+ updates.push('rule_on_autofix = ?')
613
+ params.push(rules.onAutofix ? 1 : 0)
614
+ }
615
+ if (rules?.onAll !== undefined) {
616
+ updates.push('rule_on_all = ?')
617
+ params.push(rules.onAll ? 1 : 0)
618
+ }
619
+
620
+ if (updates.length > 0) {
621
+ updates.push('updated_at = ?')
622
+ params.push(now)
623
+ params.push('default')
624
+
625
+ sqlite.prepare(`
626
+ UPDATE notification_config SET ${updates.join(', ')} WHERE id = ?
627
+ `).run(...params)
628
+
629
+ createActivityLog(null, 'user', 'notification_config.updated', 'Notification config updated')
630
+ }
631
+
632
+ res.json({ success: true, message: 'Notification config updated' })
633
+ } catch (error) {
634
+ console.error('Error updating notification config:', error)
635
+ res.status(500).json({ success: false, error: 'Failed to update notification config' })
636
+ }
637
+ })
638
+
639
+ // POST /notification-config/test - Slack 테스트 알림 발송
640
+ alertsRouter.post('/notification-config/test', async (req, res) => {
641
+ try {
642
+ const { webhook_url } = req.body
643
+
644
+ let url = webhook_url
645
+
646
+ // webhook_url이 없으면 저장된 URL 사용
647
+ if (!url) {
648
+ const sqlite = getSqlite()
649
+ const config = sqlite.prepare('SELECT slack_webhook_url FROM notification_config WHERE id = ?').get('default') as {
650
+ slack_webhook_url: string | null
651
+ } | undefined
652
+
653
+ if (!config?.slack_webhook_url) {
654
+ return res.status(400).json({ success: false, error: 'No webhook URL configured' })
655
+ }
656
+
657
+ url = safeDecrypt(config.slack_webhook_url)
658
+ }
659
+
660
+ const result = await sendTestNotification(url)
661
+
662
+ if (result.success) {
663
+ createActivityLog(null, 'user', 'notification.test', 'Test notification sent successfully')
664
+ res.json({ success: true, message: 'Test notification sent' })
665
+ } else {
666
+ res.status(400).json({ success: false, error: result.error })
667
+ }
668
+ } catch (error) {
669
+ console.error('Error sending test notification:', error)
670
+ res.status(500).json({ success: false, error: 'Failed to send test notification' })
671
+ }
672
+ })
673
+
674
+ // =============================================
675
+ // Webhook Config CRUD Endpoints
676
+ // =============================================
677
+
678
+ // GET /webhook-configs - Webhook 설정 목록 조회
679
+ alertsRouter.get('/webhook-configs', async (_req, res) => {
680
+ try {
681
+ const sqlite = getSqlite()
682
+ const configs = sqlite.prepare(`
683
+ SELECT id, name, source, endpoint_path, enabled, created_at, updated_at
684
+ FROM webhook_configs
685
+ ORDER BY created_at DESC
686
+ `).all() as Array<{
687
+ id: string
688
+ name: string
689
+ source: string
690
+ endpoint_path: string
691
+ enabled: number
692
+ created_at: number
693
+ updated_at: number
694
+ }>
695
+
696
+ res.json({
697
+ success: true,
698
+ data: configs.map(c => ({
699
+ id: c.id,
700
+ name: c.name,
701
+ source: c.source,
702
+ endpoint: c.endpoint_path, // frontend expects 'endpoint'
703
+ enabled: Boolean(c.enabled),
704
+ created_at: c.created_at,
705
+ updated_at: c.updated_at,
706
+ // 시크릿은 노출하지 않음
707
+ has_secret: true,
708
+ })),
709
+ })
710
+ } catch (error) {
711
+ console.error('Error getting webhook configs:', error)
712
+ res.status(500).json({ success: false, error: 'Failed to get webhook configs' })
713
+ }
714
+ })
715
+
716
+ // POST /webhook-configs - 새 Webhook 설정 생성
717
+ alertsRouter.post('/webhook-configs', async (req, res) => {
718
+ try {
719
+ const sqlite = getSqlite()
720
+ const { name, source, project_filter } = req.body
721
+
722
+ if (!name || !source) {
723
+ return res.status(400).json({ success: false, error: 'name and source are required' })
724
+ }
725
+
726
+ const id = randomUUID()
727
+ const secret = generateSecret()
728
+ const endpointPath = `/api/alerts/webhooks/custom/${id}`
729
+ const now = Date.now()
730
+
731
+ sqlite.prepare(`
732
+ INSERT INTO webhook_configs (id, name, source, secret, endpoint_path, project_filter, enabled, created_at, updated_at)
733
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
734
+ `).run(
735
+ id,
736
+ name,
737
+ source,
738
+ encrypt(secret),
739
+ endpointPath,
740
+ project_filter ? JSON.stringify(project_filter) : null,
741
+ 1,
742
+ now,
743
+ now
744
+ )
745
+
746
+ createActivityLog(null, 'user', 'webhook_config.created', `Webhook config "${name}" created`)
747
+
748
+ res.json({
749
+ success: true,
750
+ data: {
751
+ id,
752
+ name,
753
+ source,
754
+ endpoint: endpointPath, // frontend expects 'endpoint'
755
+ secret, // 생성 시에만 시크릿 반환
756
+ enabled: true,
757
+ },
758
+ })
759
+ } catch (error) {
760
+ console.error('Error creating webhook config:', error)
761
+ res.status(500).json({ success: false, error: 'Failed to create webhook config' })
762
+ }
763
+ })
764
+
765
+ // PATCH /webhook-configs/:id - Webhook 설정 수정
766
+ alertsRouter.patch('/webhook-configs/:id', async (req, res) => {
767
+ try {
768
+ const sqlite = getSqlite()
769
+ const { id } = req.params
770
+ const { name, source, project_filter, enabled } = req.body
771
+
772
+ const existing = sqlite.prepare('SELECT * FROM webhook_configs WHERE id = ?').get(id)
773
+ if (!existing) {
774
+ return res.status(404).json({ success: false, error: 'Webhook config not found' })
775
+ }
776
+
777
+ const updates: string[] = []
778
+ const params: (string | number | null)[] = []
779
+
780
+ if (name !== undefined) {
781
+ updates.push('name = ?')
782
+ params.push(name)
783
+ }
784
+
785
+ if (source !== undefined) {
786
+ updates.push('source = ?')
787
+ params.push(source)
788
+ }
789
+
790
+ if (project_filter !== undefined) {
791
+ updates.push('project_filter = ?')
792
+ params.push(project_filter ? JSON.stringify(project_filter) : null)
793
+ }
794
+
795
+ if (enabled !== undefined) {
796
+ updates.push('enabled = ?')
797
+ params.push(enabled ? 1 : 0)
798
+ }
799
+
800
+ if (updates.length > 0) {
801
+ updates.push('updated_at = ?')
802
+ params.push(Date.now())
803
+ params.push(id)
804
+
805
+ sqlite.prepare(`
806
+ UPDATE webhook_configs SET ${updates.join(', ')} WHERE id = ?
807
+ `).run(...params)
808
+
809
+ createActivityLog(null, 'user', 'webhook_config.updated', `Webhook config "${id}" updated`)
810
+ }
811
+
812
+ res.json({ success: true, message: 'Webhook config updated' })
813
+ } catch (error) {
814
+ console.error('Error updating webhook config:', error)
815
+ res.status(500).json({ success: false, error: 'Failed to update webhook config' })
816
+ }
817
+ })
818
+
819
+ // DELETE /webhook-configs/:id - Webhook 설정 삭제
820
+ alertsRouter.delete('/webhook-configs/:id', async (req, res) => {
821
+ try {
822
+ const sqlite = getSqlite()
823
+ const { id } = req.params
824
+
825
+ const existing = sqlite.prepare('SELECT name FROM webhook_configs WHERE id = ?').get(id) as { name: string } | undefined
826
+ if (!existing) {
827
+ return res.status(404).json({ success: false, error: 'Webhook config not found' })
828
+ }
829
+
830
+ sqlite.prepare('DELETE FROM webhook_configs WHERE id = ?').run(id)
831
+ createActivityLog(null, 'user', 'webhook_config.deleted', `Webhook config "${existing.name}" deleted`)
832
+
833
+ res.json({ success: true, message: 'Webhook config deleted' })
834
+ } catch (error) {
835
+ console.error('Error deleting webhook config:', error)
836
+ res.status(500).json({ success: false, error: 'Failed to delete webhook config' })
837
+ }
838
+ })
839
+
840
+ // POST /webhook-configs/:id/regenerate-secret - 시크릿 재생성
841
+ alertsRouter.post('/webhook-configs/:id/regenerate-secret', async (req, res) => {
842
+ try {
843
+ const sqlite = getSqlite()
844
+ const { id } = req.params
845
+
846
+ const existing = sqlite.prepare('SELECT name FROM webhook_configs WHERE id = ?').get(id) as { name: string } | undefined
847
+ if (!existing) {
848
+ return res.status(404).json({ success: false, error: 'Webhook config not found' })
849
+ }
850
+
851
+ const newSecret = generateSecret()
852
+
853
+ sqlite.prepare(`
854
+ UPDATE webhook_configs SET secret = ?, updated_at = ? WHERE id = ?
855
+ `).run(encrypt(newSecret), Date.now(), id)
856
+
857
+ createActivityLog(null, 'user', 'webhook_config.secret_regenerated', `Webhook config "${existing.name}" secret regenerated`)
858
+
859
+ res.json({
860
+ success: true,
861
+ data: {
862
+ secret: newSecret, // 재생성 시에만 반환
863
+ },
864
+ })
865
+ } catch (error) {
866
+ console.error('Error regenerating webhook secret:', error)
867
+ res.status(500).json({ success: false, error: 'Failed to regenerate webhook secret' })
868
+ }
869
+ })
870
+
871
+ // =============================================
872
+ // Auto-Fix Agent Endpoints
873
+ // =============================================
874
+
875
+ // POST /alerts/:id/trigger-autofix - 수동 Auto-fix 트리거
876
+ alertsRouter.post('/:id([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})/trigger-autofix', async (req, res) => {
877
+ try {
878
+ const sqlite = getSqlite()
879
+ const alertId = req.params.id
880
+
881
+ // Alert 조회
882
+ const alertRow = sqlite.prepare('SELECT * FROM alerts WHERE id = ?').get(alertId) as {
883
+ id: string
884
+ project_id: string
885
+ source: string
886
+ severity: string
887
+ status: string
888
+ title: string
889
+ message: string | null
890
+ metadata: string | null
891
+ data: string | null
892
+ created_at: number
893
+ updated_at: number
894
+ } | undefined
895
+
896
+ if (!alertRow) {
897
+ return res.status(404).json({ success: false, error: 'Alert not found' })
898
+ }
899
+
900
+ // 이미 처리 중인지 확인
901
+ const runningJobs = getRunningJobs()
902
+ if (runningJobs.includes(alertId)) {
903
+ return res.status(409).json({ success: false, error: 'Auto-fix already in progress for this alert' })
904
+ }
905
+
906
+ // Alert 객체 변환
907
+ const alert: Alert = {
908
+ id: alertRow.id,
909
+ project_id: alertRow.project_id,
910
+ source: alertRow.source as Alert['source'],
911
+ severity: alertRow.severity as Alert['severity'],
912
+ status: alertRow.status as Alert['status'],
913
+ title: alertRow.title,
914
+ message: alertRow.message || undefined,
915
+ metadata: alertRow.metadata ? JSON.parse(alertRow.metadata) : undefined,
916
+ data: alertRow.data ? JSON.parse(alertRow.data) : undefined,
917
+ created_at: alertRow.created_at,
918
+ updated_at: alertRow.updated_at,
919
+ }
920
+
921
+ // 프로젝트 경로 조회
922
+ const projectPath = alertRow.project_id
923
+ ? await getProjectPath(alertRow.project_id)
924
+ : null
925
+ const activeProject = getActiveProject()
926
+ const targetPath = projectPath || activeProject?.path || process.cwd()
927
+
928
+ // Repository 정보 추출 (metadata에서)
929
+ let repository: { owner: string; repo: string; branch: string } | undefined
930
+ if (alert.metadata?.repository) {
931
+ const repoInfo = alert.metadata.repository as { owner?: string; repo?: string; branch?: string }
932
+ if (repoInfo.owner && repoInfo.repo) {
933
+ repository = {
934
+ owner: repoInfo.owner,
935
+ repo: repoInfo.repo,
936
+ branch: repoInfo.branch || 'main',
937
+ }
938
+ }
939
+ }
940
+
941
+ // GitHub Token 확인
942
+ const githubToken = process.env.GITHUB_TOKEN
943
+ if (!githubToken) {
944
+ return res.status(400).json({
945
+ success: false,
946
+ error: 'GITHUB_TOKEN environment variable not configured',
947
+ })
948
+ }
949
+
950
+ // Alert 상태 업데이트
951
+ const now = Date.now()
952
+ sqlite.prepare(`
953
+ UPDATE alerts SET status = 'processing', updated_at = ? WHERE id = ?
954
+ `).run(now, alertId)
955
+
956
+ createActivityLog(alertId, 'user', 'autofix.triggered', 'Manual auto-fix triggered')
957
+
958
+ // Auto-fix 비동기 실행
959
+ setImmediate(async () => {
960
+ try {
961
+ const result = await processAlertForAutoFix(alert, targetPath, repository, {
962
+ githubToken,
963
+ enabled: true,
964
+ triggerOnSeverity: ['critical', 'high', 'medium'],
965
+ autoMergeEnabled: false, // 수동 트리거는 auto-merge 비활성화
966
+ dryRunMode: false,
967
+ maxConcurrentRuns: 3,
968
+ })
969
+
970
+ // 결과에 따라 Alert 상태 업데이트
971
+ const finalStatus = result?.success ? 'resolved' : 'pending'
972
+ const resolvedAt = result?.success ? Date.now() : null
973
+
974
+ sqlite.prepare(`
975
+ UPDATE alerts SET status = ?, updated_at = ?, resolved_at = ? WHERE id = ?
976
+ `).run(finalStatus, Date.now(), resolvedAt, alertId)
977
+
978
+ createActivityLog(
979
+ alertId,
980
+ 'agent',
981
+ result?.success ? 'autofix.completed' : 'autofix.failed',
982
+ result?.success
983
+ ? `Auto-fix completed. PR: ${result.workflowResult?.finalPR?.url || 'N/A'}`
984
+ : `Auto-fix failed: ${result?.error || 'Unknown error'}`
985
+ )
986
+ } catch (error) {
987
+ console.error(`[AutoFix] Manual trigger failed for alert ${alertId}:`, error)
988
+
989
+ sqlite.prepare(`
990
+ UPDATE alerts SET status = 'pending', updated_at = ? WHERE id = ?
991
+ `).run(Date.now(), alertId)
992
+
993
+ createActivityLog(alertId, 'agent', 'autofix.error', `Auto-fix error: ${error}`)
994
+ }
995
+ })
996
+
997
+ res.json({
998
+ success: true,
999
+ message: 'Auto-fix triggered',
1000
+ data: {
1001
+ alertId,
1002
+ status: 'processing',
1003
+ },
1004
+ })
1005
+ } catch (error) {
1006
+ console.error('Error triggering auto-fix:', error)
1007
+ res.status(500).json({ success: false, error: 'Failed to trigger auto-fix' })
1008
+ }
1009
+ })
1010
+
1011
+ // GET /autofix/status - Auto-fix Agent 상태 조회
1012
+ alertsRouter.get('/autofix/status', async (_req, res) => {
1013
+ try {
1014
+ const stats = getAgentStats()
1015
+ const running = getRunningJobs()
1016
+
1017
+ res.json({
1018
+ success: true,
1019
+ data: {
1020
+ stats,
1021
+ runningJobs: running,
1022
+ },
1023
+ })
1024
+ } catch (error) {
1025
+ console.error('Error getting auto-fix status:', error)
1026
+ res.status(500).json({ success: false, error: 'Failed to get auto-fix status' })
1027
+ }
1028
+ })