@cloudcli-ai/cloudcli 1.29.5 → 1.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +1 -1
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/README.tr.md +252 -0
- package/README.zh-CN.md +1 -1
- package/dist/assets/index-DF8TTVHl.css +32 -0
- package/dist/assets/index-DbZAcc9z.js +1262 -0
- package/dist/index.html +2 -2
- package/dist-server/server/claude-sdk.js +13 -8
- package/dist-server/server/claude-sdk.js.map +1 -1
- package/dist-server/server/cursor-cli.js +7 -7
- package/dist-server/server/cursor-cli.js.map +1 -1
- package/dist-server/server/gemini-cli.js +5 -5
- package/dist-server/server/gemini-cli.js.map +1 -1
- package/dist-server/server/gemini-response-handler.js +2 -2
- package/dist-server/server/gemini-response-handler.js.map +1 -1
- package/dist-server/server/index.js +139 -977
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/middleware/auth.js +1 -1
- package/dist-server/server/middleware/auth.js.map +1 -1
- package/dist-server/server/modules/database/connection.js +125 -0
- package/dist-server/server/modules/database/connection.js.map +1 -0
- package/dist-server/server/modules/database/index.js +13 -0
- package/dist-server/server/modules/database/index.js.map +1 -0
- package/dist-server/server/modules/database/init-db.js +18 -0
- package/dist-server/server/modules/database/init-db.js.map +1 -0
- package/dist-server/server/modules/database/migrations.js +370 -0
- package/dist-server/server/modules/database/migrations.js.map +1 -0
- package/dist-server/server/modules/database/repositories/api-keys.js +72 -0
- package/dist-server/server/modules/database/repositories/api-keys.js.map +1 -0
- package/dist-server/server/modules/database/repositories/app-config.js +47 -0
- package/dist-server/server/modules/database/repositories/app-config.js.map +1 -0
- package/dist-server/server/modules/database/repositories/credentials.js +68 -0
- package/dist-server/server/modules/database/repositories/credentials.js.map +1 -0
- package/dist-server/server/modules/database/repositories/github-tokens.js +54 -0
- package/dist-server/server/modules/database/repositories/github-tokens.js.map +1 -0
- package/dist-server/server/modules/database/repositories/notification-preferences.js +72 -0
- package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -0
- package/dist-server/server/modules/database/repositories/projects.db.integration.test.js +64 -0
- package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/database/repositories/projects.db.js +160 -0
- package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/push-subscriptions.js +49 -0
- package/dist-server/server/modules/database/repositories/push-subscriptions.js.map +1 -0
- package/dist-server/server/modules/database/repositories/scan-state.db.js +31 -0
- package/dist-server/server/modules/database/repositories/scan-state.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js +109 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/users.js +88 -0
- package/dist-server/server/modules/database/repositories/users.js.map +1 -0
- package/dist-server/server/modules/database/repositories/vapid-keys.js +38 -0
- package/dist-server/server/modules/database/repositories/vapid-keys.js.map +1 -0
- package/dist-server/server/modules/database/schema.js +143 -0
- package/dist-server/server/modules/database/schema.js.map +1 -0
- package/dist-server/server/modules/projects/index.js +4 -0
- package/dist-server/server/modules/projects/index.js.map +1 -0
- package/dist-server/server/modules/projects/projects.routes.js +188 -0
- package/dist-server/server/modules/projects/projects.routes.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-clone.service.js +219 -0
- package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-delete.service.js +65 -0
- package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-management.service.js +93 -0
- package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-star.service.js +60 -0
- package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js +167 -0
- package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +169 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-clone.service.test.js +126 -0
- package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-management.service.test.js +85 -0
- package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-star.service.test.js +95 -0
- package/dist-server/server/modules/projects/tests/project-star.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js +87 -0
- package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js.map +1 -0
- package/dist-server/server/modules/providers/index.js +4 -0
- package/dist-server/server/modules/providers/index.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js +103 -0
- package/dist-server/server/modules/providers/list/claude/claude-auth.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js +103 -0
- package/dist-server/server/modules/providers/list/claude/claude-mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +63 -0
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +403 -0
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js +15 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js +84 -0
- package/dist-server/server/modules/providers/list/codex/codex-auth.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js +107 -0
- package/dist-server/server/modules/providers/list/codex/codex-mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +71 -0
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +494 -0
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js +15 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js +118 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-auth.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js +80 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +127 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js +369 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-sessions.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +15 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js +131 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-auth.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js +82 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +296 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +474 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +15 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -0
- package/dist-server/server/modules/providers/provider.registry.js +31 -0
- package/dist-server/server/modules/providers/provider.registry.js.map +1 -0
- package/dist-server/server/modules/providers/provider.routes.js +331 -0
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -0
- package/dist-server/server/modules/providers/services/mcp.service.js +69 -0
- package/dist-server/server/modules/providers/services/mcp.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/provider-auth.service.js +25 -0
- package/dist-server/server/modules/providers/services/provider-auth.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +868 -0
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js +56 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js +234 -0
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/sessions.service.js +104 -0
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -0
- package/dist-server/server/modules/providers/shared/base/abstract.provider.js +14 -0
- package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -0
- package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js +102 -0
- package/dist-server/server/modules/providers/shared/mcp/mcp.provider.js.map +1 -0
- package/dist-server/server/modules/providers/tests/mcp.test.js +250 -0
- package/dist-server/server/modules/providers/tests/mcp.test.js.map +1 -0
- package/dist-server/server/modules/websocket/index.js +3 -0
- package/dist-server/server/modules/websocket/index.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +188 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +52 -0
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +334 -0
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-auth.service.js +32 -0
- package/dist-server/server/modules/websocket/services/websocket-auth.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-server.service.js +36 -0
- package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-state.service.js +14 -0
- package/dist-server/server/modules/websocket/services/websocket-state.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-writer.service.js +32 -0
- package/dist-server/server/modules/websocket/services/websocket-writer.service.js.map +1 -0
- package/dist-server/server/openai-codex.js +5 -5
- package/dist-server/server/openai-codex.js.map +1 -1
- package/dist-server/server/routes/agent.js +10 -17
- package/dist-server/server/routes/agent.js.map +1 -1
- package/dist-server/server/routes/auth.js +3 -1
- package/dist-server/server/routes/auth.js.map +1 -1
- package/dist-server/server/routes/commands.js +1 -45
- package/dist-server/server/routes/commands.js.map +1 -1
- package/dist-server/server/routes/cursor.js +9 -489
- package/dist-server/server/routes/cursor.js.map +1 -1
- package/dist-server/server/routes/gemini.js +2 -2
- package/dist-server/server/routes/gemini.js.map +1 -1
- package/dist-server/server/routes/git.js +33 -29
- package/dist-server/server/routes/git.js.map +1 -1
- package/dist-server/server/routes/mcp-utils.js +1 -18
- package/dist-server/server/routes/mcp-utils.js.map +1 -1
- package/dist-server/server/routes/settings.js +11 -1
- package/dist-server/server/routes/settings.js.map +1 -1
- package/dist-server/server/routes/taskmaster.js +97 -569
- package/dist-server/server/routes/taskmaster.js.map +1 -1
- package/dist-server/server/routes/user.js +1 -1
- package/dist-server/server/routes/user.js.map +1 -1
- package/dist-server/server/services/notification-orchestrator.js +2 -2
- package/dist-server/server/services/notification-orchestrator.js.map +1 -1
- package/dist-server/server/services/vapid-keys.js +2 -1
- package/dist-server/server/services/vapid-keys.js.map +1 -1
- package/dist-server/server/shared/interfaces.js +2 -0
- package/dist-server/server/shared/interfaces.js.map +1 -0
- package/dist-server/server/shared/types.js +2 -0
- package/dist-server/server/shared/types.js.map +1 -0
- package/dist-server/server/shared/utils.js +551 -0
- package/dist-server/server/shared/utils.js.map +1 -0
- package/dist-server/server/utils/mcp-detector.js +0 -49
- package/dist-server/server/utils/mcp-detector.js.map +1 -1
- package/dist-server/server/utils/taskmaster-websocket.js +18 -12
- package/dist-server/server/utils/taskmaster-websocket.js.map +1 -1
- package/dist-server/shared/modelConstants.js +3 -1
- package/dist-server/shared/modelConstants.js.map +1 -1
- package/package.json +7 -2
- package/server/claude-sdk.js +14 -8
- package/server/cursor-cli.js +7 -7
- package/server/gemini-cli.js +5 -5
- package/server/gemini-response-handler.js +2 -2
- package/server/index.js +173 -1035
- package/server/middleware/auth.js +1 -1
- package/server/modules/database/connection.ts +143 -0
- package/server/modules/database/index.ts +12 -0
- package/server/modules/database/init-db.ts +17 -0
- package/server/modules/database/migrations.ts +442 -0
- package/server/modules/database/repositories/api-keys.ts +119 -0
- package/server/modules/database/repositories/app-config.ts +53 -0
- package/server/modules/database/repositories/credentials.ts +106 -0
- package/server/modules/database/repositories/github-tokens.ts +100 -0
- package/server/modules/database/repositories/notification-preferences.ts +103 -0
- package/server/modules/database/repositories/projects.db.integration.test.ts +72 -0
- package/server/modules/database/repositories/projects.db.ts +183 -0
- package/server/modules/database/repositories/push-subscriptions.ts +80 -0
- package/server/modules/database/repositories/scan-state.db.ts +42 -0
- package/server/modules/database/repositories/sessions.db.ts +174 -0
- package/server/modules/database/repositories/users.ts +140 -0
- package/server/modules/database/repositories/vapid-keys.ts +57 -0
- package/server/modules/database/schema.ts +152 -0
- package/server/modules/projects/index.ts +6 -0
- package/server/modules/projects/projects.routes.ts +247 -0
- package/server/modules/projects/services/project-clone.service.ts +321 -0
- package/server/modules/projects/services/project-delete.service.ts +75 -0
- package/server/modules/projects/services/project-management.service.ts +150 -0
- package/server/modules/projects/services/project-star.service.ts +78 -0
- package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -0
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +285 -0
- package/server/modules/projects/tests/project-clone.service.test.ts +183 -0
- package/server/modules/projects/tests/project-management.service.test.ts +117 -0
- package/server/modules/projects/tests/project-star.service.test.ts +123 -0
- package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -0
- package/server/modules/providers/index.ts +4 -0
- package/server/modules/providers/list/claude/claude-auth.provider.ts +123 -0
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -0
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +110 -0
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +475 -0
- package/server/modules/providers/list/claude/claude.provider.ts +17 -0
- package/server/modules/providers/list/codex/codex-auth.provider.ts +100 -0
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -0
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +119 -0
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +564 -0
- package/server/modules/providers/list/codex/codex.provider.ts +17 -0
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -0
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -0
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +176 -0
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -0
- package/server/modules/providers/list/cursor/cursor.provider.ts +17 -0
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +151 -0
- package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -0
- package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +401 -0
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +541 -0
- package/server/modules/providers/list/gemini/gemini.provider.ts +17 -0
- package/server/modules/providers/provider.registry.ts +36 -0
- package/server/modules/providers/provider.routes.ts +425 -0
- package/server/modules/providers/services/mcp.service.ts +94 -0
- package/server/modules/providers/services/provider-auth.service.ts +26 -0
- package/server/modules/providers/services/session-conversations-search.service.ts +1167 -0
- package/server/modules/providers/services/session-synchronizer.service.ts +74 -0
- package/server/modules/providers/services/sessions-watcher.service.ts +283 -0
- package/server/modules/providers/services/sessions.service.ts +130 -0
- package/server/modules/providers/shared/base/abstract.provider.ts +27 -0
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -0
- package/server/modules/providers/tests/mcp.test.ts +293 -0
- package/server/modules/websocket/README.md +267 -0
- package/server/modules/websocket/index.ts +2 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +271 -0
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -0
- package/server/modules/websocket/services/shell-websocket.service.ts +453 -0
- package/server/modules/websocket/services/websocket-auth.service.ts +54 -0
- package/server/modules/websocket/services/websocket-server.service.ts +58 -0
- package/server/modules/websocket/services/websocket-state.service.ts +16 -0
- package/server/modules/websocket/services/websocket-writer.service.ts +38 -0
- package/server/openai-codex.js +5 -5
- package/server/routes/agent.js +11 -16
- package/server/routes/auth.js +4 -2
- package/server/routes/commands.js +1 -50
- package/server/routes/cursor.js +15 -527
- package/server/routes/gemini.js +3 -2
- package/server/routes/git.js +33 -28
- package/server/routes/mcp-utils.js +2 -19
- package/server/routes/settings.js +11 -1
- package/server/routes/taskmaster.js +107 -602
- package/server/routes/user.js +1 -1
- package/server/services/notification-orchestrator.js +3 -2
- package/server/services/vapid-keys.js +2 -1
- package/server/shared/interfaces.ts +92 -0
- package/server/shared/types.ts +327 -0
- package/server/shared/utils.ts +669 -0
- package/server/tsconfig.json +6 -3
- package/server/utils/mcp-detector.js +0 -51
- package/server/utils/taskmaster-websocket.js +19 -13
- package/shared/modelConstants.js +3 -1
- package/dist/assets/index-BBAE1OJ_.css +0 -32
- package/dist/assets/index-Ci1GOyV7.js +0 -1262
- package/dist-server/server/database/db.js +0 -535
- package/dist-server/server/database/db.js.map +0 -1
- package/dist-server/server/database/schema.js +0 -97
- package/dist-server/server/database/schema.js.map +0 -1
- package/dist-server/server/projects.js +0 -2325
- package/dist-server/server/projects.js.map +0 -1
- package/dist-server/server/providers/claude/adapter.js +0 -266
- package/dist-server/server/providers/claude/adapter.js.map +0 -1
- package/dist-server/server/providers/claude/status.js +0 -121
- package/dist-server/server/providers/claude/status.js.map +0 -1
- package/dist-server/server/providers/codex/adapter.js +0 -232
- package/dist-server/server/providers/codex/adapter.js.map +0 -1
- package/dist-server/server/providers/codex/status.js +0 -70
- package/dist-server/server/providers/codex/status.js.map +0 -1
- package/dist-server/server/providers/cursor/adapter.js +0 -342
- package/dist-server/server/providers/cursor/adapter.js.map +0 -1
- package/dist-server/server/providers/cursor/status.js +0 -118
- package/dist-server/server/providers/cursor/status.js.map +0 -1
- package/dist-server/server/providers/gemini/adapter.js +0 -174
- package/dist-server/server/providers/gemini/adapter.js.map +0 -1
- package/dist-server/server/providers/gemini/status.js +0 -104
- package/dist-server/server/providers/gemini/status.js.map +0 -1
- package/dist-server/server/providers/registry.js +0 -58
- package/dist-server/server/providers/registry.js.map +0 -1
- package/dist-server/server/providers/types.js +0 -117
- package/dist-server/server/providers/types.js.map +0 -1
- package/dist-server/server/providers/utils.js +0 -28
- package/dist-server/server/providers/utils.js.map +0 -1
- package/dist-server/server/routes/cli-auth.js +0 -25
- package/dist-server/server/routes/cli-auth.js.map +0 -1
- package/dist-server/server/routes/codex.js +0 -294
- package/dist-server/server/routes/codex.js.map +0 -1
- package/dist-server/server/routes/mcp.js +0 -480
- package/dist-server/server/routes/mcp.js.map +0 -1
- package/dist-server/server/routes/messages.js +0 -56
- package/dist-server/server/routes/messages.js.map +0 -1
- package/dist-server/server/routes/projects.js +0 -505
- package/dist-server/server/routes/projects.js.map +0 -1
- package/server/database/db.js +0 -593
- package/server/database/schema.js +0 -102
- package/server/projects.js +0 -2555
- package/server/providers/claude/adapter.js +0 -278
- package/server/providers/claude/status.js +0 -136
- package/server/providers/codex/adapter.js +0 -248
- package/server/providers/codex/status.js +0 -78
- package/server/providers/cursor/adapter.js +0 -348
- package/server/providers/cursor/status.js +0 -128
- package/server/providers/gemini/adapter.js +0 -186
- package/server/providers/gemini/status.js +0 -111
- package/server/providers/registry.js +0 -67
- package/server/providers/types.js +0 -132
- package/server/providers/utils.js +0 -29
- package/server/routes/cli-auth.js +0 -27
- package/server/routes/codex.js +0 -329
- package/server/routes/mcp.js +0 -552
- package/server/routes/messages.js +0 -61
- package/server/routes/projects.js +0 -548
|
@@ -13,15 +13,24 @@ import fs from 'fs';
|
|
|
13
13
|
import path from 'path';
|
|
14
14
|
import { promises as fsPromises } from 'fs';
|
|
15
15
|
import { spawn } from 'child_process';
|
|
16
|
-
import {
|
|
17
|
-
import { dirname } from 'path';
|
|
18
|
-
import os from 'os';
|
|
19
|
-
import { extractProjectDirectory } from '../projects.js';
|
|
16
|
+
import { projectsDb } from '../modules/database/index.js';
|
|
20
17
|
import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
|
|
21
18
|
import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the absolute project directory from a DB-assigned `projectId`.
|
|
22
|
+
*
|
|
23
|
+
* TaskMaster routes used to accept a Claude-encoded folder name (`projectName`)
|
|
24
|
+
* and derive the path from JSONL history. After the projectId migration the
|
|
25
|
+
* only identifier we accept is the primary key of the `projects` table, so
|
|
26
|
+
* every handler calls this helper and 404s when the id is unknown.
|
|
27
|
+
*/
|
|
28
|
+
async function resolveProjectPathFromId(projectId) {
|
|
29
|
+
if (!projectId) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return projectsDb.getProjectPathById(projectId);
|
|
33
|
+
}
|
|
25
34
|
|
|
26
35
|
const router = express.Router();
|
|
27
36
|
|
|
@@ -100,140 +109,6 @@ async function checkTaskMasterInstallation() {
|
|
|
100
109
|
});
|
|
101
110
|
}
|
|
102
111
|
|
|
103
|
-
/**
|
|
104
|
-
* Detect .taskmaster folder presence in a given project directory
|
|
105
|
-
* @param {string} projectPath - Absolute path to project directory
|
|
106
|
-
* @returns {Promise<Object>} Detection result with status and metadata
|
|
107
|
-
*/
|
|
108
|
-
async function detectTaskMasterFolder(projectPath) {
|
|
109
|
-
try {
|
|
110
|
-
const taskMasterPath = path.join(projectPath, '.taskmaster');
|
|
111
|
-
|
|
112
|
-
// Check if .taskmaster directory exists
|
|
113
|
-
try {
|
|
114
|
-
const stats = await fsPromises.stat(taskMasterPath);
|
|
115
|
-
if (!stats.isDirectory()) {
|
|
116
|
-
return {
|
|
117
|
-
hasTaskmaster: false,
|
|
118
|
-
reason: '.taskmaster exists but is not a directory'
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
} catch (error) {
|
|
122
|
-
if (error.code === 'ENOENT') {
|
|
123
|
-
return {
|
|
124
|
-
hasTaskmaster: false,
|
|
125
|
-
reason: '.taskmaster directory not found'
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
throw error;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Check for key TaskMaster files
|
|
132
|
-
const keyFiles = [
|
|
133
|
-
'tasks/tasks.json',
|
|
134
|
-
'config.json'
|
|
135
|
-
];
|
|
136
|
-
|
|
137
|
-
const fileStatus = {};
|
|
138
|
-
let hasEssentialFiles = true;
|
|
139
|
-
|
|
140
|
-
for (const file of keyFiles) {
|
|
141
|
-
const filePath = path.join(taskMasterPath, file);
|
|
142
|
-
try {
|
|
143
|
-
await fsPromises.access(filePath, fs.constants.R_OK);
|
|
144
|
-
fileStatus[file] = true;
|
|
145
|
-
} catch (error) {
|
|
146
|
-
fileStatus[file] = false;
|
|
147
|
-
if (file === 'tasks/tasks.json') {
|
|
148
|
-
hasEssentialFiles = false;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Parse tasks.json if it exists for metadata
|
|
154
|
-
let taskMetadata = null;
|
|
155
|
-
if (fileStatus['tasks/tasks.json']) {
|
|
156
|
-
try {
|
|
157
|
-
const tasksPath = path.join(taskMasterPath, 'tasks/tasks.json');
|
|
158
|
-
const tasksContent = await fsPromises.readFile(tasksPath, 'utf8');
|
|
159
|
-
const tasksData = JSON.parse(tasksContent);
|
|
160
|
-
|
|
161
|
-
// Handle both tagged and legacy formats
|
|
162
|
-
let tasks = [];
|
|
163
|
-
if (tasksData.tasks) {
|
|
164
|
-
// Legacy format
|
|
165
|
-
tasks = tasksData.tasks;
|
|
166
|
-
} else {
|
|
167
|
-
// Tagged format - get tasks from all tags
|
|
168
|
-
Object.values(tasksData).forEach(tagData => {
|
|
169
|
-
if (tagData.tasks) {
|
|
170
|
-
tasks = tasks.concat(tagData.tasks);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Calculate task statistics
|
|
176
|
-
const stats = tasks.reduce((acc, task) => {
|
|
177
|
-
acc.total++;
|
|
178
|
-
acc[task.status] = (acc[task.status] || 0) + 1;
|
|
179
|
-
|
|
180
|
-
// Count subtasks
|
|
181
|
-
if (task.subtasks) {
|
|
182
|
-
task.subtasks.forEach(subtask => {
|
|
183
|
-
acc.subtotalTasks++;
|
|
184
|
-
acc.subtasks = acc.subtasks || {};
|
|
185
|
-
acc.subtasks[subtask.status] = (acc.subtasks[subtask.status] || 0) + 1;
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return acc;
|
|
190
|
-
}, {
|
|
191
|
-
total: 0,
|
|
192
|
-
subtotalTasks: 0,
|
|
193
|
-
pending: 0,
|
|
194
|
-
'in-progress': 0,
|
|
195
|
-
done: 0,
|
|
196
|
-
review: 0,
|
|
197
|
-
deferred: 0,
|
|
198
|
-
cancelled: 0,
|
|
199
|
-
subtasks: {}
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
taskMetadata = {
|
|
203
|
-
taskCount: stats.total,
|
|
204
|
-
subtaskCount: stats.subtotalTasks,
|
|
205
|
-
completed: stats.done || 0,
|
|
206
|
-
pending: stats.pending || 0,
|
|
207
|
-
inProgress: stats['in-progress'] || 0,
|
|
208
|
-
review: stats.review || 0,
|
|
209
|
-
completionPercentage: stats.total > 0 ? Math.round((stats.done / stats.total) * 100) : 0,
|
|
210
|
-
lastModified: (await fsPromises.stat(tasksPath)).mtime.toISOString()
|
|
211
|
-
};
|
|
212
|
-
} catch (parseError) {
|
|
213
|
-
console.warn('Failed to parse tasks.json:', parseError.message);
|
|
214
|
-
taskMetadata = { error: 'Failed to parse tasks.json' };
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
return {
|
|
219
|
-
hasTaskmaster: true,
|
|
220
|
-
hasEssentialFiles,
|
|
221
|
-
files: fileStatus,
|
|
222
|
-
metadata: taskMetadata,
|
|
223
|
-
path: taskMasterPath
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
} catch (error) {
|
|
227
|
-
console.error('Error detecting TaskMaster folder:', error);
|
|
228
|
-
return {
|
|
229
|
-
hasTaskmaster: false,
|
|
230
|
-
reason: `Error checking directory: ${error.message}`
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// MCP detection is now handled by the centralized utility
|
|
236
|
-
|
|
237
112
|
// API Routes
|
|
238
113
|
|
|
239
114
|
/**
|
|
@@ -272,313 +147,22 @@ router.get('/installation-status', async (req, res) => {
|
|
|
272
147
|
});
|
|
273
148
|
|
|
274
149
|
/**
|
|
275
|
-
* GET /api/taskmaster/
|
|
276
|
-
* Detect TaskMaster configuration for a specific project
|
|
277
|
-
*/
|
|
278
|
-
router.get('/detect/:projectName', async (req, res) => {
|
|
279
|
-
try {
|
|
280
|
-
const { projectName } = req.params;
|
|
281
|
-
|
|
282
|
-
// Use the existing extractProjectDirectory function to get actual project path
|
|
283
|
-
let projectPath;
|
|
284
|
-
try {
|
|
285
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
286
|
-
} catch (error) {
|
|
287
|
-
console.error('Error extracting project directory:', error);
|
|
288
|
-
return res.status(404).json({
|
|
289
|
-
error: 'Project path not found',
|
|
290
|
-
projectName,
|
|
291
|
-
message: error.message
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// Verify the project path exists
|
|
296
|
-
try {
|
|
297
|
-
await fsPromises.access(projectPath, fs.constants.R_OK);
|
|
298
|
-
} catch (error) {
|
|
299
|
-
return res.status(404).json({
|
|
300
|
-
error: 'Project path not accessible',
|
|
301
|
-
projectPath,
|
|
302
|
-
projectName,
|
|
303
|
-
message: error.message
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Run detection in parallel
|
|
308
|
-
const [taskMasterResult, mcpResult] = await Promise.all([
|
|
309
|
-
detectTaskMasterFolder(projectPath),
|
|
310
|
-
detectTaskMasterMCPServer()
|
|
311
|
-
]);
|
|
312
|
-
|
|
313
|
-
// Determine overall status
|
|
314
|
-
let status = 'not-configured';
|
|
315
|
-
if (taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles) {
|
|
316
|
-
if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
|
|
317
|
-
status = 'fully-configured';
|
|
318
|
-
} else {
|
|
319
|
-
status = 'taskmaster-only';
|
|
320
|
-
}
|
|
321
|
-
} else if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
|
|
322
|
-
status = 'mcp-only';
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
const responseData = {
|
|
326
|
-
projectName,
|
|
327
|
-
projectPath,
|
|
328
|
-
status,
|
|
329
|
-
taskmaster: taskMasterResult,
|
|
330
|
-
mcp: mcpResult,
|
|
331
|
-
timestamp: new Date().toISOString()
|
|
332
|
-
};
|
|
333
|
-
|
|
334
|
-
res.json(responseData);
|
|
335
|
-
|
|
336
|
-
} catch (error) {
|
|
337
|
-
console.error('TaskMaster detection error:', error);
|
|
338
|
-
res.status(500).json({
|
|
339
|
-
error: 'Failed to detect TaskMaster configuration',
|
|
340
|
-
message: error.message
|
|
341
|
-
});
|
|
342
|
-
}
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
/**
|
|
346
|
-
* GET /api/taskmaster/detect-all
|
|
347
|
-
* Detect TaskMaster configuration for all known projects
|
|
348
|
-
* This endpoint works with the existing projects system
|
|
349
|
-
*/
|
|
350
|
-
router.get('/detect-all', async (req, res) => {
|
|
351
|
-
try {
|
|
352
|
-
// Import getProjects from the projects module
|
|
353
|
-
const { getProjects } = await import('../projects.js');
|
|
354
|
-
const projects = await getProjects();
|
|
355
|
-
|
|
356
|
-
// Run detection for all projects in parallel
|
|
357
|
-
const detectionPromises = projects.map(async (project) => {
|
|
358
|
-
try {
|
|
359
|
-
// Use the project's fullPath if available, otherwise extract the directory
|
|
360
|
-
let projectPath;
|
|
361
|
-
if (project.fullPath) {
|
|
362
|
-
projectPath = project.fullPath;
|
|
363
|
-
} else {
|
|
364
|
-
try {
|
|
365
|
-
projectPath = await extractProjectDirectory(project.name);
|
|
366
|
-
} catch (error) {
|
|
367
|
-
throw new Error(`Failed to extract project directory: ${error.message}`);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
const [taskMasterResult, mcpResult] = await Promise.all([
|
|
372
|
-
detectTaskMasterFolder(projectPath),
|
|
373
|
-
detectTaskMasterMCPServer()
|
|
374
|
-
]);
|
|
375
|
-
|
|
376
|
-
// Determine status
|
|
377
|
-
let status = 'not-configured';
|
|
378
|
-
if (taskMasterResult.hasTaskmaster && taskMasterResult.hasEssentialFiles) {
|
|
379
|
-
if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
|
|
380
|
-
status = 'fully-configured';
|
|
381
|
-
} else {
|
|
382
|
-
status = 'taskmaster-only';
|
|
383
|
-
}
|
|
384
|
-
} else if (mcpResult.hasMCPServer && mcpResult.isConfigured) {
|
|
385
|
-
status = 'mcp-only';
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
return {
|
|
389
|
-
projectName: project.name,
|
|
390
|
-
displayName: project.displayName,
|
|
391
|
-
projectPath,
|
|
392
|
-
status,
|
|
393
|
-
taskmaster: taskMasterResult,
|
|
394
|
-
mcp: mcpResult
|
|
395
|
-
};
|
|
396
|
-
} catch (error) {
|
|
397
|
-
return {
|
|
398
|
-
projectName: project.name,
|
|
399
|
-
displayName: project.displayName,
|
|
400
|
-
status: 'error',
|
|
401
|
-
error: error.message
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
const results = await Promise.all(detectionPromises);
|
|
407
|
-
|
|
408
|
-
res.json({
|
|
409
|
-
projects: results,
|
|
410
|
-
summary: {
|
|
411
|
-
total: results.length,
|
|
412
|
-
fullyConfigured: results.filter(p => p.status === 'fully-configured').length,
|
|
413
|
-
taskmasterOnly: results.filter(p => p.status === 'taskmaster-only').length,
|
|
414
|
-
mcpOnly: results.filter(p => p.status === 'mcp-only').length,
|
|
415
|
-
notConfigured: results.filter(p => p.status === 'not-configured').length,
|
|
416
|
-
errors: results.filter(p => p.status === 'error').length
|
|
417
|
-
},
|
|
418
|
-
timestamp: new Date().toISOString()
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
} catch (error) {
|
|
422
|
-
console.error('Bulk TaskMaster detection error:', error);
|
|
423
|
-
res.status(500).json({
|
|
424
|
-
error: 'Failed to detect TaskMaster configuration for projects',
|
|
425
|
-
message: error.message
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
});
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
* POST /api/taskmaster/initialize/:projectName
|
|
432
|
-
* Initialize TaskMaster in a project (placeholder for future CLI integration)
|
|
433
|
-
*/
|
|
434
|
-
router.post('/initialize/:projectName', async (req, res) => {
|
|
435
|
-
try {
|
|
436
|
-
const { projectName } = req.params;
|
|
437
|
-
const { rules } = req.body; // Optional rule profiles
|
|
438
|
-
|
|
439
|
-
// This will be implemented in a later subtask with CLI integration
|
|
440
|
-
res.status(501).json({
|
|
441
|
-
error: 'TaskMaster initialization not yet implemented',
|
|
442
|
-
message: 'This endpoint will execute task-master init via CLI in a future update',
|
|
443
|
-
projectName,
|
|
444
|
-
rules
|
|
445
|
-
});
|
|
446
|
-
|
|
447
|
-
} catch (error) {
|
|
448
|
-
console.error('TaskMaster initialization error:', error);
|
|
449
|
-
res.status(500).json({
|
|
450
|
-
error: 'Failed to initialize TaskMaster',
|
|
451
|
-
message: error.message
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* GET /api/taskmaster/next/:projectName
|
|
458
|
-
* Get the next recommended task using task-master CLI
|
|
459
|
-
*/
|
|
460
|
-
router.get('/next/:projectName', async (req, res) => {
|
|
461
|
-
try {
|
|
462
|
-
const { projectName } = req.params;
|
|
463
|
-
|
|
464
|
-
// Get project path
|
|
465
|
-
let projectPath;
|
|
466
|
-
try {
|
|
467
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
468
|
-
} catch (error) {
|
|
469
|
-
return res.status(404).json({
|
|
470
|
-
error: 'Project not found',
|
|
471
|
-
message: `Project "${projectName}" does not exist`
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// Try to execute task-master next command
|
|
476
|
-
try {
|
|
477
|
-
const { spawn } = await import('child_process');
|
|
478
|
-
|
|
479
|
-
const nextTaskCommand = spawn('task-master', ['next'], {
|
|
480
|
-
cwd: projectPath,
|
|
481
|
-
stdio: ['pipe', 'pipe', 'pipe']
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
let stdout = '';
|
|
485
|
-
let stderr = '';
|
|
486
|
-
|
|
487
|
-
nextTaskCommand.stdout.on('data', (data) => {
|
|
488
|
-
stdout += data.toString();
|
|
489
|
-
});
|
|
490
|
-
|
|
491
|
-
nextTaskCommand.stderr.on('data', (data) => {
|
|
492
|
-
stderr += data.toString();
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
await new Promise((resolve, reject) => {
|
|
496
|
-
nextTaskCommand.on('close', (code) => {
|
|
497
|
-
if (code === 0) {
|
|
498
|
-
resolve();
|
|
499
|
-
} else {
|
|
500
|
-
reject(new Error(`task-master next failed with code ${code}: ${stderr}`));
|
|
501
|
-
}
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
nextTaskCommand.on('error', (error) => {
|
|
505
|
-
reject(error);
|
|
506
|
-
});
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
// Parse the output - task-master next usually returns JSON
|
|
510
|
-
let nextTaskData = null;
|
|
511
|
-
if (stdout.trim()) {
|
|
512
|
-
try {
|
|
513
|
-
nextTaskData = JSON.parse(stdout);
|
|
514
|
-
} catch (parseError) {
|
|
515
|
-
// If not JSON, treat as plain text
|
|
516
|
-
nextTaskData = { message: stdout.trim() };
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
res.json({
|
|
521
|
-
projectName,
|
|
522
|
-
projectPath,
|
|
523
|
-
nextTask: nextTaskData,
|
|
524
|
-
timestamp: new Date().toISOString()
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
} catch (cliError) {
|
|
528
|
-
console.warn('Failed to execute task-master CLI:', cliError.message);
|
|
529
|
-
|
|
530
|
-
// Fallback to loading tasks and finding next one locally
|
|
531
|
-
// Use localhost to bypass proxy for internal server-to-server calls
|
|
532
|
-
const tasksResponse = await fetch(`http://localhost:${process.env.SERVER_PORT || process.env.PORT || '3001'}/api/taskmaster/tasks/${encodeURIComponent(projectName)}`, {
|
|
533
|
-
headers: {
|
|
534
|
-
'Authorization': req.headers.authorization
|
|
535
|
-
}
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
if (tasksResponse.ok) {
|
|
539
|
-
const tasksData = await tasksResponse.json();
|
|
540
|
-
const nextTask = tasksData.tasks?.find(task =>
|
|
541
|
-
task.status === 'pending' || task.status === 'in-progress'
|
|
542
|
-
) || null;
|
|
543
|
-
|
|
544
|
-
res.json({
|
|
545
|
-
projectName,
|
|
546
|
-
projectPath,
|
|
547
|
-
nextTask,
|
|
548
|
-
fallback: true,
|
|
549
|
-
message: 'Used fallback method (CLI not available)',
|
|
550
|
-
timestamp: new Date().toISOString()
|
|
551
|
-
});
|
|
552
|
-
} else {
|
|
553
|
-
throw new Error('Failed to load tasks via fallback method');
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
} catch (error) {
|
|
558
|
-
console.error('TaskMaster next task error:', error);
|
|
559
|
-
res.status(500).json({
|
|
560
|
-
error: 'Failed to get next task',
|
|
561
|
-
message: error.message
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* GET /api/taskmaster/tasks/:projectName
|
|
150
|
+
* GET /api/taskmaster/tasks/:projectId
|
|
568
151
|
* Load actual tasks from .taskmaster/tasks/tasks.json
|
|
152
|
+
*
|
|
153
|
+
* `projectId` is the DB primary key of the project; the folder is resolved via
|
|
154
|
+
* the projects table rather than extracted from Claude JSONL history.
|
|
569
155
|
*/
|
|
570
|
-
router.get('/tasks/:
|
|
156
|
+
router.get('/tasks/:projectId', async (req, res) => {
|
|
571
157
|
try {
|
|
572
|
-
const {
|
|
573
|
-
|
|
574
|
-
// Get project path
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
578
|
-
} catch (error) {
|
|
158
|
+
const { projectId } = req.params;
|
|
159
|
+
|
|
160
|
+
// Get project path via the DB; the legacy JSONL-based resolver is gone.
|
|
161
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
162
|
+
if (!projectPath) {
|
|
579
163
|
return res.status(404).json({
|
|
580
164
|
error: 'Project not found',
|
|
581
|
-
message: `Project "${
|
|
165
|
+
message: `Project "${projectId}" does not exist`
|
|
582
166
|
});
|
|
583
167
|
}
|
|
584
168
|
|
|
@@ -590,7 +174,7 @@ router.get('/tasks/:projectName', async (req, res) => {
|
|
|
590
174
|
await fsPromises.access(tasksFilePath);
|
|
591
175
|
} catch (error) {
|
|
592
176
|
return res.json({
|
|
593
|
-
|
|
177
|
+
projectId,
|
|
594
178
|
tasks: [],
|
|
595
179
|
message: 'No tasks.json file found'
|
|
596
180
|
});
|
|
@@ -645,7 +229,7 @@ router.get('/tasks/:projectName', async (req, res) => {
|
|
|
645
229
|
}));
|
|
646
230
|
|
|
647
231
|
res.json({
|
|
648
|
-
|
|
232
|
+
projectId,
|
|
649
233
|
projectPath,
|
|
650
234
|
tasks: transformedTasks,
|
|
651
235
|
currentTag,
|
|
@@ -679,21 +263,19 @@ router.get('/tasks/:projectName', async (req, res) => {
|
|
|
679
263
|
});
|
|
680
264
|
|
|
681
265
|
/**
|
|
682
|
-
* GET /api/taskmaster/prd/:
|
|
266
|
+
* GET /api/taskmaster/prd/:projectId
|
|
683
267
|
* List all PRD files in the project's .taskmaster/docs directory
|
|
684
268
|
*/
|
|
685
|
-
router.get('/prd/:
|
|
269
|
+
router.get('/prd/:projectId', async (req, res) => {
|
|
686
270
|
try {
|
|
687
|
-
const {
|
|
688
|
-
|
|
689
|
-
//
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
693
|
-
} catch (error) {
|
|
271
|
+
const { projectId } = req.params;
|
|
272
|
+
|
|
273
|
+
// projectId → projectPath lookup through the DB (post-migration).
|
|
274
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
275
|
+
if (!projectPath) {
|
|
694
276
|
return res.status(404).json({
|
|
695
277
|
error: 'Project not found',
|
|
696
|
-
message: `Project "${
|
|
278
|
+
message: `Project "${projectId}" does not exist`
|
|
697
279
|
});
|
|
698
280
|
}
|
|
699
281
|
|
|
@@ -704,7 +286,7 @@ router.get('/prd/:projectName', async (req, res) => {
|
|
|
704
286
|
await fsPromises.access(docsPath, fs.constants.R_OK);
|
|
705
287
|
} catch (error) {
|
|
706
288
|
return res.json({
|
|
707
|
-
|
|
289
|
+
projectId,
|
|
708
290
|
prdFiles: [],
|
|
709
291
|
message: 'No .taskmaster/docs directory found'
|
|
710
292
|
});
|
|
@@ -731,7 +313,7 @@ router.get('/prd/:projectName', async (req, res) => {
|
|
|
731
313
|
}
|
|
732
314
|
|
|
733
315
|
res.json({
|
|
734
|
-
|
|
316
|
+
projectId,
|
|
735
317
|
projectPath,
|
|
736
318
|
prdFiles: prdFiles.sort((a, b) => new Date(b.modified) - new Date(a.modified)),
|
|
737
319
|
timestamp: new Date().toISOString()
|
|
@@ -755,12 +337,12 @@ router.get('/prd/:projectName', async (req, res) => {
|
|
|
755
337
|
});
|
|
756
338
|
|
|
757
339
|
/**
|
|
758
|
-
* POST /api/taskmaster/prd/:
|
|
340
|
+
* POST /api/taskmaster/prd/:projectId
|
|
759
341
|
* Create or update a PRD file in the project's .taskmaster/docs directory
|
|
760
342
|
*/
|
|
761
|
-
router.post('/prd/:
|
|
343
|
+
router.post('/prd/:projectId', async (req, res) => {
|
|
762
344
|
try {
|
|
763
|
-
const {
|
|
345
|
+
const { projectId } = req.params;
|
|
764
346
|
const { fileName, content } = req.body;
|
|
765
347
|
|
|
766
348
|
if (!fileName || !content) {
|
|
@@ -778,14 +360,12 @@ router.post('/prd/:projectName', async (req, res) => {
|
|
|
778
360
|
});
|
|
779
361
|
}
|
|
780
362
|
|
|
781
|
-
//
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
785
|
-
} catch (error) {
|
|
363
|
+
// Resolve the project folder through the DB using the projectId param.
|
|
364
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
365
|
+
if (!projectPath) {
|
|
786
366
|
return res.status(404).json({
|
|
787
367
|
error: 'Project not found',
|
|
788
|
-
message: `Project "${
|
|
368
|
+
message: `Project "${projectId}" does not exist`
|
|
789
369
|
});
|
|
790
370
|
}
|
|
791
371
|
|
|
@@ -811,7 +391,7 @@ router.post('/prd/:projectName', async (req, res) => {
|
|
|
811
391
|
const stats = await fsPromises.stat(filePath);
|
|
812
392
|
|
|
813
393
|
res.json({
|
|
814
|
-
|
|
394
|
+
projectId,
|
|
815
395
|
projectPath,
|
|
816
396
|
fileName,
|
|
817
397
|
filePath: path.relative(projectPath, filePath),
|
|
@@ -840,21 +420,18 @@ router.post('/prd/:projectName', async (req, res) => {
|
|
|
840
420
|
});
|
|
841
421
|
|
|
842
422
|
/**
|
|
843
|
-
* GET /api/taskmaster/prd/:
|
|
423
|
+
* GET /api/taskmaster/prd/:projectId/:fileName
|
|
844
424
|
* Get content of a specific PRD file
|
|
845
425
|
*/
|
|
846
|
-
router.get('/prd/:
|
|
426
|
+
router.get('/prd/:projectId/:fileName', async (req, res) => {
|
|
847
427
|
try {
|
|
848
|
-
const {
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
try {
|
|
853
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
854
|
-
} catch (error) {
|
|
428
|
+
const { projectId, fileName } = req.params;
|
|
429
|
+
|
|
430
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
431
|
+
if (!projectPath) {
|
|
855
432
|
return res.status(404).json({
|
|
856
433
|
error: 'Project not found',
|
|
857
|
-
message: `Project "${
|
|
434
|
+
message: `Project "${projectId}" does not exist`
|
|
858
435
|
});
|
|
859
436
|
}
|
|
860
437
|
|
|
@@ -876,7 +453,7 @@ router.get('/prd/:projectName/:fileName', async (req, res) => {
|
|
|
876
453
|
const stats = await fsPromises.stat(filePath);
|
|
877
454
|
|
|
878
455
|
res.json({
|
|
879
|
-
|
|
456
|
+
projectId,
|
|
880
457
|
projectPath,
|
|
881
458
|
fileName,
|
|
882
459
|
filePath: path.relative(projectPath, filePath),
|
|
@@ -905,81 +482,18 @@ router.get('/prd/:projectName/:fileName', async (req, res) => {
|
|
|
905
482
|
});
|
|
906
483
|
|
|
907
484
|
/**
|
|
908
|
-
*
|
|
909
|
-
* Delete a specific PRD file
|
|
910
|
-
*/
|
|
911
|
-
router.delete('/prd/:projectName/:fileName', async (req, res) => {
|
|
912
|
-
try {
|
|
913
|
-
const { projectName, fileName } = req.params;
|
|
914
|
-
|
|
915
|
-
// Get project path
|
|
916
|
-
let projectPath;
|
|
917
|
-
try {
|
|
918
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
919
|
-
} catch (error) {
|
|
920
|
-
return res.status(404).json({
|
|
921
|
-
error: 'Project not found',
|
|
922
|
-
message: `Project "${projectName}" does not exist`
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
const filePath = path.join(projectPath, '.taskmaster', 'docs', fileName);
|
|
927
|
-
|
|
928
|
-
// Check if file exists
|
|
929
|
-
try {
|
|
930
|
-
await fsPromises.access(filePath, fs.constants.F_OK);
|
|
931
|
-
} catch (error) {
|
|
932
|
-
return res.status(404).json({
|
|
933
|
-
error: 'PRD file not found',
|
|
934
|
-
message: `File "${fileName}" does not exist`
|
|
935
|
-
});
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
// Delete the file
|
|
939
|
-
try {
|
|
940
|
-
await fsPromises.unlink(filePath);
|
|
941
|
-
|
|
942
|
-
res.json({
|
|
943
|
-
projectName,
|
|
944
|
-
projectPath,
|
|
945
|
-
fileName,
|
|
946
|
-
message: 'PRD file deleted successfully',
|
|
947
|
-
timestamp: new Date().toISOString()
|
|
948
|
-
});
|
|
949
|
-
|
|
950
|
-
} catch (deleteError) {
|
|
951
|
-
console.error('Failed to delete PRD file:', deleteError);
|
|
952
|
-
return res.status(500).json({
|
|
953
|
-
error: 'Failed to delete PRD file',
|
|
954
|
-
message: deleteError.message
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
} catch (error) {
|
|
959
|
-
console.error('PRD delete error:', error);
|
|
960
|
-
res.status(500).json({
|
|
961
|
-
error: 'Failed to delete PRD file',
|
|
962
|
-
message: error.message
|
|
963
|
-
});
|
|
964
|
-
}
|
|
965
|
-
});
|
|
966
|
-
|
|
967
|
-
/**
|
|
968
|
-
* POST /api/taskmaster/init/:projectName
|
|
485
|
+
* POST /api/taskmaster/init/:projectId
|
|
969
486
|
* Initialize TaskMaster in a project
|
|
970
487
|
*/
|
|
971
|
-
router.post('/init/:
|
|
488
|
+
router.post('/init/:projectId', async (req, res) => {
|
|
972
489
|
try {
|
|
973
|
-
const {
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
try {
|
|
978
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
979
|
-
} catch (error) {
|
|
490
|
+
const { projectId } = req.params;
|
|
491
|
+
|
|
492
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
493
|
+
if (!projectPath) {
|
|
980
494
|
return res.status(404).json({
|
|
981
495
|
error: 'Project not found',
|
|
982
|
-
message: `Project "${
|
|
496
|
+
message: `Project "${projectId}" does not exist`
|
|
983
497
|
});
|
|
984
498
|
}
|
|
985
499
|
|
|
@@ -1014,17 +528,19 @@ router.post('/init/:projectName', async (req, res) => {
|
|
|
1014
528
|
|
|
1015
529
|
initProcess.on('close', (code) => {
|
|
1016
530
|
if (code === 0) {
|
|
1017
|
-
// Broadcast TaskMaster project update via WebSocket
|
|
531
|
+
// Broadcast TaskMaster project update via WebSocket. The
|
|
532
|
+
// WebSocket payload keeps using `projectId` so the frontend
|
|
533
|
+
// can match notifications against the current selection.
|
|
1018
534
|
if (req.app.locals.wss) {
|
|
1019
535
|
broadcastTaskMasterProjectUpdate(
|
|
1020
|
-
req.app.locals.wss,
|
|
1021
|
-
|
|
536
|
+
req.app.locals.wss,
|
|
537
|
+
projectId,
|
|
1022
538
|
{ hasTaskmaster: true, status: 'initialized' }
|
|
1023
539
|
);
|
|
1024
540
|
}
|
|
1025
541
|
|
|
1026
542
|
res.json({
|
|
1027
|
-
|
|
543
|
+
projectId,
|
|
1028
544
|
projectPath,
|
|
1029
545
|
message: 'TaskMaster initialized successfully',
|
|
1030
546
|
output: stdout,
|
|
@@ -1054,12 +570,12 @@ router.post('/init/:projectName', async (req, res) => {
|
|
|
1054
570
|
});
|
|
1055
571
|
|
|
1056
572
|
/**
|
|
1057
|
-
* POST /api/taskmaster/add-task/:
|
|
573
|
+
* POST /api/taskmaster/add-task/:projectId
|
|
1058
574
|
* Add a new task to the project
|
|
1059
575
|
*/
|
|
1060
|
-
router.post('/add-task/:
|
|
576
|
+
router.post('/add-task/:projectId', async (req, res) => {
|
|
1061
577
|
try {
|
|
1062
|
-
const {
|
|
578
|
+
const { projectId } = req.params;
|
|
1063
579
|
const { prompt, title, description, priority = 'medium', dependencies } = req.body;
|
|
1064
580
|
|
|
1065
581
|
if (!prompt && (!title || !description)) {
|
|
@@ -1068,15 +584,12 @@ router.post('/add-task/:projectName', async (req, res) => {
|
|
|
1068
584
|
message: 'Either "prompt" or both "title" and "description" are required'
|
|
1069
585
|
});
|
|
1070
586
|
}
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
try {
|
|
1075
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
1076
|
-
} catch (error) {
|
|
587
|
+
|
|
588
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
589
|
+
if (!projectPath) {
|
|
1077
590
|
return res.status(404).json({
|
|
1078
591
|
error: 'Project not found',
|
|
1079
|
-
message: `Project "${
|
|
592
|
+
message: `Project "${projectId}" does not exist`
|
|
1080
593
|
});
|
|
1081
594
|
}
|
|
1082
595
|
|
|
@@ -1121,16 +634,17 @@ router.post('/add-task/:projectName', async (req, res) => {
|
|
|
1121
634
|
console.log('Stderr:', stderr);
|
|
1122
635
|
|
|
1123
636
|
if (code === 0) {
|
|
1124
|
-
// Broadcast task update via WebSocket
|
|
637
|
+
// Broadcast task update via WebSocket using the projectId so
|
|
638
|
+
// clients subscribed to this project get notified immediately.
|
|
1125
639
|
if (req.app.locals.wss) {
|
|
1126
640
|
broadcastTaskMasterTasksUpdate(
|
|
1127
|
-
req.app.locals.wss,
|
|
1128
|
-
|
|
641
|
+
req.app.locals.wss,
|
|
642
|
+
projectId
|
|
1129
643
|
);
|
|
1130
644
|
}
|
|
1131
645
|
|
|
1132
646
|
res.json({
|
|
1133
|
-
|
|
647
|
+
projectId,
|
|
1134
648
|
projectPath,
|
|
1135
649
|
message: 'Task added successfully',
|
|
1136
650
|
output: stdout,
|
|
@@ -1158,22 +672,19 @@ router.post('/add-task/:projectName', async (req, res) => {
|
|
|
1158
672
|
});
|
|
1159
673
|
|
|
1160
674
|
/**
|
|
1161
|
-
* PUT /api/taskmaster/update-task/:
|
|
675
|
+
* PUT /api/taskmaster/update-task/:projectId/:taskId
|
|
1162
676
|
* Update a specific task using TaskMaster CLI
|
|
1163
677
|
*/
|
|
1164
|
-
router.put('/update-task/:
|
|
678
|
+
router.put('/update-task/:projectId/:taskId', async (req, res) => {
|
|
1165
679
|
try {
|
|
1166
|
-
const {
|
|
680
|
+
const { projectId, taskId } = req.params;
|
|
1167
681
|
const { title, description, status, priority, details } = req.body;
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
try {
|
|
1172
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
1173
|
-
} catch (error) {
|
|
682
|
+
|
|
683
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
684
|
+
if (!projectPath) {
|
|
1174
685
|
return res.status(404).json({
|
|
1175
686
|
error: 'Project not found',
|
|
1176
|
-
message: `Project "${
|
|
687
|
+
message: `Project "${projectId}" does not exist`
|
|
1177
688
|
});
|
|
1178
689
|
}
|
|
1179
690
|
|
|
@@ -1199,11 +710,11 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
|
|
|
1199
710
|
if (code === 0) {
|
|
1200
711
|
// Broadcast task update via WebSocket
|
|
1201
712
|
if (req.app.locals.wss) {
|
|
1202
|
-
broadcastTaskMasterTasksUpdate(req.app.locals.wss,
|
|
713
|
+
broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
|
|
1203
714
|
}
|
|
1204
715
|
|
|
1205
716
|
res.json({
|
|
1206
|
-
|
|
717
|
+
projectId,
|
|
1207
718
|
projectPath,
|
|
1208
719
|
taskId,
|
|
1209
720
|
message: 'Task status updated successfully',
|
|
@@ -1251,11 +762,11 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
|
|
|
1251
762
|
if (code === 0) {
|
|
1252
763
|
// Broadcast task update via WebSocket
|
|
1253
764
|
if (req.app.locals.wss) {
|
|
1254
|
-
broadcastTaskMasterTasksUpdate(req.app.locals.wss,
|
|
765
|
+
broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
|
|
1255
766
|
}
|
|
1256
767
|
|
|
1257
768
|
res.json({
|
|
1258
|
-
|
|
769
|
+
projectId,
|
|
1259
770
|
projectPath,
|
|
1260
771
|
taskId,
|
|
1261
772
|
message: 'Task updated successfully',
|
|
@@ -1285,22 +796,19 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
|
|
|
1285
796
|
});
|
|
1286
797
|
|
|
1287
798
|
/**
|
|
1288
|
-
* POST /api/taskmaster/parse-prd/:
|
|
799
|
+
* POST /api/taskmaster/parse-prd/:projectId
|
|
1289
800
|
* Parse a PRD file to generate tasks
|
|
1290
801
|
*/
|
|
1291
|
-
router.post('/parse-prd/:
|
|
802
|
+
router.post('/parse-prd/:projectId', async (req, res) => {
|
|
1292
803
|
try {
|
|
1293
|
-
const {
|
|
804
|
+
const { projectId } = req.params;
|
|
1294
805
|
const { fileName = 'prd.txt', numTasks, append = false } = req.body;
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
try {
|
|
1299
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
1300
|
-
} catch (error) {
|
|
806
|
+
|
|
807
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
808
|
+
if (!projectPath) {
|
|
1301
809
|
return res.status(404).json({
|
|
1302
810
|
error: 'Project not found',
|
|
1303
|
-
message: `Project "${
|
|
811
|
+
message: `Project "${projectId}" does not exist`
|
|
1304
812
|
});
|
|
1305
813
|
}
|
|
1306
814
|
|
|
@@ -1351,13 +859,13 @@ router.post('/parse-prd/:projectName', async (req, res) => {
|
|
|
1351
859
|
// Broadcast task update via WebSocket
|
|
1352
860
|
if (req.app.locals.wss) {
|
|
1353
861
|
broadcastTaskMasterTasksUpdate(
|
|
1354
|
-
req.app.locals.wss,
|
|
1355
|
-
|
|
862
|
+
req.app.locals.wss,
|
|
863
|
+
projectId
|
|
1356
864
|
);
|
|
1357
865
|
}
|
|
1358
866
|
|
|
1359
867
|
res.json({
|
|
1360
|
-
|
|
868
|
+
projectId,
|
|
1361
869
|
projectPath,
|
|
1362
870
|
prdFile: fileName,
|
|
1363
871
|
message: 'PRD parsed and tasks generated successfully',
|
|
@@ -1832,12 +1340,12 @@ Description of the business problem, data sources, and expected insights.
|
|
|
1832
1340
|
});
|
|
1833
1341
|
|
|
1834
1342
|
/**
|
|
1835
|
-
* POST /api/taskmaster/apply-template/:
|
|
1343
|
+
* POST /api/taskmaster/apply-template/:projectId
|
|
1836
1344
|
* Apply a PRD template to create a new PRD file
|
|
1837
1345
|
*/
|
|
1838
|
-
router.post('/apply-template/:
|
|
1346
|
+
router.post('/apply-template/:projectId', async (req, res) => {
|
|
1839
1347
|
try {
|
|
1840
|
-
const {
|
|
1348
|
+
const { projectId } = req.params;
|
|
1841
1349
|
const { templateId, fileName = 'prd.txt', customizations = {} } = req.body;
|
|
1842
1350
|
|
|
1843
1351
|
if (!templateId) {
|
|
@@ -1847,14 +1355,11 @@ router.post('/apply-template/:projectName', async (req, res) => {
|
|
|
1847
1355
|
});
|
|
1848
1356
|
}
|
|
1849
1357
|
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
try {
|
|
1853
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
1854
|
-
} catch (error) {
|
|
1358
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
1359
|
+
if (!projectPath) {
|
|
1855
1360
|
return res.status(404).json({
|
|
1856
1361
|
error: 'Project not found',
|
|
1857
|
-
message: `Project "${
|
|
1362
|
+
message: `Project "${projectId}" does not exist`
|
|
1858
1363
|
});
|
|
1859
1364
|
}
|
|
1860
1365
|
|
|
@@ -1893,7 +1398,7 @@ router.post('/apply-template/:projectName', async (req, res) => {
|
|
|
1893
1398
|
await fsPromises.writeFile(filePath, content, 'utf8');
|
|
1894
1399
|
|
|
1895
1400
|
res.json({
|
|
1896
|
-
|
|
1401
|
+
projectId,
|
|
1897
1402
|
projectPath,
|
|
1898
1403
|
templateId,
|
|
1899
1404
|
templateName: template.name,
|