@ppdocs/mcp 3.1.0 → 3.1.2
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 +5 -4
- package/dist/storage/httpClient.d.ts +13 -0
- package/dist/storage/httpClient.js +20 -0
- package/dist/tools/index.js +15 -15
- package/package.json +1 -1
- package/templates/hooks/hook.py +6 -1
package/dist/cli.js
CHANGED
|
@@ -274,9 +274,10 @@ function copyDirRecursive(src, dest) {
|
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
276
|
/** 生成跨平台的 hooks 配置 (调用 python hook.py) */
|
|
277
|
-
function generateHooksConfig() {
|
|
278
|
-
//
|
|
279
|
-
const
|
|
277
|
+
function generateHooksConfig(cwd) {
|
|
278
|
+
// 使用绝对路径,避免 CWD 不一致导致找不到脚本
|
|
279
|
+
const hookPath = path.join(cwd, '.claude', 'hooks', 'hook.py').replace(/\\/g, '/');
|
|
280
|
+
const command = `python ${hookPath}`;
|
|
280
281
|
return {
|
|
281
282
|
hooks: {
|
|
282
283
|
UserPromptSubmit: [
|
|
@@ -340,7 +341,7 @@ function installClaudeTemplates(cwd) {
|
|
|
340
341
|
}
|
|
341
342
|
catch { /* ignore */ }
|
|
342
343
|
}
|
|
343
|
-
const hooksConfig = generateHooksConfig();
|
|
344
|
+
const hooksConfig = generateHooksConfig(cwd);
|
|
344
345
|
// 合并 MCP 权限到 permissions.allow
|
|
345
346
|
const existingPermissions = existingSettings.permissions || {};
|
|
346
347
|
const existingAllow = existingPermissions.allow || [];
|
|
@@ -104,11 +104,24 @@ export declare function getDocsByStatus(_projectId: string, statusList: string[]
|
|
|
104
104
|
export declare function getTree(_projectId: string): Promise<TreeNode[]>;
|
|
105
105
|
export declare function getRules(_projectId: string, ruleType: string): Promise<string[]>;
|
|
106
106
|
export declare function saveRules(_projectId: string, ruleType: string, rules: string[]): Promise<boolean>;
|
|
107
|
+
export declare function appendRules(_projectId: string, ruleType: string, newRules: string[]): Promise<{
|
|
108
|
+
success: boolean;
|
|
109
|
+
total: number;
|
|
110
|
+
added: number;
|
|
111
|
+
}>;
|
|
107
112
|
export declare function getRulesMeta(): Promise<Record<string, RuleMeta>>;
|
|
108
113
|
export declare function saveRulesMeta(meta: Record<string, RuleMeta>): Promise<boolean>;
|
|
114
|
+
export declare function mergeRulesMeta(newMeta: Record<string, RuleMeta>): Promise<{
|
|
115
|
+
success: boolean;
|
|
116
|
+
total: number;
|
|
117
|
+
}>;
|
|
109
118
|
export declare function crossGetRulesMeta(target: string): Promise<Record<string, RuleMeta>>;
|
|
110
119
|
export declare function getGlobalRulesMeta(): Promise<Record<string, RuleMeta>>;
|
|
111
120
|
export declare function saveGlobalRulesMeta(meta: Record<string, RuleMeta>): Promise<boolean>;
|
|
121
|
+
export declare function mergeGlobalRulesMeta(newMeta: Record<string, RuleMeta>): Promise<{
|
|
122
|
+
success: boolean;
|
|
123
|
+
total: number;
|
|
124
|
+
}>;
|
|
112
125
|
export declare function listTasks(_projectId: string, status?: 'active' | 'archived'): Promise<TaskSummary[]>;
|
|
113
126
|
export declare function getTask(_projectId: string, taskId: string): Promise<Task | null>;
|
|
114
127
|
export declare function createTask(_projectId: string, task: {
|
|
@@ -508,12 +508,26 @@ export async function getRules(_projectId, ruleType) {
|
|
|
508
508
|
export async function saveRules(_projectId, ruleType, rules) {
|
|
509
509
|
return getClient().saveRulesApi(ruleType, rules);
|
|
510
510
|
}
|
|
511
|
+
export async function appendRules(_projectId, ruleType, newRules) {
|
|
512
|
+
const existing = await getClient().getRulesApi(ruleType);
|
|
513
|
+
const existingSet = new Set(existing.map(r => r.trim()));
|
|
514
|
+
const toAdd = newRules.filter(r => !existingSet.has(r.trim()));
|
|
515
|
+
const merged = [...existing, ...toAdd];
|
|
516
|
+
const success = await getClient().saveRulesApi(ruleType, merged);
|
|
517
|
+
return { success, total: merged.length, added: toAdd.length };
|
|
518
|
+
}
|
|
511
519
|
export async function getRulesMeta() {
|
|
512
520
|
return getClient().getRulesMeta();
|
|
513
521
|
}
|
|
514
522
|
export async function saveRulesMeta(meta) {
|
|
515
523
|
return getClient().saveRulesMeta(meta);
|
|
516
524
|
}
|
|
525
|
+
export async function mergeRulesMeta(newMeta) {
|
|
526
|
+
const existing = await getClient().getRulesMeta();
|
|
527
|
+
const merged = { ...existing, ...newMeta };
|
|
528
|
+
const success = await getClient().saveRulesMeta(merged);
|
|
529
|
+
return { success, total: Object.keys(merged).length };
|
|
530
|
+
}
|
|
517
531
|
export async function crossGetRulesMeta(target) {
|
|
518
532
|
return getClient().crossGetRulesMeta(target);
|
|
519
533
|
}
|
|
@@ -523,6 +537,12 @@ export async function getGlobalRulesMeta() {
|
|
|
523
537
|
export async function saveGlobalRulesMeta(meta) {
|
|
524
538
|
return getClient().saveGlobalRulesMeta(meta);
|
|
525
539
|
}
|
|
540
|
+
export async function mergeGlobalRulesMeta(newMeta) {
|
|
541
|
+
const existing = await getClient().getGlobalRulesMeta();
|
|
542
|
+
const merged = { ...existing, ...newMeta };
|
|
543
|
+
const success = await getClient().saveGlobalRulesMeta(merged);
|
|
544
|
+
return { success, total: Object.keys(merged).length };
|
|
545
|
+
}
|
|
526
546
|
// ============ 任务管理 ============
|
|
527
547
|
export async function listTasks(_projectId, status) {
|
|
528
548
|
return getClient().listTasks(status);
|
package/dist/tools/index.js
CHANGED
|
@@ -237,20 +237,20 @@ export function registerTools(server, projectId, _user) {
|
|
|
237
237
|
}
|
|
238
238
|
return { content: [{ type: 'text', text: rules }] };
|
|
239
239
|
});
|
|
240
|
-
// 3.7 保存项目规则
|
|
241
|
-
server.tool('kg_save_rules', '保存单个类型的项目规则(
|
|
240
|
+
// 3.7 保存项目规则 (自动合并,去重追加)
|
|
241
|
+
server.tool('kg_save_rules', '保存单个类型的项目规则(自动合并:已有规则保留,新规则去重追加)', {
|
|
242
242
|
ruleType: z.string()
|
|
243
243
|
.describe('规则类型(如 userStyles, codeStyle, reviewRules, testRules, unitTests, 或自定义类型)'),
|
|
244
244
|
rules: z.array(z.string()).describe('规则数组')
|
|
245
245
|
}, async (args) => {
|
|
246
246
|
const decoded = decodeObjectStrings(args);
|
|
247
|
-
const
|
|
248
|
-
if (!success) {
|
|
247
|
+
const result = await storage.appendRules(projectId, decoded.ruleType, decoded.rules);
|
|
248
|
+
if (!result.success) {
|
|
249
249
|
return wrap('❌ 保存失败');
|
|
250
250
|
}
|
|
251
251
|
const meta = await storage.getRulesMeta();
|
|
252
252
|
const label = meta[decoded.ruleType]?.label || decoded.ruleType;
|
|
253
|
-
return wrap(`✅ ${label}已保存 (
|
|
253
|
+
return wrap(`✅ ${label}已保存 (新增${result.added}条, 共${result.total}条)`);
|
|
254
254
|
});
|
|
255
255
|
// 3.8 获取规则触发配置
|
|
256
256
|
server.tool('kg_get_rules_meta', '获取规则触发配置(所有类型的标签、关键词、触发数)。用于查看/编辑 hooks 触发条件', {}, async () => {
|
|
@@ -270,8 +270,8 @@ export function registerTools(server, projectId, _user) {
|
|
|
270
270
|
return wrap(`❌ ${String(e)}`);
|
|
271
271
|
}
|
|
272
272
|
});
|
|
273
|
-
// 3.9 保存规则触发配置
|
|
274
|
-
server.tool('kg_save_rules_meta', '保存规则触发配置(
|
|
273
|
+
// 3.9 保存规则触发配置 (自动合并)
|
|
274
|
+
server.tool('kg_save_rules_meta', '保存规则触发配置(自动合并:已有类型更新,新类型创建,其他类型不受影响)', {
|
|
275
275
|
meta: z.record(z.string(), z.object({
|
|
276
276
|
label: z.string().describe('规则显示名称'),
|
|
277
277
|
keywords: z.array(z.string()).default([]).describe('触发关键词列表'),
|
|
@@ -281,11 +281,11 @@ export function registerTools(server, projectId, _user) {
|
|
|
281
281
|
}, async (args) => {
|
|
282
282
|
try {
|
|
283
283
|
const decoded = decodeObjectStrings(args.meta);
|
|
284
|
-
const
|
|
285
|
-
if (!success) {
|
|
284
|
+
const result = await storage.mergeRulesMeta(decoded);
|
|
285
|
+
if (!result.success) {
|
|
286
286
|
return wrap('❌ 保存失败');
|
|
287
287
|
}
|
|
288
|
-
return wrap(`✅
|
|
288
|
+
return wrap(`✅ 触发配置已保存 (更新${Object.keys(decoded).length}个类型, 共${result.total}个类型)`);
|
|
289
289
|
}
|
|
290
290
|
catch (e) {
|
|
291
291
|
return wrap(`❌ ${String(e)}`);
|
|
@@ -309,8 +309,8 @@ export function registerTools(server, projectId, _user) {
|
|
|
309
309
|
return wrap(`❌ ${String(e)}`);
|
|
310
310
|
}
|
|
311
311
|
});
|
|
312
|
-
// 3.11 保存全局默认规则触发配置
|
|
313
|
-
server.tool('kg_save_global_rules_meta', '
|
|
312
|
+
// 3.11 保存全局默认规则触发配置 (自动合并)
|
|
313
|
+
server.tool('kg_save_global_rules_meta', '保存全局默认触发配置(自动合并:已有类型更新,新类型创建,其他类型不受影响)', {
|
|
314
314
|
meta: z.record(z.string(), z.object({
|
|
315
315
|
label: z.string().describe('规则显示名称'),
|
|
316
316
|
keywords: z.array(z.string()).default([]).describe('触发关键词列表'),
|
|
@@ -320,11 +320,11 @@ export function registerTools(server, projectId, _user) {
|
|
|
320
320
|
}, async (args) => {
|
|
321
321
|
try {
|
|
322
322
|
const decoded = decodeObjectStrings(args.meta);
|
|
323
|
-
const
|
|
324
|
-
if (!success) {
|
|
323
|
+
const result = await storage.mergeGlobalRulesMeta(decoded);
|
|
324
|
+
if (!result.success) {
|
|
325
325
|
return wrap('❌ 保存失败');
|
|
326
326
|
}
|
|
327
|
-
return wrap(`✅
|
|
327
|
+
return wrap(`✅ 全局触发配置已保存 (更新${Object.keys(decoded).length}个类型, 共${result.total}个类型)`);
|
|
328
328
|
}
|
|
329
329
|
catch (e) {
|
|
330
330
|
return wrap(`❌ ${String(e)}`);
|
package/package.json
CHANGED
package/templates/hooks/hook.py
CHANGED
|
@@ -60,9 +60,14 @@ def is_bypass(text):
|
|
|
60
60
|
# ╚══════════════════════════════════════════════════════════════╝
|
|
61
61
|
|
|
62
62
|
|
|
63
|
+
def get_project_root():
|
|
64
|
+
"""从 __file__ 反推项目根目录 (.claude/hooks/hook.py → 上两级)"""
|
|
65
|
+
return os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
66
|
+
|
|
67
|
+
|
|
63
68
|
def load_ppdocs_config():
|
|
64
69
|
"""读取 .ppdocs 配置"""
|
|
65
|
-
config_path = os.path.join(
|
|
70
|
+
config_path = os.path.join(get_project_root(), ".ppdocs")
|
|
66
71
|
if not os.path.exists(config_path):
|
|
67
72
|
return None
|
|
68
73
|
try:
|