autosnippet 2.19.8 → 3.0.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.
- package/README.md +26 -18
- package/dashboard/dist/assets/{index-BwISScUw.js → index-_Sk_Dmg3.js} +41 -41
- package/dashboard/dist/index.html +1 -1
- package/lib/external/mcp/McpServer.js +54 -65
- package/lib/external/mcp/handlers/bootstrap.js +7 -7
- package/lib/external/mcp/handlers/consolidated.js +290 -0
- package/lib/external/mcp/handlers/guard.js +5 -5
- package/lib/external/mcp/handlers/knowledge.js +23 -8
- package/lib/external/mcp/handlers/skill.js +4 -4
- package/lib/external/mcp/handlers/structure.js +16 -16
- package/lib/external/mcp/handlers/system.js +37 -40
- package/lib/external/mcp/tools.js +250 -646
- package/lib/service/cursor/RulesGenerator.js +2 -2
- package/lib/service/skills/SkillAdvisor.js +1 -1
- package/package.json +1 -1
- package/scripts/install-cursor-skill.js +10 -10
- package/skills/autosnippet-analysis/SKILL.md +23 -18
- package/skills/autosnippet-candidates/SKILL.md +38 -39
- package/skills/autosnippet-coldstart/SKILL.md +11 -14
- package/skills/autosnippet-concepts/SKILL.md +26 -31
- package/skills/autosnippet-create/SKILL.md +4 -6
- package/skills/autosnippet-guard/SKILL.md +14 -17
- package/skills/autosnippet-intent/SKILL.md +10 -11
- package/skills/autosnippet-lifecycle/SKILL.md +13 -18
- package/skills/autosnippet-recipes/SKILL.md +29 -62
- package/skills/autosnippet-structure/SKILL.md +19 -19
- package/templates/copilot-instructions.md +42 -41
- package/templates/recipes-setup/README.md +4 -7
|
@@ -332,7 +332,7 @@ export function createSkill(_ctx, args) {
|
|
|
332
332
|
path: skillPath,
|
|
333
333
|
overwritten: fs.existsSync(skillPath) && overwrite,
|
|
334
334
|
editorIndex: indexResult,
|
|
335
|
-
hint: `Skill "${name}" created. Use
|
|
335
|
+
hint: `Skill "${name}" created. Use autosnippet_skill({ operation: "load", name: "${name}" }) to verify content.`,
|
|
336
336
|
},
|
|
337
337
|
});
|
|
338
338
|
}
|
|
@@ -381,7 +381,7 @@ function _regenerateEditorIndex() {
|
|
|
381
381
|
'',
|
|
382
382
|
'# AutoSnippet Project Skills',
|
|
383
383
|
'',
|
|
384
|
-
`本项目已注册 ${projectSkills.length} 个自定义 Skill。使用 \`
|
|
384
|
+
`本项目已注册 ${projectSkills.length} 个自定义 Skill。使用 \`autosnippet_skill({ operation: "load", name })\` 加载完整内容。`,
|
|
385
385
|
'',
|
|
386
386
|
skillLines,
|
|
387
387
|
'',
|
|
@@ -529,7 +529,7 @@ export function updateSkill(_ctx, args) {
|
|
|
529
529
|
success: false,
|
|
530
530
|
error: {
|
|
531
531
|
code: 'SKILL_NOT_FOUND',
|
|
532
|
-
message: `Project skill "${name}" not found. Use
|
|
532
|
+
message: `Project skill "${name}" not found. Use autosnippet_skill({ operation: "create" }) to create it first.`,
|
|
533
533
|
},
|
|
534
534
|
});
|
|
535
535
|
}
|
|
@@ -592,7 +592,7 @@ export function updateSkill(_ctx, args) {
|
|
|
592
592
|
updated: true,
|
|
593
593
|
fieldsUpdated: [description ? 'description' : null, content ? 'content' : null].filter(Boolean),
|
|
594
594
|
editorIndex: indexResult,
|
|
595
|
-
hint: `Skill "${name}" updated. Use
|
|
595
|
+
hint: `Skill "${name}" updated. Use autosnippet_skill({ operation: "load", name: "${name}" }) to verify content.`,
|
|
596
596
|
},
|
|
597
597
|
});
|
|
598
598
|
}
|
|
@@ -68,7 +68,7 @@ export async function getTargets(ctx, args = {}) {
|
|
|
68
68
|
const includeSummary = args.includeSummary !== false; // 默认 true
|
|
69
69
|
|
|
70
70
|
if (!includeSummary) {
|
|
71
|
-
return envelope({ success: true, data: { targets }, meta: { tool: '
|
|
71
|
+
return envelope({ success: true, data: { targets }, meta: { tool: 'autosnippet_structure' } });
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
// 带摘要:每个 target 附加文件数、语言统计、推断职责
|
|
@@ -105,7 +105,7 @@ export async function getTargets(ctx, args = {}) {
|
|
|
105
105
|
targets: enriched,
|
|
106
106
|
summary: { targetCount: targets.length, totalFiles, languageStats: globalLangStats },
|
|
107
107
|
},
|
|
108
|
-
meta: { tool: '
|
|
108
|
+
meta: { tool: 'autosnippet_structure' },
|
|
109
109
|
});
|
|
110
110
|
}
|
|
111
111
|
|
|
@@ -160,7 +160,7 @@ export async function getTargetFiles(ctx, args) {
|
|
|
160
160
|
totalAvailable: rawFiles.length,
|
|
161
161
|
languageStats: langStats,
|
|
162
162
|
},
|
|
163
|
-
meta: { tool: '
|
|
163
|
+
meta: { tool: 'autosnippet_structure' },
|
|
164
164
|
});
|
|
165
165
|
}
|
|
166
166
|
|
|
@@ -213,13 +213,13 @@ export async function getTargetMetadata(ctx, args) {
|
|
|
213
213
|
}
|
|
214
214
|
} catch { /* knowledge_edges may not exist */ }
|
|
215
215
|
|
|
216
|
-
return envelope({ success: true, data: meta, meta: { tool: '
|
|
216
|
+
return envelope({ success: true, data: meta, meta: { tool: 'autosnippet_structure' } });
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
export async function graphQuery(ctx, args) {
|
|
220
220
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
221
221
|
if (!graphService) {
|
|
222
|
-
return envelope({ success: false, message: 'KnowledgeGraphService not available — knowledge_edges 表可能未初始化', meta: { tool: '
|
|
222
|
+
return envelope({ success: false, message: 'KnowledgeGraphService not available — knowledge_edges 表可能未初始化', meta: { tool: 'autosnippet_graph' } });
|
|
223
223
|
}
|
|
224
224
|
const nodeType = args.nodeType || 'recipe';
|
|
225
225
|
const direction = args.direction || 'both';
|
|
@@ -234,17 +234,17 @@ export async function graphQuery(ctx, args) {
|
|
|
234
234
|
// knowledge_edges 表不存在时 graceful 降级到 relations 字段
|
|
235
235
|
if (err.message?.includes('no such table')) {
|
|
236
236
|
data = await _fallbackRelationsFromRecipe(ctx, args.nodeId, args.relation, direction);
|
|
237
|
-
return envelope({ success: true, data, meta: { tool: '
|
|
237
|
+
return envelope({ success: true, data, meta: { tool: 'autosnippet_graph', source: 'relations-fallback' } });
|
|
238
238
|
}
|
|
239
239
|
throw err;
|
|
240
240
|
}
|
|
241
|
-
return envelope({ success: true, data, meta: { tool: '
|
|
241
|
+
return envelope({ success: true, data, meta: { tool: 'autosnippet_graph' } });
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
export async function graphImpact(ctx, args) {
|
|
245
245
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
246
246
|
if (!graphService) {
|
|
247
|
-
return envelope({ success: false, message: 'KnowledgeGraphService not available — knowledge_edges 表可能未初始化', meta: { tool: '
|
|
247
|
+
return envelope({ success: false, message: 'KnowledgeGraphService not available — knowledge_edges 表可能未初始化', meta: { tool: 'autosnippet_graph' } });
|
|
248
248
|
}
|
|
249
249
|
const nodeType = args.nodeType || 'recipe';
|
|
250
250
|
let impacted;
|
|
@@ -254,11 +254,11 @@ export async function graphImpact(ctx, args) {
|
|
|
254
254
|
// knowledge_edges 表不存在时 graceful 降级
|
|
255
255
|
if (err.message?.includes('no such table')) {
|
|
256
256
|
impacted = await _fallbackImpactFromRecipe(ctx, args.nodeId);
|
|
257
|
-
return envelope({ success: true, data: { nodeId: args.nodeId, impactedCount: impacted.length, impacted, degraded: true, degradedReason: 'knowledge_edges 表不存在,仅从 relations 字段反查' }, meta: { tool: '
|
|
257
|
+
return envelope({ success: true, data: { nodeId: args.nodeId, impactedCount: impacted.length, impacted, degraded: true, degradedReason: 'knowledge_edges 表不存在,仅从 relations 字段反查' }, meta: { tool: 'autosnippet_graph', source: 'relations-fallback' } });
|
|
258
258
|
}
|
|
259
259
|
throw err;
|
|
260
260
|
}
|
|
261
|
-
return envelope({ success: true, data: { nodeId: args.nodeId, impactedCount: impacted.length, impacted }, meta: { tool: '
|
|
261
|
+
return envelope({ success: true, data: { nodeId: args.nodeId, impactedCount: impacted.length, impacted }, meta: { tool: 'autosnippet_graph' } });
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
/**
|
|
@@ -341,7 +341,7 @@ export async function graphPath(ctx, args) {
|
|
|
341
341
|
if (!args.fromId || !args.toId) throw new Error('fromId and toId are required');
|
|
342
342
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
343
343
|
if (!graphService) {
|
|
344
|
-
return envelope({ success: false, message: 'KnowledgeGraphService not available', meta: { tool: '
|
|
344
|
+
return envelope({ success: false, message: 'KnowledgeGraphService not available', meta: { tool: 'autosnippet_graph' } });
|
|
345
345
|
}
|
|
346
346
|
const fromType = args.fromType || 'recipe';
|
|
347
347
|
const toType = args.toType || 'recipe';
|
|
@@ -353,11 +353,11 @@ export async function graphPath(ctx, args) {
|
|
|
353
353
|
if (err.message?.includes('no such table')) {
|
|
354
354
|
// 降级:用 relations 字段做单跳查找
|
|
355
355
|
result = await _fallbackPathFromRecipe(ctx, args.fromId, args.toId);
|
|
356
|
-
return envelope({ success: true, data: result, meta: { tool: '
|
|
356
|
+
return envelope({ success: true, data: result, meta: { tool: 'autosnippet_graph', source: 'relations-fallback' } });
|
|
357
357
|
}
|
|
358
358
|
throw err;
|
|
359
359
|
}
|
|
360
|
-
return envelope({ success: true, data: result, meta: { tool: '
|
|
360
|
+
return envelope({ success: true, data: result, meta: { tool: 'autosnippet_graph' } });
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
/**
|
|
@@ -391,16 +391,16 @@ async function _fallbackPathFromRecipe(ctx, fromId, toId) {
|
|
|
391
391
|
export async function graphStats(ctx) {
|
|
392
392
|
const graphService = ctx.container.get('knowledgeGraphService');
|
|
393
393
|
if (!graphService) {
|
|
394
|
-
return envelope({ success: false, message: 'KnowledgeGraphService not available', meta: { tool: '
|
|
394
|
+
return envelope({ success: false, message: 'KnowledgeGraphService not available', meta: { tool: 'autosnippet_graph' } });
|
|
395
395
|
}
|
|
396
396
|
let stats;
|
|
397
397
|
try {
|
|
398
398
|
stats = graphService.getStats();
|
|
399
399
|
} catch (err) {
|
|
400
400
|
if (err.message?.includes('no such table')) {
|
|
401
|
-
return envelope({ success: true, data: { totalEdges: 0, byRelation: {}, nodeTypes: [], note: 'knowledge_edges 表不存在,请运行数据库迁移' }, meta: { tool: '
|
|
401
|
+
return envelope({ success: true, data: { totalEdges: 0, byRelation: {}, nodeTypes: [], note: 'knowledge_edges 表不存在,请运行数据库迁移' }, meta: { tool: 'autosnippet_graph' } });
|
|
402
402
|
}
|
|
403
403
|
throw err;
|
|
404
404
|
}
|
|
405
|
-
return envelope({ success: true, data: stats, meta: { tool: '
|
|
405
|
+
return envelope({ success: true, data: stats, meta: { tool: 'autosnippet_graph' } });
|
|
406
406
|
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { envelope } from '../envelope.js';
|
|
9
|
-
import { TOOLS, TOOL_GATEWAY_MAP } from '../tools.js';
|
|
9
|
+
import { TOOLS, TOOL_GATEWAY_MAP, TIER_ORDER } from '../tools.js';
|
|
10
10
|
|
|
11
11
|
export async function health(ctx) {
|
|
12
12
|
const checks = { database: false, gateway: false, vectorStore: false };
|
|
@@ -112,36 +112,32 @@ export async function health(ctx) {
|
|
|
112
112
|
let _pkgVersion = null;
|
|
113
113
|
|
|
114
114
|
export function capabilities() {
|
|
115
|
-
// 工具分类映射
|
|
115
|
+
// V3 工具分类映射
|
|
116
116
|
const CATEGORY_MAP = {
|
|
117
117
|
autosnippet_health: 'system',
|
|
118
118
|
autosnippet_capabilities: 'system',
|
|
119
119
|
autosnippet_search: 'search',
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
autosnippet_get_target_metadata: 'structure',
|
|
134
|
-
autosnippet_validate_candidate: 'validate',
|
|
135
|
-
autosnippet_check_duplicate: 'validate',
|
|
136
|
-
autosnippet_guard_check: 'guard',
|
|
137
|
-
autosnippet_guard_audit_files: 'guard',
|
|
138
|
-
autosnippet_scan_project: 'scan',
|
|
139
|
-
autosnippet_enrich_candidates: 'enrich',
|
|
140
|
-
autosnippet_confirm_usage: 'telemetry',
|
|
141
|
-
autosnippet_compliance_report: 'telemetry',
|
|
120
|
+
autosnippet_knowledge: 'browse',
|
|
121
|
+
autosnippet_structure: 'structure',
|
|
122
|
+
autosnippet_graph: 'graph',
|
|
123
|
+
autosnippet_guard: 'guard',
|
|
124
|
+
autosnippet_submit_knowledge: 'submit',
|
|
125
|
+
autosnippet_submit_knowledge_batch: 'submit',
|
|
126
|
+
autosnippet_save_document: 'submit',
|
|
127
|
+
autosnippet_skill: 'skill',
|
|
128
|
+
autosnippet_bootstrap: 'bootstrap',
|
|
129
|
+
autosnippet_enrich_candidates: 'admin',
|
|
130
|
+
autosnippet_knowledge_lifecycle: 'admin',
|
|
131
|
+
autosnippet_validate_candidate: 'admin',
|
|
132
|
+
autosnippet_check_duplicate: 'admin',
|
|
142
133
|
};
|
|
143
134
|
|
|
144
|
-
|
|
135
|
+
// 根据当前 tier 决定可见工具
|
|
136
|
+
const tierName = process.env.ASD_MCP_TIER || 'agent';
|
|
137
|
+
const maxTier = TIER_ORDER[tierName] ?? TIER_ORDER.agent;
|
|
138
|
+
const visibleTools = TOOLS.filter(t => (TIER_ORDER[t.tier || 'agent'] ?? 0) <= maxTier);
|
|
139
|
+
|
|
140
|
+
const tools = visibleTools.map(t => {
|
|
145
141
|
const props = t.inputSchema.properties || {};
|
|
146
142
|
const requiredSet = new Set(t.inputSchema.required || []);
|
|
147
143
|
const params = Object.entries(props).map(([key, schema]) => ({
|
|
@@ -155,6 +151,7 @@ export function capabilities() {
|
|
|
155
151
|
const gatewayInfo = TOOL_GATEWAY_MAP[t.name];
|
|
156
152
|
return {
|
|
157
153
|
name: t.name,
|
|
154
|
+
tier: t.tier || 'agent',
|
|
158
155
|
description: t.description,
|
|
159
156
|
category: CATEGORY_MAP[t.name] || 'other',
|
|
160
157
|
gatewayGated: !!gatewayInfo,
|
|
@@ -172,27 +169,27 @@ export function capabilities() {
|
|
|
172
169
|
success: true,
|
|
173
170
|
data: {
|
|
174
171
|
count: tools.length,
|
|
172
|
+
tier: tierName,
|
|
175
173
|
categoryGuide: {
|
|
176
174
|
system: '系统状态与能力发现',
|
|
177
|
-
search: '
|
|
178
|
-
browse: '
|
|
179
|
-
graph: '
|
|
180
|
-
structure: '
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
telemetry: '使用遥测与合规',
|
|
175
|
+
search: '统合搜索 — auto(BM25+semantic 融合) / keyword / semantic / context(漏斗+会话)',
|
|
176
|
+
browse: '知识浏览 — list/get/insights/confirm_usage(operation 路由)',
|
|
177
|
+
graph: '知识图谱 — query/impact/path/stats(operation 路由)',
|
|
178
|
+
structure: '项目结构 — targets/files/metadata(operation 路由)',
|
|
179
|
+
submit: '知识提交(写操作,Gateway gated)',
|
|
180
|
+
guard: '代码 Guard 检查 — code(单文件)/files(批量)(自动路由)',
|
|
181
|
+
skill: 'Skill 管理 — list/load/create/update/delete/suggest',
|
|
182
|
+
bootstrap: '冷启动 & 扫描 — knowledge/refine/scan',
|
|
183
|
+
admin: '管理员工具(诊断/生命周期/校验/去重)',
|
|
187
184
|
},
|
|
188
185
|
byCategory,
|
|
189
186
|
tools,
|
|
190
187
|
workflows: [
|
|
191
|
-
{ name: '知识查询', steps: ['search(推荐首选,auto mode 融合)', '
|
|
192
|
-
{ name: '单条知识提交', steps: ['
|
|
193
|
-
{ name: '批量 Target 扫描', steps: ['
|
|
194
|
-
{ name: '
|
|
195
|
-
{ name: '
|
|
188
|
+
{ name: '知识查询', steps: ['search(推荐首选,auto mode 融合)', 'knowledge op=get', 'knowledge op=confirm_usage'], tips: '精确匹配用 mode=keyword,需意图+会话上下文用 mode=context' },
|
|
189
|
+
{ name: '单条知识提交', steps: ['submit_knowledge(内置校验+去重)'] },
|
|
190
|
+
{ name: '批量 Target 扫描', steps: ['structure op=targets', 'structure op=files', '(Agent 分析)', 'submit_knowledge_batch'] },
|
|
191
|
+
{ name: '冷启动', steps: ['bootstrap op=knowledge', 'bootstrap op=refine'] },
|
|
192
|
+
{ name: '代码审计', steps: ['guard (code/files)', 'knowledge op=list kind=rule'] },
|
|
196
193
|
],
|
|
197
194
|
},
|
|
198
195
|
meta: { tool: 'autosnippet_capabilities' },
|