@ppdocs/mcp 3.2.36 → 3.2.38

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.
@@ -6,7 +6,7 @@
6
6
 
7
7
  | 文件 | 用途 | 目标路径 |
8
8
  |-----|------|---------|
9
- | `hooks/hook.py` | 动态规则触发脚本 (关键词匹配 + 批量获取) | `.claude/hooks/hook.py` |
9
+ | `hooks/hook.py` | 动态文档工作流触发脚本 (关键词匹配 + 批量获取) | `.claude/hooks/hook.py` |
10
10
  | `hooks/SystemPrompt.md` | 系统提示词模板 | `.claude/hooks/SystemPrompt.md` |
11
11
  | `commands/pp/` | Claude Code 自定义命令 | `.claude/commands/pp/` |
12
12
  | `AGENT.md` | Codex/通用 Agent 提示词 | `./AGENTS.md` |
@@ -45,7 +45,7 @@ CLI 通过 `detectIDEs()` 扫描项目目录,自动为检测到的 IDE 安装
45
45
  ## Hook 触发机制
46
46
 
47
47
  ```
48
- 用户输入 → hook.py → GET /rules-meta → 关键词匹配 → POST /rules/batch → 输出规则
48
+ 用户输入 → hook.py → GET /workflows → 关键词匹配 → POST /workflows/batch → 输出工作流
49
49
  ```
50
50
 
51
51
  hooks 配置由 CLI 动态生成 (`generateHooksConfig()`),无需静态模板文件。
@@ -4,7 +4,7 @@ description: 初始化知识图谱:100%扫描代码库,为每个模块创建
4
4
 
5
5
  # /init 项目初始化
6
6
 
7
- 执行 `task_create("项目初始化: [项目名]")` → 递归扫描全部代码文件 → 逐文件审查创建节点 → 每处理5个文件调用 `task_add_log(progress)` 同步进度 → 全部完成后 `task_complete` 输出统计报告
7
+ 执行 `kg_task(action:"create", title:"项目初始化: [项目名]")` → 递归扫描全部代码文件 → 逐文件审查创建节点 → 每处理5个文件调用 `kg_task(action:"update", log_type:"progress")` 同步进度 → 全部完成后 `kg_task(action:"archive")` 输出统计报告
8
8
 
9
9
  ## 扫描规则
10
10
 
@@ -84,11 +84,11 @@ flowchart TB
84
84
 
85
85
  ## 进度同步
86
86
 
87
- 每处理5个文件或完成1个目录后,调用 `task_add_log("progress", "已处理: [文件列表], 创建节点: N个")`
87
+ 每处理5个文件或完成1个目录后,调用 `kg_task(action:"update", log_type:"progress", content:"已处理: [文件列表], 创建节点: N个")`
88
88
 
89
89
  ## 完成输出
90
90
 
91
- `task_complete` 时输出完整统计:
91
+ `kg_task(action:"archive")` 时输出完整统计:
92
92
 
93
93
  ```markdown
94
94
  | 统计项 | 数量 |
@@ -19,9 +19,9 @@
19
19
 
20
20
  **1.1 建立全景**
21
21
  ```
22
- kg_tree() 知识全景图
23
- kg_flowchart(action:"get") → 主图结构 (8个模块 + 连线)
24
- kg_rules(action:"get", ruleType:"errorAnalysis") → 错误分析规则
22
+ kg_flowchart(action:"list") 知识图谱列表
23
+ kg_flowchart(action:"get") → 主图结构 (模块 + 连线)
24
+ kg_workflow(id:"review-audit") → 诊断工作流
25
25
  ```
26
26
 
27
27
  **1.2 关键词定位模块**
@@ -68,7 +68,7 @@ Step 3: 输出疑点路径
68
68
 
69
69
  ```
70
70
  code_smart_context(嫌疑符号名)
71
- → 代码依赖 + 关联文档 + 匹配规则 + 影响范围摘要
71
+ → 代码依赖 + 关联文档 + 匹配工作流 + 影响范围摘要
72
72
 
73
73
  code_impact(嫌疑符号名)
74
74
  → L1 直接引用 (必须检查)
@@ -162,9 +162,9 @@ L2: 2个间接调用方可能受影响
162
162
 
163
163
  | 阶段 | 工具 | 用途 |
164
164
  |:---|:---|:---|
165
- | 锚定 | `kg_tree()` | 全景鸟瞰 |
165
+ | 锚定 | `kg_flowchart(list/get)` | 全景鸟瞰 |
166
166
  | 锚定 | `kg_flowchart(get)` | 主图结构 |
