aifastdb-devplan 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +669 -40
  2. package/dist/dev-plan-document-store.d.ts +309 -0
  3. package/dist/dev-plan-document-store.d.ts.map +1 -0
  4. package/dist/dev-plan-document-store.js +1543 -0
  5. package/dist/dev-plan-document-store.js.map +1 -0
  6. package/dist/dev-plan-factory.d.ts +49 -0
  7. package/dist/dev-plan-factory.d.ts.map +1 -0
  8. package/dist/dev-plan-factory.js +218 -0
  9. package/dist/dev-plan-factory.js.map +1 -0
  10. package/dist/dev-plan-graph-store.d.ts +114 -0
  11. package/dist/dev-plan-graph-store.d.ts.map +1 -0
  12. package/dist/dev-plan-graph-store.js +1073 -0
  13. package/dist/dev-plan-graph-store.js.map +1 -0
  14. package/dist/dev-plan-interface.d.ts +165 -0
  15. package/dist/dev-plan-interface.d.ts.map +1 -0
  16. package/dist/dev-plan-interface.js +10 -0
  17. package/dist/dev-plan-interface.js.map +1 -0
  18. package/dist/dev-plan-migrate.d.ts +52 -0
  19. package/dist/dev-plan-migrate.d.ts.map +1 -0
  20. package/dist/dev-plan-migrate.js +407 -0
  21. package/dist/dev-plan-migrate.js.map +1 -0
  22. package/dist/index.d.ts +20 -3
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +32 -10
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp-server/index.d.ts +1 -0
  27. package/dist/mcp-server/index.d.ts.map +1 -1
  28. package/dist/mcp-server/index.js +304 -92
  29. package/dist/mcp-server/index.js.map +1 -1
  30. package/dist/types.d.ts +375 -0
  31. package/dist/types.d.ts.map +1 -0
  32. package/dist/types.js +37 -0
  33. package/dist/types.js.map +1 -0
  34. package/dist/visualize/server.d.ts +18 -0
  35. package/dist/visualize/server.d.ts.map +1 -0
  36. package/dist/visualize/server.js +229 -0
  37. package/dist/visualize/server.js.map +1 -0
  38. package/dist/visualize/template.d.ts +8 -0
  39. package/dist/visualize/template.d.ts.map +1 -0
  40. package/dist/visualize/template.js +528 -0
  41. package/dist/visualize/template.js.map +1 -0
  42. package/package.json +14 -4
@@ -22,6 +22,7 @@
22
22
  * - devplan_list_modules: List all feature modules
23
23
  * - devplan_get_module: Get module details with associated tasks and docs
24
24
  * - devplan_update_module: Update module info
25
+ * - devplan_start_visual: Start the graph visualization HTTP server
25
26
  */
26
27
  Object.defineProperty(exports, "__esModule", { value: true });
27
28
  // @ts-ignore - MCP SDK types will be available after npm install
@@ -30,16 +31,26 @@ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
30
31
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
31
32
  // @ts-ignore - MCP SDK types will be available after npm install
32
33
  const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
33
- const dev_plan_store_1 = require("../dev-plan-store");
34
+ const dev_plan_factory_1 = require("../dev-plan-factory");
35
+ const dev_plan_migrate_1 = require("../dev-plan-migrate");
36
+ const types_1 = require("../types");
34
37
  // ============================================================================
35
38
  // DevPlan Store Cache
36
39
  // ============================================================================
37
40
  const devPlanCache = new Map();
