@cloudcli-ai/cloudcli 1.30.0 → 1.31.1
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.md +1 -1
- package/dist/assets/index-B37ufcoi.js +1262 -0
- package/dist/assets/{index-DI22MZMb.css → index-DF8TTVHl.css} +1 -1
- package/dist/index.html +2 -2
- package/dist-server/server/index.js +115 -955
- 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-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 +144 -7
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
- 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 +225 -13
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
- 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.provider.js +2 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
- 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 +277 -10
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +2 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +172 -0
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- 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 +78 -3
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
- 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/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 -1
- package/dist-server/server/routes/commands.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/settings.js +1 -1
- package/dist-server/server/routes/settings.js.map +1 -1
- package/dist-server/server/routes/taskmaster.js +97 -110
- 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/types.js +0 -1
- package/dist-server/server/shared/types.js.map +1 -1
- package/dist-server/server/shared/utils.js +408 -7
- package/dist-server/server/shared/utils.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 +2 -1
- package/dist-server/shared/modelConstants.js.map +1 -1
- package/package.json +3 -1
- package/server/index.js +146 -1012
- 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-session-synchronizer.provider.ts +110 -0
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +182 -13
- package/server/modules/providers/list/claude/claude.provider.ts +3 -1
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +119 -0
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +262 -17
- package/server/modules/providers/list/codex/codex.provider.ts +3 -1
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +176 -0
- package/server/modules/providers/list/cursor/cursor.provider.ts +3 -1
- package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +401 -0
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +327 -13
- package/server/modules/providers/list/gemini/gemini.provider.ts +3 -1
- package/server/modules/providers/provider.routes.ts +220 -12
- 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 +89 -4
- package/server/modules/providers/shared/base/abstract.provider.ts +8 -1
- 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/routes/agent.js +11 -16
- package/server/routes/auth.js +4 -2
- package/server/routes/commands.js +1 -1
- package/server/routes/gemini.js +3 -2
- package/server/routes/git.js +33 -28
- package/server/routes/settings.js +1 -1
- package/server/routes/taskmaster.js +108 -111
- 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 +39 -1
- package/server/shared/types.ts +185 -30
- package/server/shared/utils.ts +485 -9
- package/server/utils/taskmaster-websocket.js +19 -13
- package/shared/modelConstants.js +2 -1
- package/dist/assets/index-RX-W_g_Q.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/routes/codex.js +0 -18
- package/dist-server/server/routes/codex.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/routes/codex.js +0 -19
- package/server/routes/messages.js +0 -61
- package/server/routes/projects.js +0 -548
|
@@ -13,10 +13,25 @@ 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 {
|
|
16
|
+
import { projectsDb } from '../modules/database/index.js';
|
|
17
17
|
import { detectTaskMasterMCPServer } from '../utils/mcp-detector.js';
|
|
18
18
|
import { broadcastTaskMasterProjectUpdate, broadcastTaskMasterTasksUpdate } from '../utils/taskmaster-websocket.js';
|
|
19
19
|
|
|
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
|
+
}
|
|
34
|
+
|
|
20
35
|
const router = express.Router();
|
|
21
36
|
|
|
22
37
|
/**
|
|
@@ -132,21 +147,22 @@ router.get('/installation-status', async (req, res) => {
|
|
|
132
147
|
});
|
|
133
148
|
|
|
134
149
|
/**
|
|
135
|
-
* GET /api/taskmaster/tasks/:
|
|
150
|
+
* GET /api/taskmaster/tasks/:projectId
|
|
136
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.
|
|
137
155
|
*/
|
|
138
|
-
router.get('/tasks/:
|
|
156
|
+
router.get('/tasks/:projectId', async (req, res) => {
|
|
139
157
|
try {
|
|
140
|
-
const {
|
|
141
|
-
|
|
142
|
-
// Get project path
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
146
|
-
} 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) {
|
|
147
163
|
return res.status(404).json({
|
|
148
164
|
error: 'Project not found',
|
|
149
|
-
message: `Project "${
|
|
165
|
+
message: `Project "${projectId}" does not exist`
|
|
150
166
|
});
|
|
151
167
|
}
|
|
152
168
|
|
|
@@ -158,7 +174,7 @@ router.get('/tasks/:projectName', async (req, res) => {
|
|
|
158
174
|
await fsPromises.access(tasksFilePath);
|
|
159
175
|
} catch (error) {
|
|
160
176
|
return res.json({
|
|
161
|
-
|
|
177
|
+
projectId,
|
|
162
178
|
tasks: [],
|
|
163
179
|
message: 'No tasks.json file found'
|
|
164
180
|
});
|
|
@@ -213,7 +229,7 @@ router.get('/tasks/:projectName', async (req, res) => {
|
|
|
213
229
|
}));
|
|
214
230
|
|
|
215
231
|
res.json({
|
|
216
|
-
|
|
232
|
+
projectId,
|
|
217
233
|
projectPath,
|
|
218
234
|
tasks: transformedTasks,
|
|
219
235
|
currentTag,
|
|
@@ -247,21 +263,19 @@ router.get('/tasks/:projectName', async (req, res) => {
|
|
|
247
263
|
});
|
|
248
264
|
|
|
249
265
|
/**
|
|
250
|
-
* GET /api/taskmaster/prd/:
|
|
266
|
+
* GET /api/taskmaster/prd/:projectId
|
|
251
267
|
* List all PRD files in the project's .taskmaster/docs directory
|
|
252
268
|
*/
|
|
253
|
-
router.get('/prd/:
|
|
269
|
+
router.get('/prd/:projectId', async (req, res) => {
|
|
254
270
|
try {
|
|
255
|
-
const {
|
|
256
|
-
|
|
257
|
-
//
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
261
|
-
} 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) {
|
|
262
276
|
return res.status(404).json({
|
|
263
277
|
error: 'Project not found',
|
|
264
|
-
message: `Project "${
|
|
278
|
+
message: `Project "${projectId}" does not exist`
|
|
265
279
|
});
|
|
266
280
|
}
|
|
267
281
|
|
|
@@ -272,7 +286,7 @@ router.get('/prd/:projectName', async (req, res) => {
|
|
|
272
286
|
await fsPromises.access(docsPath, fs.constants.R_OK);
|
|
273
287
|
} catch (error) {
|
|
274
288
|
return res.json({
|
|
275
|
-
|
|
289
|
+
projectId,
|
|
276
290
|
prdFiles: [],
|
|
277
291
|
message: 'No .taskmaster/docs directory found'
|
|
278
292
|
});
|
|
@@ -299,7 +313,7 @@ router.get('/prd/:projectName', async (req, res) => {
|
|
|
299
313
|
}
|
|
300
314
|
|
|
301
315
|
res.json({
|
|
302
|
-
|
|
316
|
+
projectId,
|
|
303
317
|
projectPath,
|
|
304
318
|
prdFiles: prdFiles.sort((a, b) => new Date(b.modified) - new Date(a.modified)),
|
|
305
319
|
timestamp: new Date().toISOString()
|
|
@@ -323,12 +337,12 @@ router.get('/prd/:projectName', async (req, res) => {
|
|
|
323
337
|
});
|
|
324
338
|
|
|
325
339
|
/**
|
|
326
|
-
* POST /api/taskmaster/prd/:
|
|
340
|
+
* POST /api/taskmaster/prd/:projectId
|
|
327
341
|
* Create or update a PRD file in the project's .taskmaster/docs directory
|
|
328
342
|
*/
|
|
329
|
-
router.post('/prd/:
|
|
343
|
+
router.post('/prd/:projectId', async (req, res) => {
|
|
330
344
|
try {
|
|
331
|
-
const {
|
|
345
|
+
const { projectId } = req.params;
|
|
332
346
|
const { fileName, content } = req.body;
|
|
333
347
|
|
|
334
348
|
if (!fileName || !content) {
|
|
@@ -346,14 +360,12 @@ router.post('/prd/:projectName', async (req, res) => {
|
|
|
346
360
|
});
|
|
347
361
|
}
|
|
348
362
|
|
|
349
|
-
//
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
353
|
-
} catch (error) {
|
|
363
|
+
// Resolve the project folder through the DB using the projectId param.
|
|
364
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
365
|
+
if (!projectPath) {
|
|
354
366
|
return res.status(404).json({
|
|
355
367
|
error: 'Project not found',
|
|
356
|
-
message: `Project "${
|
|
368
|
+
message: `Project "${projectId}" does not exist`
|
|
357
369
|
});
|
|
358
370
|
}
|
|
359
371
|
|
|
@@ -379,7 +391,7 @@ router.post('/prd/:projectName', async (req, res) => {
|
|
|
379
391
|
const stats = await fsPromises.stat(filePath);
|
|
380
392
|
|
|
381
393
|
res.json({
|
|
382
|
-
|
|
394
|
+
projectId,
|
|
383
395
|
projectPath,
|
|
384
396
|
fileName,
|
|
385
397
|
filePath: path.relative(projectPath, filePath),
|
|
@@ -408,21 +420,18 @@ router.post('/prd/:projectName', async (req, res) => {
|
|
|
408
420
|
});
|
|
409
421
|
|
|
410
422
|
/**
|
|
411
|
-
* GET /api/taskmaster/prd/:
|
|
423
|
+
* GET /api/taskmaster/prd/:projectId/:fileName
|
|
412
424
|
* Get content of a specific PRD file
|
|
413
425
|
*/
|
|
414
|
-
router.get('/prd/:
|
|
426
|
+
router.get('/prd/:projectId/:fileName', async (req, res) => {
|
|
415
427
|
try {
|
|
416
|
-
const {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
try {
|
|
421
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
422
|
-
} catch (error) {
|
|
428
|
+
const { projectId, fileName } = req.params;
|
|
429
|
+
|
|
430
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
431
|
+
if (!projectPath) {
|
|
423
432
|
return res.status(404).json({
|
|
424
433
|
error: 'Project not found',
|
|
425
|
-
message: `Project "${
|
|
434
|
+
message: `Project "${projectId}" does not exist`
|
|
426
435
|
});
|
|
427
436
|
}
|
|
428
437
|
|
|
@@ -444,7 +453,7 @@ router.get('/prd/:projectName/:fileName', async (req, res) => {
|
|
|
444
453
|
const stats = await fsPromises.stat(filePath);
|
|
445
454
|
|
|
446
455
|
res.json({
|
|
447
|
-
|
|
456
|
+
projectId,
|
|
448
457
|
projectPath,
|
|
449
458
|
fileName,
|
|
450
459
|
filePath: path.relative(projectPath, filePath),
|
|
@@ -473,21 +482,18 @@ router.get('/prd/:projectName/:fileName', async (req, res) => {
|
|
|
473
482
|
});
|
|
474
483
|
|
|
475
484
|
/**
|
|
476
|
-
* POST /api/taskmaster/init/:
|
|
485
|
+
* POST /api/taskmaster/init/:projectId
|
|
477
486
|
* Initialize TaskMaster in a project
|
|
478
487
|
*/
|
|
479
|
-
router.post('/init/:
|
|
488
|
+
router.post('/init/:projectId', async (req, res) => {
|
|
480
489
|
try {
|
|
481
|
-
const {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
try {
|
|
486
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
487
|
-
} catch (error) {
|
|
490
|
+
const { projectId } = req.params;
|
|
491
|
+
|
|
492
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
493
|
+
if (!projectPath) {
|
|
488
494
|
return res.status(404).json({
|
|
489
495
|
error: 'Project not found',
|
|
490
|
-
message: `Project "${
|
|
496
|
+
message: `Project "${projectId}" does not exist`
|
|
491
497
|
});
|
|
492
498
|
}
|
|
493
499
|
|
|
@@ -522,17 +528,19 @@ router.post('/init/:projectName', async (req, res) => {
|
|
|
522
528
|
|
|
523
529
|
initProcess.on('close', (code) => {
|
|
524
530
|
if (code === 0) {
|
|
525
|
-
// 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.
|
|
526
534
|
if (req.app.locals.wss) {
|
|
527
535
|
broadcastTaskMasterProjectUpdate(
|
|
528
|
-
req.app.locals.wss,
|
|
529
|
-
|
|
536
|
+
req.app.locals.wss,
|
|
537
|
+
projectId,
|
|
530
538
|
{ hasTaskmaster: true, status: 'initialized' }
|
|
531
539
|
);
|
|
532
540
|
}
|
|
533
541
|
|
|
534
542
|
res.json({
|
|
535
|
-
|
|
543
|
+
projectId,
|
|
536
544
|
projectPath,
|
|
537
545
|
message: 'TaskMaster initialized successfully',
|
|
538
546
|
output: stdout,
|
|
@@ -562,12 +570,12 @@ router.post('/init/:projectName', async (req, res) => {
|
|
|
562
570
|
});
|
|
563
571
|
|
|
564
572
|
/**
|
|
565
|
-
* POST /api/taskmaster/add-task/:
|
|
573
|
+
* POST /api/taskmaster/add-task/:projectId
|
|
566
574
|
* Add a new task to the project
|
|
567
575
|
*/
|
|
568
|
-
router.post('/add-task/:
|
|
576
|
+
router.post('/add-task/:projectId', async (req, res) => {
|
|
569
577
|
try {
|
|
570
|
-
const {
|
|
578
|
+
const { projectId } = req.params;
|
|
571
579
|
const { prompt, title, description, priority = 'medium', dependencies } = req.body;
|
|
572
580
|
|
|
573
581
|
if (!prompt && (!title || !description)) {
|
|
@@ -576,15 +584,12 @@ router.post('/add-task/:projectName', async (req, res) => {
|
|
|
576
584
|
message: 'Either "prompt" or both "title" and "description" are required'
|
|
577
585
|
});
|
|
578
586
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
try {
|
|
583
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
584
|
-
} catch (error) {
|
|
587
|
+
|
|
588
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
589
|
+
if (!projectPath) {
|
|
585
590
|
return res.status(404).json({
|
|
586
591
|
error: 'Project not found',
|
|
587
|
-
message: `Project "${
|
|
592
|
+
message: `Project "${projectId}" does not exist`
|
|
588
593
|
});
|
|
589
594
|
}
|
|
590
595
|
|
|
@@ -629,16 +634,17 @@ router.post('/add-task/:projectName', async (req, res) => {
|
|
|
629
634
|
console.log('Stderr:', stderr);
|
|
630
635
|
|
|
631
636
|
if (code === 0) {
|
|
632
|
-
// Broadcast task update via WebSocket
|
|
637
|
+
// Broadcast task update via WebSocket using the projectId so
|
|
638
|
+
// clients subscribed to this project get notified immediately.
|
|
633
639
|
if (req.app.locals.wss) {
|
|
634
640
|
broadcastTaskMasterTasksUpdate(
|
|
635
|
-
req.app.locals.wss,
|
|
636
|
-
|
|
641
|
+
req.app.locals.wss,
|
|
642
|
+
projectId
|
|
637
643
|
);
|
|
638
644
|
}
|
|
639
645
|
|
|
640
646
|
res.json({
|
|
641
|
-
|
|
647
|
+
projectId,
|
|
642
648
|
projectPath,
|
|
643
649
|
message: 'Task added successfully',
|
|
644
650
|
output: stdout,
|
|
@@ -666,22 +672,19 @@ router.post('/add-task/:projectName', async (req, res) => {
|
|
|
666
672
|
});
|
|
667
673
|
|
|
668
674
|
/**
|
|
669
|
-
* PUT /api/taskmaster/update-task/:
|
|
675
|
+
* PUT /api/taskmaster/update-task/:projectId/:taskId
|
|
670
676
|
* Update a specific task using TaskMaster CLI
|
|
671
677
|
*/
|
|
672
|
-
router.put('/update-task/:
|
|
678
|
+
router.put('/update-task/:projectId/:taskId', async (req, res) => {
|
|
673
679
|
try {
|
|
674
|
-
const {
|
|
680
|
+
const { projectId, taskId } = req.params;
|
|
675
681
|
const { title, description, status, priority, details } = req.body;
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
try {
|
|
680
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
681
|
-
} catch (error) {
|
|
682
|
+
|
|
683
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
684
|
+
if (!projectPath) {
|
|
682
685
|
return res.status(404).json({
|
|
683
686
|
error: 'Project not found',
|
|
684
|
-
message: `Project "${
|
|
687
|
+
message: `Project "${projectId}" does not exist`
|
|
685
688
|
});
|
|
686
689
|
}
|
|
687
690
|
|
|
@@ -707,11 +710,11 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
|
|
|
707
710
|
if (code === 0) {
|
|
708
711
|
// Broadcast task update via WebSocket
|
|
709
712
|
if (req.app.locals.wss) {
|
|
710
|
-
broadcastTaskMasterTasksUpdate(req.app.locals.wss,
|
|
713
|
+
broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
|
|
711
714
|
}
|
|
712
715
|
|
|
713
716
|
res.json({
|
|
714
|
-
|
|
717
|
+
projectId,
|
|
715
718
|
projectPath,
|
|
716
719
|
taskId,
|
|
717
720
|
message: 'Task status updated successfully',
|
|
@@ -759,11 +762,11 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
|
|
|
759
762
|
if (code === 0) {
|
|
760
763
|
// Broadcast task update via WebSocket
|
|
761
764
|
if (req.app.locals.wss) {
|
|
762
|
-
broadcastTaskMasterTasksUpdate(req.app.locals.wss,
|
|
765
|
+
broadcastTaskMasterTasksUpdate(req.app.locals.wss, projectId);
|
|
763
766
|
}
|
|
764
767
|
|
|
765
768
|
res.json({
|
|
766
|
-
|
|
769
|
+
projectId,
|
|
767
770
|
projectPath,
|
|
768
771
|
taskId,
|
|
769
772
|
message: 'Task updated successfully',
|
|
@@ -793,22 +796,19 @@ router.put('/update-task/:projectName/:taskId', async (req, res) => {
|
|
|
793
796
|
});
|
|
794
797
|
|
|
795
798
|
/**
|
|
796
|
-
* POST /api/taskmaster/parse-prd/:
|
|
799
|
+
* POST /api/taskmaster/parse-prd/:projectId
|
|
797
800
|
* Parse a PRD file to generate tasks
|
|
798
801
|
*/
|
|
799
|
-
router.post('/parse-prd/:
|
|
802
|
+
router.post('/parse-prd/:projectId', async (req, res) => {
|
|
800
803
|
try {
|
|
801
|
-
const {
|
|
804
|
+
const { projectId } = req.params;
|
|
802
805
|
const { fileName = 'prd.txt', numTasks, append = false } = req.body;
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
try {
|
|
807
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
808
|
-
} catch (error) {
|
|
806
|
+
|
|
807
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
808
|
+
if (!projectPath) {
|
|
809
809
|
return res.status(404).json({
|
|
810
810
|
error: 'Project not found',
|
|
811
|
-
message: `Project "${
|
|
811
|
+
message: `Project "${projectId}" does not exist`
|
|
812
812
|
});
|
|
813
813
|
}
|
|
814
814
|
|
|
@@ -859,13 +859,13 @@ router.post('/parse-prd/:projectName', async (req, res) => {
|
|
|
859
859
|
// Broadcast task update via WebSocket
|
|
860
860
|
if (req.app.locals.wss) {
|
|
861
861
|
broadcastTaskMasterTasksUpdate(
|
|
862
|
-
req.app.locals.wss,
|
|
863
|
-
|
|
862
|
+
req.app.locals.wss,
|
|
863
|
+
projectId
|
|
864
864
|
);
|
|
865
865
|
}
|
|
866
866
|
|
|
867
867
|
res.json({
|
|
868
|
-
|
|
868
|
+
projectId,
|
|
869
869
|
projectPath,
|
|
870
870
|
prdFile: fileName,
|
|
871
871
|
message: 'PRD parsed and tasks generated successfully',
|
|
@@ -1340,12 +1340,12 @@ Description of the business problem, data sources, and expected insights.
|
|
|
1340
1340
|
});
|
|
1341
1341
|
|
|
1342
1342
|
/**
|
|
1343
|
-
* POST /api/taskmaster/apply-template/:
|
|
1343
|
+
* POST /api/taskmaster/apply-template/:projectId
|
|
1344
1344
|
* Apply a PRD template to create a new PRD file
|
|
1345
1345
|
*/
|
|
1346
|
-
router.post('/apply-template/:
|
|
1346
|
+
router.post('/apply-template/:projectId', async (req, res) => {
|
|
1347
1347
|
try {
|
|
1348
|
-
const {
|
|
1348
|
+
const { projectId } = req.params;
|
|
1349
1349
|
const { templateId, fileName = 'prd.txt', customizations = {} } = req.body;
|
|
1350
1350
|
|
|
1351
1351
|
if (!templateId) {
|
|
@@ -1355,14 +1355,11 @@ router.post('/apply-template/:projectName', async (req, res) => {
|
|
|
1355
1355
|
});
|
|
1356
1356
|
}
|
|
1357
1357
|
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
try {
|
|
1361
|
-
projectPath = await extractProjectDirectory(projectName);
|
|
1362
|
-
} catch (error) {
|
|
1358
|
+
const projectPath = await resolveProjectPathFromId(projectId);
|
|
1359
|
+
if (!projectPath) {
|
|
1363
1360
|
return res.status(404).json({
|
|
1364
1361
|
error: 'Project not found',
|
|
1365
|
-
message: `Project "${
|
|
1362
|
+
message: `Project "${projectId}" does not exist`
|
|
1366
1363
|
});
|
|
1367
1364
|
}
|
|
1368
1365
|
|
|
@@ -1401,7 +1398,7 @@ router.post('/apply-template/:projectName', async (req, res) => {
|
|
|
1401
1398
|
await fsPromises.writeFile(filePath, content, 'utf8');
|
|
1402
1399
|
|
|
1403
1400
|
res.json({
|
|
1404
|
-
|
|
1401
|
+
projectId,
|
|
1405
1402
|
projectPath,
|
|
1406
1403
|
templateId,
|
|
1407
1404
|
templateName: template.name,
|
package/server/routes/user.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
|
-
import { userDb } from '../database/
|
|
2
|
+
import { userDb } from '../modules/database/index.js';
|
|
3
3
|
import { authenticateToken } from '../middleware/auth.js';
|
|
4
4
|
import { getSystemGitConfig } from '../utils/gitConfig.js';
|
|
5
5
|
import { spawn } from 'child_process';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import webPush from 'web-push';
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { notificationPreferencesDb, pushSubscriptionsDb, sessionsDb } from '../modules/database/index.js';
|
|
3
4
|
|
|
4
5
|
const KIND_TO_PREF_KEY = {
|
|
5
6
|
action_required: 'actionRequired',
|
|
@@ -107,7 +108,7 @@ function resolveSessionName(event) {
|
|
|
107
108
|
return null;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
return normalizeSessionName(
|
|
111
|
+
return normalizeSessionName(sessionsDb.getSessionName(event.sessionId, event.provider));
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
function buildPushBody(event) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import webPush from 'web-push';
|
|
2
|
-
import {
|
|
2
|
+
import { getConnection } from '../modules/database/connection.js';
|
|
3
3
|
|
|
4
4
|
let cachedKeys = null;
|
|
5
|
+
const db = getConnection();
|
|
5
6
|
|
|
6
7
|
function ensureVapidKeys() {
|
|
7
8
|
if (cachedKeys) return cachedKeys;
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
UpsertProviderMcpServerInput,
|
|
10
10
|
} from '@/shared/types.js';
|
|
11
11
|
|
|
12
|
+
//----------------- PROVIDER CONTRACT INTERFACES ------------
|
|
12
13
|
/**
|
|
13
14
|
* Main provider contract for CLI and SDK integrations.
|
|
14
15
|
*
|
|
@@ -20,11 +21,16 @@ export interface IProvider {
|
|
|
20
21
|
readonly mcp: IProviderMcp;
|
|
21
22
|
readonly auth: IProviderAuth;
|
|
22
23
|
readonly sessions: IProviderSessions;
|
|
24
|
+
readonly sessionSynchronizer: IProviderSessionSynchronizer;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
// ---------------------------
|
|
28
|
+
//----------------- PROVIDER AUTH INTERFACE ------------
|
|
26
29
|
/**
|
|
27
30
|
* Auth contract for one provider.
|
|
31
|
+
*
|
|
32
|
+
* Implementations should return a complete installation/authentication status
|
|
33
|
+
* without throwing for normal "not installed" or "not authenticated" states.
|
|
28
34
|
*/
|
|
29
35
|
export interface IProviderAuth {
|
|
30
36
|
/**
|
|
@@ -33,8 +39,13 @@ export interface IProviderAuth {
|
|
|
33
39
|
getStatus(): Promise<ProviderAuthStatus>;
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
// ---------------------------
|
|
43
|
+
//----------------- PROVIDER MCP INTERFACE ------------
|
|
36
44
|
/**
|
|
37
45
|
* MCP contract for one provider.
|
|
46
|
+
*
|
|
47
|
+
* Implementations must map provider-native MCP config formats to shared
|
|
48
|
+
* `ProviderMcpServer` records used by routes and frontend state.
|
|
38
49
|
*/
|
|
39
50
|
export interface IProviderMcp {
|
|
40
51
|
listServers(options?: { workspacePath?: string }): Promise<Record<McpScope, ProviderMcpServer[]>>;
|
|
@@ -45,10 +56,37 @@ export interface IProviderMcp {
|
|
|
45
56
|
): Promise<{ removed: boolean; provider: LLMProvider; name: string; scope: McpScope }>;
|
|
46
57
|
}
|
|
47
58
|
|
|
59
|
+
// ---------------------------
|
|
60
|
+
//----------------- PROVIDER SESSION INTERFACE ------------
|
|
48
61
|
/**
|
|
49
62
|
* Session/history contract for one provider.
|
|
63
|
+
*
|
|
64
|
+
* Implementations normalize provider-specific events and message history into
|
|
65
|
+
* shared transport shapes consumed by API routes and realtime streams.
|
|
50
66
|
*/
|
|
51
67
|
export interface IProviderSessions {
|
|
52
68
|
normalizeMessage(raw: unknown, sessionId: string | null): NormalizedMessage[];
|
|
53
69
|
fetchHistory(sessionId: string, options?: FetchHistoryOptions): Promise<FetchHistoryResult>;
|
|
54
70
|
}
|
|
71
|
+
|
|
72
|
+
// ---------------------------
|
|
73
|
+
//----------------- PROVIDER SESSION SYNCHRONIZER INTERFACE ------------
|
|
74
|
+
/**
|
|
75
|
+
* Session indexing contract for one provider.
|
|
76
|
+
*
|
|
77
|
+
* Implementations scan provider-specific session artifacts on disk and upsert
|
|
78
|
+
* normalized session metadata into the database. The service layer uses this
|
|
79
|
+
* interface for both full rescans and single-file incremental sync triggered
|
|
80
|
+
* by filesystem watcher events.
|
|
81
|
+
*/
|
|
82
|
+
export interface IProviderSessionSynchronizer {
|
|
83
|
+
/**
|
|
84
|
+
* Scans provider session artifacts and upserts discovered sessions into DB.
|
|
85
|
+
*/
|
|
86
|
+
synchronize(since?: Date): Promise<number>;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Parses and upserts one provider artifact file without running a full scan.
|
|
90
|
+
*/
|
|
91
|
+
synchronizeFile(filePath: string): Promise<string | null>;
|
|
92
|
+
}
|