167
- | 锚定 | `kg_rules(get)` | 分析规则 |
167
+ | 锚定 | `kg_workflow()` / `kg_workflow(id:"...")` | 分析工作流 |
168
168
  | 下探 | `kg_flowchart(get_node, expand:N)` | 节点详情+上下游 |
169
169
  | 下探 | `kg_flowchart(get, chartId:子图)` | 进入子图 |
170
170
  | 半径 | `code_smart_context(symbol)` | 全关联上下文 |
@@ -27,10 +27,10 @@
27
27
 
28
28
  ### Phase 0: 环境准备
29
29
  ```
30
- kg_init() → 连接项目上下文
31
- kg_status() → 查看仪表盘 (文档数/任务数/状态)
32
- kg_tree() 已有知识全景图
33
- kg_flowchart(action:"list") → 已有流程图列表
30
+ kg_init() → 连接项目上下文
31
+ kg_status() → 查看仪表盘 (流程图/任务/状态)
32
+ kg_flowchart(action:"list") 已有流程图列表
33
+ kg_flowchart(action:"get") → 主图结构总览
34
34
  ```
35
35
  如果已有图谱 → 提示用户选择: 增量补充 or 重建
36
36
 
@@ -125,27 +125,18 @@ kg_flowchart(action:"bind", nodeId:"n_graph_store",
125
125
  dirs:["src-tauri/src/storage/"])
126
126
  ```
127
127
 
128
- **3.2 创建参考文档 (遵循5分类规范)**
128
+ **3.2 写入节点内置文档 (`docEntries`)**
129
129
  ```
130
- 文档分类:
131
- /模块/后端/存储层 → 对应 n_storage
132
- /模块/后端/graph_store 对应 n_graph_store
133
- /模块/前端/FlowchartView → 对应 n_flowchart_view
134
- /架构/事件驱动 → 对应架构决策
135
- /功能/知识图谱编辑 → 对应用户功能
136
-
137
- kg_doc(action:"create",
138
- path:"/模块/后端/graph_store",
139
- summary:"项目/文档/规则/搜索的核心存储, JSON持久化",
140
- content:"## 职责\n...\n## 公开API\n...\n## 文件路径\n...",
141
- bindTo:"n_graph_store")
130
+ kg_flowchart(action:"update_node", chartId:"sub_storage", nodeId:"n_graph_store",
131
+ docSummary:"项目/规则/流程图数据持久化核心",
132
+ docContent:"## 职责\n...\n## 公开 API\n...\n## 文件路径\n- src-tauri/src/storage/graph_store.rs")
142
133
  ```
143
134
 
144
135
  ### Phase 4: 健康验证
145
136
  ```
146
137
  kg_flowchart(action:"orphans") → 孤立节点 (应为0)
147
138
  kg_flowchart(action:"health") → 冷热分布
148
- kg_tree() 全景确认文档覆盖
139
+ kg_flowchart(action:"get") 全景确认节点覆盖与连线
149
140
  kg_status() → 最终仪表盘
150
141
  ```
151
142
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  | 原则 | 要求 |
6
6
  |:---|:---|
7
- | **规则驱动** | 必须先加载 kg_rules, 以项目规则为审查标准 |
7
+ | **工作流驱动** | 必须先加载 kg_workflow, Markdown 工作流为审查标准 |
8
8
  | **4维并行** | 逻辑/清洁/极简/图谱一致性 同时扫描 |
9
9
  | **零容忍** | 任一维度 CRITICAL 即驳回, 不存在"下次再改" |
10
10
  | **健康闭环** | 审查必须包含图谱健康检查, 确保知识库同步 |
@@ -26,11 +26,10 @@
26
26
  ### Phase 0: 加载审查标准
27
27
 
28
28
  ```
29
- kg_rules(action:"get", ruleType:"reviewRules") 审查规则
30
- kg_rules(action:"get", ruleType:"codeStyle") 编码风格
31
- kg_rules(action:"get", ruleType:"errorAnalysis") → 错误分析规则
29
+ kg_workflow(id:"review-audit") 审查/诊断工作流
30
+ kg_workflow(id:"common-general")通用执行工作流
32
31
  ```
33
- 将获取的规则作为本次审查的量化标准。
32
+ 将获取的文档工作流作为本次审查的量化标准。
34
33
 
35
34
  **确定审查范围**:
36
35
  ```
@@ -75,7 +74,7 @@ Bash: git log --oneline -3 → 近期提交
75
74
 
76
75
  #### C. 极简架构
