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.
- package/.claude-flow/metrics/agent-metrics.json +1 -0
- package/.claude-flow/metrics/performance.json +87 -0
- package/.claude-flow/metrics/system-metrics.json +4370 -0
- package/.claude-flow/metrics/task-metrics.json +10 -0
- package/.claude-plugin/marketplace.json +18 -0
- package/.claude-plugin/plugin.json +17 -0
- package/.gitleaks.toml +69 -0
- package/.hive-mind/config/queens.json +59 -0
- package/.hive-mind/config/workers.json +72 -0
- package/.hive-mind/config.json +111 -0
- package/.hive-mind/hive.db +0 -0
- package/.hive-mind/hive.db-shm +0 -0
- package/.hive-mind/hive.db-wal +0 -0
- package/.leann/indexes/zyflow/documents.ids.txt +2078 -0
- package/.leann/indexes/zyflow/documents.index +0 -0
- package/.leann/indexes/zyflow/documents.leann.meta.json +25 -0
- package/.leann/indexes/zyflow/documents.leann.passages.idx +0 -0
- package/.leann/indexes/zyflow/documents.leann.passages.jsonl +2078 -0
- package/.mcp.json +41 -0
- package/.moai-backups/20260126_231508/.mcp.json +11 -0
- package/.moai-backups/20260126_231508/backup_metadata.json +34 -0
- package/.moai-backups/20260129_145438/.mcp.json +41 -0
- package/.moai-backups/20260129_145438/backup_metadata.json +53 -0
- package/.moai-backups/20260129_145504/.mcp.json +41 -0
- package/.moai-backups/20260129_145504/backup_metadata.json +20 -0
- package/.moai-backups/20260201_140004/.mcp.json +41 -0
- package/.moai-backups/20260201_140004/backup_metadata.json +51 -0
- package/.moai-backups/backup/.mcp.json +12 -0
- package/.moai-backups/settings-backup/settings.local.json +61 -0
- package/.pre-commit-config.yaml +74 -0
- package/.prettierignore +3 -0
- package/.prettierrc +7 -0
- package/.scannerwork/.sonar_lock +0 -0
- package/.scannerwork/report-task.txt +6 -0
- package/.serena/project.yml +105 -0
- package/.shadcn-admin-ref/.env.example +1 -0
- package/.shadcn-admin-ref/.prettierignore +18 -0
- package/.shadcn-admin-ref/.prettierrc +50 -0
- package/.shadcn-admin-ref/LICENSE +21 -0
- package/.shadcn-admin-ref/components.json +21 -0
- package/.shadcn-admin-ref/cz.yaml +7 -0
- package/.shadcn-admin-ref/eslint.config.js +59 -0
- package/.shadcn-admin-ref/index.html +80 -0
- package/.shadcn-admin-ref/knip.config.ts +8 -0
- package/.shadcn-admin-ref/netlify.toml +4 -0
- package/.shadcn-admin-ref/package.json +83 -0
- package/.shadcn-admin-ref/public/images/favicon.png +0 -0
- package/.shadcn-admin-ref/public/images/favicon.svg +4 -0
- package/.shadcn-admin-ref/public/images/favicon_light.png +0 -0
- package/.shadcn-admin-ref/public/images/favicon_light.svg +1 -0
- package/.shadcn-admin-ref/public/images/shadcn-admin.png +0 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-discord.tsx +28 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-docker.tsx +33 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-facebook.tsx +25 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-figma.tsx +27 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-github.tsx +25 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-gitlab.tsx +25 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-gmail.tsx +28 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-medium.tsx +30 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-notion.tsx +28 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-skype.tsx +26 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-slack.tsx +28 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-stripe.tsx +25 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-telegram.tsx +25 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-trello.tsx +27 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-whatsapp.tsx +26 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/icon-zoom.tsx +26 -0
- package/.shadcn-admin-ref/src/assets/brand-icons/index.ts +16 -0
- package/.shadcn-admin-ref/src/assets/clerk-full-logo.tsx +41 -0
- package/.shadcn-admin-ref/src/assets/clerk-logo.tsx +23 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-dir.tsx +110 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-layout-compact.tsx +131 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-layout-default.tsx +124 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-layout-full.tsx +100 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-floating.tsx +82 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-inset.tsx +58 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-sidebar-sidebar.tsx +53 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-theme-dark.tsx +79 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-theme-light.tsx +78 -0
- package/.shadcn-admin-ref/src/assets/custom/icon-theme-system.tsx +116 -0
- package/.shadcn-admin-ref/src/assets/logo.tsx +24 -0
- package/.shadcn-admin-ref/src/components/coming-soon.tsx +16 -0
- package/.shadcn-admin-ref/src/components/command-menu.tsx +91 -0
- package/.shadcn-admin-ref/src/components/config-drawer.tsx +354 -0
- package/.shadcn-admin-ref/src/components/confirm-dialog.tsx +67 -0
- package/.shadcn-admin-ref/src/components/data-table/bulk-actions.tsx +213 -0
- package/.shadcn-admin-ref/src/components/data-table/column-header.tsx +74 -0
- package/.shadcn-admin-ref/src/components/data-table/faceted-filter.tsx +146 -0
- package/.shadcn-admin-ref/src/components/data-table/index.ts +6 -0
- package/.shadcn-admin-ref/src/components/data-table/pagination.tsx +130 -0
- package/.shadcn-admin-ref/src/components/data-table/toolbar.tsx +85 -0
- package/.shadcn-admin-ref/src/components/data-table/view-options.tsx +56 -0
- package/.shadcn-admin-ref/src/components/date-picker.tsx +51 -0
- package/.shadcn-admin-ref/src/components/layout/app-sidebar.tsx +37 -0
- package/.shadcn-admin-ref/src/components/layout/app-title.tsx +64 -0
- package/.shadcn-admin-ref/src/components/layout/authenticated-layout.tsx +42 -0
- package/.shadcn-admin-ref/src/components/layout/data/sidebar-data.ts +205 -0
- package/.shadcn-admin-ref/src/components/layout/header.tsx +50 -0
- package/.shadcn-admin-ref/src/components/layout/main.tsx +27 -0
- package/.shadcn-admin-ref/src/components/layout/nav-group.tsx +185 -0
- package/.shadcn-admin-ref/src/components/layout/nav-user.tsx +124 -0
- package/.shadcn-admin-ref/src/components/layout/team-switcher.tsx +86 -0
- package/.shadcn-admin-ref/src/components/layout/top-nav.tsx +67 -0
- package/.shadcn-admin-ref/src/components/layout/types.ts +44 -0
- package/.shadcn-admin-ref/src/components/learn-more.tsx +44 -0
- package/.shadcn-admin-ref/src/components/long-text.tsx +84 -0
- package/.shadcn-admin-ref/src/components/navigation-progress.tsx +25 -0
- package/.shadcn-admin-ref/src/components/password-input.tsx +42 -0
- package/.shadcn-admin-ref/src/components/profile-dropdown.tsx +75 -0
- package/.shadcn-admin-ref/src/components/search.tsx +37 -0
- package/.shadcn-admin-ref/src/components/select-dropdown.tsx +62 -0
- package/.shadcn-admin-ref/src/components/sign-out-dialog.tsx +38 -0
- package/.shadcn-admin-ref/src/components/skip-to-main.tsx +10 -0
- package/.shadcn-admin-ref/src/components/theme-switch.tsx +58 -0
- package/.shadcn-admin-ref/src/components/ui/alert-dialog.tsx +154 -0
- package/.shadcn-admin-ref/src/components/ui/alert.tsx +65 -0
- package/.shadcn-admin-ref/src/components/ui/avatar.tsx +50 -0
- package/.shadcn-admin-ref/src/components/ui/badge.tsx +45 -0
- package/.shadcn-admin-ref/src/components/ui/button.tsx +58 -0
- package/.shadcn-admin-ref/src/components/ui/calendar.tsx +210 -0
- package/.shadcn-admin-ref/src/components/ui/card.tsx +91 -0
- package/.shadcn-admin-ref/src/components/ui/checkbox.tsx +29 -0
- package/.shadcn-admin-ref/src/components/ui/collapsible.tsx +31 -0
- package/.shadcn-admin-ref/src/components/ui/command.tsx +181 -0
- package/.shadcn-admin-ref/src/components/ui/dialog.tsx +142 -0
- package/.shadcn-admin-ref/src/components/ui/dropdown-menu.tsx +254 -0
- package/.shadcn-admin-ref/src/components/ui/form.tsx +164 -0
- package/.shadcn-admin-ref/src/components/ui/input-otp.tsx +74 -0
- package/.shadcn-admin-ref/src/components/ui/input.tsx +20 -0
- package/.shadcn-admin-ref/src/components/ui/label.tsx +23 -0
- package/.shadcn-admin-ref/src/components/ui/popover.tsx +45 -0
- package/.shadcn-admin-ref/src/components/ui/radio-group.tsx +42 -0
- package/.shadcn-admin-ref/src/components/ui/scroll-area.tsx +65 -0
- package/.shadcn-admin-ref/src/components/ui/select.tsx +182 -0
- package/.shadcn-admin-ref/src/components/ui/separator.tsx +25 -0
- package/.shadcn-admin-ref/src/components/ui/sheet.tsx +136 -0
- package/.shadcn-admin-ref/src/components/ui/sidebar.tsx +728 -0
- package/.shadcn-admin-ref/src/components/ui/skeleton.tsx +13 -0
- package/.shadcn-admin-ref/src/components/ui/sonner.tsx +21 -0
- package/.shadcn-admin-ref/src/components/ui/switch.tsx +28 -0
- package/.shadcn-admin-ref/src/components/ui/table.tsx +113 -0
- package/.shadcn-admin-ref/src/components/ui/tabs.tsx +63 -0
- package/.shadcn-admin-ref/src/components/ui/textarea.tsx +17 -0
- package/.shadcn-admin-ref/src/components/ui/tooltip.tsx +60 -0
- package/.shadcn-admin-ref/src/config/fonts.ts +19 -0
- package/.shadcn-admin-ref/src/context/direction-provider.tsx +61 -0
- package/.shadcn-admin-ref/src/context/font-provider.tsx +58 -0
- package/.shadcn-admin-ref/src/context/layout-provider.tsx +85 -0
- package/.shadcn-admin-ref/src/context/search-provider.tsx +46 -0
- package/.shadcn-admin-ref/src/context/theme-provider.tsx +110 -0
- package/.shadcn-admin-ref/src/features/apps/data/apps.tsx +110 -0
- package/.shadcn-admin-ref/src/features/apps/index.tsx +179 -0
- package/.shadcn-admin-ref/src/features/auth/auth-layout.tsx +19 -0
- package/.shadcn-admin-ref/src/features/auth/forgot-password/components/forgot-password-form.tsx +82 -0
- package/.shadcn-admin-ref/src/features/auth/forgot-password/index.tsx +44 -0
- package/.shadcn-admin-ref/src/features/auth/otp/components/otp-form.tsx +100 -0
- package/.shadcn-admin-ref/src/features/auth/otp/index.tsx +44 -0
- package/.shadcn-admin-ref/src/features/auth/sign-in/assets/dashboard-dark.png +0 -0
- package/.shadcn-admin-ref/src/features/auth/sign-in/assets/dashboard-light.png +0 -0
- package/.shadcn-admin-ref/src/features/auth/sign-in/components/user-auth-form.tsx +150 -0
- package/.shadcn-admin-ref/src/features/auth/sign-in/index.tsx +51 -0
- package/.shadcn-admin-ref/src/features/auth/sign-in/sign-in-2.tsx +69 -0
- package/.shadcn-admin-ref/src/features/auth/sign-up/components/sign-up-form.tsx +143 -0
- package/.shadcn-admin-ref/src/features/auth/sign-up/index.tsx +57 -0
- package/.shadcn-admin-ref/src/features/chats/components/new-chat.tsx +127 -0
- package/.shadcn-admin-ref/src/features/chats/data/chat-types.ts +4 -0
- package/.shadcn-admin-ref/src/features/chats/data/convo.json +309 -0
- package/.shadcn-admin-ref/src/features/chats/index.tsx +349 -0
- package/.shadcn-admin-ref/src/features/dashboard/components/analytics-chart.tsx +77 -0
- package/.shadcn-admin-ref/src/features/dashboard/components/analytics.tsx +189 -0
- package/.shadcn-admin-ref/src/features/dashboard/components/overview.tsx +82 -0
- package/.shadcn-admin-ref/src/features/dashboard/components/recent-sales.tsx +83 -0
- package/.shadcn-admin-ref/src/features/dashboard/index.tsx +220 -0
- package/.shadcn-admin-ref/src/features/errors/forbidden.tsx +25 -0
- package/.shadcn-admin-ref/src/features/errors/general-error.tsx +36 -0
- package/.shadcn-admin-ref/src/features/errors/maintenance-error.tsx +19 -0
- package/.shadcn-admin-ref/src/features/errors/not-found-error.tsx +25 -0
- package/.shadcn-admin-ref/src/features/errors/unauthorized-error.tsx +25 -0
- package/.shadcn-admin-ref/src/features/settings/account/account-form.tsx +173 -0
- package/.shadcn-admin-ref/src/features/settings/account/index.tsx +14 -0
- package/.shadcn-admin-ref/src/features/settings/appearance/appearance-form.tsx +162 -0
- package/.shadcn-admin-ref/src/features/settings/appearance/index.tsx +14 -0
- package/.shadcn-admin-ref/src/features/settings/components/content-section.tsx +22 -0
- package/.shadcn-admin-ref/src/features/settings/components/sidebar-nav.tsx +84 -0
- package/.shadcn-admin-ref/src/features/settings/display/display-form.tsx +121 -0
- package/.shadcn-admin-ref/src/features/settings/display/index.tsx +13 -0
- package/.shadcn-admin-ref/src/features/settings/index.tsx +74 -0
- package/.shadcn-admin-ref/src/features/settings/notifications/index.tsx +13 -0
- package/.shadcn-admin-ref/src/features/settings/notifications/notifications-form.tsx +220 -0
- package/.shadcn-admin-ref/src/features/settings/profile/index.tsx +13 -0
- package/.shadcn-admin-ref/src/features/settings/profile/profile-form.tsx +177 -0
- package/.shadcn-admin-ref/src/features/tasks/components/data-table-bulk-actions.tsx +193 -0
- package/.shadcn-admin-ref/src/features/tasks/components/data-table-row-actions.tsx +83 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-columns.tsx +123 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-dialogs.tsx +72 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-import-dialog.tsx +110 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-multi-delete-dialog.tsx +95 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-mutate-drawer.tsx +212 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-primary-buttons.tsx +21 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-provider.tsx +36 -0
- package/.shadcn-admin-ref/src/features/tasks/components/tasks-table.tsx +197 -0
- package/.shadcn-admin-ref/src/features/tasks/data/data.tsx +77 -0
- package/.shadcn-admin-ref/src/features/tasks/data/schema.ts +13 -0
- package/.shadcn-admin-ref/src/features/tasks/data/tasks.ts +29 -0
- package/.shadcn-admin-ref/src/features/tasks/index.tsx +41 -0
- package/.shadcn-admin-ref/src/features/users/components/data-table-bulk-actions.tsx +139 -0
- package/.shadcn-admin-ref/src/features/users/components/data-table-row-actions.tsx +63 -0
- package/.shadcn-admin-ref/src/features/users/components/users-action-dialog.tsx +326 -0
- package/.shadcn-admin-ref/src/features/users/components/users-columns.tsx +138 -0
- package/.shadcn-admin-ref/src/features/users/components/users-delete-dialog.tsx +81 -0
- package/.shadcn-admin-ref/src/features/users/components/users-dialogs.tsx +51 -0
- package/.shadcn-admin-ref/src/features/users/components/users-invite-dialog.tsx +150 -0
- package/.shadcn-admin-ref/src/features/users/components/users-multi-delete-dialog.tsx +95 -0
- package/.shadcn-admin-ref/src/features/users/components/users-primary-buttons.tsx +21 -0
- package/.shadcn-admin-ref/src/features/users/components/users-provider.tsx +36 -0
- package/.shadcn-admin-ref/src/features/users/components/users-table.tsx +194 -0
- package/.shadcn-admin-ref/src/features/users/data/data.ts +35 -0
- package/.shadcn-admin-ref/src/features/users/data/schema.ts +32 -0
- package/.shadcn-admin-ref/src/features/users/data/users.ts +33 -0
- package/.shadcn-admin-ref/src/features/users/index.tsx +47 -0
- package/.shadcn-admin-ref/src/hooks/use-dialog-state.tsx +18 -0
- package/.shadcn-admin-ref/src/hooks/use-mobile.tsx +19 -0
- package/.shadcn-admin-ref/src/hooks/use-table-url-state.ts +219 -0
- package/.shadcn-admin-ref/src/lib/cookies.ts +43 -0
- package/.shadcn-admin-ref/src/lib/handle-server-error.ts +24 -0
- package/.shadcn-admin-ref/src/lib/show-submitted-data.tsx +15 -0
- package/.shadcn-admin-ref/src/lib/utils.ts +60 -0
- package/.shadcn-admin-ref/src/main.tsx +107 -0
- package/.shadcn-admin-ref/src/routeTree.gen.ts +719 -0
- package/.shadcn-admin-ref/src/routes/(auth)/forgot-password.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(auth)/otp.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(auth)/sign-in-2.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(auth)/sign-in.tsx +12 -0
- package/.shadcn-admin-ref/src/routes/(auth)/sign-up.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(errors)/401.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(errors)/403.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(errors)/404.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(errors)/500.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/(errors)/503.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/__root.tsx +30 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/apps/index.tsx +17 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/chats/index.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/errors/$error.tsx +45 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/help-center/index.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/index.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/route.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/settings/account.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/settings/appearance.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/settings/display.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/settings/index.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/settings/notifications.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/settings/route.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/tasks/index.tsx +23 -0
- package/.shadcn-admin-ref/src/routes/_authenticated/users/index.tsx +32 -0
- package/.shadcn-admin-ref/src/routes/clerk/(auth)/route.tsx +60 -0
- package/.shadcn-admin-ref/src/routes/clerk/(auth)/sign-in.tsx +14 -0
- package/.shadcn-admin-ref/src/routes/clerk/(auth)/sign-up.tsx +9 -0
- package/.shadcn-admin-ref/src/routes/clerk/_authenticated/route.tsx +6 -0
- package/.shadcn-admin-ref/src/routes/clerk/_authenticated/user-management.tsx +184 -0
- package/.shadcn-admin-ref/src/routes/clerk/route.tsx +135 -0
- package/.shadcn-admin-ref/src/stores/auth-store.ts +53 -0
- package/.shadcn-admin-ref/src/styles/index.css +87 -0
- package/.shadcn-admin-ref/src/styles/theme.css +102 -0
- package/.shadcn-admin-ref/src/tanstack-table.d.ts +10 -0
- package/.shadcn-admin-ref/src/vite-env.d.ts +1 -0
- package/.swarm/memory.db +0 -0
- package/.swarm/memory.db-shm +0 -0
- package/.swarm/memory.db-wal +0 -0
- package/.zyflow/cli-settings.json +30 -0
- package/.zyflow/db.sqlite +0 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765491505852.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765491622627.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765491794652.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765491890392.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765494002879.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765494183887.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765494342052.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765494387244.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765494387245.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765494606176.json +10 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765495967542.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765495967629.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765497861143.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765497861870.json +20 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765498021377.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765498021660.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765503255525.json +13 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765503256018.json +13 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765504009102.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765504492051.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765504946437.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1633-1765504946640.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1634-1765505950215.json +16 -0
- package/.zyflow/logs/add-gitdiagram-integration/1634-1765505950948.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1635-1765505971712.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1635-1765505971976.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1636-1765505986208.json +18 -0
- package/.zyflow/logs/add-gitdiagram-integration/1636-1765505986620.json +16 -0
- package/.zyflow/logs/integrate-claude-flow/3580-1765996816612.json +10 -0
- package/.zyflow/logs/integrate-claude-flow/3580-1766014825819.json +10 -0
- package/.zyflow/logs/integrate-claude-flow/3580-1766015183794.json +12 -0
- package/.zyflow/logs/integrate-claude-flow/3580-1766015474608.json +12 -0
- package/.zyflow/logs/integrate-claude-flow/3581-1766016502824.json +63 -0
- package/.zyflow/logs/integrate-claude-flow/3581-1766016576008.json +60 -0
- package/.zyflow/logs/integrate-claude-flow/3582-1766022737754.json +110 -0
- package/.zyflow/logs/integrate-claude-flow/3582-1766022809327.json +135 -0
- package/.zyflow/sessions.json +242 -0
- package/.zyflow/settings.json +6 -0
- package/.zyflow/tasks.db +0 -0
- package/.zyflow/tasks.db-shm +0 -0
- package/.zyflow/tasks.db-wal +0 -0
- package/.zyflow/zyflow.sqlite +0 -0
- package/Dockerfile +82 -0
- package/LICENSE +21 -0
- package/README.md +506 -0
- package/claude-flow +34 -0
- package/components.json +21 -0
- package/config/ports.ts +28 -0
- package/docker-compose.yml +52 -0
- package/eslint.config.js +34 -0
- package/index.html +19 -0
- package/logs/mcp-error.log +55 -0
- package/logs/mcp-out.log +0 -0
- package/logs/pm2-error.log +0 -0
- package/logs/pm2-out.log +265 -0
- package/logs/py-error.log +22 -0
- package/logs/py-out.log +0 -0
- package/logs/server-error.log +11000 -0
- package/logs/server-out.log +8117 -0
- package/logs/vite-error.log +404 -0
- package/logs/vite-out.log +311 -0
- package/mcp-server/agent-tools.ts +375 -0
- package/mcp-server/cli-models.ts +193 -0
- package/mcp-server/context.ts +110 -0
- package/mcp-server/diagram-tools.ts +341 -0
- package/mcp-server/index.ts +2014 -0
- package/mcp-server/integration-tools.ts +909 -0
- package/mcp-server/moai-spec-tools.ts +416 -0
- package/mcp-server/parser.ts +422 -0
- package/mcp-server/post-task-runner.ts +253 -0
- package/mcp-server/post-task-types.ts +426 -0
- package/mcp-server/quarantine-manager.ts +479 -0
- package/mcp-server/report-generator.ts +386 -0
- package/mcp-server/task-tools.ts +619 -0
- package/mcp-server/trigger-config.ts +288 -0
- package/mcp-server/trigger-router.ts +305 -0
- package/mcp-server/triggers/event-listener.ts +331 -0
- package/mcp-server/triggers/git-hooks.ts +283 -0
- package/mcp-server/triggers/scheduler.ts +289 -0
- package/mcp-server/types.ts +55 -0
- package/memory/claude-flow@alpha-data.json +5 -0
- package/nginx/zyflow.conf +144 -0
- package/openspec/config.yaml +78 -0
- package/openspec-backup.tar.gz +0 -0
- package/package.json +154 -0
- package/packages/gitdiagram-core/.claude-flow/metrics/agent-metrics.json +1 -0
- package/packages/gitdiagram-core/.claude-flow/metrics/performance.json +87 -0
- package/packages/gitdiagram-core/.claude-flow/metrics/task-metrics.json +10 -0
- package/packages/gitdiagram-core/package.json +41 -0
- package/packages/gitdiagram-core/src/file-tree.ts +272 -0
- package/packages/gitdiagram-core/src/generator.ts +283 -0
- package/packages/gitdiagram-core/src/index.ts +78 -0
- package/packages/gitdiagram-core/src/llm-adapter.ts +235 -0
- package/packages/gitdiagram-core/src/mermaid-utils.ts +304 -0
- package/packages/gitdiagram-core/src/prompts.ts +281 -0
- package/packages/zyflow-parser/package.json +34 -0
- package/packages/zyflow-parser/src/index.ts +26 -0
- package/packages/zyflow-parser/src/moai-parser.ts +603 -0
- package/packages/zyflow-parser/src/moai-types.ts +110 -0
- package/packages/zyflow-remote-plugin/.claude-flow/metrics/agent-metrics.json +1 -0
- package/packages/zyflow-remote-plugin/.claude-flow/metrics/performance.json +87 -0
- package/packages/zyflow-remote-plugin/.claude-flow/metrics/task-metrics.json +10 -0
- package/packages/zyflow-remote-plugin/package.json +31 -0
- package/packages/zyflow-remote-plugin/src/index.ts +71 -0
- package/packages/zyflow-remote-plugin/src/remote-config.ts +232 -0
- package/packages/zyflow-remote-plugin/src/router.ts +535 -0
- package/packages/zyflow-remote-plugin/src/ssh-config-parser.ts +123 -0
- package/packages/zyflow-remote-plugin/src/ssh-manager.ts +598 -0
- package/packages/zyflow-remote-plugin/src/types.ts +149 -0
- package/plugin/manifest.json +26 -0
- package/plugin/package.json +13 -0
- package/public/favicon.svg +4 -0
- package/server/adk/agents/error-analyzer.ts +223 -0
- package/server/adk/agents/fix-generator.ts +187 -0
- package/server/adk/agents/pr-agent.ts +264 -0
- package/server/adk/agents/validator.ts +187 -0
- package/server/adk/config.ts +43 -0
- package/server/adk/index.ts +69 -0
- package/server/adk/integration.ts +297 -0
- package/server/adk/orchestrator.ts +405 -0
- package/server/adk/tools/build-tools.ts +290 -0
- package/server/adk/tools/file-tools.ts +351 -0
- package/server/adk/tools/git-tools.ts +280 -0
- package/server/adk/tools/github-tools.ts +249 -0
- package/server/agents/agent-monitor.ts +416 -0
- package/server/agents/alert-integration.ts +312 -0
- package/server/agents/error-analyzer.ts +472 -0
- package/server/agents/error-detector.ts +442 -0
- package/server/agents/fix-generator.ts +421 -0
- package/server/agents/fix-validator.ts +428 -0
- package/server/agents/merge-policy.ts +362 -0
- package/server/agents/pr-workflow.ts +476 -0
- package/server/agents/prompts/error-analysis.ts +393 -0
- package/server/ai/gemini-client.ts +499 -0
- package/server/ai/index.ts +317 -0
- package/server/ai/types.ts +137 -0
- package/server/app.ts +3693 -0
- package/server/archive-manager.ts +604 -0
- package/server/backlog/index.ts +7 -0
- package/server/backlog/migration.ts +331 -0
- package/server/backlog/parser.ts +323 -0
- package/server/backlog/sync.ts +325 -0
- package/server/change-log.ts +868 -0
- package/server/claude-flow/index.ts +12 -0
- package/server/claude-flow/prompt-builder.ts +407 -0
- package/server/claude-flow/types.ts +33 -0
- package/server/cli-adapter/index.ts +11 -0
- package/server/cli-adapter/process-manager.ts +612 -0
- package/server/cli-adapter/profile-manager.ts +286 -0
- package/server/cli-adapter/routes.ts +561 -0
- package/server/cli-adapter/types.ts +226 -0
- package/server/config.d.ts +18 -0
- package/server/config.js +79 -0
- package/server/config.ts +262 -0
- package/server/flow-sync.ts +543 -0
- package/server/git/change-workflow.ts +446 -0
- package/server/git/commands.ts +370 -0
- package/server/git/github.ts +247 -0
- package/server/git/index.ts +1202 -0
- package/server/git/status.ts +322 -0
- package/server/index.ts +136 -0
- package/server/integrations/crypto.ts +142 -0
- package/server/integrations/db/client.ts +169 -0
- package/server/integrations/db/schema.ts +167 -0
- package/server/integrations/env-parser.ts +365 -0
- package/server/integrations/index.ts +101 -0
- package/server/integrations/keychain.ts +239 -0
- package/server/integrations/local/file-utils.ts +383 -0
- package/server/integrations/local/index.ts +64 -0
- package/server/integrations/local/resolver.ts +439 -0
- package/server/integrations/local/types.ts +122 -0
- package/server/integrations/routes.ts +1100 -0
- package/server/integrations/service-patterns.ts +771 -0
- package/server/integrations/services/accounts.ts +356 -0
- package/server/integrations/services/env-import.ts +279 -0
- package/server/integrations/services/projects.ts +552 -0
- package/server/integrations/services/system-import.ts +1110 -0
- package/server/migrations/ears-generator.ts +491 -0
- package/server/migrations/gherkin-generator.ts +605 -0
- package/server/migrations/index.ts +73 -0
- package/server/migrations/migrate-spec-format.ts +492 -0
- package/server/migrations/openspec-parser.ts +542 -0
- package/server/migrations/tag-generator.ts +474 -0
- package/server/moai-specs.ts +487 -0
- package/server/moai-watcher.ts +145 -0
- package/server/parser-debug.ts +37 -0
- package/server/parser-utils.ts +316 -0
- package/server/parser.d.ts +17 -0
- package/server/parser.js +221 -0
- package/server/parser.ts +342 -0
- package/server/remote-watcher.ts +367 -0
- package/server/replay-engine.ts +915 -0
- package/server/routes/alerts.ts +1028 -0
- package/server/routes/changes.ts +812 -0
- package/server/routes/docs.ts +898 -0
- package/server/routes/flow.ts +2814 -0
- package/server/routes/global-chat.ts +162 -0
- package/server/routes/leann.ts +327 -0
- package/server/routes/projects.ts +1282 -0
- package/server/routes/search.ts +266 -0
- package/server/routes/specs.ts +482 -0
- package/server/routes/webhooks.ts +579 -0
- package/server/server/parser.js +265 -0
- package/server/services/githubActionsPoller.ts +797 -0
- package/server/services/slackNotifier.ts +476 -0
- package/server/src/types/index.js +1 -0
- package/server/sync-tasks.ts +741 -0
- package/server/tasks/cli/commands.ts +269 -0
- package/server/tasks/cli/index.ts +152 -0
- package/server/tasks/core/search.ts +81 -0
- package/server/tasks/core/task.ts +307 -0
- package/server/tasks/db/client.ts +1008 -0
- package/server/tasks/db/schema.ts +572 -0
- package/server/tasks/index.ts +24 -0
- package/server/tasks.db +0 -0
- package/server/types/archive.ts +136 -0
- package/server/types/change-log.ts +643 -0
- package/server/types/spec.ts +188 -0
- package/server/unified-spec-scanner.ts +753 -0
- package/server/utils/crypto.ts +179 -0
- package/server/utils/webhook-verify.ts +216 -0
- package/server/watcher.ts +132 -0
- package/server/websocket.ts +99 -0
- package/server-output.log +6 -0
- package/sonar-project.properties +18 -0
- package/src/App.tsx +386 -0
- package/src/api/client.ts +346 -0
- package/src/api/error-interceptor.ts +366 -0
- package/src/api/errors.ts +123 -0
- package/src/api/flow.ts +233 -0
- package/src/api/offline-queue.ts +351 -0
- package/src/api/retry-logic.ts +233 -0
- package/src/components/OfflineModeBanner.tsx +159 -0
- package/src/components/SSEStatusIndicator.tsx +194 -0
- package/src/components/agent/AgentChat.tsx +243 -0
- package/src/components/agent/AgentPage.tsx +182 -0
- package/src/components/agent/AgentSidebar.tsx +231 -0
- package/src/components/agent/index.ts +7 -0
- package/src/components/alerts/AlertCenter.tsx +239 -0
- package/src/components/alerts/AlertDashboard.tsx +211 -0
- package/src/components/alerts/AlertDetail.tsx +474 -0
- package/src/components/alerts/AlertList.tsx +113 -0
- package/src/components/alerts/AlertSettings.tsx +336 -0
- package/src/components/alerts/index.ts +5 -0
- package/src/components/chat/ChatPanel.tsx +642 -0
- package/src/components/chat/index.ts +1 -0
- package/src/components/cli/AddCustomCLIDialog.tsx +210 -0
- package/src/components/cli/CLISelector.tsx +187 -0
- package/src/components/cli/index.ts +8 -0
- package/src/components/dashboard/ArchivedChangeList.tsx +102 -0
- package/src/components/dashboard/ArchivedChangeViewer.tsx +184 -0
- package/src/components/dashboard/ArchivedChangesPage.tsx +31 -0
- package/src/components/dashboard/ChangeList.tsx +86 -0
- package/src/components/dashboard/ThemeToggle.tsx +33 -0
- package/src/components/diagram/DiagramViewer.tsx +256 -0
- package/src/components/diagram/MermaidRenderer.tsx +163 -0
- package/src/components/diagram/ProjectDiagramTab.tsx +161 -0
- package/src/components/diagram/index.ts +13 -0
- package/src/components/errors/ErrorBoundary.tsx +276 -0
- package/src/components/errors/ErrorFallback.tsx +198 -0
- package/src/components/errors/ErrorToast.tsx +221 -0
- package/src/components/flow/BacklogView.tsx +1142 -0
- package/src/components/flow/ChangeDetail.tsx +475 -0
- package/src/components/flow/ChangeItem.tsx +230 -0
- package/src/components/flow/ChangeList.tsx +92 -0
- package/src/components/flow/ExecutionHistoryDialog.tsx +224 -0
- package/src/components/flow/FlowContent.tsx +212 -0
- package/src/components/flow/FlowPage.tsx +9 -0
- package/src/components/flow/PipelineBar.tsx +214 -0
- package/src/components/flow/ProjectDashboard.tsx +222 -0
- package/src/components/flow/SpecDetail.tsx +138 -0
- package/src/components/flow/SpecDetailTabs.tsx +176 -0
- package/src/components/flow/SpecItem.tsx +93 -0
- package/src/components/flow/SpecProgressBar.tsx +47 -0
- package/src/components/flow/StageContent.tsx +620 -0
- package/src/components/flow/StandaloneTasks.tsx +960 -0
- package/src/components/flow/TaskExecutionDialog.tsx +1204 -0
- package/src/components/flow/index.ts +9 -0
- package/src/components/flow/task-execution/AgentSlider.tsx +37 -0
- package/src/components/flow/task-execution/ConsensusSettings.tsx +129 -0
- package/src/components/flow/task-execution/ExecutionOutput.tsx +398 -0
- package/src/components/flow/task-execution/ModelSelector.tsx +134 -0
- package/src/components/flow/task-execution/ProviderSelector.tsx +137 -0
- package/src/components/flow/task-execution/RecommendationBanner.tsx +71 -0
- package/src/components/flow/task-execution/StatusBadge.tsx +43 -0
- package/src/components/flow/task-execution/StrategySelector.tsx +48 -0
- package/src/components/flow/task-execution/SwarmSummary.tsx +55 -0
- package/src/components/flow/task-execution/index.ts +14 -0
- package/src/components/flow/task-execution/types.ts +56 -0
- package/src/components/git/ChangeWorkflowDialog.tsx +582 -0
- package/src/components/git/ConflictResolutionDialog.tsx +398 -0
- package/src/components/git/GitBranchSelector.tsx +212 -0
- package/src/components/git/GitCommitDialog.tsx +254 -0
- package/src/components/git/GitStatusBadge.tsx +148 -0
- package/src/components/git/GitSyncButton.tsx +128 -0
- package/src/components/git/RemoteStatusBanner.tsx +143 -0
- package/src/components/git/index.ts +9 -0
- package/src/components/integrations/EnvImportDialog.tsx +524 -0
- package/src/components/integrations/EnvironmentDialog.tsx +227 -0
- package/src/components/integrations/IntegrationBadges.tsx +91 -0
- package/src/components/integrations/IntegrationsSettings.tsx +55 -0
- package/src/components/integrations/ProjectIntegrations.tsx +481 -0
- package/src/components/integrations/ServiceAccountDialog.tsx +422 -0
- package/src/components/integrations/ServiceAccountList.tsx +305 -0
- package/src/components/integrations/SystemImportDialog.tsx +436 -0
- package/src/components/integrations/TestAccountDialog.tsx +162 -0
- package/src/components/integrations/index.ts +6 -0
- package/src/components/layout/AppSidebar.tsx +284 -0
- package/src/components/layout/FlowSidebar.tsx +435 -0
- package/src/components/layout/GlobalCommandPalette.tsx +410 -0
- package/src/components/layout/MenuBar.tsx +227 -0
- package/src/components/layout/StatusBar.tsx +226 -0
- package/src/components/monitoring/ErrorDashboard.tsx +274 -0
- package/src/components/monitoring/ErrorDetailPanel.tsx +200 -0
- package/src/components/monitoring/ErrorFilters.tsx +219 -0
- package/src/components/monitoring/ErrorHistoryList.tsx +141 -0
- package/src/components/monitoring/ErrorStats.tsx +249 -0
- package/src/components/remote/RemoteFileBrowser.tsx +249 -0
- package/src/components/remote/RemoteServerDialog.tsx +234 -0
- package/src/components/remote/RemoteServerList.tsx +366 -0
- package/src/components/remote/index.ts +7 -0
- package/src/components/settings/CLISettings.tsx +522 -0
- package/src/components/settings/CustomCLIDialog.tsx +548 -0
- package/src/components/settings/IntegrationsSettings.tsx +51 -0
- package/src/components/settings/ProjectSettings.tsx +441 -0
- package/src/components/settings/ProjectsSettings.tsx +541 -0
- package/src/components/settings/SearchSettings.tsx +272 -0
- package/src/components/settings/SettingsPage.tsx +68 -0
- package/src/components/settings/index.ts +5 -0
- package/src/components/swarm/ExecutionPanel.tsx +284 -0
- package/src/components/swarm/LogViewer.tsx +196 -0
- package/src/components/swarm/ProgressIndicator.tsx +111 -0
- package/src/components/swarm/index.ts +3 -0
- package/src/components/tasks/ArchiveTable.tsx +203 -0
- package/src/components/tasks/KanbanBoard.tsx +264 -0
- package/src/components/tasks/TaskCard.tsx +138 -0
- package/src/components/tasks/TaskColumn.tsx +81 -0
- package/src/components/tasks/TaskDialog.tsx +274 -0
- package/src/components/tasks/index.ts +5 -0
- package/src/components/tasks/types.ts +43 -0
- package/src/components/ui/alert-dialog.tsx +154 -0
- package/src/components/ui/alert.tsx +65 -0
- package/src/components/ui/badge.tsx +45 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/card.tsx +91 -0
- package/src/components/ui/checkbox.tsx +29 -0
- package/src/components/ui/collapsible.tsx +31 -0
- package/src/components/ui/command.tsx +184 -0
- package/src/components/ui/confirm-dialog.tsx +55 -0
- package/src/components/ui/dialog.tsx +142 -0
- package/src/components/ui/dropdown-menu.tsx +254 -0
- package/src/components/ui/input.tsx +20 -0
- package/src/components/ui/label.tsx +22 -0
- package/src/components/ui/markdown.tsx +100 -0
- package/src/components/ui/progress.tsx +27 -0
- package/src/components/ui/resizable-sidebar.tsx +156 -0
- package/src/components/ui/resizable.tsx +54 -0
- package/src/components/ui/right-resizable-sidebar.tsx +158 -0
- package/src/components/ui/scroll-area.tsx +64 -0
- package/src/components/ui/select.tsx +185 -0
- package/src/components/ui/separator.tsx +25 -0
- package/src/components/ui/sheet.tsx +136 -0
- package/src/components/ui/sidebar.tsx +726 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/slider.tsx +56 -0
- package/src/components/ui/switch.tsx +29 -0
- package/src/components/ui/table.tsx +113 -0
- package/src/components/ui/tabs.tsx +63 -0
- package/src/components/ui/textarea.tsx +17 -0
- package/src/components/ui/tooltip.tsx +60 -0
- package/src/config/api.ts +83 -0
- package/src/constants/error-codes.ts +255 -0
- package/src/constants/stages.ts +27 -0
- package/src/context/ErrorContext.tsx +185 -0
- package/src/context/theme-provider.tsx +63 -0
- package/src/hooks/use-mobile.tsx +19 -0
- package/src/hooks/useAI.ts +206 -0
- package/src/hooks/useAgentSession.ts +431 -0
- package/src/hooks/useAlerts.ts +935 -0
- package/src/hooks/useArchivedChanges.ts +39 -0
- package/src/hooks/useAsyncError.ts +45 -0
- package/src/hooks/useChangeGit.ts +727 -0
- package/src/hooks/useChanges.ts +20 -0
- package/src/hooks/useClaude.ts +130 -0
- package/src/hooks/useDocs.ts +182 -0
- package/src/hooks/useErrorDashboard.ts +243 -0
- package/src/hooks/useErrorHandler.ts +150 -0
- package/src/hooks/useExecutionHistory.ts +55 -0
- package/src/hooks/useFlowChanges.ts +850 -0
- package/src/hooks/useFlowItems.ts +205 -0
- package/src/hooks/useGit.ts +427 -0
- package/src/hooks/useHideCompletedSpecs.ts +15 -0
- package/src/hooks/useInstance.ts +40 -0
- package/src/hooks/useIntegrations.ts +737 -0
- package/src/hooks/useLeannStatus.ts +93 -0
- package/src/hooks/useNetworkStatus.ts +167 -0
- package/src/hooks/useProjects.ts +353 -0
- package/src/hooks/useRemoteServers.ts +383 -0
- package/src/hooks/useSSEConnection.ts +346 -0
- package/src/hooks/useSpecs.ts +39 -0
- package/src/hooks/useSwarm.ts +462 -0
- package/src/hooks/useTasks.ts +137 -0
- package/src/hooks/useURLSync.ts +122 -0
- package/src/hooks/useWebSocket.ts +262 -0
- package/src/lib/utils.ts +121 -0
- package/src/main.tsx +22 -0
- package/src/stores/errorStore.ts +301 -0
- package/src/stores/offlineStore.ts +266 -0
- package/src/stores/sseStore.ts +247 -0
- package/src/stores/useHideCompletedStore.ts +21 -0
- package/src/styles/index.css +87 -0
- package/src/styles/theme.css +102 -0
- package/src/types/ai.ts +191 -0
- package/src/types/errors.ts +253 -0
- package/src/types/flow.ts +382 -0
- package/src/types/index.ts +614 -0
- package/src/utils/error-logger.ts +399 -0
- package/src/utils/error-statistics.ts +305 -0
- package/src/utils/logger.ts +280 -0
- package/src/utils/task-routing.ts +795 -0
- package/src/vite-env.d.ts +1 -0
- package/test-results/.last-run.json +4 -0
- package/tmp/check-docker-final.ts +48 -0
- package/tmp/check-docker-tasks.ts +58 -0
- package/tmp/check-docker-tasks2.ts +48 -0
- package/tmp/check-docker-tasks3.ts +42 -0
- package/tmp/check-mobile-tasks.ts +57 -0
- package/tmp/check-zywiki-tasks.ts +49 -0
- package/tmp/sync-mobile.ts +11 -0
- package/tmp/sync-zywiki.ts +68 -0
- package/tmp/test-docker-parser.ts +15 -0
- package/tmp/test-mobile-parser.ts +28 -0
- package/tmp/test-parser.ts +27 -0
- package/tmp/test-unnumbered.ts +35 -0
- 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
|
+
})
|