@ppdocs/mcp 2.7.1 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,99 +1,62 @@
1
- export type EdgeType = 'contains' | 'uses' | 'extends' | 'implements';
2
- export interface Edge {
3
- source: string;
4
- target: string;
5
- type: EdgeType;
6
- auto?: boolean;
7
- }
8
- export type NodeType = 'logic' | 'data' | 'intro';
9
- export type NodeStatus = 'incomplete' | 'complete' | 'fixing' | 'refactoring' | 'deprecated';
10
- export interface DataRef {
11
- type: string;
12
- description: string;
13
- formatPath?: string;
14
- }
15
- export interface Dependency {
16
- name: string;
17
- description: string;
18
- nodePath?: string;
19
- }
1
+ /** 版本记录 */
20
2
  export interface VersionRecord {
21
3
  version: number;
22
4
  date: string;
23
5
  changes: string;
24
6
  }
7
+ /** 错误修复记录 */
25
8
  export interface BugfixRecord {
26
- id: string;
27
9
  date: string;
28
10
  issue: string;
29
11
  solution: string;
30
- impact?: string;
31
12
  }
32
- export interface NodeData {
33
- id: string;
34
- title: string;
35
- type: NodeType;
36
- status: NodeStatus;
37
- x: number;
38
- y: number;
39
- locked: boolean;
40
- isOrigin?: boolean;
41
- signature: string;
42
- categories: string[];
13
+ /** 文档数据 (4个核心字段) */
14
+ export interface DocData {
15
+ summary: string;
16
+ content: string;
17
+ versions: VersionRecord[];
18
+ bugfixes: BugfixRecord[];
19
+ }
20
+ /** 文档节点 (含路径信息,用于列表展示) */
21
+ export interface DocNode {
43
22
  path: string;
44
- description: string;
45
- summary?: string;
46
- dataInput?: DataRef;
47
- dataOutput?: DataRef;
48
- dependencies: Dependency[];
49
- relatedFiles?: string[];
50
- userStyles?: string[];
51
- testRules?: string[];
52
- reviewRules?: string[];
53
- codeStyle?: string[];
54
- unitTests?: string[];
55
- createdAt?: string;
56
- updatedAt?: string;
57
- lastAccessedAt?: string;
58
- lastSyncAt?: string;
59
- versions?: VersionRecord[];
60
- bugfixes?: BugfixRecord[];
23
+ name: string;
24
+ summary: string;
25
+ isDir: boolean;
26
+ }
27
+ /** 文档搜索结果 */
28
+ export interface DocSearchResult {
29
+ path: string;
30
+ name: string;
31
+ summary: string;
32
+ score: number;
61
33
  }
62
34
  export interface ProjectMeta {
63
35
  projectId: string;
64
36
  projectName: string;
65
37
  updatedAt: string;
66
- edges: Edge[];
38
+ password?: string;
67
39
  }
68
40
  export interface Project {
69
41
  id: string;
70
42
  name: string;
43
+ description?: string;
71
44
  updatedAt: string;
72
45
  }
73
- export interface SearchResult {
74
- node: NodeData;
75
- score: number;
76
- matches: string[];
77
- }
78
- export interface PathResult {
79
- path: NodeData[];
80
- edges: Edge[];
81
- }
82
46
  export type TaskLogType = 'progress' | 'issue' | 'solution' | 'reference';
83
47
  export interface TaskLog {
84
48
  time: string;
85
49
  log_type: TaskLogType;
86
50
  content: string;
87
51
  }
88
- export interface TaskReference {
89
- title: string;
90
- url?: string;
91
- }
92
52
  export interface TaskExperience {
93
53
  summary: string;
94
54
  difficulties: string[];
95
55
  solutions: string[];
96
- references: TaskReference[];
56
+ references: Array<{
57
+ title: string;
58
+ url?: string;
59
+ }>;
97
60
  }
98
61
  export interface TaskDetail {
99
62
  description: string;
@@ -1,2 +1,2 @@
1
- // 知识图谱类型定义 - UI 和 Tauri 后端保持同步
1
+ // ppdocs - 文档类型定义 (简化版)
2
2
  export {};
@@ -1,8 +1,7 @@
1
1
  /**
2
2
  * MCP 工具辅助函数
3
- * 提取自 index.ts,避免重复代码
4
3
  */
5
- import type { NodeData } from '../storage/types.js';
4
+ import type { DocData } from '../storage/types.js';
6
5
  /**
7
6
  * 包装返回结果为 MCP 格式
8
7
  */
@@ -12,43 +11,23 @@ export declare function wrap(text: string): {
12
11
  text: string;
13
12
  }[];
14
13
  };
15
- interface RelationItem {
16
- id: string;
17
- title: string;
18
- edge: string;
19
- }
20
- /**
21
- * 递归获取节点的上下游关系
22
- */
23
- export declare function fetchRelations(projectId: string, nodeId: string, maxDepth: number): Promise<{
24
- outgoing: RelationItem[];
25
- incoming: RelationItem[];
26
- }>;
27
14
  /**
28
- * 格式化节点为 Markdown 输出
15
+ * 格式化文档为 Markdown 输出
29
16
  */
30
- export declare function formatNodeMarkdown(node: NodeData): string[];
31
- /**
32
- * 格式化关系输出
33
- */
34
- export declare function formatRelationsMarkdown(outgoing: RelationItem[], incoming: RelationItem[]): string[];
17
+ export declare function formatDocMarkdown(doc: DocData, path: string): string[];
35
18
  interface TreeNode {
19
+ path: string;
36
20
  name: string;
37
- type: 'folder' | 'node';
38
- nodeId?: string;
39
- status?: string;
21
+ summary?: string;
22
+ isDir: boolean;
40
23
  children?: TreeNode[];
41
24
  }
42
- /**
43
- * 构建目录树结构
44
- */
45
- export declare function buildDirectoryTree(nodes: NodeData[]): TreeNode;
46
25
  /**
47
26
  * 格式化树为文本
48
27
  */
49
- export declare function formatTreeText(tree: TreeNode): string;
28
+ export declare function formatTreeText(tree: TreeNode[]): string;
50
29
  /**
51
- * 统计树中的节点数
30
+ * 统计树中的文档数
52
31
  */
53
- export declare function countTreeNodes(tree: TreeNode): number;
32
+ export declare function countTreeDocs(tree: TreeNode[]): number;
54
33
  export {};
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * MCP 工具辅助函数
3
- * 提取自 index.ts,避免重复代码
4
3
  */
5
- import * as storage from '../storage/httpClient.js';
6
4
  // ==================== 通用包装 ====================
7
5
  /**
8
6
  * 包装返回结果为 MCP 格式
@@ -10,196 +8,74 @@ import * as storage from '../storage/httpClient.js';
10
8
  export function wrap(text) {
11
9
  return { content: [{ type: 'text', text }] };
12
10
  }
11
+ // ==================== 文档格式化 ====================
13
12
  /**
14
- * 递归获取节点的上下游关系
13
+ * 格式化文档为 Markdown 输出
15
14
  */
16
- export async function fetchRelations(projectId, nodeId, maxDepth) {
17
- const visited = new Set();
18
- const outgoing = [];
19
- const incoming = [];
20
- async function recurse(currentNodeId, currentDepth, direction) {
21
- if (currentDepth > maxDepth || visited.has(`${currentNodeId}-${direction}`))
22
- return;
23
- visited.add(`${currentNodeId}-${direction}`);
24
- const relations = await storage.getRelations(projectId, currentNodeId);
25
- for (const r of relations) {
26
- if (r.direction === 'outgoing' && (direction === 'outgoing' || direction === 'both')) {
27
- if (!outgoing.some(o => o.id === r.nodeId)) {
28
- outgoing.push({ id: r.nodeId, title: r.title, edge: r.edgeType });
29
- await recurse(r.nodeId, currentDepth + 1, 'outgoing');
30
- }
31
- }
32
- if (r.direction === 'incoming' && (direction === 'incoming' || direction === 'both')) {
33
- if (!incoming.some(i => i.id === r.nodeId)) {
34
- incoming.push({ id: r.nodeId, title: r.title, edge: r.edgeType });
35
- await recurse(r.nodeId, currentDepth + 1, 'incoming');
36
- }
37
- }
38
- }
39
- }
40
- await recurse(nodeId, 1, 'both');
41
- return { outgoing, incoming };
42
- }
43
- // ==================== 节点格式化 ====================
44
- /**
45
- * 格式化节点为 Markdown 输出
46
- */
47
- export function formatNodeMarkdown(node) {
15
+ export function formatDocMarkdown(doc, path) {
48
16
  const lines = [];
49
- // 基础信息
50
- lines.push(`## ${node.title}\n`);
51
- if (node.summary) {
52
- lines.push(`> ${node.summary}\n`);
17
+ const name = path.split('/').pop() || path;
18
+ // 标题和简介
19
+ lines.push(`## ${name}\n`);
20
+ if (doc.summary) {
21
+ lines.push(`> ${doc.summary}\n`);
53
22
  }
54
- lines.push('**基础信息**');
55
- lines.push(`| 字段 | 值 |`);
56
- lines.push(`|:---|:---|`);
57
- lines.push(`| ID | ${node.id} |`);
58
- lines.push(`| 类型 | ${node.type} |`);
59
- lines.push(`| 状态 | ${node.status} |`);
60
- lines.push(`| 签名 | ${node.signature} |`);
61
- if (node.categories && node.categories.length > 0) {
62
- lines.push(`| 标签 | ${node.categories.join(', ')} |`);
63
- }
64
- lines.push('');
65
- // 关联文件
66
- if (node.relatedFiles && node.relatedFiles.length > 0) {
67
- lines.push('**关联文件**');
68
- node.relatedFiles.forEach((f) => lines.push(`- ${f}`));
69
- lines.push('');
70
- }
71
- // 依赖关系
72
- if (node.dependencies && node.dependencies.length > 0) {
73
- lines.push('**依赖关系**');
74
- node.dependencies.forEach((d) => lines.push(`- ${d.name}: ${d.description}`));
75
- lines.push('');
76
- }
77
- // 描述内容
78
- if (node.description) {
79
- lines.push('**描述内容**');
80
- lines.push(node.description);
23
+ // 内容
24
+ if (doc.content) {
25
+ lines.push('**内容**');
26
+ lines.push(doc.content);
81
27
  lines.push('');
82
28
  }
83
29
  // 更新历史
84
- if (node.versions && node.versions.length > 0) {
30
+ if (doc.versions && doc.versions.length > 0) {
85
31
  lines.push('**更新历史**');
86
32
  lines.push('| 版本 | 日期 | 变更 |');
87
33
  lines.push('|:---|:---|:---|');
88
- node.versions.forEach((v) => lines.push(`| ${v.version} | ${v.date} | ${v.changes} |`));
34
+ doc.versions.forEach((v) => lines.push(`| ${v.version} | ${v.date} | ${v.changes} |`));
89
35
  lines.push('');
90
36
  }
91
37
  // 修复历史
92
- if (node.bugfixes && node.bugfixes.length > 0) {
38
+ if (doc.bugfixes && doc.bugfixes.length > 0) {
93
39
  lines.push('**修复历史**');
94
- lines.push('| ID | 日期 | 问题 | 方案 |');
95
- lines.push('|:---|:---|:---|:---|');
96
- node.bugfixes.forEach((b) => lines.push(`| ${b.id} | ${b.date} | ${b.issue} | ${b.solution} |`));
97
- lines.push('');
98
- }
99
- return lines;
100
- }
101
- /**
102
- * 格式化关系输出
103
- */
104
- export function formatRelationsMarkdown(outgoing, incoming) {
105
- const lines = [];
106
- if (outgoing.length > 0 || incoming.length > 0) {
107
- lines.push('**上下游关系**');
108
- if (outgoing.length > 0) {
109
- lines.push(`- 依赖 (${outgoing.length}): ${outgoing.map(o => o.title).join(', ')}`);
110
- }
111
- if (incoming.length > 0) {
112
- lines.push(`- 被依赖 (${incoming.length}): ${incoming.map(i => i.title).join(', ')}`);
113
- }
40
+ lines.push('| 日期 | 问题 | 方案 |');
41
+ lines.push('|:---|:---|:---|');
42
+ doc.bugfixes.forEach((b) => lines.push(`| ${b.date} | ${b.issue} | ${b.solution} |`));
114
43
  lines.push('');
115
44
  }
116
45
  return lines;
117
46
  }
118
- /**
119
- * 构建目录树结构
120
- */
121
- export function buildDirectoryTree(nodes) {
122
- const root = { name: '/', type: 'folder', children: [] };
123
- // 过滤掉根节点
124
- const docNodes = nodes.filter(n => !n.isOrigin && n.id !== 'root');
125
- for (const node of docNodes) {
126
- const pathSegments = (node.path || '').split('/').filter(Boolean);
127
- let current = root;
128
- // 遍历路径段,创建目录结构
129
- for (const segment of pathSegments) {
130
- if (!current.children)
131
- current.children = [];
132
- let child = current.children.find(c => c.name === segment && c.type === 'folder');
133
- if (!child) {
134
- child = { name: segment, type: 'folder', children: [] };
135
- current.children.push(child);
136
- }
137
- current = child;
138
- }
139
- // 添加节点
140
- if (!current.children)
141
- current.children = [];
142
- current.children.push({
143
- name: node.title,
144
- type: 'node',
145
- nodeId: node.id,
146
- status: node.status
147
- });
148
- }
149
- // 递归排序 (目录在前,节点在后)
150
- sortTree(root);
151
- return root;
152
- }
153
- function sortTree(node) {
154
- if (!node.children)
155
- return;
156
- node.children.sort((a, b) => {
157
- if (a.type === 'folder' && b.type !== 'folder')
158
- return -1;
159
- if (a.type !== 'folder' && b.type === 'folder')
160
- return 1;
161
- return a.name.localeCompare(b.name, 'zh-CN');
162
- });
163
- for (const child of node.children) {
164
- if (child.type === 'folder')
165
- sortTree(child);
166
- }
167
- }
168
47
  /**
169
48
  * 格式化树为文本
170
49
  */
171
50
  export function formatTreeText(tree) {
172
- function format(node, prefix = '', isLast = true) {
51
+ function format(nodes, prefix = '') {
173
52
  const lines = [];
174
- const connector = isLast ? '└── ' : '├── ';
175
- const childPrefix = isLast ? ' ' : '│ ';
176
- if (node.name !== '/') {
177
- const icon = node.type === 'folder' ? '📁' : '📄';
178
- const status = node.status ? ` [${node.status}]` : '';
179
- lines.push(`${prefix}${connector}${icon} ${node.name}${status}`);
180
- }
181
- if (node.children) {
182
- for (let i = 0; i < node.children.length; i++) {
183
- const child = node.children[i];
184
- const childIsLast = i === node.children.length - 1;
185
- const newPrefix = node.name === '/' ? '' : prefix + childPrefix;
186
- lines.push(...format(child, newPrefix, childIsLast));
53
+ nodes.forEach((node, index) => {
54
+ const isLast = index === nodes.length - 1;
55
+ const connector = isLast ? '└── ' : '├── ';
56
+ const childPrefix = isLast ? ' ' : '';
57
+ const icon = node.isDir ? '📁' : '📄';
58
+ const summary = node.summary ? ` - ${node.summary}` : '';
59
+ lines.push(`${prefix}${connector}${icon} ${node.name}${summary}`);
60
+ if (node.children && node.children.length > 0) {
61
+ lines.push(...format(node.children, prefix + childPrefix));
187
62
  }
188
- }
63
+ });
189
64
  return lines;
190
65
  }
191
66
  return format(tree).join('\n');
192
67
  }
193
68
  /**
194
- * 统计树中的节点数
69
+ * 统计树中的文档数
195
70
  */
196
- export function countTreeNodes(tree) {
71
+ export function countTreeDocs(tree) {
197
72
  let count = 0;
198
- function traverse(node) {
199
- if (node.type === 'node')
200
- count++;
201
- if (node.children) {
202
- node.children.forEach(traverse);
73
+ function traverse(nodes) {
74
+ for (const node of nodes) {
75
+ if (!node.isDir)
76
+ count++;
77
+ if (node.children)
78
+ traverse(node.children);
203
79
  }
204
80
  }
205
81
  traverse(tree);