autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
128 lines (127 loc) • 5.12 kB
JavaScript
/**
* MCP Handlers — 系统类
* health
*/
import fs from 'node:fs';
import path from 'node:path';
import { PACKAGE_ROOT } from '#shared/package-root.js';
import { resolveProjectRoot } from '#shared/resolveProjectRoot.js';
import { envelope } from '../envelope.js';
export async function health(ctx) {
const checks = { database: false, gateway: false, vectorStore: false };
const issues = [];
let knowledgeBase = null;
// 1) AI 配置
let aiInfo = { provider: 'unknown', hasKey: false };
try {
const { getAiConfigInfo } = await import('#external/ai/AiFactory.js');
aiInfo = getAiConfigInfo();
}
catch (e) {
issues.push(`ai: ${e instanceof Error ? e.message : String(e)}`);
}
// 2) Database 连通性 + 知识库统计
try {
const knowledgeRepo = ctx.container.get('knowledgeRepository');
if (knowledgeRepo) {
const stats = (await knowledgeRepo.getStats());
checks.database = true;
if (stats) {
knowledgeBase = {
recipes: {
total: stats.total,
active: stats.active,
rules: stats.rules,
patterns: stats.patterns,
facts: stats.facts,
},
candidates: { total: stats.total, pending: stats.pending },
};
}
}
}
catch (e) {
issues.push(`database: ${e instanceof Error ? e.message : String(e)}`);
}
// 3) Gateway 可用性
try {
const gw = ctx.container.get('gateway');
checks.gateway = !!gw;
}
catch (e) {
issues.push(`gateway: ${e instanceof Error ? e.message : String(e)}`);
}
// 4) VectorStore 可用性
try {
const vs = ctx.container.get('vectorStore');
if (vs) {
const vsStats = typeof vs.getStats === 'function' ? await vs.getStats() : null;
checks.vectorStore = true;
if (vsStats) {
knowledgeBase =
knowledgeBase ||
{
recipes: { total: 0, active: 0, rules: 0, patterns: 0, facts: 0 },
candidates: { total: 0, pending: 0 },
};
knowledgeBase.vectorIndex = {
documentCount: vsStats.documentCount ?? vsStats.totalDocuments ?? 0,
};
}
}
}
catch (e) {
issues.push(`vectorStore: ${e instanceof Error ? e.message : String(e)}`);
}
// 5) 版本号(从 AutoSnippet 包自身的 package.json 读取,不依赖 cwd)
if (!_pkgVersion) {
try {
const pkgPath = path.resolve(PACKAGE_ROOT, 'package.json');
_pkgVersion = JSON.parse(fs.readFileSync(pkgPath, 'utf8')).version || '2.0.0';
}
catch {
_pkgVersion = '2.0.0';
}
}
// 6) 综合状态
const allCritical = checks.database; // DB 是唯一硬性依赖
const status = allCritical ? 'ok' : 'degraded';
// 如果 DB 不可用但冷启动仍可执行,附加提示避免 Agent 浪费时间修复 DB
const actionHints = [];
if (!checks.database) {
actionHints.push('DB 不可用不影响冷启动:autosnippet_bootstrap 不依赖数据库(纯文件系统分析),可直接调用。DB 会在首次 submit_knowledge 时自动重试初始化。');
}
if (!knowledgeBase || knowledgeBase.recipes.total === 0) {
actionHints.push('知识库为空,建议执行冷启动:(1) 调用 autosnippet_bootstrap 获取 Mission Briefing → (2) 按维度分析代码并提交知识 → (3) 调用 autosnippet_dimension_complete 完成每个维度。');
actionHints.push('💡 冷启动指引:调用 autosnippet_bootstrap 获取 Mission Briefing → 按维度分析代码 → 调用 autosnippet_dimension_complete 完成每个维度');
}
return envelope({
success: true,
data: {
status,
version: _pkgVersion,
uptime: Math.floor((Date.now() - (ctx.startedAt ?? Date.now())) / 1000),
projectRoot: resolveProjectRoot(ctx.container),
ai: aiInfo,
checks,
services: ctx.container.getServiceNames?.() ?? [],
knowledgeBase,
// P3: Session 信息
...(ctx.session
? {
session: {
id: ctx.session.id,
intentPhase: ctx.session.intent?.phase ?? 'idle',
toolCallCount: ctx.session.toolCallCount,
toolsUsed: Array.from(ctx.session.toolsUsed),
durationMs: Date.now() - ctx.session.startedAt,
},
}
: {}),
...(issues.length ? { issues } : {}),
...(actionHints.length ? { actionHints } : {}),
},
meta: { tool: 'autosnippet_health' },
});
}
let _pkgVersion = null;