38
- function getDevPlan(projectName) {
39
- if (!devPlanCache.has(projectName)) {
40
- devPlanCache.set(projectName, (0, dev_plan_store_1.createDevPlan)(projectName));
41
+ function getDevPlan(projectName, engine) {
42
+ const cacheKey = projectName;
43
+ if (engine) {
44
+ // 显式指定引擎时,清除缓存以使用新引擎
45
+ devPlanCache.delete(cacheKey);
46
+ const plan = (0, dev_plan_factory_1.createDevPlan)(projectName, undefined, engine);
47
+ devPlanCache.set(cacheKey, plan);
48
+ return plan;
41
49
  }
42
- return devPlanCache.get(projectName);
50
+ if (!devPlanCache.has(cacheKey)) {
51
+ devPlanCache.set(cacheKey, (0, dev_plan_factory_1.createDevPlan)(projectName));
52
+ }
53
+ return devPlanCache.get(cacheKey);
43
54
  }
44
55
  // ============================================================================
45
56
  // Tool Definitions
@@ -47,51 +58,51 @@ function getDevPlan(projectName) {
47
58
  const TOOLS = [
48
59
  {
49
60
  name: 'devplan_init',
50
- description: 'Initialize a development plan for a project. Creates an empty plan structure. Also lists existing plans if no projectName is given.',
61
+ description: 'Initialize a development plan for a project. Creates an empty plan structure. Also lists existing plans if no projectName is given.\n初始化项目的开发计划。创建空的计划结构。如果不提供 projectName 则列出已有的计划。',
51
62
  inputSchema: {
52
63
  type: 'object',
53
64
  properties: {
54
65
  projectName: {
55
66
  type: 'string',
56
- description: 'Project name (e.g., "federation-db", "aidb-viewer"). Omit to list existing plans.',
67
+ description: 'Project name (e.g., "federation-db", "aidb-viewer"). Omit to list existing plans.\n项目名称(如 "federation-db")。省略则列出已有计划。',
57
68
  },
58
69
  },
59
70
  },
60
71
  },
61
72
  {
62
73
  name: 'devplan_save_section',
63
- description: 'Save or update a document section in the dev plan. Sections are typed: overview, core_concepts, api_design, file_structure, config, examples, technical_notes, api_endpoints, milestones, changelog, custom. technical_notes and custom support subSection for multiple sub-documents.',
74
+ description: 'Save or update a document section in the dev plan. Sections are typed: overview, core_concepts, api_design, file_structure, config, examples, technical_notes, api_endpoints, milestones, changelog, custom. technical_notes and custom support subSection for multiple sub-documents.\n保存或更新开发计划中的文档片段。支持 11 种标准类型。technical_notes 和 custom 支持通过 subSection 存储多个子文档。',
64
75
  inputSchema: {
65
76
  type: 'object',
66
77
  properties: {
67
78
  projectName: {
68
79
  type: 'string',
69
- description: 'Project name',
80
+ description: 'Project name\n项目名称',
70
81
  },
71
82
  section: {
72
83
  type: 'string',
73
84
  enum: ['overview', 'core_concepts', 'api_design', 'file_structure', 'config', 'examples', 'technical_notes', 'api_endpoints', 'milestones', 'changelog', 'custom'],
74
- description: 'Document section type',
85
+ description: 'Document section type\n文档片段类型',
75
86
  },
76
87
  title: {
77
88
  type: 'string',
78
- description: 'Section title (e.g., "概述 - 背景与目标")',
89
+ description: 'Section title (e.g., "Overview - Background")\n片段标题(如 "概述 - 背景与目标"',
79
90
  },
80
91
  content: {
81
92
  type: 'string',
82
- description: 'Markdown content for this section',
93
+ description: 'Markdown content for this section\n该片段的 Markdown 内容',
83
94
  },
84
95
  version: {
85
96
  type: 'string',
86
- description: 'Optional version string (default: "1.0.0")',
97
+ description: 'Optional version string (default: "1.0.0")\n可选版本号(默认 "1.0.0")',
87
98
  },
88
99
  subSection: {
89
100
  type: 'string',
90
- description: 'Optional sub-section name for technical_notes/custom (e.g., "security", "resilience")',
101
+ description: 'Optional sub-section name for technical_notes/custom (e.g., "security", "resilience")\n可选子片段名称,用于 technical_notes/custom(如 "security")',
91
102
  },
92
103
  moduleId: {
93
104
  type: 'string',
94
- description: 'Optional: Associate with a feature module',
105
+ description: 'Optional: Associate with a feature module\n可选:关联到功能模块',
95
106
  },
96
107
  },
97
108
  required: ['projectName', 'section', 'title', 'content'],
@@ -99,22 +110,22 @@ const TOOLS = [
99
110
  },
100
111
  {
101
112
  name: 'devplan_get_section',
102
- description: 'Read a specific document section from the dev plan.',
113
+ description: 'Read a specific document section from the dev plan.\n读取开发计划中的指定文档片段。',
103
114
  inputSchema: {
104
115
  type: 'object',
105
116
  properties: {
106
117
  projectName: {
107
118
  type: 'string',
108
- description: 'Project name',
119
+ description: 'Project name\n项目名称',
109
120
  },
110
121
  section: {
111
122
  type: 'string',
112
123
  enum: ['overview', 'core_concepts', 'api_design', 'file_structure', 'config', 'examples', 'technical_notes', 'api_endpoints', 'milestones', 'changelog', 'custom'],
113
- description: 'Document section type',
124
+ description: 'Document section type\n文档片段类型',
114
125
  },
115
126
  subSection: {
116
127
  type: 'string',
117
- description: 'Optional sub-section name',
128
+ description: 'Optional sub-section name\n可选子片段名称',
118
129
  },
119
130
  },
120
131
  required: ['projectName', 'section'],
@@ -122,13 +133,13 @@ const TOOLS = [
122
133
  },
123
134
  {
124
135
  name: 'devplan_list_sections',
125
- description: 'List all document sections in the dev plan for a project.',
136
+ description: 'List all document sections in the dev plan for a project.\n列出项目开发计划中的所有文档片段。',
126
137
  inputSchema: {
127
138
  type: 'object',
128
139
  properties: {
129
140
  projectName: {
130
141
  type: 'string',
131
- description: 'Project name',
142
+ description: 'Project name\n项目名称',
132
143
  },
133
144
  },
134
145
  required: ['projectName'],
@@ -136,38 +147,38 @@ const TOOLS = [
136
147
  },
137
148
  {
138
149
  name: 'devplan_create_main_task',
139
- description: 'Create a main task (development phase) in the dev plan. A main task groups multiple sub-tasks.',
150
+ description: 'Create a main task (development phase) in the dev plan. A main task groups multiple sub-tasks.\n在开发计划中创建主任务(开发阶段)。一个主任务下包含多个子任务。',
140
151
  inputSchema: {
141
152
  type: 'object',
142
153
  properties: {
143
154
  projectName: {
144
155
  type: 'string',
145
- description: 'Project name',
156
+ description: 'Project name\n项目名称',
146
157
  },
147
158
  taskId: {
148
159
  type: 'string',
149
- description: 'Main task ID (e.g., "phase-7", "phase-14B")',
160
+ description: 'Main task ID (e.g., "phase-7", "phase-14B")\n主任务 ID(如 "phase-7")',
150
161
  },
151
162
  title: {
152
163
  type: 'string',
153
- description: 'Task title (e.g., "阶段七:Store Trait 与适配器")',
164
+ description: 'Task title (e.g., "Phase 7: Store Trait & Adapters")\n任务标题(如 "阶段七:Store Trait 与适配器"',
154
165
  },
155
166
  priority: {
156
167
  type: 'string',
157
168
  enum: ['P0', 'P1', 'P2'],
158
- description: 'Priority level',
169
+ description: 'Priority level\n优先级',
159
170
  },
160
171
  description: {
161
172
  type: 'string',
162
- description: 'Optional task description',
173
+ description: 'Optional task description\n可选任务描述',
163
174
  },
164
175
  estimatedHours: {
165
176
  type: 'number',
166
- description: 'Optional estimated hours',
177
+ description: 'Optional estimated hours\n可选预估工时',
167
178
  },
168
179
  moduleId: {
169
180
  type: 'string',
170
- description: 'Optional: Associate with a feature module',
181
+ description: 'Optional: Associate with a feature module\n可选:关联到功能模块',
171
182
  },
172
183
  },
173
184
  required: ['projectName', 'taskId', 'title', 'priority'],
@@ -175,33 +186,33 @@ const TOOLS = [
175
186
  },
176
187
  {
177
188
  name: 'devplan_add_sub_task',
178
- description: 'Add a sub-task under a main task. Sub-tasks correspond to Cursor TodoList items.',
189
+ description: 'Add a sub-task under a main task. Sub-tasks correspond to Cursor TodoList items.\n在主任务下添加子任务。子任务对应 Cursor 的 TodoList 条目。',
179
190
  inputSchema: {
180
191
  type: 'object',
181
192
  properties: {
182
193
  projectName: {
183
194
  type: 'string',
184
- description: 'Project name',
195
+ description: 'Project name\n项目名称',
185
196
  },
186
197
  taskId: {
187
198
  type: 'string',
188
- description: 'Sub-task ID (e.g., "T7.2", "T14.8")',
199
+ description: 'Sub-task ID (e.g., "T7.2", "T14.8")\n子任务 ID(如 "T7.2")',
189
200
  },
190
201
  parentTaskId: {
191
202
  type: 'string',
192
- description: 'Parent main task ID (e.g., "phase-7")',
203
+ description: 'Parent main task ID (e.g., "phase-7")\n所属主任务 ID(如 "phase-7")',
193
204
  },
194
205
  title: {
195
206
  type: 'string',
196
- description: 'Sub-task title',
207
+ description: 'Sub-task title\n子任务标题',
197
208
  },
198
209
  estimatedHours: {
199
210
  type: 'number',
200
- description: 'Optional estimated hours',
211
+ description: 'Optional estimated hours\n可选预估工时',
201
212
  },
202
213
  description: {
203
214
  type: 'string',
204
- description: 'Optional task description',
215
+ description: 'Optional task description\n可选任务描述',
205
216
  },
206
217
  },
207
218
  required: ['projectName', 'taskId', 'parentTaskId', 'title'],
@@ -209,56 +220,56 @@ const TOOLS = [
209
220
  },
210
221
  {
211
222
  name: 'devplan_upsert_task',
212
- description: 'Idempotent import (upsert) for main tasks or sub-tasks. If the task does not exist, it will be created. If it already exists, it will be updated with the new data while preserving the higher-priority status (e.g., completed tasks will not be reverted to pending). This is the recommended tool for bulk data import to prevent duplicates.',
223
+ description: 'Idempotent import (upsert) for main tasks or sub-tasks. If the task does not exist, it will be created. If it already exists, it will be updated with the new data while preserving the higher-priority status (e.g., completed tasks will not be reverted to pending). This is the recommended tool for bulk data import to prevent duplicates.\n幂等导入(upsert)主任务或子任务。任务不存在则创建,已存在则更新(保留更高优先级的状态,如已完成的任务不会被回退为待处理)。推荐用于批量数据导入以防重复。',
213
224
  inputSchema: {
214
225
  type: 'object',
215
226
  properties: {
216
227
  projectName: {
217
228
  type: 'string',
218
- description: 'Project name',
229
+ description: 'Project name\n项目名称',
219
230
  },
220
231
  taskType: {
221
232
  type: 'string',
222
233
  enum: ['main', 'sub'],
223
- description: 'Whether this is a main task or sub-task',
234
+ description: 'Whether this is a main task or sub-task\n任务类型:主任务 (main) 或子任务 (sub)',
224
235
  },
225
236
  taskId: {
226
237
  type: 'string',
227
- description: 'Task ID (e.g., "phase-7" for main, "T7.2" for sub)',
238
+ description: 'Task ID (e.g., "phase-7" for main, "T7.2" for sub)\n任务 ID(主任务如 "phase-7",子任务如 "T7.2")',
228
239
  },
229
240
  title: {
230
241
  type: 'string',
231
- description: 'Task title',
242
+ description: 'Task title\n任务标题',
232
243
  },
233
244
  priority: {
234
245
  type: 'string',
235
246
  enum: ['P0', 'P1', 'P2'],
236
- description: 'Priority level (required for main tasks)',
247
+ description: 'Priority level (required for main tasks)\n优先级(主任务必填)',
237
248
  },
238
249
  parentTaskId: {
239
250
  type: 'string',
240
- description: 'Parent main task ID (required for sub-tasks)',
251
+ description: 'Parent main task ID (required for sub-tasks)\n所属主任务 ID(子任务必填)',
241
252
  },
242
253
  description: {
243
254
  type: 'string',
244
- description: 'Optional task description',
255
+ description: 'Optional task description\n可选任务描述',
245
256
  },
246
257
  estimatedHours: {
247
258
  type: 'number',
248
- description: 'Optional estimated hours',
259
+ description: 'Optional estimated hours\n可选预估工时',
249
260
  },
250
261
  status: {
251
262
  type: 'string',
252
263
  enum: ['pending', 'in_progress', 'completed', 'cancelled'],
253
- description: 'Target status (default: pending). Higher-priority existing status is preserved unless preserveStatus is false.',
264
+ description: 'Target status (default: pending). Higher-priority existing status is preserved unless preserveStatus is false.\n目标状态(默认 pending)。已有的更高优先级状态会被保留,除非 preserveStatus 为 false。',
254
265
  },
255
266
  preserveStatus: {
256
267
  type: 'boolean',
257
- description: 'If true (default), existing higher-priority status is preserved. Set to false to force overwrite.',
268
+ description: 'If true (default), existing higher-priority status is preserved. Set to false to force overwrite.\n为 true(默认)时保留已有的更高优先级状态。设为 false 强制覆盖。',
258
269
  },
259
270
  moduleId: {
260
271
  type: 'string',
261
- description: 'Optional: Associate with a feature module (main tasks only)',
272
+ description: 'Optional: Associate with a feature module (main tasks only)\n可选:关联到功能模块(仅主任务)',
262
273
  },
263
274
  },
264
275
  required: ['projectName', 'taskType', 'taskId', 'title'],
@@ -266,22 +277,22 @@ const TOOLS = [
266
277
  },
267
278
  {
268
279
  name: 'devplan_complete_task',
269
- description: 'Mark a task as completed. For sub-tasks: auto-updates parent main task progress count and completedAt timestamp. If all sub-tasks are done, the main task is also auto-completed. For main tasks: directly marks as completed.',
280
+ description: 'Mark a task as completed. For sub-tasks: auto-updates parent main task progress count and completedAt timestamp. If all sub-tasks are done, the main task is also auto-completed. For main tasks: directly marks as completed.\n将任务标记为已完成。子任务完成时自动更新主任务的进度计数和完成时间戳。当所有子任务完成时,主任务也会自动标记为完成。',
270
281
  inputSchema: {
271
282
  type: 'object',
272
283
  properties: {
273
284
  projectName: {
274
285
  type: 'string',
275
- description: 'Project name',
286
+ description: 'Project name\n项目名称',
276
287
  },
277
288
  taskId: {
278
289
  type: 'string',
279
- description: 'Task ID (sub-task like "T7.2" or main task like "phase-7")',
290
+ description: 'Task ID (sub-task like "T7.2" or main task like "phase-7")\n任务 ID(子任务如 "T7.2",主任务如 "phase-7")',
280
291
  },
281
292
  taskType: {
282
293
  type: 'string',
283
294
  enum: ['sub', 'main'],
284
- description: 'Whether this is a sub-task or main task (default: "sub")',
295
+ description: 'Whether this is a sub-task or main task (default: "sub")\n任务类型:子任务 (sub) 或主任务 (main),默认 "sub"',
285
296
  },
286
297
  },
287
298
  required: ['projectName', 'taskId'],
@@ -289,31 +300,31 @@ const TOOLS = [
289
300
  },
290
301
  {
291
302
  name: 'devplan_list_tasks',
292
- description: 'List tasks in the dev plan. Can list main tasks, or sub-tasks of a specific main task. When parentTaskId is omitted but status is provided, aggregates sub-tasks across ALL main tasks matching the status filter.',
303
+ description: 'List tasks in the dev plan. Can list main tasks, or sub-tasks of a specific main task. When parentTaskId is omitted but status is provided, aggregates sub-tasks across ALL main tasks matching the status filter.\n列出开发计划中的任务。可列出主任务,或指定主任务下的子任务。省略 parentTaskId 但提供 status 时,跨所有主任务聚合匹配状态的子任务。',
293
304
  inputSchema: {
294
305
  type: 'object',
295
306
  properties: {
296
307
  projectName: {
297
308
  type: 'string',
298
- description: 'Project name',
309
+ description: 'Project name\n项目名称',
299
310
  },
300
311
  parentTaskId: {
301
312
  type: 'string',
302
- description: 'Optional: List sub-tasks of this main task ID. If omitted, lists main tasks.',
313
+ description: 'Optional: List sub-tasks of this main task ID. If omitted, lists main tasks.\n可选:指定主任务 ID 以列出其子任务。省略则列出主任务。',
303
314
  },
304
315
  status: {
305
316
  type: 'string',
306
317
  enum: ['pending', 'in_progress', 'completed', 'cancelled'],
307
- description: 'Optional: Filter by status',
318
+ description: 'Optional: Filter by status\n可选:按状态筛选',
308
319
  },
309
320
  priority: {
310
321
  type: 'string',
311
322
  enum: ['P0', 'P1', 'P2'],
312
- description: 'Optional: Filter by priority (main tasks only)',
323
+ description: 'Optional: Filter by priority (main tasks only)\n可选:按优先级筛选(仅主任务)',
313
324
  },
314
325
  moduleId: {
315
326
  type: 'string',
316
- description: 'Optional: Filter by feature module ID',
327
+ description: 'Optional: Filter by feature module ID\n可选:按功能模块 ID 筛选',
317
328
  },
318
329
  },
319
330
  required: ['projectName'],
@@ -321,13 +332,13 @@ const TOOLS = [
321
332
  },
322
333
  {
323
334
  name: 'devplan_get_progress',
324
- description: 'Get overall project progress: section count, main task count, sub-task completion rates, per-phase progress bars.',
335
+ description: 'Get overall project progress: section count, main task count, sub-task completion rates, per-phase progress bars.\n获取项目整体进度概览:文档片段数、主任务数、子任务完成率、各阶段进度条。',
325
336
  inputSchema: {
326
337
  type: 'object',
327
338
  properties: {
328
339
  projectName: {
329
340
  type: 'string',
330
- description: 'Project name',
341
+ description: 'Project name\n项目名称',
331
342
  },
332
343
  },
333
344
  required: ['projectName'],
@@ -335,18 +346,18 @@ const TOOLS = [
335
346
  },
336
347
  {
337
348
  name: 'devplan_export_markdown',
338
- description: 'Export the dev plan as a Markdown document. Scope can be "full" (documents + tasks) or "tasks" (task summary only).',
349
+ description: 'Export the dev plan as a Markdown document. Scope can be "full" (documents + tasks) or "tasks" (task summary only).\n将开发计划导出为 Markdown 文档。scope 可选 "full"(文档+任务)或 "tasks"(仅任务摘要)。',
339
350
  inputSchema: {
340
351
  type: 'object',
341
352
  properties: {
342
353
  projectName: {
343
354
  type: 'string',
344
- description: 'Project name',
355
+ description: 'Project name\n项目名称',
345
356
  },
346
357
  scope: {
347
358
  type: 'string',
348
359
  enum: ['full', 'tasks'],
349
- description: 'Export scope: "full" for documents + tasks, "tasks" for task summary only (default: "tasks")',
360
+ description: 'Export scope: "full" for documents + tasks, "tasks" for task summary only (default: "tasks")\n导出范围:"full" 包含文档和任务,"tasks" 仅任务摘要(默认 "tasks")',
350
361
  },
351
362
  },
352
363
  required: ['projectName'],
@@ -354,17 +365,17 @@ const TOOLS = [
354
365
  },
355
366
  {
356
367
  name: 'devplan_sync_git',
357
- description: 'Synchronize DevPlan task statuses with Git history. Checks if completed tasks\' commits are still ancestors of the current HEAD. If a completed task\'s commit was rolled back (e.g., via git reset), the task is automatically reverted to pending. Use dryRun=true to preview changes without modifying data.',
368
+ description: 'Synchronize DevPlan task statuses with Git history. Checks if completed tasks\' commits are still ancestors of the current HEAD. If a completed task\'s commit was rolled back (e.g., via git reset), the task is automatically reverted to pending. Use dryRun=true to preview changes without modifying data.\n将 DevPlan 任务状态与 Git 历史同步。检查已完成任务的 commit 是否仍是当前 HEAD 的祖先。如果已完成任务的 commit 被回滚(如 git reset),任务会自动回退为待处理。使用 dryRun=true 可预览变更而不修改数据。',
358
369
  inputSchema: {
359
370
  type: 'object',
360
371
  properties: {
361
372
  projectName: {
362
373
  type: 'string',
363
- description: 'Project name',
374
+ description: 'Project name\n项目名称',
364
375
  },
365
376
  dryRun: {
366
377
  type: 'boolean',
367
- description: 'If true, only report which tasks would be reverted without actually changing them (default: false)',
378
+ description: 'If true, only report which tasks would be reverted without actually changing them (default: false)\n为 true 时仅报告哪些任务会被回退,不实际修改数据(默认 false)',
368
379
  },
369
380
  },
370
381
  required: ['projectName'],
@@ -372,30 +383,30 @@ const TOOLS = [
372
383
  },
373
384
  {
374
385
  name: 'devplan_create_module',
375
- description: 'Create/register a feature module in the dev plan. Modules represent independent functional areas of the project (e.g., "vector-store", "permission-system"). Main tasks and documents can be associated with modules.',
386
+ description: 'Create/register a feature module in the dev plan. Modules represent independent functional areas of the project (e.g., "vector-store", "permission-system"). Main tasks and documents can be associated with modules.\n在开发计划中创建/注册功能模块。模块代表项目的独立功能区域(如 "vector-store"、"permission-system")。主任务和文档可以关联到模块。',
376
387
  inputSchema: {
377
388
  type: 'object',
378
389
  properties: {
379
390
  projectName: {
380
391
  type: 'string',
381
- description: 'Project name',
392
+ description: 'Project name\n项目名称',
382
393
  },
383
394
  moduleId: {
384
395
  type: 'string',
385
- description: 'Module identifier (e.g., "vector-store", "permission")',
396
+ description: 'Module identifier (e.g., "vector-store", "permission")\n模块标识符(如 "vector-store"、"permission")',
386
397
  },
387
398
  name: {
388
399
  type: 'string',
389
- description: 'Module display name (e.g., "向量存储模块")',
400
+ description: 'Module display name (e.g., "Vector Store Module")\n模块显示名称(如 "向量存储模块"',
390
401
  },
391
402
  description: {
392
403
  type: 'string',
393
- description: 'Optional module description',
404
+ description: 'Optional module description\n可选模块描述',
394
405
  },
395
406
  status: {
396
407
  type: 'string',
397
408
  enum: ['planning', 'active', 'completed', 'deprecated'],
398
- description: 'Module status (default: active)',
409
+ description: 'Module status (default: active)\n模块状态(默认 active)',
399
410
  },
400
411
  },
401
412
  required: ['projectName', 'moduleId', 'name'],
@@ -403,18 +414,18 @@ const TOOLS = [
403
414
  },
404
415
  {
405
416
  name: 'devplan_list_modules',
406
- description: 'List all feature modules in the dev plan, with main task count, sub-task count (total and completed), and document counts.',
417
+ description: 'List all feature modules in the dev plan, with main task count, sub-task count (total and completed), and document counts.\n列出开发计划中的所有功能模块,包含主任务数、子任务数(总数和已完成数)、文档数。',
407
418
  inputSchema: {
408
419
  type: 'object',
409
420
  properties: {
410
421
  projectName: {
411
422
  type: 'string',
412
- description: 'Project name',
423
+ description: 'Project name\n项目名称',
413
424
  },
414
425
  status: {
415
426
  type: 'string',
416
427
  enum: ['planning', 'active', 'completed', 'deprecated'],
417
- description: 'Optional: Filter by module status',
428
+ description: 'Optional: Filter by module status\n可选:按模块状态筛选',
418
429
  },
419
430
  },
420
431
  required: ['projectName'],
@@ -422,17 +433,17 @@ const TOOLS = [
422
433
  },
423
434
  {
424
435
  name: 'devplan_get_module',
425
- description: 'Get module details including all associated main tasks, sub-tasks, and documents.',
436
+ description: 'Get module details including all associated main tasks, sub-tasks, and documents.\n获取模块详情,包含所有关联的主任务、子任务和文档。',
426
437
  inputSchema: {
427
438
  type: 'object',
428
439
  properties: {
429
440
  projectName: {
430
441
  type: 'string',
431
- description: 'Project name',
442
+ description: 'Project name\n项目名称',
432
443
  },
433
444
  moduleId: {
434
445
  type: 'string',
435
- description: 'Module identifier',
446
+ description: 'Module identifier\n模块标识符',
436
447
  },
437
448
  },
438
449
  required: ['projectName', 'moduleId'],
@@ -440,58 +451,133 @@ const TOOLS = [
440
451
  },
441
452
  {
442
453
  name: 'devplan_update_module',
443
- description: 'Update module information (name, description, status).',
454
+ description: 'Update module information (name, description, status).\n更新模块信息(名称、描述、状态)。',
444
455
  inputSchema: {
445
456
  type: 'object',
446
457
  properties: {
447
458
  projectName: {
448
459
  type: 'string',
449
- description: 'Project name',
460
+ description: 'Project name\n项目名称',
450
461
  },
451
462
  moduleId: {
452
463
  type: 'string',
453
- description: 'Module identifier',
464
+ description: 'Module identifier\n模块标识符',
454
465
  },
455
466
  name: {
456
467
  type: 'string',
457
- description: 'New module name',
468
+ description: 'New module name\n新的模块名称',
458
469
  },
459
470
  description: {
460
471
  type: 'string',
461
- description: 'New module description',
472
+ description: 'New module description\n新的模块描述',
462
473
  },
463
474
  status: {
464
475
  type: 'string',
465
476
  enum: ['planning', 'active', 'completed', 'deprecated'],
466
- description: 'New module status',
477
+ description: 'New module status\n新的模块状态',
467
478
  },
468
479
  },
469
480
  required: ['projectName', 'moduleId'],
470
481
  },
471
482
  },
483
+ {
484
+ name: 'devplan_export_graph',
485
+ description: 'Export the DevPlan as a graph structure (nodes + edges) for visualization. Only available when the project uses the "graph" engine (SocialGraphV2). Returns { nodes, edges } compatible with vis-network.\n将 DevPlan 导出为图结构(节点+边)用于可视化。仅在项目使用 "graph" 引擎 (SocialGraphV2) 时可用。返回兼容 vis-network 的 { nodes, edges }。',
486
+ inputSchema: {
487
+ type: 'object',
488
+ properties: {
489
+ projectName: {
490
+ type: 'string',
491
+ description: 'Project name\n项目名称',
492
+ },
493
+ includeDocuments: {
494
+ type: 'boolean',
495
+ description: 'Whether to include document nodes (default: true)\n是否包含文档节点(默认 true)',
496
+ },
497
+ includeModules: {
498
+ type: 'boolean',
499
+ description: 'Whether to include module nodes (default: true)\n是否包含模块节点(默认 true)',
500
+ },
501
+ },
502
+ required: ['projectName'],
503
+ },
504
+ },
505
+ {
506
+ name: 'devplan_migrate_engine',
507
+ description: 'Migrate project data between storage engines. Supports migration from "document" (EnhancedDocumentStore/JSONL) to "graph" (SocialGraphV2) or vice versa. Automatically backs up old data before migration. Use dryRun=true to preview without changes.\n在存储引擎之间迁移项目数据。支持从 "document"(EnhancedDocumentStore/JSONL)迁移到 "graph"(SocialGraphV2),或反向迁移。迁移前自动备份旧数据。使用 dryRun=true 可预览而不实际修改。',
508
+ inputSchema: {
509
+ type: 'object',
510
+ properties: {
511
+ projectName: {
512
+ type: 'string',
513
+ description: 'Project name\n项目名称',
514
+ },
515
+ targetEngine: {
516
+ type: 'string',
517
+ enum: ['graph', 'document'],
518
+ description: 'Target engine to migrate to\n目标引擎类型',
519
+ },
520
+ backup: {
521
+ type: 'boolean',
522
+ description: 'Whether to backup old data before migration (default: true)\n是否在迁移前备份旧数据(默认 true)',
523
+ },
524
+ dryRun: {
525
+ type: 'boolean',
526
+ description: 'If true, only preview what would be migrated without making changes (default: false)\n为 true 时仅预览迁移内容,不实际修改(默认 false)',
527
+ },
528
+ },
529
+ required: ['projectName', 'targetEngine'],
530
+ },
531
+ },
532
+ {
533
+ name: 'devplan_start_visual',
534
+ description: 'Start the graph visualization HTTP server. Opens an interactive vis-network page in the browser to visualize modules, tasks, and their relationships as a graph. The server runs in the background. Only works with projects using the "graph" engine.\n启动图谱可视化 HTTP 服务器。在浏览器中打开交互式 vis-network 页面,将模块、任务及其关系以图谱形式可视化展示。服务器在后台运行。仅支持使用 "graph" 引擎的项目。',
535
+ inputSchema: {
536
+ type: 'object',
537
+ properties: {
538
+ projectName: {
539
+ type: 'string',
540
+ description: 'Project name\n项目名称',
541
+ },
542
+ port: {
543
+ type: 'number',
544
+ description: 'HTTP server port (default: 3210)\nHTTP 服务器端口(默认 3210)',
545
+ },
546
+ },
547
+ required: ['projectName'],
548
+ },
549
+ },
472
550
  ];
473
551
  async function handleToolCall(name, args) {
474
552
  switch (name) {
475
553
  case 'devplan_init': {
476
554
  if (!args.projectName) {
477
- // List existing plans
478
- const plans = (0, dev_plan_store_1.listDevPlans)();
555
+ // List existing plans with engine info
556
+ const plans = (0, dev_plan_factory_1.listDevPlans)();
557
+ const planDetails = plans.map((name) => ({
558
+ name,
559
+ engine: (0, dev_plan_factory_1.getProjectEngine)(name) || 'unknown',
560
+ }));
479
561
  return JSON.stringify({
480
- existingPlans: plans,
481
- availableSections: dev_plan_store_1.ALL_SECTIONS,
482
- sectionDescriptions: dev_plan_store_1.SECTION_DESCRIPTIONS,
562
+ existingPlans: planDetails,
563
+ availableSections: types_1.ALL_SECTIONS,
564
+ sectionDescriptions: types_1.SECTION_DESCRIPTIONS,
565
+ availableEngines: ['graph', 'document'],
566
+ defaultEngine: 'graph',
483
567
  message: plans.length > 0
484
568
  ? `Found ${plans.length} existing plan(s). Provide a projectName to initialize a new one.`
485
569
  : 'No existing plans. Provide a projectName to create one.',
486
570
  });
487
571
  }
488
572
  const plan = getDevPlan(args.projectName);
573
+ const engine = (0, dev_plan_factory_1.getProjectEngine)(args.projectName) || 'graph';
489
574
  return JSON.stringify({
490
575
  success: true,
491
576
  projectName: args.projectName,
492
- availableSections: dev_plan_store_1.ALL_SECTIONS,
493
- sectionDescriptions: dev_plan_store_1.SECTION_DESCRIPTIONS,
494
- message: `DevPlan initialized for "${args.projectName}". Use devplan_save_section to add document sections and devplan_create_main_task to add development phases.`,
577
+ engine,
578
+ availableSections: types_1.ALL_SECTIONS,
579
+ sectionDescriptions: types_1.SECTION_DESCRIPTIONS,
580
+ message: `DevPlan initialized for "${args.projectName}" with engine "${engine}". Use devplan_save_section to add document sections and devplan_create_main_task to add development phases.`,
495
581
  });
496
582
  }
497
583
  case 'devplan_save_section': {
@@ -950,6 +1036,132 @@ async function handleToolCall(name, args) {
950
1036
  }
951
1037
  return JSON.stringify({ success: true, module: updated });
952
1038
  }
1039
+ case 'devplan_export_graph': {
1040
+ if (!args.projectName) {
1041
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: projectName');
1042
+ }
1043
+ const plan = getDevPlan(args.projectName);
1044
+ const engine = (0, dev_plan_factory_1.getProjectEngine)(args.projectName);
1045
+ if (engine !== 'graph' || !plan.exportGraph) {
1046
+ return JSON.stringify({
1047
+ error: `Graph export is only available for projects using the "graph" engine. Project "${args.projectName}" uses "${engine || 'document'}" engine.`,
1048
+ hint: 'Re-initialize the project with engine "graph" to enable graph export.',
1049
+ });
1050
+ }
1051
+ try {
1052
+ const graph = plan.exportGraph({
1053
+ includeDocuments: args.includeDocuments,
1054
+ includeModules: args.includeModules,
1055
+ });
1056
+ return JSON.stringify({
1057
+ success: true,
1058
+ projectName: args.projectName,
1059
+ engine: 'graph',
1060
+ nodeCount: graph?.nodes.length || 0,
1061
+ edgeCount: graph?.edges.length || 0,
1062
+ graph,
1063
+ });
1064
+ }
1065
+ catch (err) {
1066
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
1067
+ }
1068
+ }
1069
+ case 'devplan_migrate_engine': {
1070
+ if (!args.projectName || !args.targetEngine) {
1071
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: projectName, targetEngine');
1072
+ }
1073
+ const validEngines = ['graph', 'document'];
1074
+ if (!validEngines.includes(args.targetEngine)) {
1075
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Invalid targetEngine "${args.targetEngine}". Must be one of: ${validEngines.join(', ')}`);
1076
+ }
1077
+ try {
1078
+ const result = (0, dev_plan_migrate_1.migrateEngine)(args.projectName, args.targetEngine, undefined, {
1079
+ backup: args.backup,
1080
+ dryRun: args.dryRun,
1081
+ });
1082
+ // 迁移成功后清除缓存,下次访问时使用新引擎
1083
+ if (result.success && !args.dryRun) {
1084
+ devPlanCache.delete(args.projectName);
1085
+ }
1086
+ const statusIcon = result.success ? '✅' : '⚠️';
1087
+ const modeLabel = args.dryRun ? ' (dry run)' : '';
1088
+ return JSON.stringify({
1089
+ ...result,
1090
+ summary: result.fromEngine === result.toEngine
1091
+ ? `ℹ️ Project "${args.projectName}" already uses "${result.toEngine}" engine. No migration needed.`
1092
+ : result.success
1093
+ ? `${statusIcon} Successfully migrated "${args.projectName}" from "${result.fromEngine}" to "${result.toEngine}"${modeLabel}. ` +
1094
+ `Stats: ${result.stats.modules} modules, ${result.stats.documents} documents, ` +
1095
+ `${result.stats.mainTasks} main tasks, ${result.stats.subTasks} sub-tasks. ` +
1096
+ `Duration: ${result.durationMs}ms.` +
1097
+ (result.backupPath ? ` Backup: ${result.backupPath}` : '')
1098
+ : `${statusIcon} Migration failed with ${result.errors.length} error(s): ${result.errors.join('; ')}`,
1099
+ });
1100
+ }
1101
+ catch (err) {
1102
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
1103
+ }
1104
+ }
1105
+ case 'devplan_start_visual': {
1106
+ if (!args.projectName) {
1107
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: projectName');
1108
+ }
1109
+ const engine = (0, dev_plan_factory_1.getProjectEngine)(args.projectName);
1110
+ if (engine !== 'graph') {
1111
+ return JSON.stringify({
1112
+ success: false,
1113
+ error: `Graph visualization requires "graph" engine. Project "${args.projectName}" uses "${engine || 'document'}" engine.`,
1114
+ hint: 'Use devplan_migrate_engine to migrate to "graph" engine first.',
1115
+ });
1116
+ }
1117
+ const port = args.port || 3210;
1118
+ try {
1119
+ const { spawn } = require('child_process');
1120
+ const serverScript = require('path').resolve(__dirname, '../visualize/server.js');
1121
+ const child = spawn(process.execPath, [
1122
+ serverScript,
1123
+ '--project', args.projectName,
1124
+ '--port', String(port),
1125
+ ], {
1126
+ detached: true,
1127
+ stdio: 'ignore',
1128
+ });
1129
+ child.unref();
1130
+ const url = `http://localhost:${port}`;
1131
+ // 尝试自动打开浏览器
1132
+ const platform = process.platform;
1133
+ let openCmd;
1134
+ let openArgs;
1135
+ if (platform === 'win32') {
1136
+ openCmd = 'cmd';
1137
+ openArgs = ['/c', 'start', '', url];
1138
+ }
1139
+ else if (platform === 'darwin') {
1140
+ openCmd = 'open';
1141
+ openArgs = [url];
1142
+ }
1143
+ else {
1144
+ openCmd = 'xdg-open';
1145
+ openArgs = [url];
1146
+ }
1147
+ const browser = spawn(openCmd, openArgs, {
1148
+ detached: true,
1149
+ stdio: 'ignore',
1150
+ });
1151
+ browser.unref();
1152
+ return JSON.stringify({
1153
+ success: true,
1154
+ projectName: args.projectName,
1155
+ port,
1156
+ url,
1157
+ pid: child.pid,
1158
+ message: `Visualization server started at ${url} (PID: ${child.pid}). Browser should open automatically. Use Ctrl+Click to drag connected nodes together.`,
1159
+ });
1160
+ }
1161
+ catch (err) {
1162
+ throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
1163
+ }
1164
+ }
953
1165
  default:
954
1166
  throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
955
1167
  }