77
76
  ```
78
- 对照 codeStyle 规则逐条检查:
77
+ 对照已加载文档工作流中的编码约束逐条检查:
79
78
  × 函数超50行 → 🟡 拆分建议
80
79
  × 嵌套超3层 → 🟡 扁平化建议
81
80
  × 重复造轮子 (code_query 搜索已有实现) → 🔴
@@ -144,9 +143,9 @@ kg_flowchart(action:"health")
144
143
  **概览**: 评分 85/100 | 🔴 0 | 🟡 2 | 🔵 1
145
144
  **状态**: ✅ 通过 / ❌ 驳回
146
145
 
147
- **应用规则**:
148
- - reviewRules: 已加载 N 条
149
- - codeStyle: 已加载 M 条
146
+ **应用文档工作流**:
147
+ - review-audit: 已加载
148
+ - common-general: 已加载
150
149
 
151
150
  **逻辑验证图** (A维度):
152
151
  [用户输入] → [参数校验] → [业务处理] → [返回结果] ✅ 闭环
@@ -174,7 +173,7 @@ kg_flowchart(action:"health")
174
173
 
175
174
  | 阶段 | 工具 | 用途 |
176
175
  |:---|:---|:---|
177
- | 加载 | `kg_rules(get)` | 审查规则/编码风格 |
176
+ | 加载 | `kg_workflow(id:"...")` | 审查/执行工作流 |
178
177
  | 范围 | `code_context(file)` | 变更文件的依赖 |
179
178
  | A逻辑 | 人工推演 + ASCII图 | 逻辑闭环验证 |
180
179
  | B清洁 | `Grep(pattern)` | 死代码/调试残留扫描 |
@@ -7,7 +7,7 @@
7
7
  | **代码即真理** | 代码与图谱冲突时以 Git 状态为准, 强制覆写 |
8
8
  | **层级感知** | 变更定位到具体子图层级, 逐层向上验证影响链 |
9
9
  | **最小变更** | 只更新有差异的节点/文档, 不做无意义的全量覆写 |
10
- | **创建即关联** | 新增节点必须 bind 源码 + 创建/关联文档, 无孤立资产 |
10
+ | **创建即关联** | 新增节点必须 bind 源码 + 写入节点文档, 无孤立资产 |
11
11
 
12
12
  ---
13
13
 
@@ -30,9 +30,9 @@
30
30
  **1.1 获取图谱现状**
31
31
  ```
32
32
  kg_init() → 确保项目连接
33
- kg_tree() → 文档全景
34
33
  kg_flowchart(action:"list") → 所有流程图
35
34
  kg_flowchart(action:"get") → 主图节点+连线
35
+ kg_flowchart(action:"search", query:"关键词") → 快速定位相关节点
36
36
  ```
37
37
 
38
38
  **1.2 获取代码变更**
@@ -106,12 +106,10 @@ all 模式:
106
106
  3. 绑定源码:
107
107
  kg_flowchart(action:"bind", nodeId:"n_xxx", files:["src/..."])
108
108
 
109
- 4. 创建文档 (遵循5分类):
110
- kg_doc(action:"create",
111
- path:"/模块/前端/xxx",
112
- summary:"一句话职责",
113
- content:"## 职责\n...\n## 公开API\n...\n## 文件路径\n...",
114
- bindTo:"n_xxx")
109
+ 4. 写入节点文档:
110
+ kg_flowchart(action:"update_node", chartId:目标子图, nodeId:"n_xxx",
111
+ docSummary:"一句话职责",
112
+ docContent:"## 职责\n...\n## 公开API\n...\n## 文件路径\n...")
115
113
  ```
116
114
 
117
115
  **3.2 处理 [MOD] — 更新节点**
@@ -126,8 +124,9 @@ all 模式:
126
124
  docSummary:"更新后的摘要")
127
125
 
128
126
  3. 追加版本记录:
129
- kg_doc(action:"update", path:"/模块/.../xxx",
130
- versions:[{version:当前+0.1, date:"ISO日期", changes:"变更摘要"}])
127
+ kg_flowchart(action:"update_node", chartId:目标子图, nodeId:"n_xxx",
128
+ docSummary:"本次变更摘要",
129
+ docContent:"更新后的详细文档")
131
130
 
132
131
  4. 检查连线是否需要更新:
133
132
  code_context(filePath) → 新的import列表
@@ -142,7 +141,6 @@ all 模式:
142
141
 
143
142
  选项B - 彻底删除:
144
143
  kg_flowchart(action:"delete_node", nodeId:"n_xxx")
