aifastdb-devplan 1.6.2 → 1.6.3
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/dist/dev-plan-factory.d.ts.map +1 -1
- package/dist/dev-plan-factory.js +2 -1
- package/dist/dev-plan-factory.js.map +1 -1
- package/dist/dev-plan-graph-store.d.ts +278 -9
- package/dist/dev-plan-graph-store.d.ts.map +1 -1
- package/dist/dev-plan-graph-store.js +2057 -215
- package/dist/dev-plan-graph-store.js.map +1 -1
- package/dist/dev-plan-interface.d.ts +96 -1
- package/dist/dev-plan-interface.d.ts.map +1 -1
- package/dist/mcp-server/index.js +533 -0
- package/dist/mcp-server/index.js.map +1 -1
- package/dist/shard-config.d.ts +64 -0
- package/dist/shard-config.d.ts.map +1 -0
- package/dist/shard-config.js +109 -0
- package/dist/shard-config.js.map +1 -0
- package/dist/types.d.ts +218 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/visualize/graph-canvas/styles.d.ts.map +1 -1
- package/dist/visualize/graph-canvas/styles.js +10 -0
- package/dist/visualize/graph-canvas/styles.js.map +1 -1
- package/dist/visualize/server.js +222 -0
- package/dist/visualize/server.js.map +1 -1
- package/dist/visualize/template-core.d.ts.map +1 -1
- package/dist/visualize/template-core.js +13 -6
- package/dist/visualize/template-core.js.map +1 -1
- package/dist/visualize/template-detail-panel.d.ts.map +1 -1
- package/dist/visualize/template-detail-panel.js +74 -3
- package/dist/visualize/template-detail-panel.js.map +1 -1
- package/dist/visualize/template-graph-3d.d.ts.map +1 -1
- package/dist/visualize/template-graph-3d.js +4 -2
- package/dist/visualize/template-graph-3d.js.map +1 -1
- package/dist/visualize/template-graph-vis.d.ts.map +1 -1
- package/dist/visualize/template-graph-vis.js +13 -2
- package/dist/visualize/template-graph-vis.js.map +1 -1
- package/dist/visualize/template-html.d.ts +1 -1
- package/dist/visualize/template-html.d.ts.map +1 -1
- package/dist/visualize/template-html.js +153 -2
- package/dist/visualize/template-html.js.map +1 -1
- package/dist/visualize/template-md-viewer.d.ts +11 -0
- package/dist/visualize/template-md-viewer.d.ts.map +1 -0
- package/dist/visualize/template-md-viewer.js +806 -0
- package/dist/visualize/template-md-viewer.js.map +1 -0
- package/dist/visualize/template-pages.d.ts.map +1 -1
- package/dist/visualize/template-pages.js +1087 -1
- package/dist/visualize/template-pages.js.map +1 -1
- package/dist/visualize/template-stats-modal.d.ts.map +1 -1
- package/dist/visualize/template-stats-modal.js +70 -10
- package/dist/visualize/template-stats-modal.js.map +1 -1
- package/dist/visualize/template-styles.d.ts.map +1 -1
- package/dist/visualize/template-styles.js +137 -1
- package/dist/visualize/template-styles.js.map +1 -1
- package/dist/visualize/template.d.ts +1 -0
- package/dist/visualize/template.d.ts.map +1 -1
- package/dist/visualize/template.js +6 -0
- package/dist/visualize/template.js.map +1 -1
- package/package.json +2 -2
package/dist/mcp-server/index.js
CHANGED
|
@@ -456,6 +456,38 @@ const TOOLS = [
|
|
|
456
456
|
required: ['projectName'],
|
|
457
457
|
},
|
|
458
458
|
},
|
|
459
|
+
{
|
|
460
|
+
name: 'devplan_cleanup_duplicates',
|
|
461
|
+
description: 'Phase-21: Scan and cleanup duplicate entities in the WAL. Deduplicates main tasks (by taskId), sub-tasks (by taskId), modules (by moduleId), and documents (by section+subSection). Keeps the entity with the highest status priority (completed > in_progress > pending > cancelled) and latest updatedAt. Use dryRun=true to preview without changes.\nPhase-21: 扫描并清理 WAL 中的重复 Entity。按业务键去重(mainTask 按 taskId,subTask 按 taskId,module 按 moduleId,doc 按 section+subSection)。保留状态优先级最高 + updatedAt 最新的 Entity。使用 dryRun=true 可预览而不实际修改。',
|
|
462
|
+
inputSchema: {
|
|
463
|
+
type: 'object',
|
|
464
|
+
properties: {
|
|
465
|
+
projectName: {
|
|
466
|
+
type: 'string',
|
|
467
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
468
|
+
},
|
|
469
|
+
dryRun: {
|
|
470
|
+
type: 'boolean',
|
|
471
|
+
description: 'If true, only report which duplicates would be cleaned without actually deleting them (default: false)\n为 true 时仅报告哪些重复 Entity 会被清理,不实际删除(默认 false)',
|
|
472
|
+
},
|
|
473
|
+
},
|
|
474
|
+
required: ['projectName'],
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
{
|
|
478
|
+
name: 'devplan_repair_counts',
|
|
479
|
+
description: 'Phase-45: Repair all main task sub-task counts and auto-complete status. Recalculates totalSubtasks/completedSubtasks from actual sub-task data and auto-completes main tasks where all sub-tasks are done but status is still in_progress. Fixes data inconsistencies caused by updateEntity routing issues.\nPhase-45: 修复所有主任务的子任务计数和自动完成状态。从实际子任务数据重新计算 totalSubtasks/completedSubtasks,并自动完成所有子任务已完成但状态仍为 in_progress 的主任务。修复因 updateEntity 路由问题导致的数据不一致。',
|
|
480
|
+
inputSchema: {
|
|
481
|
+
type: 'object',
|
|
482
|
+
properties: {
|
|
483
|
+
projectName: {
|
|
484
|
+
type: 'string',
|
|
485
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
required: ['projectName'],
|
|
489
|
+
},
|
|
490
|
+
},
|
|
459
491
|
{
|
|
460
492
|
name: 'devplan_create_module',
|
|
461
493
|
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")。主任务和文档可以关联到模块。',
|
|
@@ -813,6 +845,253 @@ const TOOLS = [
|
|
|
813
845
|
required: ['projectName'],
|
|
814
846
|
},
|
|
815
847
|
},
|
|
848
|
+
// ========================================================================
|
|
849
|
+
// Memory Tools (Cursor 长期记忆)
|
|
850
|
+
// ========================================================================
|
|
851
|
+
{
|
|
852
|
+
name: 'devplan_memory_save',
|
|
853
|
+
description: 'Save a memory entry to the dev plan for long-term Cursor context. Memories are automatically embedded for semantic recall. Types: decision (architecture decisions), pattern (code patterns), bugfix (bug fixes), insight (learnings), preference (user/project preferences), summary (session summaries).\n保存一条记忆到开发计划,为 Cursor 提供长期上下文。记忆会自动向量化以支持语义召回。类型:decision(架构决策)、pattern(代码模式)、bugfix(Bug修复)、insight(开发洞察)、preference(偏好约定)、summary(会话摘要)。',
|
|
854
|
+
inputSchema: {
|
|
855
|
+
type: 'object',
|
|
856
|
+
properties: {
|
|
857
|
+
projectName: {
|
|
858
|
+
type: 'string',
|
|
859
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
860
|
+
},
|
|
861
|
+
memoryType: {
|
|
862
|
+
type: 'string',
|
|
863
|
+
enum: ['decision', 'pattern', 'bugfix', 'insight', 'preference', 'summary'],
|
|
864
|
+
description: 'Memory type\n记忆类型',
|
|
865
|
+
},
|
|
866
|
+
content: {
|
|
867
|
+
type: 'string',
|
|
868
|
+
description: 'Memory content (Markdown supported)\n记忆内容(支持 Markdown)',
|
|
869
|
+
},
|
|
870
|
+
tags: {
|
|
871
|
+
type: 'array',
|
|
872
|
+
items: { type: 'string' },
|
|
873
|
+
description: 'Optional: Custom tags for categorization\n可选:分类标签',
|
|
874
|
+
},
|
|
875
|
+
relatedTaskId: {
|
|
876
|
+
type: 'string',
|
|
877
|
+
description: 'Optional: Related main task ID (e.g., "phase-24")\n可选:关联的主任务 ID',
|
|
878
|
+
},
|
|
879
|
+
importance: {
|
|
880
|
+
type: 'number',
|
|
881
|
+
description: 'Optional: Importance score 0~1 (default: 0.5)\n可选:重要性评分 0~1(默认 0.5)',
|
|
882
|
+
},
|
|
883
|
+
sourceId: {
|
|
884
|
+
type: 'string',
|
|
885
|
+
description: 'Optional: Source ID tracking which document/task this memory was generated from. Used by devplan_memory_generate for dedup. Format: taskId (e.g., "phase-7") or "section|subSection" (e.g., "overview", "technical_notes|security"). **IMPORTANT**: When saving memories from devplan_memory_generate candidates, ALWAYS pass the candidate\'s `sourceId` field here to enable proper dedup tracking.\n可选:记忆来源 ID,标记该记忆由哪个文档/任务生成。用于 devplan_memory_generate 的去重。格式:taskId(如 "phase-7")或 "section|subSection"(如 "overview")。**重要**:从 devplan_memory_generate 候选项保存记忆时,务必传入候选项的 sourceId 以启用去重追踪。',
|
|
886
|
+
},
|
|
887
|
+
moduleId: {
|
|
888
|
+
type: 'string',
|
|
889
|
+
description: 'Optional: Associate with a feature module (e.g., "vector-store"). Automatically creates MODULE_MEMORY relation to integrate the memory into the module-level knowledge graph.\n可选:关联到功能模块(如 "vector-store")。自动创建 MODULE_MEMORY 关系,将记忆融入模块级知识图谱。',
|
|
890
|
+
},
|
|
891
|
+
},
|
|
892
|
+
required: ['projectName', 'memoryType', 'content'],
|
|
893
|
+
},
|
|
894
|
+
},
|
|
895
|
+
{
|
|
896
|
+
name: 'devplan_memory_recall',
|
|
897
|
+
description: 'Intelligently recall memories relevant to a query using semantic vector search. Automatically updates hit counts for recalled memories. Falls back to literal matching when semantic search is unavailable.\n通过语义向量搜索智能召回与查询相关的记忆。自动更新被召回记忆的命中次数。语义搜索不可用时退化为字面匹配。\n\n**Unified Recall (统一召回)**: By default, also searches document sections and merges results via RRF fusion. Each result includes `sourceKind` ("memory" or "doc") to indicate its origin. Set `includeDocs=false` to search memories only.',
|
|
898
|
+
inputSchema: {
|
|
899
|
+
type: 'object',
|
|
900
|
+
properties: {
|
|
901
|
+
projectName: {
|
|
902
|
+
type: 'string',
|
|
903
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
904
|
+
},
|
|
905
|
+
query: {
|
|
906
|
+
type: 'string',
|
|
907
|
+
description: 'Search query text\n搜索查询文本',
|
|
908
|
+
},
|
|
909
|
+
memoryType: {
|
|
910
|
+
type: 'string',
|
|
911
|
+
enum: ['decision', 'pattern', 'bugfix', 'insight', 'preference', 'summary'],
|
|
912
|
+
description: 'Optional: Filter by memory type\n可选:按记忆类型过滤',
|
|
913
|
+
},
|
|
914
|
+
limit: {
|
|
915
|
+
type: 'number',
|
|
916
|
+
description: 'Optional: Maximum results (default: 10)\n可选:最大返回数(默认 10)',
|
|
917
|
+
},
|
|
918
|
+
minScore: {
|
|
919
|
+
type: 'number',
|
|
920
|
+
description: 'Optional: Minimum relevance score 0~1 (default: 0)\n可选:最低相关性评分(默认 0)',
|
|
921
|
+
},
|
|
922
|
+
includeDocs: {
|
|
923
|
+
type: 'boolean',
|
|
924
|
+
description: 'Whether to include document sections in recall results via unified search (default: true). Set to false to search memories only.\n是否通过统一召回包含文档搜索结果(默认 true)。设为 false 仅搜索记忆。',
|
|
925
|
+
},
|
|
926
|
+
graphExpand: {
|
|
927
|
+
type: 'boolean',
|
|
928
|
+
description: 'Whether to expand results via MEMORY_RELATES graph traversal (default: true). When enabled, related memories connected through the memory network are also discovered and RRF-fused with vector results.\n是否通过 MEMORY_RELATES 图谱遍历扩展结果(默认 true)。启用时,通过记忆网络关联的记忆也会被发现并与向量结果 RRF 融合。',
|
|
929
|
+
},
|
|
930
|
+
},
|
|
931
|
+
required: ['projectName', 'query'],
|
|
932
|
+
},
|
|
933
|
+
},
|
|
934
|
+
{
|
|
935
|
+
name: 'devplan_memory_list',
|
|
936
|
+
description: 'List saved memories with optional filters.\n列出已保存的记忆,支持过滤。',
|
|
937
|
+
inputSchema: {
|
|
938
|
+
type: 'object',
|
|
939
|
+
properties: {
|
|
940
|
+
projectName: {
|
|
941
|
+
type: 'string',
|
|
942
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
943
|
+
},
|
|
944
|
+
memoryType: {
|
|
945
|
+
type: 'string',
|
|
946
|
+
enum: ['decision', 'pattern', 'bugfix', 'insight', 'preference', 'summary'],
|
|
947
|
+
description: 'Optional: Filter by memory type\n可选:按记忆类型过滤',
|
|
948
|
+
},
|
|
949
|
+
relatedTaskId: {
|
|
950
|
+
type: 'string',
|
|
951
|
+
description: 'Optional: Filter by related task ID\n可选:按关联任务 ID 过滤',
|
|
952
|
+
},
|
|
953
|
+
limit: {
|
|
954
|
+
type: 'number',
|
|
955
|
+
description: 'Optional: Maximum results (default: all)\n可选:最大返回数(默认全部)',
|
|
956
|
+
},
|
|
957
|
+
},
|
|
958
|
+
required: ['projectName'],
|
|
959
|
+
},
|
|
960
|
+
},
|
|
961
|
+
{
|
|
962
|
+
name: 'devplan_memory_delete',
|
|
963
|
+
description: 'Delete a specific memory entry by ID.\n按 ID 删除一条记忆。',
|
|
964
|
+
inputSchema: {
|
|
965
|
+
type: 'object',
|
|
966
|
+
properties: {
|
|
967
|
+
projectName: {
|
|
968
|
+
type: 'string',
|
|
969
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
970
|
+
},
|
|
971
|
+
memoryId: {
|
|
972
|
+
type: 'string',
|
|
973
|
+
description: 'Memory ID to delete\n要删除的记忆 ID',
|
|
974
|
+
},
|
|
975
|
+
},
|
|
976
|
+
required: ['projectName', 'memoryId'],
|
|
977
|
+
},
|
|
978
|
+
},
|
|
979
|
+
{
|
|
980
|
+
name: 'devplan_memory_clear',
|
|
981
|
+
description: 'Batch clear all memories for a project. Optionally filter by memoryType. Use this before re-importing memories with the fixed batch generator.\n批量清除项目的所有记忆。可选按 memoryType 过滤。用于重新导入记忆前的清理。',
|
|
982
|
+
inputSchema: {
|
|
983
|
+
type: 'object',
|
|
984
|
+
properties: {
|
|
985
|
+
projectName: {
|
|
986
|
+
type: 'string',
|
|
987
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
988
|
+
},
|
|
989
|
+
memoryType: {
|
|
990
|
+
type: 'string',
|
|
991
|
+
enum: ['decision', 'pattern', 'bugfix', 'insight', 'preference', 'summary'],
|
|
992
|
+
description: 'Optional: Only clear memories of this type. Omit to clear ALL memories.\n可选:仅清除指定类型的记忆。省略则清除全部。',
|
|
993
|
+
},
|
|
994
|
+
confirm: {
|
|
995
|
+
type: 'boolean',
|
|
996
|
+
description: 'Must be true to confirm deletion. Safety guard.\n必须为 true 以确认删除操作。安全保护。',
|
|
997
|
+
},
|
|
998
|
+
},
|
|
999
|
+
required: ['projectName', 'confirm'],
|
|
1000
|
+
},
|
|
1001
|
+
},
|
|
1002
|
+
{
|
|
1003
|
+
name: 'devplan_memory_clusters',
|
|
1004
|
+
description: 'Get memory topic clusters based on MEMORY_RELATES graph connectivity. Automatically groups semantically related memories into themed clusters using connected component analysis. Returns cluster themes, member counts, and memory summaries.\n基于 MEMORY_RELATES 图谱连通性获取记忆主题集群。自动将语义关联的记忆按连通分量聚合为主题集群。返回集群主题、成员数量和记忆摘要。',
|
|
1005
|
+
inputSchema: {
|
|
1006
|
+
type: 'object',
|
|
1007
|
+
properties: {
|
|
1008
|
+
projectName: {
|
|
1009
|
+
type: 'string',
|
|
1010
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
1011
|
+
},
|
|
1012
|
+
},
|
|
1013
|
+
required: ['projectName'],
|
|
1014
|
+
},
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
name: 'devplan_memory_context',
|
|
1018
|
+
description: 'Get comprehensive project context for a new Cursor session. Aggregates recent tasks, relevant memories (via semantic search), project preferences, and recent decisions. This is the PRIMARY tool for session initialization.\n获取新 Cursor 会话的综合项目上下文。聚合最近任务、相关记忆(语义搜索)、项目偏好和最近决策。这是会话初始化的核心工具。\n\n**Unified Recall**: When a query is provided, automatically searches both memories AND documents, returning merged results. Also includes `relatedDocs` field with key document summaries (overview, core_concepts).',
|
|
1019
|
+
inputSchema: {
|
|
1020
|
+
type: 'object',
|
|
1021
|
+
properties: {
|
|
1022
|
+
projectName: {
|
|
1023
|
+
type: 'string',
|
|
1024
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
1025
|
+
},
|
|
1026
|
+
query: {
|
|
1027
|
+
type: 'string',
|
|
1028
|
+
description: 'Optional: Query text for semantic memory recall\n可选:用于语义召回的查询文本',
|
|
1029
|
+
},
|
|
1030
|
+
maxMemories: {
|
|
1031
|
+
type: 'number',
|
|
1032
|
+
description: 'Optional: Maximum memories to include (default: 10)\n可选:最大记忆数(默认 10)',
|
|
1033
|
+
},
|
|
1034
|
+
},
|
|
1035
|
+
required: ['projectName'],
|
|
1036
|
+
},
|
|
1037
|
+
},
|
|
1038
|
+
{
|
|
1039
|
+
name: 'devplan_memory_generate',
|
|
1040
|
+
description: 'Generate memory candidates from existing documents and completed tasks. Returns structured candidates that the AI can review and selectively save as memories via devplan_memory_save. This tool aggregates raw data; the AI provides the intelligence to extract meaningful memories.\n从已有文档和已完成任务中生成记忆候选项。返回结构化候选项供 AI 审查后通过 devplan_memory_save 批量保存为记忆。此工具聚合原始数据,AI 负责提取有意义的记忆。\n\n**Batch AI Workflow (批量 AI 处理工作流)**:\nWhen user says "批量生成记忆" / "全量导入记忆" / "batch generate memories":\n1. Call this tool with limit=5 to get a small batch\n2. For EACH candidate: read its content, extract 1-3 key insights, determine the best memoryType\n3. Call devplan_memory_save for each with AI-refined content (concise, 1-3 sentences), **MUST pass sourceId from candidate.sourceId**\n4. Check stats.remaining — if > 0, repeat from step 1\n5. Continue until remaining === 0\n\n**Memory Tree / suggestedRelations (记忆树 / 建议关联)**:\nEach candidate may include a `suggestedRelations` array with `{ targetSourceId, relationType, weight, reason }` entries.\nThese represent inferred connections between candidates (e.g., task→doc DERIVED_FROM, consecutive phases TEMPORAL_NEXT, same-module RELATES).\n`targetSourceId` references another candidate\'s `sourceId`. After saving all memories, map sourceId→entityId and build relations via the graph.\nThis transforms flat memories into a connected Memory Tree graph.\n\n**CRITICAL — sourceId dedup tracking**: Each candidate has a `sourceId` field (e.g., "phase-7" for tasks, "overview" or "technical_notes|security" for docs). When calling devplan_memory_save, you MUST pass `sourceId: candidate.sourceId` so that subsequent calls to devplan_memory_generate can skip already-processed sources. Without sourceId, the same candidates will keep appearing.\n\nThe stats.remaining field tells how many more eligible candidates exist beyond the current batch.',
|
|
1041
|
+
inputSchema: {
|
|
1042
|
+
type: 'object',
|
|
1043
|
+
properties: {
|
|
1044
|
+
projectName: {
|
|
1045
|
+
type: 'string',
|
|
1046
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
1047
|
+
},
|
|
1048
|
+
source: {
|
|
1049
|
+
type: 'string',
|
|
1050
|
+
enum: ['tasks', 'docs', 'both'],
|
|
1051
|
+
description: 'Data source: "tasks" for completed phases, "docs" for documents, "both" for all (default: "both")\n数据源:"tasks" 已完成阶段、"docs" 文档、"both" 全部(默认 "both")',
|
|
1052
|
+
},
|
|
1053
|
+
taskId: {
|
|
1054
|
+
type: 'string',
|
|
1055
|
+
description: 'Optional: Extract from a specific phase only (e.g., "phase-7")\n可选:仅从指定阶段提取(如 "phase-7")',
|
|
1056
|
+
},
|
|
1057
|
+
section: {
|
|
1058
|
+
type: 'string',
|
|
1059
|
+
description: 'Optional: Extract from a specific document section only\n可选:仅从指定文档章节提取',
|
|
1060
|
+
},
|
|
1061
|
+
subSection: {
|
|
1062
|
+
type: 'string',
|
|
1063
|
+
description: 'Optional: Extract from a specific document sub-section\n可选:仅从指定子章节提取',
|
|
1064
|
+
},
|
|
1065
|
+
limit: {
|
|
1066
|
+
type: 'number',
|
|
1067
|
+
description: 'Optional: Maximum candidates to return (default: 50). For AI batch workflow, use limit=5 to process in small batches. stats.remaining shows how many more are available.\n可选:最大候选项数(默认 50)。AI 批量工作流建议用 limit=5 分小批处理。stats.remaining 显示剩余待处理数。',
|
|
1068
|
+
},
|
|
1069
|
+
},
|
|
1070
|
+
required: ['projectName'],
|
|
1071
|
+
},
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
name: 'devplan_memory_lifecycle',
|
|
1075
|
+
description: 'Run memory lifecycle management scan using DynamicNode promote/demote. Long-idle memories are demoted to shadow state (excluded from vector search but preserved in graph). Re-accessed memories are auto-promoted back. This implements biological memory forgetting and reinforcement.\n运行记忆生命周期管理扫描。长期未访问的记忆降级为 shadow 状态(不参与向量搜索但保留在图谱中),被重新访问时自动恢复。实现生物记忆的遗忘与强化机制。',
|
|
1076
|
+
inputSchema: {
|
|
1077
|
+
type: 'object',
|
|
1078
|
+
properties: {
|
|
1079
|
+
projectName: {
|
|
1080
|
+
type: 'string',
|
|
1081
|
+
description: `Project name (default: "${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")\n项目名称(默认:"${dev_plan_factory_1.DEFAULT_PROJECT_NAME}")`,
|
|
1082
|
+
},
|
|
1083
|
+
demoteIdleTimeoutSecs: {
|
|
1084
|
+
type: 'number',
|
|
1085
|
+
description: 'Idle seconds before demotion to shadow (default: 2592000 = 30 days)\n降级前的闲置秒数(默认 2592000 = 30 天)',
|
|
1086
|
+
},
|
|
1087
|
+
promoteHitThreshold: {
|
|
1088
|
+
type: 'number',
|
|
1089
|
+
description: 'Minimum hit count to promote from shadow (default: 3)\n从 shadow 恢复的最低命中次数(默认 3)',
|
|
1090
|
+
},
|
|
1091
|
+
},
|
|
1092
|
+
required: ['projectName'],
|
|
1093
|
+
},
|
|
1094
|
+
},
|
|
816
1095
|
];
|
|
817
1096
|
/**
|
|
818
1097
|
* 解析 projectName
|
|
@@ -1014,6 +1293,7 @@ async function handleToolCall(name, args) {
|
|
|
1014
1293
|
}
|
|
1015
1294
|
const plan = getDevPlan(args.projectName);
|
|
1016
1295
|
try {
|
|
1296
|
+
// Phase-23: createMainTask 内部已幂等处理(upsertEntityByProp),无需额外检查
|
|
1017
1297
|
const mainTask = plan.createMainTask({
|
|
1018
1298
|
projectName: args.projectName,
|
|
1019
1299
|
taskId: args.taskId,
|
|
@@ -1047,6 +1327,7 @@ async function handleToolCall(name, args) {
|
|
|
1047
1327
|
}
|
|
1048
1328
|
const plan = getDevPlan(args.projectName);
|
|
1049
1329
|
try {
|
|
1330
|
+
// Phase-23: addSubTask 内部已幂等处理(upsertEntityByProp),无需额外检查
|
|
1050
1331
|
const subTask = plan.addSubTask({
|
|
1051
1332
|
projectName: args.projectName,
|
|
1052
1333
|
taskId: args.taskId,
|
|
@@ -1366,6 +1647,57 @@ async function handleToolCall(name, args) {
|
|
|
1366
1647
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
|
|
1367
1648
|
}
|
|
1368
1649
|
}
|
|
1650
|
+
case 'devplan_cleanup_duplicates': {
|
|
1651
|
+
if (!args.projectName) {
|
|
1652
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: projectName');
|
|
1653
|
+
}
|
|
1654
|
+
const plan = getDevPlan(args.projectName);
|
|
1655
|
+
const dryRun = args.dryRun ?? false;
|
|
1656
|
+
if (typeof plan.cleanupDuplicates !== 'function') {
|
|
1657
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Duplicate cleanup requires "graph" engine. Project "${args.projectName}" uses a different engine.`);
|
|
1658
|
+
}
|
|
1659
|
+
try {
|
|
1660
|
+
const result = plan.cleanupDuplicates(dryRun);
|
|
1661
|
+
return JSON.stringify({
|
|
1662
|
+
success: true,
|
|
1663
|
+
dryRun,
|
|
1664
|
+
cleaned: result.cleaned,
|
|
1665
|
+
details: result.details,
|
|
1666
|
+
summary: result.cleaned === 0
|
|
1667
|
+
? '✅ No duplicate entities found. WAL is clean.'
|
|
1668
|
+
: dryRun
|
|
1669
|
+
? `⚠️ Found ${result.cleaned} duplicate entities (dry run, no changes made)`
|
|
1670
|
+
: `🧹 Cleaned ${result.cleaned} duplicate entities from WAL`,
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
catch (err) {
|
|
1674
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
case 'devplan_repair_counts': {
|
|
1678
|
+
if (!args.projectName) {
|
|
1679
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: projectName');
|
|
1680
|
+
}
|
|
1681
|
+
const plan = getDevPlan(args.projectName);
|
|
1682
|
+
if (typeof plan.repairAllMainTaskCounts !== 'function') {
|
|
1683
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Repair counts requires "graph" engine. Project "${args.projectName}" uses a different engine.`);
|
|
1684
|
+
}
|
|
1685
|
+
try {
|
|
1686
|
+
const result = plan.repairAllMainTaskCounts();
|
|
1687
|
+
return JSON.stringify({
|
|
1688
|
+
success: true,
|
|
1689
|
+
repaired: result.repaired,
|
|
1690
|
+
autoCompleted: result.autoCompleted,
|
|
1691
|
+
details: result.details,
|
|
1692
|
+
summary: result.repaired === 0
|
|
1693
|
+
? '✅ All main task counts are correct. No repair needed.'
|
|
1694
|
+
: `🔧 Repaired ${result.repaired} main tasks (${result.autoCompleted} auto-completed)`,
|
|
1695
|
+
});
|
|
1696
|
+
}
|
|
1697
|
+
catch (err) {
|
|
1698
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, err instanceof Error ? err.message : String(err));
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1369
1701
|
case 'devplan_create_module': {
|
|
1370
1702
|
if (!args.projectName || !args.moduleId || !args.name) {
|
|
1371
1703
|
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: projectName, moduleId, name');
|
|
@@ -1825,6 +2157,207 @@ async function handleToolCall(name, args) {
|
|
|
1825
2157
|
prompts,
|
|
1826
2158
|
}, null, 2);
|
|
1827
2159
|
}
|
|
2160
|
+
// ==================================================================
|
|
2161
|
+
// Memory Tools (Cursor 长期记忆)
|
|
2162
|
+
// ==================================================================
|
|
2163
|
+
case 'devplan_memory_save': {
|
|
2164
|
+
const projectName = args.projectName;
|
|
2165
|
+
const content = args.content;
|
|
2166
|
+
const memoryType = args.memoryType;
|
|
2167
|
+
if (!content) {
|
|
2168
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: content');
|
|
2169
|
+
}
|
|
2170
|
+
if (!memoryType) {
|
|
2171
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: memoryType');
|
|
2172
|
+
}
|
|
2173
|
+
const validTypes = ['decision', 'pattern', 'bugfix', 'insight', 'preference', 'summary'];
|
|
2174
|
+
if (!validTypes.includes(memoryType)) {
|
|
2175
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Invalid memoryType: "${memoryType}". Must be one of: ${validTypes.join(', ')}`);
|
|
2176
|
+
}
|
|
2177
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2178
|
+
if (typeof plan.saveMemory !== 'function') {
|
|
2179
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory features require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2180
|
+
}
|
|
2181
|
+
const memory = plan.saveMemory({
|
|
2182
|
+
projectName,
|
|
2183
|
+
content,
|
|
2184
|
+
memoryType: memoryType,
|
|
2185
|
+
importance: args.importance,
|
|
2186
|
+
tags: args.tags,
|
|
2187
|
+
relatedTaskId: args.relatedTaskId,
|
|
2188
|
+
sourceId: args.sourceId,
|
|
2189
|
+
moduleId: args.moduleId,
|
|
2190
|
+
source: args.source || 'cursor',
|
|
2191
|
+
});
|
|
2192
|
+
return JSON.stringify({
|
|
2193
|
+
status: 'saved',
|
|
2194
|
+
memory,
|
|
2195
|
+
}, null, 2);
|
|
2196
|
+
}
|
|
2197
|
+
case 'devplan_memory_recall': {
|
|
2198
|
+
const projectName = args.projectName;
|
|
2199
|
+
const query = args.query;
|
|
2200
|
+
if (!query) {
|
|
2201
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: query');
|
|
2202
|
+
}
|
|
2203
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2204
|
+
if (typeof plan.recallMemory !== 'function') {
|
|
2205
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory features require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2206
|
+
}
|
|
2207
|
+
const includeDocs = args.includeDocs !== undefined ? args.includeDocs : true;
|
|
2208
|
+
const graphExpand = args.graphExpand !== undefined ? args.graphExpand : true;
|
|
2209
|
+
const memories = plan.recallMemory(query, {
|
|
2210
|
+
memoryType: args.memoryType,
|
|
2211
|
+
limit: args.limit,
|
|
2212
|
+
minScore: args.minScore,
|
|
2213
|
+
includeDocs,
|
|
2214
|
+
graphExpand,
|
|
2215
|
+
});
|
|
2216
|
+
// 统计来源分布
|
|
2217
|
+
const memoryCount = memories.filter((m) => m.sourceKind === 'memory' || !m.sourceKind).length;
|
|
2218
|
+
const docCount = memories.filter((m) => m.sourceKind === 'doc').length;
|
|
2219
|
+
return JSON.stringify({
|
|
2220
|
+
projectName,
|
|
2221
|
+
query,
|
|
2222
|
+
count: memories.length,
|
|
2223
|
+
memoryCount,
|
|
2224
|
+
docCount,
|
|
2225
|
+
unifiedRecall: includeDocs,
|
|
2226
|
+
memories,
|
|
2227
|
+
}, null, 2);
|
|
2228
|
+
}
|
|
2229
|
+
case 'devplan_memory_list': {
|
|
2230
|
+
const projectName = args.projectName;
|
|
2231
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2232
|
+
if (typeof plan.listMemories !== 'function') {
|
|
2233
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory features require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2234
|
+
}
|
|
2235
|
+
const memories = plan.listMemories({
|
|
2236
|
+
memoryType: args.memoryType,
|
|
2237
|
+
limit: args.limit,
|
|
2238
|
+
});
|
|
2239
|
+
return JSON.stringify({
|
|
2240
|
+
projectName,
|
|
2241
|
+
count: memories.length,
|
|
2242
|
+
filter: {
|
|
2243
|
+
memoryType: args.memoryType || null,
|
|
2244
|
+
limit: args.limit || null,
|
|
2245
|
+
},
|
|
2246
|
+
memories,
|
|
2247
|
+
}, null, 2);
|
|
2248
|
+
}
|
|
2249
|
+
case 'devplan_memory_delete': {
|
|
2250
|
+
const projectName = args.projectName;
|
|
2251
|
+
const memoryId = args.memoryId;
|
|
2252
|
+
if (!memoryId) {
|
|
2253
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing required: memoryId');
|
|
2254
|
+
}
|
|
2255
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2256
|
+
if (typeof plan.deleteMemory !== 'function') {
|
|
2257
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory features require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2258
|
+
}
|
|
2259
|
+
const success = plan.deleteMemory(memoryId);
|
|
2260
|
+
return JSON.stringify({
|
|
2261
|
+
status: success ? 'deleted' : 'not_found',
|
|
2262
|
+
memoryId,
|
|
2263
|
+
}, null, 2);
|
|
2264
|
+
}
|
|
2265
|
+
case 'devplan_memory_clear': {
|
|
2266
|
+
const projectName = args.projectName;
|
|
2267
|
+
const confirm = args.confirm;
|
|
2268
|
+
if (confirm !== true) {
|
|
2269
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Safety guard: confirm must be true to clear memories. Set confirm: true to proceed.');
|
|
2270
|
+
}
|
|
2271
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2272
|
+
if (typeof plan.clearAllMemories !== 'function') {
|
|
2273
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory features require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2274
|
+
}
|
|
2275
|
+
const memoryType = args.memoryType;
|
|
2276
|
+
const result = plan.clearAllMemories(memoryType);
|
|
2277
|
+
return JSON.stringify({
|
|
2278
|
+
status: 'cleared',
|
|
2279
|
+
...result,
|
|
2280
|
+
memoryType: memoryType || 'all',
|
|
2281
|
+
projectName,
|
|
2282
|
+
}, null, 2);
|
|
2283
|
+
}
|
|
2284
|
+
case 'devplan_memory_clusters': {
|
|
2285
|
+
const projectName = args.projectName;
|
|
2286
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2287
|
+
if (typeof plan.getMemoryClusters !== 'function') {
|
|
2288
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory clusters require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2289
|
+
}
|
|
2290
|
+
const clusters = plan.getMemoryClusters();
|
|
2291
|
+
const totalMemories = clusters.reduce((sum, c) => sum + c.memoryCount, 0);
|
|
2292
|
+
return JSON.stringify({
|
|
2293
|
+
projectName,
|
|
2294
|
+
totalClusters: clusters.length,
|
|
2295
|
+
totalMemories,
|
|
2296
|
+
clusters: clusters.map((c) => ({
|
|
2297
|
+
clusterId: c.clusterId,
|
|
2298
|
+
theme: c.theme,
|
|
2299
|
+
memoryCount: c.memoryCount,
|
|
2300
|
+
topMemoryTypes: c.topMemoryTypes,
|
|
2301
|
+
memories: c.memories.map((m) => ({
|
|
2302
|
+
id: m.id,
|
|
2303
|
+
memoryType: m.memoryType,
|
|
2304
|
+
content: m.content.length > 100 ? m.content.slice(0, 100) + '...' : m.content,
|
|
2305
|
+
importance: m.importance,
|
|
2306
|
+
tags: m.tags,
|
|
2307
|
+
})),
|
|
2308
|
+
})),
|
|
2309
|
+
}, null, 2);
|
|
2310
|
+
}
|
|
2311
|
+
case 'devplan_memory_context': {
|
|
2312
|
+
const projectName = args.projectName;
|
|
2313
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2314
|
+
if (typeof plan.getMemoryContext !== 'function') {
|
|
2315
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory features require "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2316
|
+
}
|
|
2317
|
+
const context = plan.getMemoryContext(args.query, args.maxMemories);
|
|
2318
|
+
return JSON.stringify({
|
|
2319
|
+
projectName,
|
|
2320
|
+
context,
|
|
2321
|
+
}, null, 2);
|
|
2322
|
+
}
|
|
2323
|
+
case 'devplan_memory_generate': {
|
|
2324
|
+
const projectName = args.projectName;
|
|
2325
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2326
|
+
if (typeof plan.generateMemoryCandidates !== 'function') {
|
|
2327
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory generation requires "graph" engine. Project "${projectName}" uses a different engine.`);
|
|
2328
|
+
}
|
|
2329
|
+
const result = plan.generateMemoryCandidates({
|
|
2330
|
+
source: args.source,
|
|
2331
|
+
taskId: args.taskId,
|
|
2332
|
+
section: args.section,
|
|
2333
|
+
subSection: args.subSection,
|
|
2334
|
+
limit: args.limit,
|
|
2335
|
+
});
|
|
2336
|
+
return JSON.stringify(result, null, 2);
|
|
2337
|
+
}
|
|
2338
|
+
case 'devplan_memory_lifecycle': {
|
|
2339
|
+
const projectName = args.projectName;
|
|
2340
|
+
const plan = (0, dev_plan_factory_1.createDevPlan)(projectName);
|
|
2341
|
+
if (typeof plan.runMemoryLifecycle !== 'function') {
|
|
2342
|
+
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, `Memory lifecycle requires "graph" engine with dynamicScan support. Project "${projectName}" may use a different engine or older aifastdb version.`);
|
|
2343
|
+
}
|
|
2344
|
+
const report = plan.runMemoryLifecycle({
|
|
2345
|
+
demoteIdleTimeoutSecs: args.demoteIdleTimeoutSecs,
|
|
2346
|
+
promoteHitThreshold: args.promoteHitThreshold,
|
|
2347
|
+
});
|
|
2348
|
+
if (report === null) {
|
|
2349
|
+
return JSON.stringify({
|
|
2350
|
+
status: 'unsupported',
|
|
2351
|
+
message: 'dynamicScan not available in current aifastdb version. Please upgrade to aifastdb >= 2.8.0.',
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
return JSON.stringify({
|
|
2355
|
+
status: 'completed',
|
|
2356
|
+
projectName,
|
|
2357
|
+
report,
|
|
2358
|
+
message: `Scanned ${report.scanned} memories: ${report.promoted} promoted, ${report.demoted} demoted (${report.durationMs}ms)`,
|
|
2359
|
+
});
|
|
2360
|
+
}
|
|
1828
2361
|
default:
|
|
1829
2362
|
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
|
|
1830
2363
|
}
|