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.
@@ -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 autosnippet_load_skill to verify content.`,
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。使用 \`autosnippet_load_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 autosnippet_create_skill to create it first.`,
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 autosnippet_load_skill to verify content.`,
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: 'autosnippet_get_targets' } });
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: 'autosnippet_get_targets' },
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: 'autosnippet_get_target_files' },
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: 'autosnippet_get_target_metadata' } });
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: 'autosnippet_graph_query' } });
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: 'autosnippet_graph_query', source: 'relations-fallback' } });
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: 'autosnippet_graph_query' } });
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: 'autosnippet_graph_impact' } });
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: 'autosnippet_graph_impact', source: 'relations-fallback' } });
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: 'autosnippet_graph_impact' } });
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: 'autosnippet_graph_path' } });
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: 'autosnippet_graph_path', source: 'relations-fallback' } });
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: 'autosnippet_graph_path' } });
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: 'autosnippet_graph_stats' } });
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: 'autosnippet_graph_stats' } });
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: 'autosnippet_graph_stats' } });
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
- autosnippet_context_search: 'search',
121
- autosnippet_keyword_search: 'search',
122
- autosnippet_semantic_search: 'search',
123
- autosnippet_list_rules: 'browse',
124
- autosnippet_list_patterns: 'browse',
125
- autosnippet_list_facts: 'browse',
126
- autosnippet_list_recipes: 'browse',
127
- autosnippet_get_recipe: 'browse',
128
- autosnippet_recipe_insights: 'browse',
129
- autosnippet_graph_query: 'graph',
130
- autosnippet_graph_impact: 'graph',
131
- autosnippet_get_targets: 'structure',
132
- autosnippet_get_target_files: 'structure',
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
- const tools = TOOLS.map(t => {
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: '知识库搜索search(auto 融合推荐) / keyword_search(SQL LIKE 精确) / semantic_search(向量语义) / context_search(Agent+漏斗+会话)',
178
- browse: '知识浏览(list / get / insights)',
179
- graph: '知识图谱关系查询与影响分析',
180
- structure: 'SPM Target 结构发现',
181
- validate: '候选预校验与去重检测',
182
- submit: '候选提交(写操作,Gateway gated)',
183
- guard: '代码 Guard 规则审计(写操作,Gateway gated)',
184
- scan: '全项目扫描(文件收集 + Guard 检查)',
185
- enrich: 'AI 语义字段补全(写操作,Gateway gated)',
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 融合)', 'get_recipe', 'confirm_usage'], tips: '精确匹配用 keyword_search,需意图+会话上下文用 context_search' },
192
- { name: '单条知识提交', steps: ['check_duplicate', 'validate_candidate', 'submit_knowledge'] },
193
- { name: '批量 Target 扫描', steps: ['get_targets', 'get_target_files', '(Agent 分析)', 'submit_knowledge_batch'] },
194
- { name: '全项目深度扫描', steps: ['scan_project', '(Agent 语义分析)', 'submit_knowledge_batch', 'enrich_candidates'] },
195
- { name: '候选就绪检查', steps: ['enrich_candidates', 'validate_candidate', 'check_duplicate'] },
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' },