145
- kg_doc(action:"delete", path:"/模块/.../xxx")
146
144
  ```
147
145
 
148
146
  **3.4 处理 [DRIFT] — 路径漂移**
@@ -177,7 +175,7 @@ kg_task(action:"update", taskId:"当前任务", log_type:"progress",
177
175
  ```
178
176
  kg_flowchart(action:"orphans") → 全局孤立节点 (应为0)
179
177
  kg_flowchart(action:"health") → 冷热分布
180
- kg_tree() 文档覆盖确认
178
+ kg_flowchart(action:"get") 节点覆盖确认
181
179
  ```
182
180
 
183
181
  ### Phase 5: 交付报告
@@ -12,9 +12,10 @@ kg_discuss(action:"list") -> ???????
12
12
  ## 1. ????????
13
13
 
14
14
  - ??: `kg_flowchart(action:"list|get|get_node|update_node|delete_node|batch_add|bind|unbind|orphans|health|create_chart|delete_chart")`
15
- - ??: `kg_rules(action:"get|save|get_meta|save_meta")`
15
+ - ??: `kg_workflow()` / `kg_workflow(id:"...")` / `kg_workflow(action:"save|delete")`
16
16
  - ??: `kg_task(action:"create|get|update|archive|delete")`
17
17
  - ??: `kg_files(action:"list|read|upload|download|public_*")`
18
+ - ??: `kg_ref(action:"list|get|save|delete|read_file")`
18
19
  - ??/??: `kg_discuss(...)`, `kg_meeting(...)`
19
20
  - ????: `code_scan()`, `code_smart_context(symbolName)`, `code_full_path(symbolA, symbolB)`
20
21
  - ????: ?????????????????????????????? fallback????????????
@@ -22,7 +23,7 @@ kg_discuss(action:"list") -> ???????
22
23
  ## 2. ?????
23
24
 
24
25
  ### Step 1: ????
25
- 1. ?? `kg_flowchart(get)` ????????? `kg_rules(get)` ?????
26
+ 1. ?? `kg_flowchart(get)` ????????? `kg_workflow()` ?????
26
27
  2. ???????? `kg_flowchart(get_node, expand:2, includeDoc:true, includeFiles:true)`?
27
28
  3. ????? `subFlowchart`???????????????
28
29
  4. ??????????? `code_scan()`??? `code_smart_context` / `code_full_path`?
@@ -7,8 +7,8 @@
7
7
  | 原则 | 要求 |
8
8
  |:---|:---|
9
9
  | **知识图谱中心** | 方案制定前检索图谱+代码双重验证;任务结束提示沉淀至图谱 |
10
- | **任务驱动开发** | 复杂任务必须 `task_create`;过程记录 `task_add_log`;完成 `task_complete` |
11
- | **规则引用** | 编码前读 `codeStyle`;测试前读 `testRules`;审查前读 `reviewRules` |
10
+ | **任务驱动开发** | 复杂任务必须 `kg_task(action:"create")`;过程记录 `kg_task(action:"update")`;完成 `kg_task(action:"archive")` |
11
+ | **工作流引用** | `kg_workflow()` 查看当前可用文档工作流;执行前优先读 `common-general`,审查/诊断前优先读 `review-audit` |
12
12
  | **绝对真实性** | 禁用 faker/模拟数据,必须真实环境验证 |
13
13
  | **沟通可视化** | 禁纯文字/Mermaid代码;强制 ASCII流程图 + Markdown表格 |
14
14
  | **极简模块化** | 拆解为原子函数,清理注释旧代码/Debug日志 |
@@ -17,7 +17,7 @@
17
17
 
18
18
  ## 任务生命周期
19
19
  ```
