@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.
@@ -4,129 +4,55 @@
4
4
  *
5
5
  * API URL 格式: http://localhost:20001/api/:projectId/:password/...
6
6
  */
7
- import type { NodeData, SearchResult, PathResult, BugfixRecord, Task, TaskSummary, TaskLogType, TaskExperience } from './types.js';
8
- export interface ListNodesFilter {
9
- status?: 'incomplete' | 'complete' | 'fixing' | 'refactoring' | 'deprecated';
10
- minEdges?: number;
11
- maxEdges?: number;
7
+ import type { DocData, DocNode, DocSearchResult, Task, TaskSummary, TaskLogType, TaskExperience } from './types.js';
8
+ interface TreeNode {
9
+ path: string;
10
+ name: string;
11
+ summary?: string;
12
+ isDir: boolean;
13
+ children?: TreeNode[];
12
14
  }
13
15
  export declare class PpdocsApiClient {
14
16
  private baseUrl;
15
17
  constructor(apiUrl: string);
16
18
  private request;
17
- listNodes(filter?: ListNodesFilter): Promise<NodeData[]>;
18
- getNode(nodeId: string): Promise<NodeData | null>;
19
- createNode(node: Partial<NodeData>): Promise<NodeData>;
20
- updateNode(nodeId: string, updates: Partial<NodeData>): Promise<NodeData | null>;
21
- updateRoot(updates: {
22
- title?: string;
23
- description?: string;
24
- userStyles?: string[];
25
- testRules?: string[];
26
- reviewRules?: string[];
27
- codeStyle?: string[];
28
- }): Promise<NodeData | null>;
29
- deleteNode(nodeId: string): Promise<boolean>;
30
- lockNode(nodeId: string, locked: boolean): Promise<NodeData | null>;
31
- searchNodes(keywords: string[], limit?: number): Promise<SearchResult[]>;
32
- findPath(startId: string, endId: string): Promise<PathResult | null>;
33
- getRelations(nodeId: string): Promise<Array<{
34
- nodeId: string;
35
- title: string;
36
- description: string;
37
- edgeType: string;
38
- direction: 'outgoing' | 'incoming';
39
- }>>;
40
- addBugfix(nodeId: string, bugfix: {
41
- issue: string;
42
- solution: string;
43
- impact?: string;
44
- }): Promise<BugfixRecord | null>;
19
+ listDocs(): Promise<DocNode[]>;
20
+ getDoc(docPath: string): Promise<DocData | null>;
21
+ createDoc(docPath: string, doc: Partial<DocData>): Promise<DocData>;
22
+ updateDoc(docPath: string, updates: Partial<DocData>): Promise<DocData | null>;
23
+ deleteDoc(docPath: string): Promise<boolean>;
24
+ searchDocs(keywords: string[], limit?: number): Promise<DocSearchResult[]>;
25
+ /** 获取目录树结构 */
26
+ getTree(): Promise<TreeNode[]>;
27
+ getRulesApi(ruleType: string): Promise<string[]>;
28
+ saveRulesApi(ruleType: string, rules: string[]): Promise<boolean>;
45
29
  listTasks(status?: 'active' | 'archived'): Promise<TaskSummary[]>;
46
30
  getTask(taskId: string): Promise<Task | null>;
47
31
  createTask(task: {
48
32
  title: string;
49
33
  description: string;
50
34
  goals: string[];
51
- related_nodes?: string[];
52
35
  }, creator: string): Promise<Task>;
53
36
  addTaskLog(taskId: string, logType: TaskLogType, content: string): Promise<Task | null>;
54
37
  completeTask(taskId: string, experience: TaskExperience): Promise<Task | null>;
55
- getRulesApi(ruleType: string): Promise<string[]>;
56
- saveRulesApi(ruleType: string, rules: string[]): Promise<boolean>;
57
- vectorSearch(query: string, limit: number, mode: string): Promise<Array<{
58
- id: string;
59
- title: string;
60
- score: number;
61
- match_type: string;
62
- keyword_score: number;
63
- semantic_score: number;
64
- }>>;
65
- vectorStats(): Promise<{
66
- model_downloaded: boolean;
67
- model_loaded: boolean;
68
- model_path: string;
69
- index_count: number;
70
- }>;
71
38
  }
72
39
  export declare function initClient(apiUrl: string): void;
73
- export declare function listNodes(_projectId: string, filter?: ListNodesFilter): Promise<NodeData[]>;
74
- export declare function getNode(_projectId: string, nodeId: string): Promise<NodeData | null>;
75
- export declare function createNode(_projectId: string, node: Partial<NodeData>): Promise<NodeData>;
76
- export declare function updateNode(_projectId: string, nodeId: string, updates: Partial<NodeData>): Promise<NodeData | null>;
77
- export declare function updateRoot(_projectId: string, updates: {
78
- title?: string;
79
- description?: string;
80
- userStyles?: string[];
81
- testRules?: string[];
82
- reviewRules?: string[];
83
- codeStyle?: string[];
84
- }): Promise<NodeData | null>;
85
- export declare function deleteNode(_projectId: string, nodeId: string): Promise<boolean>;
86
- export declare function lockNode(_projectId: string, nodeId: string, locked: boolean): Promise<NodeData | null>;
87
- export declare function searchNodes(_projectId: string, keywords: string[], limit?: number): Promise<SearchResult[]>;
88
- export declare function findPath(_projectId: string, startId: string, endId: string): Promise<PathResult | null>;
89
- export declare function getRelations(_projectId: string, nodeId: string): Promise<Array<{
90
- nodeId: string;
91
- title: string;
92
- description: string;
93
- edgeType: string;
94
- direction: 'outgoing' | 'incoming';
95
- }>>;
96
- export declare function addBugfix(_projectId: string, nodeId: string, bugfix: {
97
- issue: string;
98
- solution: string;
99
- impact?: string;
100
- }): Promise<BugfixRecord | null>;
40
+ export declare function listDocs(_projectId: string): Promise<DocNode[]>;
41
+ export declare function getDoc(_projectId: string, docPath: string): Promise<DocData | null>;
42
+ export declare function createDoc(_projectId: string, docPath: string, doc: Partial<DocData>): Promise<DocData>;
43
+ export declare function updateDoc(_projectId: string, docPath: string, updates: Partial<DocData>): Promise<DocData | null>;
44
+ export declare function deleteDoc(_projectId: string, docPath: string): Promise<boolean>;
45
+ export declare function searchDocs(_projectId: string, keywords: string[], limit?: number): Promise<DocSearchResult[]>;
46
+ export declare function getTree(_projectId: string): Promise<TreeNode[]>;
47
+ export declare function getRules(_projectId: string, ruleType: string): Promise<string[]>;
48
+ export declare function saveRules(_projectId: string, ruleType: string, rules: string[]): Promise<boolean>;
101
49
  export declare function listTasks(_projectId: string, status?: 'active' | 'archived'): Promise<TaskSummary[]>;
102
50
  export declare function getTask(_projectId: string, taskId: string): Promise<Task | null>;
103
51
  export declare function createTask(_projectId: string, task: {
104
52
  title: string;
105
53
  description: string;
106
54
  goals: string[];
107
- related_nodes?: string[];
108
55
  }, creator: string): Promise<Task>;
109
56
  export declare function addTaskLog(_projectId: string, taskId: string, logType: TaskLogType, content: string): Promise<Task | null>;
110
57
  export declare function completeTask(_projectId: string, taskId: string, experience: TaskExperience): Promise<Task | null>;
111
- export declare function getRules(_projectId: string, ruleType: string): Promise<string[]>;
112
- export declare function saveRules(_projectId: string, ruleType: string, rules: string[]): Promise<boolean>;
113
- /** 向量搜索结果 */
114
- export interface VectorSearchResult {
115
- id: string;
116
- title: string;
117
- score: number;
118
- match_type: string;
119
- keyword_score: number;
120
- semantic_score: number;
121
- }
122
- /** 向量索引状态 */
123
- export interface VectorStats {
124
- model_downloaded: boolean;
125
- model_loaded: boolean;
126
- model_path: string;
127
- index_count: number;
128
- }
129
- /** 混合搜索 (关键词 + 语义) */
130
- export declare function vectorSearch(_projectId: string, query: string, limit: number, mode: 'hybrid' | 'keyword' | 'semantic'): Promise<VectorSearchResult[]>;
131
- /** 获取向量索引状态 */
132
- export declare function vectorStats(_projectId: string): Promise<VectorStats>;
58
+ export type { TreeNode };
@@ -4,58 +4,38 @@
4
4
  *
5
5
  * API URL 格式: http://localhost:20001/api/:projectId/:password/...
6
6
  */
7
- // ============ 智能定位算法 ============
8
- const SMART_NODE_GAP = 180;
9
- const SMART_SEARCH_RADIUS = 10;
10
- /**
11
- * 计算新节点的智能位置 (关联中心 + 螺旋搜索空位)
12
- */
13
- function computeSmartPosition(deps, nodes) {
14
- // 1. 找关联节点
15
- const related = [];
16
- if (deps && deps.length > 0) {
17
- const depNames = deps.map(d => d.name.toLowerCase());
18
- nodes.forEach(n => {
19
- if (n.signature && depNames.some(name => n.signature.toLowerCase().startsWith(name))) {
20
- related.push(n);
21
- }
22
- });
23
- }
24
- // 2. 计算中心点
25
- let cx, cy;
26
- if (related.length > 0) {
27
- cx = related.reduce((s, n) => s + n.x, 0) / related.length;
28
- cy = related.reduce((s, n) => s + n.y, 0) / related.length + SMART_NODE_GAP;
29
- }
30
- else {
31
- const root = nodes.find(n => n.isOrigin);
32
- cx = root?.x ?? 0;
33
- cy = (root?.y ?? 0) + SMART_NODE_GAP;
34
- }
35
- // 3. 碰撞检测
36
- const collides = (x, y) => nodes.some(n => Math.abs(n.x - x) < SMART_NODE_GAP && Math.abs(n.y - y) < SMART_NODE_GAP * 0.6);
37
- if (!collides(cx, cy))
38
- return { x: Math.round(cx), y: Math.round(cy) };
39
- // 4. 螺旋搜索
40
- const dirs = [[1, 0], [0, 1], [-1, 0], [0, -1]];
41
- let x = cx, y = cy, step = 1, dir = 0, steps = 0, turns = 0;
42
- for (let i = 0; i < SMART_SEARCH_RADIUS * SMART_SEARCH_RADIUS * 4; i++) {
43
- x += dirs[dir][0] * SMART_NODE_GAP;
44
- y += dirs[dir][1] * SMART_NODE_GAP * 0.6;
45
- steps++;
46
- if (!collides(x, y))
47
- return { x: Math.round(x), y: Math.round(y) };
48
- if (steps >= step) {
49
- steps = 0;
50
- dir = (dir + 1) % 4;
51
- if (++turns >= 2) {
52
- turns = 0;
53
- step++;
54
- }
7
+ /** 从扁平文档列表构建目录树 */
8
+ function buildTree(docs) {
9
+ const root = [];
10
+ const pathMap = new Map();
11
+ // 按路径深度排序,确保父目录先处理
12
+ const sorted = [...docs].sort((a, b) => {
13
+ const depthA = (a.path.match(/\//g) || []).length;
14
+ const depthB = (b.path.match(/\//g) || []).length;
15
+ return depthA - depthB;
16
+ });
17
+ for (const doc of sorted) {
18
+ const node = {
19
+ path: doc.path,
20
+ name: doc.name,
21
+ summary: doc.summary,
22
+ isDir: doc.isDir,
23
+ children: doc.isDir ? [] : undefined
24
+ };
25
+ // 找父路径
26
+ const lastSlash = doc.path.lastIndexOf('/');
27
+ const parentPath = lastSlash > 0 ? doc.path.substring(0, lastSlash) : '';
28
+ if (parentPath && pathMap.has(parentPath)) {
29
+ pathMap.get(parentPath).children.push(node);
30
+ }
31
+ else {
32
+ root.push(node);
33
+ }
34
+ if (doc.isDir) {
35
+ pathMap.set(doc.path, node);
55
36
  }
56
37
  }
57
- const maxX = Math.max(...nodes.map(n => n.x), 0);
58
- return { x: Math.round(maxX + SMART_NODE_GAP), y: Math.round(cy) };
38
+ return root;
59
39
  }
60
40
  // API 客户端类
61
41
  export class PpdocsApiClient {
@@ -98,91 +78,51 @@ export class PpdocsApiClient {
98
78
  clearTimeout(timeout);
99
79
  }
100
80
  }
101
- // ============ 节点操作 ============
102
- async listNodes(filter) {
103
- const nodes = await this.request('/nodes');
104
- if (!filter)
105
- return nodes;
106
- // 计算每个节点的连接数 (入边+出边)
107
- const edgeCounts = new Map();
108
- nodes.forEach(n => edgeCounts.set(n.id, 0));
109
- nodes.forEach(n => {
110
- (n.dependencies || []).forEach(dep => {
111
- // 出边: 当前节点依赖别人
112
- edgeCounts.set(n.id, (edgeCounts.get(n.id) || 0) + 1);
113
- // 入边: 被依赖的节点 (按 signature 匹配)
114
- const target = nodes.find(t => t.signature?.toLowerCase() === dep.name.toLowerCase());
115
- if (target)
116
- edgeCounts.set(target.id, (edgeCounts.get(target.id) || 0) + 1);
117
- });
118
- });
119
- // 过滤
120
- return nodes.filter(n => {
121
- if (filter.status && n.status !== filter.status)
122
- return false;
123
- const edges = edgeCounts.get(n.id) || 0;
124
- if (filter.minEdges !== undefined && edges < filter.minEdges)
125
- return false;
126
- if (filter.maxEdges !== undefined && edges > filter.maxEdges)
127
- return false;
128
- return true;
129
- });
81
+ // ============ 文档操作 ============
82
+ async listDocs() {
83
+ return this.request('/docs');
130
84
  }
131
- async getNode(nodeId) {
85
+ async getDoc(docPath) {
132
86
  try {
133
- return await this.request(`/nodes/${nodeId}`);
87
+ // 移除开头的斜杠,API 路径会自动处理
88
+ const cleanPath = docPath.replace(/^\//, '');
89
+ return await this.request(`/docs/${cleanPath}`);
134
90
  }
135
91
  catch {
136
92
  return null;
137
93
  }
138
94
  }
139
- async createNode(node) {
140
- // 智能定位: 计算新节点位置
141
- let x = node.x ?? 0;
142
- let y = node.y ?? 0;
143
- // 如果未指定位置,自动计算
144
- if (node.x === undefined && node.y === undefined) {
145
- const existingNodes = await this.listNodes();
146
- const pos = computeSmartPosition(node.dependencies, existingNodes);
147
- x = pos.x;
148
- y = pos.y;
149
- }
95
+ async createDoc(docPath, doc) {
96
+ const cleanPath = docPath.replace(/^\//, '');
150
97
  const payload = {
151
- id: '', // 服务端自动生成
152
- title: node.title || '',
153
- type: node.type || 'logic',
154
- status: node.status || 'incomplete',
155
- x,
156
- y,
157
- locked: false,
158
- signature: node.signature || node.title || '',
159
- categories: node.categories || [],
160
- description: node.description || '',
161
- dependencies: node.dependencies || [],
162
- relatedFiles: node.relatedFiles || [],
163
- createdAt: new Date().toISOString(),
164
- updatedAt: new Date().toISOString(),
165
- lastAccessedAt: new Date().toISOString(),
166
- versions: [],
167
- bugfixes: []
98
+ summary: doc.summary || '',
99
+ content: doc.content || '',
100
+ versions: doc.versions || [{
101
+ version: 0.1,
102
+ date: new Date().toISOString(),
103
+ changes: '初始创建'
104
+ }],
105
+ bugfixes: doc.bugfixes || []
168
106
  };
169
- return this.request('/nodes', {
107
+ return this.request(`/docs/${cleanPath}`, {
170
108
  method: 'POST',
171
109
  body: JSON.stringify(payload)
172
110
  });
173
111
  }
174
- async updateNode(nodeId, updates) {
175
- // 先获取现有节点,合并更新
176
- const existing = await this.getNode(nodeId);
177
- if (!existing)
178
- return null;
179
- const payload = {
180
- ...existing,
181
- ...updates,
182
- updatedAt: new Date().toISOString()
183
- };
112
+ async updateDoc(docPath, updates) {
184
113
  try {
185
- return await this.request(`/nodes/${nodeId}`, {
114
+ const cleanPath = docPath.replace(/^\//, '');
115
+ // 先获取现有文档
116
+ const existing = await this.getDoc(docPath);
117
+ if (!existing)
118
+ return null;
119
+ const payload = {
120
+ summary: updates.summary ?? existing.summary,
121
+ content: updates.content ?? existing.content,
122
+ versions: updates.versions ?? existing.versions,
123
+ bugfixes: updates.bugfixes ?? existing.bugfixes
124
+ };
125
+ return await this.request(`/docs/${cleanPath}`, {
186
126
  method: 'PUT',
187
127
  body: JSON.stringify(payload)
188
128
  });
@@ -191,104 +131,48 @@ export class PpdocsApiClient {
191
131
  return null;
192
132
  }
193
133
  }
194
- async updateRoot(updates) {
195
- // 专用根节点更新,支持所有规则字段
196
- const root = await this.getNode('root');
197
- if (!root)
198
- return null;
199
- if (root.locked)
200
- return null; // 锁定时拒绝
201
- // 构建更新载荷 (只传入有值的字段)
202
- const payload = { updatedAt: new Date().toISOString() };
203
- if (updates.title !== undefined)
204
- payload.title = updates.title;
205
- if (updates.description !== undefined)
206
- payload.description = updates.description;
207
- if (updates.userStyles !== undefined)
208
- payload.userStyles = updates.userStyles;
209
- if (updates.testRules !== undefined)
210
- payload.testRules = updates.testRules;
211
- if (updates.reviewRules !== undefined)
212
- payload.reviewRules = updates.reviewRules;
213
- if (updates.codeStyle !== undefined)
214
- payload.codeStyle = updates.codeStyle;
134
+ async deleteDoc(docPath) {
215
135
  try {
216
- return await this.request('/nodes/root', {
217
- method: 'PUT',
218
- body: JSON.stringify({ ...root, ...payload })
219
- });
220
- }
221
- catch {
222
- return null;
223
- }
224
- }
225
- async deleteNode(nodeId) {
226
- try {
227
- await this.request(`/nodes/${nodeId}`, { method: 'DELETE' });
136
+ const cleanPath = docPath.replace(/^\//, '');
137
+ await this.request(`/docs/${cleanPath}`, { method: 'DELETE' });
228
138
  return true;
229
139
  }
230
140
  catch {
231
141
  return false;
232
142
  }
233
143
  }
234
- async lockNode(nodeId, locked) {
144
+ async searchDocs(keywords, limit = 20) {
145
+ return this.request('/docs/search', {
146
+ method: 'POST',
147
+ body: JSON.stringify({ keywords, limit })
148
+ });
149
+ }
150
+ /** 获取目录树结构 */
151
+ async getTree() {
152
+ const docs = await this.listDocs();
153
+ return buildTree(docs);
154
+ }
155
+ // ============ 规则 API ============
156
+ async getRulesApi(ruleType) {
235
157
  try {
236
- return await this.request(`/nodes/${nodeId}/lock`, {
237
- method: 'PUT',
238
- body: JSON.stringify({ locked })
239
- });
158
+ return await this.request(`/rules/${ruleType}`);
240
159
  }
241
160
  catch {
242
- return null;
161
+ return [];
243
162
  }
244
163
  }
245
- // ============ 搜索与路径 ============
246
- async searchNodes(keywords, limit = 20) {
247
- return this.request('/search', {
248
- method: 'POST',
249
- body: JSON.stringify({ keywords, limit })
250
- });
251
- }
252
- async findPath(startId, endId) {
164
+ async saveRulesApi(ruleType, rules) {
253
165
  try {
254
- return await this.request('/path', {
255
- method: 'POST',
256
- body: JSON.stringify({ start_id: startId, end_id: endId })
166
+ await this.request(`/rules/${ruleType}`, {
167
+ method: 'PUT',
168
+ body: JSON.stringify(rules)
257
169
  });
170
+ return true;
258
171
  }
259
172
  catch {
260
- return null;
173
+ return false;
261
174
  }
262
175
  }
263
- async getRelations(nodeId) {
264
- const result = await this.request(`/relations/${nodeId}`);
265
- // 转换字段名 (API 返回 type,前端期望 edgeType)
266
- return result.map(r => ({
267
- nodeId: r.nodeId,
268
- title: r.title,
269
- description: r.description,
270
- edgeType: r.type,
271
- direction: r.direction
272
- }));
273
- }
274
- // ============ Bugfix ============
275
- async addBugfix(nodeId, bugfix) {
276
- // 添加 bugfix 需要先获取节点,追加 bugfix,然后更新
277
- const node = await this.getNode(nodeId);
278
- if (!node || node.locked)
279
- return null;
280
- const newBugfix = {
281
- id: `bug-${Date.now()}`,
282
- date: new Date().toISOString(),
283
- issue: bugfix.issue,
284
- solution: bugfix.solution,
285
- impact: bugfix.impact
286
- };
287
- const updated = await this.updateNode(nodeId, {
288
- bugfixes: [newBugfix, ...(node.bugfixes || [])].slice(0, 20)
289
- });
290
- return updated ? newBugfix : null;
291
- }
292
176
  // ============ 任务管理 ============
293
177
  async listTasks(status) {
294
178
  const query = status ? `?status=${status}` : '';
@@ -309,7 +193,7 @@ export class PpdocsApiClient {
309
193
  detail: {
310
194
  description: task.description,
311
195
  goals: task.goals,
312
- related_nodes: task.related_nodes || []
196
+ related_nodes: []
313
197
  }
314
198
  };
315
199
  return this.request('/tasks', {
@@ -339,39 +223,8 @@ export class PpdocsApiClient {
339
223
  return null;
340
224
  }
341
225
  }
342
- // ============ 规则 API (独立文件存储) ============
343
- async getRulesApi(ruleType) {
344
- try {
345
- return await this.request(`/rules/${ruleType}`);
346
- }
347
- catch {
348
- return [];
349
- }
350
- }
351
- async saveRulesApi(ruleType, rules) {
352
- try {
353
- await this.request(`/rules/${ruleType}`, {
354
- method: 'PUT',
355
- body: JSON.stringify(rules)
356
- });
357
- return true;
358
- }
359
- catch {
360
- return false;
361
- }
362
- }
363
- // ============ 向量搜索 API ============
364
- async vectorSearch(query, limit, mode) {
365
- return this.request('/vector/search', {
366
- method: 'POST',
367
- body: JSON.stringify({ query, limit, mode })
368
- });
369
- }
370
- async vectorStats() {
371
- return this.request('/vector/stats');
372
- }
373
226
  }
374
- // ============ 模块级 API (兼容现有 tools/index.ts) ============
227
+ // ============ 模块级 API ============
375
228
  let client = null;
376
229
  export function initClient(apiUrl) {
377
230
  client = new PpdocsApiClient(apiUrl);
@@ -382,39 +235,34 @@ function getClient() {
382
235
  }
383
236
  return client;
384
237
  }
385
- // 导出与 fileStorage 相同的函数签名
386
- export async function listNodes(_projectId, filter) {
387
- return getClient().listNodes(filter);
238
+ // ============ 文档管理 ============
239
+ export async function listDocs(_projectId) {
240
+ return getClient().listDocs();
388
241
  }
389
- export async function getNode(_projectId, nodeId) {
390
- return getClient().getNode(nodeId);
242
+ export async function getDoc(_projectId, docPath) {
243
+ return getClient().getDoc(docPath);
391
244
  }
392
- export async function createNode(_projectId, node) {
393
- return getClient().createNode(node);
245
+ export async function createDoc(_projectId, docPath, doc) {
246
+ return getClient().createDoc(docPath, doc);
394
247
  }
395
- export async function updateNode(_projectId, nodeId, updates) {
396
- return getClient().updateNode(nodeId, updates);
248
+ export async function updateDoc(_projectId, docPath, updates) {
249
+ return getClient().updateDoc(docPath, updates);
397
250
  }
398
- export async function updateRoot(_projectId, updates) {
399
- return getClient().updateRoot(updates);
251
+ export async function deleteDoc(_projectId, docPath) {
252
+ return getClient().deleteDoc(docPath);
400
253
  }
401
- export async function deleteNode(_projectId, nodeId) {
402
- return getClient().deleteNode(nodeId);
254
+ export async function searchDocs(_projectId, keywords, limit) {
255
+ return getClient().searchDocs(keywords, limit);
403
256
  }
404
- export async function lockNode(_projectId, nodeId, locked) {
405
- return getClient().lockNode(nodeId, locked);
257
+ export async function getTree(_projectId) {
258
+ return getClient().getTree();
406
259
  }
407
- export async function searchNodes(_projectId, keywords, limit) {
408
- return getClient().searchNodes(keywords, limit);
409
- }
410
- export async function findPath(_projectId, startId, endId) {
411
- return getClient().findPath(startId, endId);
412
- }
413
- export async function getRelations(_projectId, nodeId) {
414
- return getClient().getRelations(nodeId);
260
+ // ============ 规则管理 ============
261
+ export async function getRules(_projectId, ruleType) {
262
+ return getClient().getRulesApi(ruleType);
415
263
  }
416
- export async function addBugfix(_projectId, nodeId, bugfix) {
417
- return getClient().addBugfix(nodeId, bugfix);
264
+ export async function saveRules(_projectId, ruleType, rules) {
265
+ return getClient().saveRulesApi(ruleType, rules);
418
266
  }
419
267
  // ============ 任务管理 ============
420
268
  export async function listTasks(_projectId, status) {
@@ -432,18 +280,3 @@ export async function addTaskLog(_projectId, taskId, logType, content) {
432
280
  export async function completeTask(_projectId, taskId, experience) {
433
281
  return getClient().completeTask(taskId, experience);
434
282
  }
435
- // ============ 规则管理 (独立文件存储) ============
436
- export async function getRules(_projectId, ruleType) {
437
- return getClient().getRulesApi(ruleType);
438
- }
439
- export async function saveRules(_projectId, ruleType, rules) {
440
- return getClient().saveRulesApi(ruleType, rules);
441
- }
442
- /** 混合搜索 (关键词 + 语义) */
443
- export async function vectorSearch(_projectId, query, limit, mode) {
444
- return getClient().vectorSearch(query, limit, mode);
445
- }
446
- /** 获取向量索引状态 */
447
- export async function vectorStats(_projectId) {
448
- return getClient().vectorStats();
449
- }