aifastdb 2.2.2 → 2.2.6
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/aifastdb.win32-x64-msvc.node +0 -0
- package/dist/dev-plan-store.d.ts +104 -0
- package/dist/dev-plan-store.d.ts.map +1 -1
- package/dist/dev-plan-store.js +331 -34
- package/dist/dev-plan-store.js.map +1 -1
- package/dist/federation/FederatedDb.d.ts +138 -1
- package/dist/federation/FederatedDb.d.ts.map +1 -1
- package/dist/federation/FederatedDb.js +158 -0
- package/dist/federation/FederatedDb.js.map +1 -1
- package/dist/federation/index.d.ts +1 -1
- package/dist/federation/index.d.ts.map +1 -1
- package/dist/federation/index.js.map +1 -1
- package/dist/federation/types.d.ts +136 -4
- package/dist/federation/types.d.ts.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/index.d.ts +5 -16
- package/dist/mcp-server/index.d.ts.map +1 -1
- package/dist/mcp-server/index.js +6 -689
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/security/server/routes.d.ts +46 -0
- package/dist/security/server/routes.d.ts.map +1 -1
- package/dist/security/server/routes.js +568 -1
- package/dist/security/server/routes.js.map +1 -1
- package/package.json +1 -1
package/dist/dev-plan-store.js
CHANGED
|
@@ -138,6 +138,7 @@ class DevPlanStore {
|
|
|
138
138
|
this.projectName = projectName;
|
|
139
139
|
this.docStore = new native_1.EnhancedDocumentStore(config.documentPath, (0, document_store_1.documentStoreProductionConfig)());
|
|
140
140
|
this.taskStore = new native_1.EnhancedDocumentStore(config.taskPath, (0, document_store_1.documentStoreProductionConfig)());
|
|
141
|
+
this.moduleStore = new native_1.EnhancedDocumentStore(config.modulePath, (0, document_store_1.documentStoreProductionConfig)());
|
|
141
142
|
}
|
|
142
143
|
// ==========================================================================
|
|
143
144
|
// Document Section Operations
|
|
@@ -155,15 +156,20 @@ class DevPlanStore {
|
|
|
155
156
|
}
|
|
156
157
|
const version = input.version || '1.0.0';
|
|
157
158
|
const now = Date.now();
|
|
159
|
+
const finalModuleId = input.moduleId || existing?.moduleId;
|
|
160
|
+
const tags = [
|
|
161
|
+
`plan:${this.projectName}`,
|
|
162
|
+
`section:${input.section}`,
|
|
163
|
+
...(input.subSection ? [`sub:${input.subSection}`] : []),
|
|
164
|
+
`ver:${version}`,
|
|
165
|
+
];
|
|
166
|
+
if (finalModuleId) {
|
|
167
|
+
tags.push(`module:${finalModuleId}`);
|
|
168
|
+
}
|
|
158
169
|
const docInput = {
|
|
159
170
|
content: input.content,
|
|
160
171
|
contentType: native_2.ContentType.Text,
|
|
161
|
-
tags
|
|
162
|
-
`plan:${this.projectName}`,
|
|
163
|
-
`section:${input.section}`,
|
|
164
|
-
...(input.subSection ? [`sub:${input.subSection}`] : []),
|
|
165
|
-
`ver:${version}`,
|
|
166
|
-
],
|
|
172
|
+
tags,
|
|
167
173
|
metadata: {
|
|
168
174
|
projectName: this.projectName,
|
|
169
175
|
section: input.section,
|
|
@@ -171,6 +177,7 @@ class DevPlanStore {
|
|
|
171
177
|
version,
|
|
172
178
|
subSection: input.subSection || null,
|
|
173
179
|
relatedSections: input.relatedSections || [],
|
|
180
|
+
moduleId: finalModuleId || null,
|
|
174
181
|
createdAt: existing?.createdAt || now,
|
|
175
182
|
updatedAt: now,
|
|
176
183
|
},
|
|
@@ -302,20 +309,25 @@ class DevPlanStore {
|
|
|
302
309
|
totalSubtasks: 0,
|
|
303
310
|
completedSubtasks: 0,
|
|
304
311
|
};
|
|
312
|
+
const tags = [
|
|
313
|
+
`plan:${this.projectName}`,
|
|
314
|
+
'type:main-task',
|
|
315
|
+
`mtask:${input.taskId}`,
|
|
316
|
+
`priority:${input.priority}`,
|
|
317
|
+
'status:pending',
|
|
318
|
+
];
|
|
319
|
+
if (input.moduleId) {
|
|
320
|
+
tags.push(`module:${input.moduleId}`);
|
|
321
|
+
}
|
|
305
322
|
const docInput = {
|
|
306
323
|
content: JSON.stringify(taskData),
|
|
307
324
|
contentType: native_2.ContentType.Text,
|
|
308
|
-
tags
|
|
309
|
-
`plan:${this.projectName}`,
|
|
310
|
-
'type:main-task',
|
|
311
|
-
`mtask:${input.taskId}`,
|
|
312
|
-
`priority:${input.priority}`,
|
|
313
|
-
'status:pending',
|
|
314
|
-
],
|
|
325
|
+
tags,
|
|
315
326
|
metadata: {
|
|
316
327
|
projectName: this.projectName,
|
|
317
328
|
taskId: input.taskId,
|
|
318
329
|
status: 'pending',
|
|
330
|
+
moduleId: input.moduleId || null,
|
|
319
331
|
createdAt: now,
|
|
320
332
|
updatedAt: now,
|
|
321
333
|
completedAt: null,
|
|
@@ -328,6 +340,7 @@ class DevPlanStore {
|
|
|
328
340
|
id,
|
|
329
341
|
projectName: this.projectName,
|
|
330
342
|
...taskData,
|
|
343
|
+
moduleId: input.moduleId,
|
|
331
344
|
status: 'pending',
|
|
332
345
|
createdAt: now,
|
|
333
346
|
updatedAt: now,
|
|
@@ -378,6 +391,7 @@ class DevPlanStore {
|
|
|
378
391
|
this.deleteAndEnsureTimestampAdvance(this.taskStore, existing.id);
|
|
379
392
|
const now = Date.now();
|
|
380
393
|
const completedAt = finalStatus === 'completed' ? (existing.completedAt || now) : null;
|
|
394
|
+
const finalModuleId = input.moduleId || existing.moduleId;
|
|
381
395
|
const taskData = {
|
|
382
396
|
taskId: input.taskId,
|
|
383
397
|
title: input.title,
|
|
@@ -388,20 +402,25 @@ class DevPlanStore {
|
|
|
388
402
|
totalSubtasks: existing.totalSubtasks,
|
|
389
403
|
completedSubtasks: existing.completedSubtasks,
|
|
390
404
|
};
|
|
405
|
+
const tags = [
|
|
406
|
+
`plan:${this.projectName}`,
|
|
407
|
+
'type:main-task',
|
|
408
|
+
`mtask:${input.taskId}`,
|
|
409
|
+
`priority:${input.priority}`,
|
|
410
|
+
`status:${finalStatus}`,
|
|
411
|
+
];
|
|
412
|
+
if (finalModuleId) {
|
|
413
|
+
tags.push(`module:${finalModuleId}`);
|
|
414
|
+
}
|
|
391
415
|
const docInput = {
|
|
392
416
|
content: JSON.stringify(taskData),
|
|
393
417
|
contentType: native_2.ContentType.Text,
|
|
394
|
-
tags
|
|
395
|
-
`plan:${this.projectName}`,
|
|
396
|
-
'type:main-task',
|
|
397
|
-
`mtask:${input.taskId}`,
|
|
398
|
-
`priority:${input.priority}`,
|
|
399
|
-
`status:${finalStatus}`,
|
|
400
|
-
],
|
|
418
|
+
tags,
|
|
401
419
|
metadata: {
|
|
402
420
|
projectName: this.projectName,
|
|
403
421
|
taskId: input.taskId,
|
|
404
422
|
status: finalStatus,
|
|
423
|
+
moduleId: finalModuleId || null,
|
|
405
424
|
createdAt: existing.createdAt,
|
|
406
425
|
updatedAt: now,
|
|
407
426
|
completedAt,
|
|
@@ -414,6 +433,7 @@ class DevPlanStore {
|
|
|
414
433
|
...taskData,
|
|
415
434
|
id,
|
|
416
435
|
projectName: this.projectName,
|
|
436
|
+
moduleId: finalModuleId,
|
|
417
437
|
status: finalStatus,
|
|
418
438
|
createdAt: existing.createdAt,
|
|
419
439
|
updatedAt: now,
|
|
@@ -454,6 +474,10 @@ class DevPlanStore {
|
|
|
454
474
|
const priorityTag = `priority:${filter.priority}`;
|
|
455
475
|
docs = docs.filter((doc) => doc.tags.includes(priorityTag));
|
|
456
476
|
}
|
|
477
|
+
if (filter?.moduleId) {
|
|
478
|
+
const moduleTag = `module:${filter.moduleId}`;
|
|
479
|
+
docs = docs.filter((doc) => doc.tags.includes(moduleTag));
|
|
480
|
+
}
|
|
457
481
|
return docs.map((doc) => this.docToMainTask(doc));
|
|
458
482
|
}
|
|
459
483
|
/**
|
|
@@ -476,20 +500,25 @@ class DevPlanStore {
|
|
|
476
500
|
totalSubtasks: mainTask.totalSubtasks,
|
|
477
501
|
completedSubtasks: mainTask.completedSubtasks,
|
|
478
502
|
};
|
|
503
|
+
const tags = [
|
|
504
|
+
`plan:${this.projectName}`,
|
|
505
|
+
'type:main-task',
|
|
506
|
+
`mtask:${mainTask.taskId}`,
|
|
507
|
+
`priority:${mainTask.priority}`,
|
|
508
|
+
`status:${status}`,
|
|
509
|
+
];
|
|
510
|
+
if (mainTask.moduleId) {
|
|
511
|
+
tags.push(`module:${mainTask.moduleId}`);
|
|
512
|
+
}
|
|
479
513
|
const docInput = {
|
|
480
514
|
content: JSON.stringify(taskData),
|
|
481
515
|
contentType: native_2.ContentType.Text,
|
|
482
|
-
tags
|
|
483
|
-
`plan:${this.projectName}`,
|
|
484
|
-
'type:main-task',
|
|
485
|
-
`mtask:${mainTask.taskId}`,
|
|
486
|
-
`priority:${mainTask.priority}`,
|
|
487
|
-
`status:${status}`,
|
|
488
|
-
],
|
|
516
|
+
tags,
|
|
489
517
|
metadata: {
|
|
490
518
|
projectName: this.projectName,
|
|
491
519
|
taskId: mainTask.taskId,
|
|
492
520
|
status,
|
|
521
|
+
moduleId: mainTask.moduleId || null,
|
|
493
522
|
createdAt: mainTask.createdAt,
|
|
494
523
|
updatedAt: now,
|
|
495
524
|
completedAt,
|
|
@@ -968,6 +997,196 @@ class DevPlanStore {
|
|
|
968
997
|
return md;
|
|
969
998
|
}
|
|
970
999
|
// ==========================================================================
|
|
1000
|
+
// Module Operations
|
|
1001
|
+
// ==========================================================================
|
|
1002
|
+
/**
|
|
1003
|
+
* 创建功能模块
|
|
1004
|
+
*/
|
|
1005
|
+
createModule(input) {
|
|
1006
|
+
const existing = this.getModule(input.moduleId);
|
|
1007
|
+
if (existing) {
|
|
1008
|
+
throw new Error(`Module "${input.moduleId}" already exists for project "${this.projectName}"`);
|
|
1009
|
+
}
|
|
1010
|
+
const now = Date.now();
|
|
1011
|
+
const status = input.status || 'active';
|
|
1012
|
+
const moduleData = {
|
|
1013
|
+
moduleId: input.moduleId,
|
|
1014
|
+
name: input.name,
|
|
1015
|
+
description: input.description || '',
|
|
1016
|
+
};
|
|
1017
|
+
const docInput = {
|
|
1018
|
+
content: JSON.stringify(moduleData),
|
|
1019
|
+
contentType: native_2.ContentType.Text,
|
|
1020
|
+
tags: [
|
|
1021
|
+
`plan:${this.projectName}`,
|
|
1022
|
+
'type:module',
|
|
1023
|
+
`module:${input.moduleId}`,
|
|
1024
|
+
`status:${status}`,
|
|
1025
|
+
],
|
|
1026
|
+
metadata: {
|
|
1027
|
+
projectName: this.projectName,
|
|
1028
|
+
moduleId: input.moduleId,
|
|
1029
|
+
status,
|
|
1030
|
+
createdAt: now,
|
|
1031
|
+
updatedAt: now,
|
|
1032
|
+
},
|
|
1033
|
+
importance: 0.85,
|
|
1034
|
+
};
|
|
1035
|
+
const id = this.moduleStore.put(docInput);
|
|
1036
|
+
this.moduleStore.flush();
|
|
1037
|
+
return {
|
|
1038
|
+
id,
|
|
1039
|
+
projectName: this.projectName,
|
|
1040
|
+
moduleId: input.moduleId,
|
|
1041
|
+
name: input.name,
|
|
1042
|
+
description: input.description,
|
|
1043
|
+
status,
|
|
1044
|
+
mainTaskCount: 0,
|
|
1045
|
+
subTaskCount: 0,
|
|
1046
|
+
completedSubTaskCount: 0,
|
|
1047
|
+
docCount: 0,
|
|
1048
|
+
createdAt: now,
|
|
1049
|
+
updatedAt: now,
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
/**
|
|
1053
|
+
* 获取功能模块(含自动计算的 taskCount/docCount)
|
|
1054
|
+
*/
|
|
1055
|
+
getModule(moduleId) {
|
|
1056
|
+
const tag = `module:${moduleId}`;
|
|
1057
|
+
const docs = this.moduleStore.findByTag(tag)
|
|
1058
|
+
.filter((doc) => doc.tags.includes(`plan:${this.projectName}`));
|
|
1059
|
+
if (docs.length === 0)
|
|
1060
|
+
return null;
|
|
1061
|
+
const latest = docs.sort((a, b) => this.getDocUpdatedAt(b) - this.getDocUpdatedAt(a))[0];
|
|
1062
|
+
return this.docToModule(latest);
|
|
1063
|
+
}
|
|
1064
|
+
/**
|
|
1065
|
+
* 列出所有功能模块
|
|
1066
|
+
*/
|
|
1067
|
+
listModules(filter) {
|
|
1068
|
+
let docs = this.moduleStore.findByTag(`plan:${this.projectName}`)
|
|
1069
|
+
.filter((doc) => doc.tags.includes('type:module'));
|
|
1070
|
+
// 按 moduleId 去重
|
|
1071
|
+
const latestMap = new Map();
|
|
1072
|
+
for (const doc of docs) {
|
|
1073
|
+
const data = JSON.parse(doc.content);
|
|
1074
|
+
const moduleId = data.moduleId;
|
|
1075
|
+
if (!moduleId)
|
|
1076
|
+
continue;
|
|
1077
|
+
const existing = latestMap.get(moduleId);
|
|
1078
|
+
if (!existing || this.getDocUpdatedAt(doc) > this.getDocUpdatedAt(existing)) {
|
|
1079
|
+
latestMap.set(moduleId, doc);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
docs = Array.from(latestMap.values());
|
|
1083
|
+
if (filter?.status) {
|
|
1084
|
+
const statusTag = `status:${filter.status}`;
|
|
1085
|
+
docs = docs.filter((doc) => doc.tags.includes(statusTag));
|
|
1086
|
+
}
|
|
1087
|
+
return docs.map((doc) => this.docToModule(doc));
|
|
1088
|
+
}
|
|
1089
|
+
/**
|
|
1090
|
+
* 更新功能模块
|
|
1091
|
+
*/
|
|
1092
|
+
updateModule(moduleId, updates) {
|
|
1093
|
+
const existing = this.getModule(moduleId);
|
|
1094
|
+
if (!existing)
|
|
1095
|
+
return null;
|
|
1096
|
+
this.deleteAndEnsureTimestampAdvance(this.moduleStore, existing.id);
|
|
1097
|
+
const now = Date.now();
|
|
1098
|
+
const newName = updates.name || existing.name;
|
|
1099
|
+
const newDescription = updates.description !== undefined ? updates.description : existing.description;
|
|
1100
|
+
const newStatus = updates.status || existing.status;
|
|
1101
|
+
const moduleData = {
|
|
1102
|
+
moduleId,
|
|
1103
|
+
name: newName,
|
|
1104
|
+
description: newDescription || '',
|
|
1105
|
+
};
|
|
1106
|
+
const docInput = {
|
|
1107
|
+
content: JSON.stringify(moduleData),
|
|
1108
|
+
contentType: native_2.ContentType.Text,
|
|
1109
|
+
tags: [
|
|
1110
|
+
`plan:${this.projectName}`,
|
|
1111
|
+
'type:module',
|
|
1112
|
+
`module:${moduleId}`,
|
|
1113
|
+
`status:${newStatus}`,
|
|
1114
|
+
],
|
|
1115
|
+
metadata: {
|
|
1116
|
+
projectName: this.projectName,
|
|
1117
|
+
moduleId,
|
|
1118
|
+
status: newStatus,
|
|
1119
|
+
createdAt: existing.createdAt,
|
|
1120
|
+
updatedAt: now,
|
|
1121
|
+
},
|
|
1122
|
+
importance: 0.85,
|
|
1123
|
+
};
|
|
1124
|
+
const id = this.moduleStore.put(docInput);
|
|
1125
|
+
this.moduleStore.flush();
|
|
1126
|
+
return {
|
|
1127
|
+
id,
|
|
1128
|
+
projectName: this.projectName,
|
|
1129
|
+
moduleId,
|
|
1130
|
+
name: newName,
|
|
1131
|
+
description: newDescription,
|
|
1132
|
+
status: newStatus,
|
|
1133
|
+
mainTaskCount: existing.mainTaskCount,
|
|
1134
|
+
subTaskCount: existing.subTaskCount,
|
|
1135
|
+
completedSubTaskCount: existing.completedSubTaskCount,
|
|
1136
|
+
docCount: existing.docCount,
|
|
1137
|
+
createdAt: existing.createdAt,
|
|
1138
|
+
updatedAt: now,
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* 删除功能模块
|
|
1143
|
+
*/
|
|
1144
|
+
deleteModule(moduleId) {
|
|
1145
|
+
const existing = this.getModule(moduleId);
|
|
1146
|
+
if (!existing)
|
|
1147
|
+
return false;
|
|
1148
|
+
this.moduleStore.delete(existing.id);
|
|
1149
|
+
this.moduleStore.flush();
|
|
1150
|
+
return true;
|
|
1151
|
+
}
|
|
1152
|
+
/**
|
|
1153
|
+
* 获取模块详情 — 包含关联的任务和文档
|
|
1154
|
+
*/
|
|
1155
|
+
getModuleDetail(moduleId) {
|
|
1156
|
+
const mod = this.getModule(moduleId);
|
|
1157
|
+
if (!mod)
|
|
1158
|
+
return null;
|
|
1159
|
+
// 获取关联的主任务
|
|
1160
|
+
const moduleTag = `module:${moduleId}`;
|
|
1161
|
+
let taskDocs = this.taskStore.findByTag(moduleTag)
|
|
1162
|
+
.filter((doc) => doc.tags.includes(`plan:${this.projectName}`) &&
|
|
1163
|
+
doc.tags.includes('type:main-task'));
|
|
1164
|
+
taskDocs = this.deduplicateByTaskId(taskDocs);
|
|
1165
|
+
const mainTasks = taskDocs.map((doc) => this.docToMainTask(doc));
|
|
1166
|
+
// 获取关联的所有子任务(通过主任务间接关联)
|
|
1167
|
+
const subTasks = [];
|
|
1168
|
+
for (const mt of mainTasks) {
|
|
1169
|
+
const subs = this.listSubTasks(mt.taskId);
|
|
1170
|
+
subTasks.push(...subs);
|
|
1171
|
+
}
|
|
1172
|
+
// 获取关联的文档
|
|
1173
|
+
let docDocs = this.docStore.findByTag(moduleTag)
|
|
1174
|
+
.filter((doc) => doc.tags.includes(`plan:${this.projectName}`));
|
|
1175
|
+
// 按 section+subSection 去重
|
|
1176
|
+
const latestDocMap = new Map();
|
|
1177
|
+
for (const doc of docDocs) {
|
|
1178
|
+
const sectionTag = doc.tags.find((t) => t.startsWith('section:'));
|
|
1179
|
+
const subTag = doc.tags.find((t) => t.startsWith('sub:'));
|
|
1180
|
+
const key = `${sectionTag || 'unknown'}|${subTag || ''}`;
|
|
1181
|
+
const ex = latestDocMap.get(key);
|
|
1182
|
+
if (!ex || this.getDocUpdatedAt(doc) > this.getDocUpdatedAt(ex)) {
|
|
1183
|
+
latestDocMap.set(key, doc);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
const documents = Array.from(latestDocMap.values()).map((doc) => this.docToDevPlanDoc(doc));
|
|
1187
|
+
return { module: mod, mainTasks, subTasks, documents };
|
|
1188
|
+
}
|
|
1189
|
+
// ==========================================================================
|
|
971
1190
|
// Utility
|
|
972
1191
|
// ==========================================================================
|
|
973
1192
|
/**
|
|
@@ -976,6 +1195,7 @@ class DevPlanStore {
|
|
|
976
1195
|
sync() {
|
|
977
1196
|
this.docStore.flush();
|
|
978
1197
|
this.taskStore.flush();
|
|
1198
|
+
this.moduleStore.flush();
|
|
979
1199
|
}
|
|
980
1200
|
/**
|
|
981
1201
|
* 获取项目名称
|
|
@@ -1058,6 +1278,8 @@ class DevPlanStore {
|
|
|
1058
1278
|
const section = (sectionTag?.replace('section:', '') || 'custom');
|
|
1059
1279
|
const subTag = doc.tags.find((t) => t.startsWith('sub:'));
|
|
1060
1280
|
const subSection = subTag?.replace('sub:', '');
|
|
1281
|
+
const moduleTag = doc.tags.find((t) => t.startsWith('module:'));
|
|
1282
|
+
const moduleId = moduleTag?.replace('module:', '') || undefined;
|
|
1061
1283
|
return {
|
|
1062
1284
|
id: doc.id,
|
|
1063
1285
|
projectName: this.projectName,
|
|
@@ -1067,6 +1289,7 @@ class DevPlanStore {
|
|
|
1067
1289
|
version: doc.metadata?.version || '1.0.0',
|
|
1068
1290
|
subSection,
|
|
1069
1291
|
relatedSections: doc.metadata?.relatedSections || [],
|
|
1292
|
+
moduleId,
|
|
1070
1293
|
createdAt: doc.metadata?.createdAt || doc.createdAt,
|
|
1071
1294
|
updatedAt: doc.metadata?.updatedAt || doc.createdAt,
|
|
1072
1295
|
};
|
|
@@ -1075,6 +1298,8 @@ class DevPlanStore {
|
|
|
1075
1298
|
const data = JSON.parse(doc.content);
|
|
1076
1299
|
const statusTag = doc.tags.find((t) => t.startsWith('status:'));
|
|
1077
1300
|
const status = (statusTag?.replace('status:', '') || 'pending');
|
|
1301
|
+
const moduleTag = doc.tags.find((t) => t.startsWith('module:'));
|
|
1302
|
+
const moduleId = moduleTag?.replace('module:', '') || undefined;
|
|
1078
1303
|
return {
|
|
1079
1304
|
id: doc.id,
|
|
1080
1305
|
projectName: this.projectName,
|
|
@@ -1084,6 +1309,7 @@ class DevPlanStore {
|
|
|
1084
1309
|
description: data.description,
|
|
1085
1310
|
estimatedHours: data.estimatedHours,
|
|
1086
1311
|
relatedSections: data.relatedSections || [],
|
|
1312
|
+
moduleId,
|
|
1087
1313
|
totalSubtasks: data.totalSubtasks || 0,
|
|
1088
1314
|
completedSubtasks: data.completedSubtasks || 0,
|
|
1089
1315
|
status,
|
|
@@ -1092,6 +1318,71 @@ class DevPlanStore {
|
|
|
1092
1318
|
completedAt: doc.metadata?.completedAt || null,
|
|
1093
1319
|
};
|
|
1094
1320
|
}
|
|
1321
|
+
docToModule(doc) {
|
|
1322
|
+
const data = JSON.parse(doc.content);
|
|
1323
|
+
const statusTag = doc.tags.find((t) => t.startsWith('status:'));
|
|
1324
|
+
const status = (statusTag?.replace('status:', '') || 'active');
|
|
1325
|
+
const moduleId = data.moduleId;
|
|
1326
|
+
// 计算关联的主任务数(去重)
|
|
1327
|
+
const moduleTag = `module:${moduleId}`;
|
|
1328
|
+
const taskDocs = this.taskStore.findByTag(moduleTag)
|
|
1329
|
+
.filter((d) => d.tags.includes(`plan:${this.projectName}`) &&
|
|
1330
|
+
d.tags.includes('type:main-task'));
|
|
1331
|
+
const uniqueTaskIds = new Set();
|
|
1332
|
+
for (const td of taskDocs) {
|
|
1333
|
+
try {
|
|
1334
|
+
uniqueTaskIds.add(JSON.parse(td.content).taskId);
|
|
1335
|
+
}
|
|
1336
|
+
catch { }
|
|
1337
|
+
}
|
|
1338
|
+
// 计算关联的子任务数(遍历关联主任务下的所有子任务)
|
|
1339
|
+
let subTaskCount = 0;
|
|
1340
|
+
let completedSubTaskCount = 0;
|
|
1341
|
+
for (const mainTaskId of uniqueTaskIds) {
|
|
1342
|
+
const subDocs = this.taskStore.findByTag(`parent:${mainTaskId}`)
|
|
1343
|
+
.filter((d) => d.tags.includes(`plan:${this.projectName}`) &&
|
|
1344
|
+
d.tags.includes('type:sub-task'));
|
|
1345
|
+
// 按 taskId 去重
|
|
1346
|
+
const seenSubIds = new Set();
|
|
1347
|
+
for (const sd of subDocs) {
|
|
1348
|
+
try {
|
|
1349
|
+
const subData = JSON.parse(sd.content);
|
|
1350
|
+
if (seenSubIds.has(subData.taskId))
|
|
1351
|
+
continue;
|
|
1352
|
+
seenSubIds.add(subData.taskId);
|
|
1353
|
+
subTaskCount++;
|
|
1354
|
+
const subStatusTag = sd.tags.find((t) => t.startsWith('status:'));
|
|
1355
|
+
if (subStatusTag === 'status:completed') {
|
|
1356
|
+
completedSubTaskCount++;
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
catch { }
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
// 计算关联的文档数(按 section+subSection 去重)
|
|
1363
|
+
const docDocs = this.docStore.findByTag(moduleTag)
|
|
1364
|
+
.filter((d) => d.tags.includes(`plan:${this.projectName}`));
|
|
1365
|
+
const uniqueDocKeys = new Set();
|
|
1366
|
+
for (const dd of docDocs) {
|
|
1367
|
+
const st = dd.tags.find((t) => t.startsWith('section:'));
|
|
1368
|
+
const sub = dd.tags.find((t) => t.startsWith('sub:'));
|
|
1369
|
+
uniqueDocKeys.add(`${st || ''}|${sub || ''}`);
|
|
1370
|
+
}
|
|
1371
|
+
return {
|
|
1372
|
+
id: doc.id,
|
|
1373
|
+
projectName: this.projectName,
|
|
1374
|
+
moduleId,
|
|
1375
|
+
name: data.name,
|
|
1376
|
+
description: data.description || undefined,
|
|
1377
|
+
status,
|
|
1378
|
+
mainTaskCount: uniqueTaskIds.size,
|
|
1379
|
+
subTaskCount,
|
|
1380
|
+
completedSubTaskCount,
|
|
1381
|
+
docCount: uniqueDocKeys.size,
|
|
1382
|
+
createdAt: doc.metadata?.createdAt || doc.createdAt,
|
|
1383
|
+
updatedAt: doc.metadata?.updatedAt || doc.createdAt,
|
|
1384
|
+
};
|
|
1385
|
+
}
|
|
1095
1386
|
docToSubTask(doc) {
|
|
1096
1387
|
const data = JSON.parse(doc.content);
|
|
1097
1388
|
const statusTag = doc.tags.find((t) => t.startsWith('status:'));
|
|
@@ -1140,20 +1431,25 @@ class DevPlanStore {
|
|
|
1140
1431
|
totalSubtasks: subs.length,
|
|
1141
1432
|
completedSubtasks: completedCount,
|
|
1142
1433
|
};
|
|
1434
|
+
const tags = [
|
|
1435
|
+
`plan:${this.projectName}`,
|
|
1436
|
+
'type:main-task',
|
|
1437
|
+
`mtask:${mainTask.taskId}`,
|
|
1438
|
+
`priority:${mainTask.priority}`,
|
|
1439
|
+
`status:${mainTask.status}`,
|
|
1440
|
+
];
|
|
1441
|
+
if (mainTask.moduleId) {
|
|
1442
|
+
tags.push(`module:${mainTask.moduleId}`);
|
|
1443
|
+
}
|
|
1143
1444
|
const docInput = {
|
|
1144
1445
|
content: JSON.stringify(taskData),
|
|
1145
1446
|
contentType: native_2.ContentType.Text,
|
|
1146
|
-
tags
|
|
1147
|
-
`plan:${this.projectName}`,
|
|
1148
|
-
'type:main-task',
|
|
1149
|
-
`mtask:${mainTask.taskId}`,
|
|
1150
|
-
`priority:${mainTask.priority}`,
|
|
1151
|
-
`status:${mainTask.status}`,
|
|
1152
|
-
],
|
|
1447
|
+
tags,
|
|
1153
1448
|
metadata: {
|
|
1154
1449
|
projectName: this.projectName,
|
|
1155
1450
|
taskId: mainTask.taskId,
|
|
1156
1451
|
status: mainTask.status,
|
|
1452
|
+
moduleId: mainTask.moduleId || null,
|
|
1157
1453
|
createdAt: mainTask.createdAt,
|
|
1158
1454
|
updatedAt: now,
|
|
1159
1455
|
completedAt: mainTask.completedAt,
|
|
@@ -1335,6 +1631,7 @@ function createDevPlan(projectName, basePath) {
|
|
|
1335
1631
|
return new DevPlanStore(projectName, {
|
|
1336
1632
|
documentPath: path.join(base, projectName, 'documents.jsonl'),
|
|
1337
1633
|
taskPath: path.join(base, projectName, 'tasks.jsonl'),
|
|
1634
|
+
modulePath: path.join(base, projectName, 'modules.jsonl'),
|
|
1338
1635
|
});
|
|
1339
1636
|
}
|
|
1340
1637
|
/**
|