20
- task_createtask_add_log(progress/issue/solution/reference) → task_complete
20
+ kg_task(action:"create")kg_task(action:"update", log_type:"progress|issue|solution|reference") → kg_task(action:"archive")
21
21
  ```
22
22
  | 日志类型 | 用途 | 示例 |
23
23
  |:---|:---|:---|
@@ -32,44 +32,44 @@ task_create → task_add_log(progress/issue/solution/reference) → task_complet
32
32
 
33
33
  ### Step 1: 分析与澄清
34
34
  1. 接收需求,识别意图
35
- 2. `kg_search` 检索现有节点/历史坑点 (读取 bugfixes)
36
- 3. `kg_get_rules()` 获取项目规则
35
+ 2. `kg_flowchart(action:"search", query:"关键词")` 检索现有节点/历史坑点
36
+ 3. `kg_workflow()` 获取全局/项目文档工作流,按需 `kg_workflow(id:"common-general")`
37
37
  4. 有歧义则列选项供用户选择
38
38
 
39
39
  **输出**: 需求确认清单 (表格)
40
40
 
41
41
  ### Step 2: 逻辑设计
42
42
  1. 结合图谱+代码设计方案
43
- 2. `kg_get_rules(ruleType:"codeStyle")` 确认编码规范
43
+ 2. `kg_workflow(id:"common-general")` 确认通用执行工作流
44
44
  3. 检查现有复用函数,拒绝重复建设
45
- 4. 大型任务: `task_create`
45
+ 4. 大型任务: `kg_task(action:"create")`
46
46
 
47
47
  **输出**: ASCII流程图 + 对比表 + 子任务列表
48
48
  **里程碑**: 等待用户确认 (不写代码)
49
49
 
50
50
  ### Step 3: 模块化编码
51
51
  **前置**: 用户确认方案
52
- 1. `task_add_log(progress, "开始编码")`
52
+ 1. `kg_task(action:"update", log_type:"progress", content:"开始编码")`
53
53
  2. 优先编写/更新工具函数,再业务组装
54
- 3. 遵循 codeStyle 规则
54
+ 3. 遵循已加载文档工作流中的编码约束
55
55
  4. 清理现场,无残留代码
56
56
 
57
57
  **输出**: 结构清晰的代码
58
58
 
59
59
  ### Step 4: 真实验证
60
- 1. `kg_get_rules(ruleType:"testRules")` 获取测试规则
60
+ 1. `kg_workflow(id:"review-audit")` 获取验证/诊断工作流
61
61
  2. 在 `tests/` 对应目录创建测试
62
62
  3. 真实环境运行,验证输出
63
- 4. 失败时: `task_add_log(issue, "xxx失败")` → 回溯Step2
63
+ 4. 失败时: `kg_task(action:"update", log_type:"issue", content:"xxx失败")` → 回溯Step2
64
64
 
65
65
  **严禁**: "测试环境所以失败"借口
66
66
 
67
67
  ### Step 5: 审查与沉淀
68
- 1. `kg_get_rules(ruleType:"reviewRules")` 获取审查规则
68
+ 1. `kg_workflow(id:"review-audit")` 获取审查工作流
69
69
  2. 审查目录结构/代码简洁度
70
- 3. 发现BUG → `kg_update_node` 写入 bugfixes
71
- 4. 新逻辑 → `kg_create_node` `kg_update_node` (追加 versions)
72
- 5. `task_complete({summary, difficulties, solutions, references})`
70
+ 3. 发现BUG → `kg_flowchart(action:"update_node")` 回写节点说明与文档
71
+ 4. 新逻辑 → `kg_flowchart(action:"batch_add")` 新增节点,或 `kg_flowchart(action:"update_node")` 追加文档/版本
72
+ 5. `kg_task(action:"archive", summary, difficulties, solutions)`
73
73
 
74
74
  **输出**: 交付确认 + 图谱更新清单
75
75
 
@@ -78,7 +78,7 @@ task_create → task_add_log(progress/issue/solution/reference) → task_complet
78
78
  ## 异常处理
79
79
  | 场景 | 反应 |
80
80
  |:---|:---|
81
- | Step4 测试失败 | 停止 → 分析日志 → task_add_log(issue) → 回溯Step2 → 修正 → 重测 |
81
+ | Step4 测试失败 | 停止 → 分析日志 → `kg_task(action:"update", log_type:"issue")` → 回溯Step2 → 修正 → 重测 |
82
82
  | 发现历史BUG | 读取节点 bugfixes 参考历史方案 |
83
83
  | 重复造轮子 | 终止 → 指出现有实现 → 要求复用 |
84
84
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env python
2
2
  # -*- coding: utf-8 -*-
3
3
  """
4
- Claude Code Hook - 动态规则触发
5
- GET /rules-meta → 关键词匹配 → POST /rules/batch 批量获取
4
+ Claude Code Hook - 动态工作流触发
5
+ GET /workflows → 关键词匹配 → POST /workflows/batch 批量获取 Markdown 工作流
6
6
  兼容 Python 2.7+ / 3.x,支持 Windows / macOS / Linux
7
7
  """
8
8
 
@@ -123,14 +123,14 @@ def api_post(api_base, project_id, key, path, body):
123
123
  return None
124
124
 
125
125
 
126
- def fetch_rules_meta(api_base, project_id, key):
127
- """获取规则触发配置"""
128
- return api_get(api_base, project_id, key, "/rules-meta") or {}
126
+ def fetch_workflows(api_base, project_id, key):
127
+ """获取可用工作流摘要"""
128
+ return api_get(api_base, project_id, key, "/workflows") or []
129
129
 
130
130
 
131
- def fetch_rules_batch(api_base, project_id, key, types):
132
- """批量获取多个规则类型的内容"""
133
- return api_post(api_base, project_id, key, "/rules/batch", types) or {}
131
+ def fetch_workflows_batch(api_base, project_id, key, items):
132
+ """批量获取工作流正文"""
133
+ return api_post(api_base, project_id, key, "/workflows/batch", items) or []
134
134
 
135
135
 
136
136
  # ╔══════════════════════════════════════════════════════════════╗
@@ -143,27 +143,36 @@ def count_hits(text, keywords):
143
143
  return sum(1 for kw in keywords if kw.lower() in text)
144
144
 
145
145
 
146
- def match_all(text, meta):
147
- """匹配所有触发的规则类型,返回 [(rule_type, label), ...]"""
146
+ def match_all(text, workflows):
147
+ """匹配所有触发的工作流,返回工作流摘要列表"""
148
148
  matched = []
149
- for rule_type, config in meta.items():
150
- if config.get("always"):
151
- matched.append((rule_type, config.get("label", rule_type)))
149
+ for wf in workflows:
150
+ if wf.get("always"):
151
+ matched.append(wf)
152
152
  continue
153
- keywords = config.get("keywords", [])
154
- min_hits = config.get("min_hits", 1)
153
+ keywords = wf.get("keywords", [])
154
+ min_hits = wf.get("minHits", 1)
155
155
  if keywords and count_hits(text, keywords) >= min_hits:
156
- matched.append((rule_type, config.get("label", rule_type)))
156
+ matched.append(wf)
157
157
  return matched
158
158
 
159
159
 
160
- def format_rules(items, label):
161
- """格式化规则输出"""
162
- if not items:
160
+ def format_workflow(item):
161
+ """格式化工作流输出"""
162
+ content = item.get("content", "")
163
+ if not content:
163
164
  return ""
164
- lines = ["# %s\n" % label]
165
- for item in items:
166
- lines.append("- %s" % item)
165
+ lines = ["# %s" % item.get("title", item.get("id", "workflow"))]
166
+ meta = []
167
+ if item.get("scope"):
168
+ meta.append("scope=%s" % item.get("scope"))
169
+ if item.get("system"):
170
+ meta.append("system=%s" % item.get("system"))
171
+ if meta:
172
+ lines.append("")
173
+ lines.append("> %s" % " | ".join(meta))
174
+ lines.append("")
175
+ lines.append(content)
167
176
  return "\n".join(lines)
168
177
 
169
178
 
@@ -204,27 +213,35 @@ def main():
204
213
  if not project_id or not key:
205
214
  return
206
215
 
207
- # 从服务器获取触发配置
208
- meta = fetch_rules_meta(api_base, project_id, key)
209
- if not meta:
216
+ # 从服务器获取工作流摘要
217
+ workflows = fetch_workflows(api_base, project_id, key)
218
+ if not workflows:
210
219
  return
211
220
 
212
- # 匹配所有触发的规则
213
- matched = match_all(user_input_lower, meta)
221
+ # 匹配所有触发的工作流
222
+ matched = match_all(user_input_lower, workflows)
214
223
  if not matched:
215
224
  return
216
225
 
217
- # 批量获取所有命中的规则内容 (单次请求)
218
- type_list = [rule_type for rule_type, _ in matched]
219
- label_map = {rule_type: label for rule_type, label in matched}
220
- batch = fetch_rules_batch(api_base, project_id, key, type_list)
226
+ # 批量获取所有命中的工作流正文
227
+ selectors = [{"id": wf.get("id", ""), "scope": wf.get("scope", "")} for wf in matched if wf.get("id")]
228
+ batch = fetch_workflows_batch(api_base, project_id, key, selectors)
229
+ if not batch:
230
+ return
231
+
232
+ batch_map = {}
233
+ for item in batch:
234
+ batch_map["%s:%s" % (item.get("scope", ""), item.get("id", ""))] = item
221
235
 
222
236
  # 按匹配顺序格式化输出
223
237
  output_parts = []
224
- for rule_type in type_list:
225
- rules = batch.get(rule_type, [])
226
- if rules:
227
- output_parts.append(format_rules(rules, label_map[rule_type]))
238
+ for wf in matched:
239
+ key_name = "%s:%s" % (wf.get("scope", ""), wf.get("id", ""))
240
+ item = batch_map.get(key_name)
241
+ if item:
242
+ rendered = format_workflow(item)
243
+ if rendered:
244
+ output_parts.append(rendered)
228
245
 
229
246
  if output_parts:
230
247
  print("\n\n".join(output_parts))
@@ -12,9 +12,10 @@ kg_discuss(action:"list") -> ???????
12
12
  ## 1. ????????
13
13
 
14
14
  - ??: `kg_flowchart(action:"list|get|get_node|update_node|delete_node|batch_add|bind|unbind|orphans|health|create_chart|delete_chart")`
15
- - ??: `kg_rules(action:"get|save|get_meta|save_meta")`
15
+ - ??: `kg_workflow()` / `kg_workflow(id:"...")` / `kg_workflow(action:"save|delete")`
16
16
  - ??: `kg_task(action:"create|get|update|archive|delete")`
17
17
  - ??: `kg_files(action:"list|read|upload|download|public_*")`
18
+ - ??: `kg_ref(action:"list|get|save|delete|read_file")`
18
19
  - ??/??: `kg_discuss(...)`, `kg_meeting(...)`
19
20
  - ????: `code_scan()`, `code_smart_context(symbolName)`, `code_full_path(symbolA, symbolB)`
20
21
  - ????: ?????????????????????????????? fallback????????????
@@ -22,7 +23,7 @@ kg_discuss(action:"list") -> ???????
22
23
  ## 2. ?????
23
24
 
24
25
  ### Step 1: ????
25
- 1. ?? `kg_flowchart(get)` ????????? `kg_rules(get)` ?????
26
+ 1. ?? `kg_flowchart(get)` ????????? `kg_workflow()` ?????
26
27
  2. ???????? `kg_flowchart(get_node, expand:2, includeDoc:true, includeFiles:true)`?
27
28
  3. ????? `subFlowchart`???????????????
28
29
  4. ??????????? `code_scan()`??? `code_smart_context` / `code_full_path`?
@@ -1,8 +0,0 @@
1
- /**
2
- * 📏 kg_rules (6→1)
3
- * 合并: kg_get_rules, kg_save_rules, kg_get_rules_meta, kg_save_rules_meta
4
- * 删除: kg_get_global_rules_meta, kg_save_global_rules_meta (管理员操作)
5
- */
6
- import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
- import { type McpContext } from './shared.js';
8
- export declare function registerRuleTools(server: McpServer, ctx: McpContext): void;
@@ -1,121 +0,0 @@
1
- /**
2
- * 📏 kg_rules (6→1)
3
- * 合并: kg_get_rules, kg_save_rules, kg_get_rules_meta, kg_save_rules_meta
4
- * 删除: kg_get_global_rules_meta, kg_save_global_rules_meta (管理员操作)
5
- */
6
- import { z } from 'zod';
7
- import { getClient } from '../storage/httpClient.js';
8
- import { decodeObjectStrings, getRules, RULE_TYPE_LABELS } from '../utils.js';
9
- import { wrap, safeTool, crossPrefix } from './shared.js';
10
- export function registerRuleTools(server, ctx) {
11
- const client = () => getClient();
12
- server.tool('kg_rules', '📏 项目规则管理 — 读取或保存代码风格、审查规则等。action: get(读取规则)|save(保存规则)|get_meta(读取触发配置)|save_meta(保存触发配置)', {
13
- action: z.enum(['get', 'save', 'get_meta', 'save_meta', 'delete'])
14
- .describe('操作类型'),
15
- ruleType: z.string().optional()
16
- .describe('规则类型(如 userStyles, codeStyle, reviewRules)。get/save 时使用,不传则获取全部'),
17
- rules: z.array(z.string()).optional()
18
- .describe('save 时的规则数组'),
19
- meta: z.record(z.string(), z.object({
20
- label: z.string().describe('规则显示名称'),
21
- keywords: z.array(z.string()).default([]).describe('触发关键词列表'),
22
- min_hits: z.number().default(1).describe('最低触发关键词数'),
23
- always: z.boolean().default(false).describe('是否始终触发')
24
- })).optional().describe('save_meta 时的触发配置映射'),
25
- targetProject: z.string().optional()
26
- .describe('跨项目读取 (get)'),
27
- }, async (args) => safeTool(async () => {
28
- const decoded = decodeObjectStrings(args);
29
- switch (decoded.action) {
30
- case 'get': {
31
- if (decoded.targetProject) {
32
- const crossMeta = await client().crossGetRulesMeta(decoded.targetProject);
33
- if (decoded.ruleType) {
34
- const rules = await client().crossGetRules(decoded.targetProject, decoded.ruleType);
35
- if (rules.length === 0) {
36
- const label = crossMeta[decoded.ruleType]?.label || decoded.ruleType;
37
- return wrap(`暂无${label}规则(项目: ${decoded.targetProject})`);
38
- }
39
- return wrap(`${crossPrefix(decoded.targetProject)}${rules.join('\n')}`);
40
- }
41
- const types = Object.keys(crossMeta).length > 0 ? Object.keys(crossMeta) : Object.keys(RULE_TYPE_LABELS);
42
- const allRules = [];
43
- for (const type of types) {
44
- const rules = await client().crossGetRules(decoded.targetProject, type);
45
- if (rules.length > 0) {
46
- const label = crossMeta[type]?.label || RULE_TYPE_LABELS[type] || type;
47
- allRules.push(`## ${label}\n${rules.join('\n')}`);
48
- }
49
- }
50
- if (allRules.length === 0)
51
- return wrap(`暂无项目规则(项目: ${decoded.targetProject})`);
52
- return wrap(`${crossPrefix(decoded.targetProject)}${allRules.join('\n\n')}`);
53
- }
54
- const rules = await getRules(ctx.projectId, decoded.ruleType || undefined);
55
- if (!rules || rules.trim() === '') {
56
- const meta = await client().getRulesMeta();
57
- const typeName = decoded.ruleType ? (meta[decoded.ruleType]?.label || decoded.ruleType) : '项目';
58
- return wrap(`暂无${typeName}规则`);
59
- }
60
- return wrap(rules);
61
- }
62
- case 'save': {
63
- if (!decoded.ruleType)
64
- return wrap('❌ save 需要 ruleType');
65
- if (!decoded.rules)
66
- return wrap('❌ save 需要 rules 数组');
67
- const existing = await client().getRulesApi(decoded.ruleType);
68
- const existingSet = new Set(existing.map(r => r.trim()));
69
- const toAdd = decoded.rules.filter((r) => !existingSet.has(r.trim()));
70
- const merged = [...existing, ...toAdd];
71
- const success = await client().saveRulesApi(decoded.ruleType, merged);
72
- if (!success)
73
- return wrap('❌ 保存失败');
74
- const meta = await client().getRulesMeta();
75
- const label = meta[decoded.ruleType]?.label || decoded.ruleType;
76
- return wrap(`✅ ${label}已保存 (新增${toAdd.length}条, 共${merged.length}条)`);
77
- }
78
- case 'get_meta': {
79
- const meta = await client().getRulesMeta();
80
- if (Object.keys(meta).length === 0)
81
- return wrap('暂无规则配置');
82
- const lines = Object.entries(meta).map(([type, m]) => {
83
- const kw = m.keywords.length > 0 ? m.keywords.join(', ') : '(无)';
84
- const trigger = m.always ? '始终触发' : `关键词≥${m.min_hits}: ${kw}`;
85
- return `- **${m.label}** (${type}): ${trigger}`;
86
- });
87
- return wrap(`规则触发配置:\n\n${lines.join('\n')}`);
88
- }
89
- case 'save_meta': {
90
- if (!decoded.meta)
91
- return wrap('❌ save_meta 需要 meta');
92
- const existing = await client().getRulesMeta();
93
- const merged = { ...existing, ...decoded.meta };
94
- const success = await client().saveRulesMeta(merged);
95
- if (!success)
96
- return wrap('❌ 保存失败');
97
- return wrap(`✅ 触发配置已保存 (更新${Object.keys(decoded.meta).length}个类型, 共${Object.keys(merged).length}个类型)`);
98
- }
99
- case 'delete': {
100
- if (!decoded.ruleType)
101
- return wrap('❌ delete 需要 ruleType');
102
- if (!decoded.rules || decoded.rules.length === 0)
103
- return wrap('❌ delete 需要 rules 数组(要删除的规则内容)');
104
- const existing = await client().getRulesApi(decoded.ruleType);
105
- const toDelete = new Set(decoded.rules.map((r) => r.trim()));
106
- const filtered = existing.filter((r) => !toDelete.has(r.trim()));
107
- const removed = existing.length - filtered.length;
108
- if (removed === 0)
109
- return wrap('ℹ️ 未找到匹配的规则');
110
- const success = await client().saveRulesApi(decoded.ruleType, filtered);
111
- if (!success)
112
- return wrap('❌ 删除失败');
113
- const meta = await client().getRulesMeta();
114
- const label = meta[decoded.ruleType]?.label || decoded.ruleType;
115
- return wrap(`✅ ${label}: 已删除${removed}条, 剩余${filtered.length}条`);
116
- }
117
- default:
118
- return wrap(`❌ 未知 action: ${decoded.action}`);
119
- }
120
- }));
121
- }