@ppdocs/mcp 3.2.18 → 3.2.20
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/cli.js +52 -39
- package/dist/storage/httpClient.d.ts +27 -0
- package/dist/storage/httpClient.js +102 -0
- package/dist/tools/analyzer.d.ts +2 -1
- package/dist/tools/analyzer.js +127 -14
- package/dist/tools/discussion.d.ts +3 -2
- package/dist/tools/discussion.js +67 -45
- package/dist/tools/docs.d.ts +2 -1
- package/dist/tools/docs.js +1 -1
- package/dist/tools/index.d.ts +3 -2
- package/dist/tools/index.js +10 -6
- package/dist/tools/meeting.d.ts +7 -0
- package/dist/tools/meeting.js +97 -0
- package/dist/tools/tasks.d.ts +2 -1
- package/dist/tools/tasks.js +2 -2
- package/package.json +1 -1
- package/templates/commands/pp/audit.md +87 -0
- package/templates/commands/pp/diagnose.md +82 -0
- package/templates/commands/pp/discuss.md +90 -0
- package/templates/commands/pp/execute.md +84 -0
- package/templates/hooks/SystemPrompt.md +16 -0
- package/dist/storage/discussion.d.ts +0 -33
- package/dist/storage/discussion.js +0 -116
package/dist/tools/discussion.js
CHANGED
|
@@ -1,13 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 💬 kg_discuss (6→1)
|
|
3
|
-
* 合并:
|
|
4
|
-
*
|
|
3
|
+
* 合并: list, read, create, reply, close, delete
|
|
4
|
+
* 统一走 HTTP → Rust 后端 (单一写入者)
|
|
5
|
+
* sender 格式: "projectId:user" (如 "p-ca3sgejg:张三")
|
|
5
6
|
*/
|
|
6
7
|
import { z } from 'zod';
|
|
7
8
|
import { getClient } from '../storage/httpClient.js';
|
|
8
9
|
import { decodeObjectStrings } from '../utils.js';
|
|
9
10
|
import { wrap, safeTool } from './shared.js';
|
|
10
|
-
|
|
11
|
+
function sender(ctx) {
|
|
12
|
+
return `${ctx.projectId}:${ctx.user}`;
|
|
13
|
+
}
|
|
14
|
+
function relativeTime(iso) {
|
|
15
|
+
try {
|
|
16
|
+
const diff = Date.now() - new Date(iso).getTime();
|
|
17
|
+
if (diff < 60000)
|
|
18
|
+
return '刚刚';
|
|
19
|
+
if (diff < 3600000)
|
|
20
|
+
return `${Math.floor(diff / 60000)}分钟前`;
|
|
21
|
+
if (diff < 86400000)
|
|
22
|
+
return `${Math.floor(diff / 3600000)}小时前`;
|
|
23
|
+
return `${Math.floor(diff / 86400000)}天前`;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return iso;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function formatList(items, ctx) {
|
|
30
|
+
const lines = [
|
|
31
|
+
`本项目: ${sender(ctx)}`,
|
|
32
|
+
``,
|
|
33
|
+
`📋 活跃讨论 (${items.length}个)`,
|
|
34
|
+
``,
|
|
35
|
+
`| ID | 标题 | 发起方 | 参与方 | 摘要 | 回复 | 更新 |`,
|
|
36
|
+
`|:---|:---|:---|:---|:---|:---:|:---|`,
|
|
37
|
+
];
|
|
38
|
+
for (const d of items) {
|
|
39
|
+
const others = d.participants.filter(p => p !== d.initiator).join(', ') || '—';
|
|
40
|
+
lines.push(`| ${d.id} | ${d.title} | ${d.initiator} | ${others} | ${d.summary} | ${d.status} | ${relativeTime(d.updatedAt)} |`);
|
|
41
|
+
}
|
|
42
|
+
return lines.join('\n');
|
|
43
|
+
}
|
|
44
|
+
function formatDetail(d) {
|
|
45
|
+
const msgs = d.messages || [];
|
|
46
|
+
const lines = [
|
|
47
|
+
`💬 ${d.title}`,
|
|
48
|
+
`发起: ${d.initiator} | 参与: ${d.participants.length}方 | 状态: ${d.status}`,
|
|
49
|
+
`📌 ${d.summary}`,
|
|
50
|
+
``,
|
|
51
|
+
];
|
|
52
|
+
msgs.forEach((m, i) => {
|
|
53
|
+
lines.push(`--- 消息 ${i + 1}/${msgs.length} [${m.sender}] ${relativeTime(m.timestamp)} ---`);
|
|
54
|
+
lines.push(m.content);
|
|
55
|
+
lines.push('');
|
|
56
|
+
});
|
|
57
|
+
return lines.join('\n');
|
|
58
|
+
}
|
|
11
59
|
export function registerDiscussionTools(server, ctx) {
|
|
12
60
|
const client = () => getClient();
|
|
13
61
|
server.tool('kg_discuss', '💬 跨项目讨论 — 发起、回复、归档协同讨论。action: list(列出活跃讨论)|read(读取详情)|create(发起)|reply(回复)|close(结案归档)|delete(删除)', {
|
|
@@ -29,23 +77,22 @@ export function registerDiscussionTools(server, ctx) {
|
|
|
29
77
|
.describe('更新进展摘要 (reply)'),
|
|
30
78
|
}, async (args) => safeTool(async () => {
|
|
31
79
|
const decoded = decodeObjectStrings(args);
|
|
80
|
+
const me = sender(ctx);
|
|
32
81
|
switch (decoded.action) {
|
|
33
82
|
case 'list': {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return wrap(`当前无活跃的讨论 (本项目ID: ${ctx.projectId})${cleanMsg}`);
|
|
39
|
-
return wrap(`本项目ID: ${ctx.projectId}\n活跃讨论区 (${active.length} 个):${cleanMsg}\n\n` + JSON.stringify(active, null, 2));
|
|
83
|
+
const active = await client().discussionList();
|
|
84
|
+
if (!Array.isArray(active) || active.length === 0)
|
|
85
|
+
return wrap(`当前无活跃的讨论 (本项目: ${me})`);
|
|
86
|
+
return wrap(formatList(active, ctx));
|
|
40
87
|
}
|
|
41
88
|
case 'read': {
|
|
42
89
|
const readIds = decoded.ids || (decoded.id ? [decoded.id] : []);
|
|
43
90
|
if (readIds.length === 0)
|
|
44
91
|
return wrap('❌ read 需要 id 或 ids');
|
|
45
|
-
const discussions =
|
|
46
|
-
if (discussions.length === 0)
|
|
92
|
+
const discussions = await client().discussionReadByIds(readIds);
|
|
93
|
+
if (!Array.isArray(discussions) || discussions.length === 0)
|
|
47
94
|
return wrap('未找到对应的讨论记录');
|
|
48
|
-
return wrap(
|
|
95
|
+
return wrap(discussions.map(formatDetail).join('\n\n━━━━━━━━━━━━━━━━━━━━\n\n'));
|
|
49
96
|
}
|
|
50
97
|
case 'create': {
|
|
51
98
|
if (!decoded.title)
|
|
@@ -54,55 +101,30 @@ export function registerDiscussionTools(server, ctx) {
|
|
|
54
101
|
return wrap('❌ create 需要 participants');
|
|
55
102
|
if (!decoded.content)
|
|
56
103
|
return wrap('❌ create 需要 content');
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
return wrap('❌ 活跃讨论已达上限(10条)');
|
|
60
|
-
const id = DiscussionManager.create(decoded.title, ctx.projectId, decoded.participants, decoded.content);
|
|
61
|
-
return wrap(`✅ 讨论已发起,ID: ${id}\n发起方: ${ctx.projectId}\n参与方: ${decoded.participants.join(', ')}`);
|
|
104
|
+
const result = await client().discussionCreate(decoded.title, me, decoded.participants, decoded.content);
|
|
105
|
+
return wrap(`✅ 讨论已发起\nID: ${result.id}\n发起方: ${me}\n参与方: ${decoded.participants.join(', ')}`);
|
|
62
106
|
}
|
|
63
107
|
case 'reply': {
|
|
64
108
|
if (!decoded.id)
|
|
65
109
|
return wrap('❌ reply 需要 id');
|
|
66
110
|
if (!decoded.content)
|
|
67
111
|
return wrap('❌ reply 需要 content');
|
|
68
|
-
|
|
69
|
-
return wrap(
|
|
112
|
+
await client().discussionReply(decoded.id, me, decoded.content, decoded.newSummary);
|
|
113
|
+
return wrap(`✅ 回复成功 (ID: ${decoded.id}, 身份: ${me})`);
|
|
70
114
|
}
|
|
71
115
|
case 'close': {
|
|
72
116
|
if (!decoded.id)
|
|
73
117
|
return wrap('❌ close 需要 id');
|
|
74
118
|
if (!decoded.conclusion)
|
|
75
119
|
return wrap('❌ close 需要 conclusion');
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
return wrap('❌ 讨论不存在或已被归档清理');
|
|
79
|
-
let md = `# 跨项目协同: ${topic.title}\n\n`;
|
|
80
|
-
md += `**发起方**: ${topic.initiator}\n`;
|
|
81
|
-
md += `**参与方**: ${topic.participants.join(', ')}\n`;
|
|
82
|
-
md += `**结案总结**: ${decoded.conclusion}\n\n`;
|
|
83
|
-
md += `## 讨论还原 (Timeline)\n\n`;
|
|
84
|
-
for (const msg of topic.messages) {
|
|
85
|
-
md += `### [${msg.sender}] (${msg.timestamp})\n${msg.content}\n\n`;
|
|
86
|
-
}
|
|
87
|
-
const safeTitle = topic.title.replace(/[\/\\?%*:|"<>]/g, '_');
|
|
88
|
-
const path = `/跨项目协同记录/${decoded.id}_${safeTitle}`;
|
|
89
|
-
try {
|
|
90
|
-
await client().createDoc(path, {
|
|
91
|
-
summary: decoded.conclusion, content: md,
|
|
92
|
-
versions: [{ version: 1.0, date: new Date().toISOString(), changes: '结案归档' }],
|
|
93
|
-
bugfixes: [], status: '已完成'
|
|
94
|
-
});
|
|
95
|
-
return wrap(`✅ 讨论已结案并归档: \`${path}\``);
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
return wrap(`⚠️ 讨论已清除,但归档失败: ${err}\n\n${md}`);
|
|
99
|
-
}
|
|
120
|
+
const result = await client().discussionClose(decoded.id, decoded.conclusion);
|
|
121
|
+
return wrap(`✅ 讨论已结案并归档: \`${result.archived_path}\``);
|
|
100
122
|
}
|
|
101
123
|
case 'delete': {
|
|
102
124
|
if (!decoded.id)
|
|
103
125
|
return wrap('❌ delete 需要 id');
|
|
104
|
-
|
|
105
|
-
return wrap(
|
|
126
|
+
await client().discussionDelete(decoded.id);
|
|
127
|
+
return wrap(`✅ 讨论已删除 (ID: ${decoded.id})`);
|
|
106
128
|
}
|
|
107
129
|
default:
|
|
108
130
|
return wrap(`❌ 未知 action: ${decoded.action}`);
|
package/dist/tools/docs.d.ts
CHANGED
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
* kg_get_tree, kg_get_docs_by_status
|
|
5
5
|
*/
|
|
6
6
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
-
|
|
7
|
+
import { type McpContext } from './shared.js';
|
|
8
|
+
export declare function registerDocTools(server: McpServer, ctx: McpContext): void;
|
package/dist/tools/docs.js
CHANGED
|
@@ -7,7 +7,7 @@ import { z } from 'zod';
|
|
|
7
7
|
import { getClient } from '../storage/httpClient.js';
|
|
8
8
|
import { decodeObjectStrings } from '../utils.js';
|
|
9
9
|
import { wrap, safeTool, crossPrefix, formatDocMarkdown, formatTreeText, countTreeDocs } from './shared.js';
|
|
10
|
-
export function registerDocTools(server,
|
|
10
|
+
export function registerDocTools(server, ctx) {
|
|
11
11
|
const client = () => getClient();
|
|
12
12
|
// ========== kg_doc: 文档 CRUD 统一入口 ==========
|
|
13
13
|
server.tool('kg_doc', '📄 知识文档操作 — 创建、读取、更新、删除、复制文档。action: create(创建)|read(读取)|update(更新)|delete(删除)|batch_update(批量更新)|copy(跨项目复制)', {
|
package/dist/tools/index.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP 工具注册入口
|
|
3
|
-
*
|
|
3
|
+
* 18 个工具, 7 个子模块
|
|
4
4
|
*
|
|
5
5
|
* 🔗 初始化: kg_init (1个)
|
|
6
6
|
* 📊 导航: kg_status, kg_tree (2个)
|
|
7
7
|
* 📚 知识: kg_doc, kg_projects, kg_rules (3个)
|
|
8
8
|
* 📝 工作流: kg_task, kg_files, kg_discuss (3个)
|
|
9
|
-
* 🔬 代码分析: code_scan, code_query, code_impact, code_context, code_path (
|
|
9
|
+
* 🔬 代码分析: code_scan, code_query, code_impact, code_context, code_path, code_smart_context, code_full_path (7个)
|
|
10
|
+
* 🏛️ 协作: kg_meeting (1个)
|
|
10
11
|
*/
|
|
11
12
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
12
13
|
export declare function registerTools(server: McpServer, projectId: string, user: string, onProjectChange?: (newProjectId: string, newApiUrl: string) => void): void;
|
package/dist/tools/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP 工具注册入口
|
|
3
|
-
*
|
|
3
|
+
* 18 个工具, 7 个子模块
|
|
4
4
|
*
|
|
5
5
|
* 🔗 初始化: kg_init (1个)
|
|
6
6
|
* 📊 导航: kg_status, kg_tree (2个)
|
|
7
7
|
* 📚 知识: kg_doc, kg_projects, kg_rules (3个)
|
|
8
8
|
* 📝 工作流: kg_task, kg_files, kg_discuss (3个)
|
|
9
|
-
* 🔬 代码分析: code_scan, code_query, code_impact, code_context, code_path (
|
|
9
|
+
* 🔬 代码分析: code_scan, code_query, code_impact, code_context, code_path, code_smart_context, code_full_path (7个)
|
|
10
|
+
* 🏛️ 协作: kg_meeting (1个)
|
|
10
11
|
*/
|
|
11
12
|
import { createContext } from './shared.js';
|
|
12
13
|
import { registerInitTool } from './init.js';
|
|
@@ -18,6 +19,7 @@ import { registerTaskTools } from './tasks.js';
|
|
|
18
19
|
import { registerFileTools } from './files.js';
|
|
19
20
|
import { registerDiscussionTools } from './discussion.js';
|
|
20
21
|
import { registerAnalyzerTools } from './analyzer.js';
|
|
22
|
+
import { registerMeetingTools } from './meeting.js';
|
|
21
23
|
export function registerTools(server, projectId, user, onProjectChange) {
|
|
22
24
|
// 创建共享可变上下文 — 所有工具捕获此对象引用
|
|
23
25
|
const ctx = createContext(projectId, user);
|
|
@@ -26,13 +28,15 @@ export function registerTools(server, projectId, user, onProjectChange) {
|
|
|
26
28
|
// 📊 导航 (kg_status + kg_tree在docs中)
|
|
27
29
|
registerStatusTool(server, ctx);
|
|
28
30
|
// 📚 知识 (kg_doc + kg_tree + kg_projects + kg_rules)
|
|
29
|
-
registerDocTools(server, ctx
|
|
31
|
+
registerDocTools(server, ctx);
|
|
30
32
|
registerProjectTools(server, ctx);
|
|
31
33
|
registerRuleTools(server, ctx);
|
|
32
34
|
// 📝 工作流 (kg_task + kg_files + kg_discuss)
|
|
33
|
-
registerTaskTools(server, ctx
|
|
35
|
+
registerTaskTools(server, ctx);
|
|
34
36
|
registerFileTools(server);
|
|
35
37
|
registerDiscussionTools(server, ctx);
|
|
36
|
-
// 🔬 代码分析 (
|
|
37
|
-
registerAnalyzerTools(server, ctx
|
|
38
|
+
// 🔬 代码分析 (code_scan, code_query, code_impact, code_context, code_path, code_smart_context, code_full_path)
|
|
39
|
+
registerAnalyzerTools(server, ctx);
|
|
40
|
+
// 🏛️ 多AI协作 (kg_meeting)
|
|
41
|
+
registerMeetingTools(server, ctx);
|
|
38
42
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 多AI协作会议工具
|
|
3
|
+
* kg_meeting: join | leave | post | claim | release | status
|
|
4
|
+
*/
|
|
5
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
import { type McpContext } from './shared.js';
|
|
7
|
+
export declare function registerMeetingTools(server: McpServer, ctx: McpContext): void;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 多AI协作会议工具
|
|
3
|
+
* kg_meeting: join | leave | post | claim | release | status
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { getClient } from '../storage/httpClient.js';
|
|
7
|
+
import { wrap, safeTool } from './shared.js';
|
|
8
|
+
function formatStatus(status) {
|
|
9
|
+
const lines = [
|
|
10
|
+
`🏛️ 会议室: ${status.projectId}`,
|
|
11
|
+
``,
|
|
12
|
+
];
|
|
13
|
+
// 参与者
|
|
14
|
+
if (status.agents.length > 0) {
|
|
15
|
+
lines.push(`### 👥 参与者 (${status.agents.length})`);
|
|
16
|
+
for (const agent of status.agents) {
|
|
17
|
+
const ago = Math.floor((Date.now() / 1000 - agent.lastHeartbeat) / 60);
|
|
18
|
+
lines.push(` 🤖 ${agent.agentId} (${agent.agentType}) — 心跳 ${ago}分钟前`);
|
|
19
|
+
}
|
|
20
|
+
lines.push('');
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
lines.push('📭 会议室为空');
|
|
24
|
+
lines.push('');
|
|
25
|
+
}
|
|
26
|
+
// 文件锁
|
|
27
|
+
const locks = Object.entries(status.fileLocks);
|
|
28
|
+
if (locks.length > 0) {
|
|
29
|
+
lines.push(`### 🔒 文件锁定 (${locks.length})`);
|
|
30
|
+
for (const [file, owner] of locks) {
|
|
31
|
+
lines.push(` 📄 ${file} ← ${owner}`);
|
|
32
|
+
}
|
|
33
|
+
lines.push('');
|
|
34
|
+
}
|
|
35
|
+
// 最近消息
|
|
36
|
+
if (status.recentMessages.length > 0) {
|
|
37
|
+
lines.push(`### 💬 最近消息 (${status.recentMessages.length})`);
|
|
38
|
+
for (const msg of status.recentMessages.slice(-10)) {
|
|
39
|
+
const time = new Date(msg.timestamp * 1000).toLocaleTimeString();
|
|
40
|
+
const icon = msg.msgType === 'decision' ? '⚡' : msg.msgType === 'question' ? '❓' : '💬';
|
|
41
|
+
lines.push(` ${icon} [${time}] ${msg.agentId}: ${msg.content}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return lines.join('\n');
|
|
45
|
+
}
|
|
46
|
+
export function registerMeetingTools(server, ctx) {
|
|
47
|
+
const client = () => getClient();
|
|
48
|
+
server.tool('kg_meeting', '🏛️ 多AI协作会议 — 多个AI编辑器同时操作同一项目时,通过"会议室"共享状态、认领文件、发布决策。action: join(加入)|leave(离开)|post(发消息)|claim(认领文件)|release(释放文件)|status(查看状态)', {
|
|
49
|
+
action: z.enum(['join', 'leave', 'post', 'claim', 'release', 'status']).describe('操作类型'),
|
|
50
|
+
agentId: z.string().optional().describe('Agent标识(如"cursor-1", "claude-code-2")。join/leave/post/claim/release 必填'),
|
|
51
|
+
agentType: z.string().optional().describe('Agent类型(如"cursor", "claude", "kiro")。join 时使用'),
|
|
52
|
+
content: z.string().optional().describe('消息内容 (post 时必填)'),
|
|
53
|
+
msgType: z.enum(['status', 'decision', 'question']).optional().describe('消息类型 (post, 默认status)'),
|
|
54
|
+
filePath: z.string().optional().describe('文件路径 (claim/release 时必填)'),
|
|
55
|
+
}, async (args) => safeTool(async () => {
|
|
56
|
+
switch (args.action) {
|
|
57
|
+
case 'join': {
|
|
58
|
+
if (!args.agentId)
|
|
59
|
+
return wrap('❌ join 需要 agentId');
|
|
60
|
+
const status = await client().meetingJoin(args.agentId, args.agentType || 'unknown');
|
|
61
|
+
return wrap(`✅ ${args.agentId} 已加入会议\n\n${formatStatus(status)}`);
|
|
62
|
+
}
|
|
63
|
+
case 'leave': {
|
|
64
|
+
if (!args.agentId)
|
|
65
|
+
return wrap('❌ leave 需要 agentId');
|
|
66
|
+
const status = await client().meetingLeave(args.agentId);
|
|
67
|
+
return wrap(`✅ ${args.agentId} 已离开会议\n\n${formatStatus(status)}`);
|
|
68
|
+
}
|
|
69
|
+
case 'post': {
|
|
70
|
+
if (!args.agentId || !args.content)
|
|
71
|
+
return wrap('❌ post 需要 agentId 和 content');
|
|
72
|
+
const status = await client().meetingPost(args.agentId, args.content, args.msgType || 'status');
|
|
73
|
+
return wrap(`✅ 消息已发送\n\n${formatStatus(status)}`);
|
|
74
|
+
}
|
|
75
|
+
case 'claim': {
|
|
76
|
+
if (!args.agentId || !args.filePath)
|
|
77
|
+
return wrap('❌ claim 需要 agentId 和 filePath');
|
|
78
|
+
const status = await client().meetingClaim(args.agentId, args.filePath);
|
|
79
|
+
return wrap(`✅ ${args.agentId} 已认领 ${args.filePath}\n\n${formatStatus(status)}`);
|
|
80
|
+
}
|
|
81
|
+
case 'release': {
|
|
82
|
+
if (!args.agentId || !args.filePath)
|
|
83
|
+
return wrap('❌ release 需要 agentId 和 filePath');
|
|
84
|
+
const status = await client().meetingRelease(args.agentId, args.filePath);
|
|
85
|
+
return wrap(`✅ ${args.agentId} 已释放 ${args.filePath}\n\n${formatStatus(status)}`);
|
|
86
|
+
}
|
|
87
|
+
case 'status': {
|
|
88
|
+
const status = await client().meetingStatus();
|
|
89
|
+
if (!status)
|
|
90
|
+
return wrap('📭 该项目暂无活跃会议');
|
|
91
|
+
return wrap(formatStatus(status));
|
|
92
|
+
}
|
|
93
|
+
default:
|
|
94
|
+
return wrap(`❌ 未知 action: ${args.action}`);
|
|
95
|
+
}
|
|
96
|
+
}));
|
|
97
|
+
}
|
package/dist/tools/tasks.d.ts
CHANGED
|
@@ -3,4 +3,5 @@
|
|
|
3
3
|
* 合并: task_create, task_get, task_update, task_archive
|
|
4
4
|
*/
|
|
5
5
|
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
-
|
|
6
|
+
import { type McpContext } from './shared.js';
|
|
7
|
+
export declare function registerTaskTools(server: McpServer, ctx: McpContext): void;
|
package/dist/tools/tasks.js
CHANGED
|
@@ -6,7 +6,7 @@ import { z } from 'zod';
|
|
|
6
6
|
import { getClient } from '../storage/httpClient.js';
|
|
7
7
|
import { decodeObjectStrings } from '../utils.js';
|
|
8
8
|
import { wrap, safeTool } from './shared.js';
|
|
9
|
-
export function registerTaskTools(server,
|
|
9
|
+
export function registerTaskTools(server, ctx) {
|
|
10
10
|
const client = () => getClient();
|
|
11
11
|
server.tool('kg_task', '📝 任务管理 — 创建、查询、更新进展、归档。action: create(创建)|get(查询)|update(添加日志)|archive(归档)', {
|
|
12
12
|
action: z.enum(['create', 'get', 'update', 'archive'])
|
|
@@ -43,7 +43,7 @@ export function registerTaskTools(server, projectId, user) {
|
|
|
43
43
|
title: decoded.title,
|
|
44
44
|
description: decoded.description,
|
|
45
45
|
goals: decoded.goals || []
|
|
46
|
-
}, user);
|
|
46
|
+
}, ctx.user);
|
|
47
47
|
return wrap(JSON.stringify(task, null, 2));
|
|
48
48
|
}
|
|
49
49
|
case 'get': {
|
package/package.json
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# 🛡️ "Sentinel-4" 多智能体审计协议 任务成果审查或代码审查
|
|
2
|
+
|
|
3
|
+
本工作流启用**4个独立智能体**并行工作,对任务成果进行“死刑级”严格审查。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### 1.智能体部署 (Agent Deployment) 🤖
|
|
8
|
+
四个专家智能体同时介入,各司其职:
|
|
9
|
+
|
|
10
|
+
#### 🕵️ 智能体 A:逻辑审计官 (Logic Auditor)
|
|
11
|
+
* **职责**:对照预期目标。
|
|
12
|
+
* **检查点**:
|
|
13
|
+
* 🔹 流程是否完全闭环?
|
|
14
|
+
* 🔹 是否存在逻辑断层?
|
|
15
|
+
|
|
16
|
+
#### 🧹 智能体 B:代码清洁工 (Code Janitor)
|
|
17
|
+
* **职责**:通过静态分析寻找“垃圾”。
|
|
18
|
+
* **检查点**:
|
|
19
|
+
* × **死代码 (Dead Code)**:检测未被调用的函数/变量。
|
|
20
|
+
* × **新旧混合**:确保没有注释掉的旧逻辑残留。
|
|
21
|
+
* × **冗余**:消除任何重复逻辑。
|
|
22
|
+
|
|
23
|
+
#### ⚡ 智能体 C:极简架构师 (Minimalist Architect)
|
|
24
|
+
* **职责**:强制执行“单行原则”与模块化。
|
|
25
|
+
* **检查点**:
|
|
26
|
+
* 🔹 **解耦**:模块之间是否彻底分离?
|
|
27
|
+
* 🔹 **行数**:两行能写完的,是否用了三行?(臃肿判定)
|
|
28
|
+
|
|
29
|
+
#### 📚 智能体 D:知识图谱守护者 (Graph Keeper)
|
|
30
|
+
* **职责**:真理一致性校验。
|
|
31
|
+
* **检查点**:
|
|
32
|
+
* × **偏差**:代码逻辑是否违背了知识图谱中的标准定义?
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### 2.综合裁决 (Synthesis & Verdict) ⚖️
|
|
37
|
+
* **汇总**:收集 4 个智能体的 Flag(报错)。
|
|
38
|
+
* **判定**:
|
|
39
|
+
* 只要有 **1个** 智能体亮红灯 🔴 -> **驳回重构**。
|
|
40
|
+
* 全员亮绿灯 🟢 -> **生成最终报告**。
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### 3.最终交付:审查报告 (Final Report) 📝
|
|
45
|
+
报告将以“简单自然语言 + 可视化图标”输出:
|
|
46
|
+
* **状态**:✅ 通过 / ❌ 驳回
|
|
47
|
+
* **评分**:代码纯净度 (0-100%)
|
|
48
|
+
* **风险点**:(如果有)
|
|
49
|
+
* **改进建议**:(针对性优化)
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
### 📊 审计流程可视化图解 (ASCII)
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
+----------------------+
|
|
57
|
+
| 📦 提交任务成果 |
|
|
58
|
+
+----------+-----------+
|
|
59
|
+
|
|
|
60
|
+
v
|
|
61
|
+
+----------+-----------+
|
|
62
|
+
| ⚡ 并行分发 |
|
|
63
|
+
+----------+-----------+
|
|
64
|
+
/ / | \ \
|
|
65
|
+
v v v v v
|
|
66
|
+
+--------+ +--------+ +--------+ +--------+
|
|
67
|
+
| 🕵️ A | | 🧹 B | | ⚡ C | | 📚 D |
|
|
68
|
+
| 逻辑 | | 代码 | | 极简 | | 图谱 |
|
|
69
|
+
+--------+ +--------+ +--------+ +--------+
|
|
70
|
+
| | | |
|
|
71
|
+
+--------+--------+--------+
|
|
72
|
+
|
|
|
73
|
+
v
|
|
74
|
+
+--------+--------+
|
|
75
|
+
| ⚖️ 综合裁决 |
|
|
76
|
+
+--------+--------+
|
|
77
|
+
|
|
|
78
|
+
/-------+-------\
|
|
79
|
+
/ 发现问题? \
|
|
80
|
+
v v
|
|
81
|
+
+-----------+ +------------+
|
|
82
|
+
| ❌ 驳回 | | 📝 生成报告 |
|
|
83
|
+
| (Reject) | | (Success) |
|
|
84
|
+
+-----------+ +------------+
|
|
85
|
+
|
|
|
86
|
+
v
|
|
87
|
+
(To: Iteration Loop)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# 🔍 "Deep-Trace" Diagnostic Protocol (深层溯源诊断协议)
|
|
2
|
+
|
|
3
|
+
核心理念:**先在宏观地图(图谱)上定位,再在微观战场(代码)上排查,绝不盲目翻看代码。**
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
### 1.第一阶段:知识锚定 (Knowledge Anchoring) ⚓️
|
|
8
|
+
🔹 **核心目标**:在动手之前,通过 PPDocs 明确“正确应该是什么样”。
|
|
9
|
+
✏️ **动作**:
|
|
10
|
+
* **查询图谱**:输入问题关键词,提取标准业务逻辑。
|
|
11
|
+
* **建立基准**:以图谱中的描述作为“真理标准 (Truth)”。
|
|
12
|
+
× **禁区**:
|
|
13
|
+
* 禁止在未查询图谱前,直接跳入代码库阅读(防止陷入细节泥潭)。
|
|
14
|
+
|
|
15
|
+
### 2.第二阶段:抽象映射 (Abstract Mapping) 🗺️
|
|
16
|
+
🔹 **核心目标**:利用链式思维 (CoT),绘制高层级逻辑流。
|
|
17
|
+
✏️ **动作**:
|
|
18
|
+
* **绘制流程**:忽略实现细节,仅画出模块间的输入/输出流转(数据流)。
|
|
19
|
+
* **可视化**:生成 ASCII 或 Mermaid 流程图,展示当前链路。
|
|
20
|
+
* **标记疑点**:在流程图上圈出逻辑可能断裂的节点。
|
|
21
|
+
|
|
22
|
+
### 3.第三阶段:靶点锁定 (Target Locking) 🎯
|
|
23
|
+
🔹 **核心目标**:将问题范围从“整个项目”缩小到“单一节点”。
|
|
24
|
+
✏️ **动作**:
|
|
25
|
+
* **定位区域**:确定问题具体发生在 PPDocs 的哪个 `Node`(节点)或 `Edge`(连线)上。
|
|
26
|
+
* **隔离上下文**:只关注该节点的前置依赖(Pre-requisites)和后置影响(Post-effects)。
|
|
27
|
+
|
|
28
|
+
### 4.第四阶段:双层取证 (Dual-Layer Forensics) 🕵️
|
|
29
|
+
🔹 **核心目标**:对比“理论(图谱)”与“现实(代码)”的差异。
|
|
30
|
+
✏️ **动作**:
|
|
31
|
+
* **左眼看图谱**:阅读 PPDocs 中该节点的逻辑定义。
|
|
32
|
+
* **右眼看代码**:审查该节点对应的实际代码实现。
|
|
33
|
+
* **寻找裂痕**:
|
|
34
|
+
* 🔴 **代码错误 (Bug)**:图谱逻辑正确,代码实现错误。
|
|
35
|
+
* 🟠 **设计缺陷 (Design Flaw)**:代码符合图谱,但结果依然错误(图谱本身逻辑有误)。
|
|
36
|
+
* 🟡 **文档脱节 (Sync Issue)**:代码逻辑正确且有效,但图谱未记载(需同步)。
|
|
37
|
+
|
|
38
|
+
### 5.第五阶段:分析结案 (Verdict) 📝
|
|
39
|
+
🔹 **核心目标**:输出可执行的诊断报告。
|
|
40
|
+
✏️ **动作**:
|
|
41
|
+
* 输出标准化的**《问题诊断报告》**。
|
|
42
|
+
* **流转**:将报告作为输入,传递给 **[任务方案生成工作流]** 进行修复。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
### 📊 诊断逻辑可视化图解 (ASCII)
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
+-------------------------+
|
|
50
|
+
| 🚨 问题触发 (Issue) |
|
|
51
|
+
+------------+------------+
|
|
52
|
+
|
|
|
53
|
+
v
|
|
54
|
+
+------------+------------+
|
|
55
|
+
| ⚓️ 知识锚定 (PPDocs) | <--- 获取标准逻辑 (Truth)
|
|
56
|
+
+------------+------------+
|
|
57
|
+
|
|
|
58
|
+
v
|
|
59
|
+
[ 🗺️ 抽象逻辑层 ]
|
|
60
|
+
+-------------------------+
|
|
61
|
+
| Step1 -> Step2 ... | (绘制链式流程)
|
|
62
|
+
| | |
|
|
63
|
+
| [ ? ] <---------+--- 🎯 锁定可疑节点
|
|
64
|
+
+-----------+-------------+
|
|
65
|
+
|
|
|
66
|
+
v
|
|
67
|
+
+-----------+-------------+
|
|
68
|
+
| 🕵️ 双层取证 (Compare) |
|
|
69
|
+
+-----+-------------+-----+
|
|
70
|
+
| |
|
|
71
|
+
(📜 PPDocs) vs (💻 Code)
|
|
72
|
+
| |
|
|
73
|
+
+------+------+
|
|
74
|
+
|
|
|
75
|
+
v
|
|
76
|
+
/-------+-------\
|
|
77
|
+
/ 根本原因? \
|
|
78
|
+
v v
|
|
79
|
+
+--------------+ +--------------+
|
|
80
|
+
| 🐛 代码 Bug | | 📐 设计/文档错 |
|
|
81
|
+
| (Fix Code) | | (Fix Graph) |
|
|
82
|
+
+--------------+ +--------------+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# 💬 Discussion Responder (讨论响应协议)
|
|
2
|
+
|
|
3
|
+
本工作流用于检查、分析、回复跨项目讨论。可手动触发或会话启动时自动检查。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 标准流程
|
|
8
|
+
|
|
9
|
+
### Step 1: 扫描待处理讨论
|
|
10
|
+
```
|
|
11
|
+
kg_discuss({ action: "list" })
|
|
12
|
+
```
|
|
13
|
+
- 过滤涉及本项目的讨论 (sender 含本项目ID)
|
|
14
|
+
- 无讨论 → 输出 "当前无待处理讨论" → 结束
|
|
15
|
+
|
|
16
|
+
### Step 2: 展示摘要
|
|
17
|
+
以表格展示所有待处理讨论:
|
|
18
|
+
|
|
19
|
+
| ID | 标题 | 发起方 | 摘要 | 回复数 | 更新时间 |
|
|
20
|
+
|:---|:---|:---|:---|:---:|:---|
|
|
21
|
+
|
|
22
|
+
用户选择要处理的讨论 (可多选)
|
|
23
|
+
|
|
24
|
+
### Step 3: 读取详情 + 知识锚定
|
|
25
|
+
```
|
|
26
|
+
kg_discuss({ action: "read", id: "选中ID" })
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**并行执行**:
|
|
30
|
+
1. 阅读讨论全部消息, 理解各方立场
|
|
31
|
+
2. `kg_search` 检索相关知识节点, 获取本项目的标准逻辑
|
|
32
|
+
3. `kg_get_rules(ruleType: "codeStyle")` 获取编码规范 (如涉及代码)
|
|
33
|
+
|
|
34
|
+
### Step 4: 分析与回复
|
|
35
|
+
**分析框架**:
|
|
36
|
+
| 维度 | 检查 |
|
|
37
|
+
|:---|:---|
|
|
38
|
+
| 技术可行性 | 本项目能否支持对方提出的方案? |
|
|
39
|
+
| 影响范围 | 改动会影响本项目哪些模块? |
|
|
40
|
+
| 替代方案 | 是否有更优解? |
|
|
41
|
+
| 依赖关系 | 需要对方先做什么? 本方需要先做什么? |
|
|
42
|
+
|
|
43
|
+
**回复**:
|
|
44
|
+
```
|
|
45
|
+
kg_discuss({
|
|
46
|
+
action: "reply",
|
|
47
|
+
id: "讨论ID",
|
|
48
|
+
content: "基于分析的回复内容",
|
|
49
|
+
newSummary: "更新摘要 (可选, 如有阶段性结论)"
|
|
50
|
+
})
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 5: 结案判断
|
|
54
|
+
如果所有方已达成共识:
|
|
55
|
+
```
|
|
56
|
+
kg_discuss({
|
|
57
|
+
action: "close",
|
|
58
|
+
id: "讨论ID",
|
|
59
|
+
conclusion: "结案总结 (含最终方案 + 各方责任)"
|
|
60
|
+
})
|
|
61
|
+
```
|
|
62
|
+
归档文档自动存入知识图谱。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 回复质量标准
|
|
67
|
+
| 要求 | 说明 |
|
|
68
|
+
|:---|:---|
|
|
69
|
+
| **有据可查** | 引用知识图谱节点或代码文件支撑观点 |
|
|
70
|
+
| **明确立场** | 同意/反对/有条件同意, 不含糊 |
|
|
71
|
+
| **可执行** | 回复中包含具体行动项, 非空谈 |
|
|
72
|
+
| **格式规范** | Markdown 格式, 要点用列表, 代码用代码块 |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## 发起新讨论
|
|
77
|
+
当本项目需要向其他项目发起协商:
|
|
78
|
+
```
|
|
79
|
+
kg_discuss({
|
|
80
|
+
action: "create",
|
|
81
|
+
title: "讨论标题",
|
|
82
|
+
participants: ["目标项目ID"],
|
|
83
|
+
content: "问题描述 + 本方立场 + 期望回复"
|
|
84
|
+
})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**发起前检查**:
|
|
88
|
+
1. `kg_search` 确认问题确实需要跨项目协商
|
|
89
|
+
2. 明确参与方 (通过 `kg_projects` 查看可用项目)
|
|
90
|
+
3. 内容包含: 背景、问题、本方方案、期望对方行动
|