UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

296 lines (295 loc) 9.35 kB
/** * CursorDeliveryPipeline 6 通道交付主入口 * * 读取知识库 筛选 + 分类 + 排序 + 压缩 写入 6 个通道 * * Channel A: .cursor/rules/autosnippet-project-rules.mdc (alwaysApply rules) * Channel B: .cursor/rules/autosnippet-patterns-{topic}.mdc (smart rules) * Channel C: .cursor/skills/ (project skills sync) * Channel D: .cursor/skills/autosnippet-devdocs/ (dev documents) * Channel F: AGENTS.md + CLAUDE.md + .github/copilot-instructions.md (agent instructions) * + Mirror: .qoder/ .trae/ (IDE mirror) * * 触发时机: * 1. bootstrap 完成后自动触发 * 2. `asd cursor-rules` CLI 命令手动触发 * 3. Recipe 状态变更(pending active)后触发 * 4. `asd upgrade` 时作为升级步骤执行 */ import type { KnowledgeEntryProps } from '../../domain/knowledge/KnowledgeEntry.js'; import { AgentInstructionsGenerator } from './AgentInstructionsGenerator.js'; import { KnowledgeCompressor } from './KnowledgeCompressor.js'; import { RulesGenerator } from './RulesGenerator.js'; import { SkillsSyncer } from './SkillsSyncer.js'; import { TopicClassifier } from './TopicClassifier.js'; export declare class CursorDeliveryPipeline { agentInstructions: AgentInstructionsGenerator; compressor: KnowledgeCompressor; database: Record<string, unknown> | null; knowledgeService: { list: (filter: Record<string, unknown>, pagination: { page: number; pageSize: number; }) => Promise<unknown>; }; logger: { info?: (...args: unknown[]) => void; warn?: (...args: unknown[]) => void; error?: (...args: unknown[]) => void; }; projectName: string; projectRoot: string; rulesGenerator: RulesGenerator; skillsSyncer: SkillsSyncer; topicClassifier: TopicClassifier; /** * @param options.knowledgeService KnowledgeService 实例 * @param options.projectRoot 用户项目根目录 * @param [options.projectName] 项目名称 * @param [options.logger] 日志器 */ constructor({ knowledgeService, projectRoot, projectName, logger, database, }: { knowledgeService: { list: (filter: Record<string, unknown>, pagination: { page: number; pageSize: number; }) => Promise<unknown>; }; projectRoot: string; projectName?: string; logger?: { info?: (...args: unknown[]) => void; warn?: (...args: unknown[]) => void; error?: (...args: unknown[]) => void; }; database?: Record<string, unknown> | null; }); /** * 完整交付流程 生成 6 通道消费物料 * @returns >} */ deliver(): Promise<{ channelA: { filePath: string; tokensUsed: number; rulesCount: number; } | { rulesCount: number; tokensUsed: number; filePath: null; }; channelB: { topicCount: number; patternsCount: number; factsCount: number; totalTokens: number; topics: Record<string, { patternsCount: number; factsCount: number; tokensUsed: number; }>; }; channelC: { synced: number; builtinSynced: number; projectSynced: number; skipped: number; errors: number; details: { synced: string[]; skipped: string[]; errors: string[]; builtinSynced: string[]; }; }; channelD: { documentsCount: number; filesWritten: number; filePaths: string[]; }; channelF: { filesWritten: number; totalTokens: number; files: { agents: string; claude: string; copilot: string; }; } | { filesWritten: number; totalTokens: number; files: { agents?: undefined; claude?: undefined; copilot?: undefined; }; }; stats: { channelA: { rulesCount: number; tokensUsed: number; }; channelB: { topicCount: number; patternsCount: number; totalTokens: number; topics: Record<string, { patternsCount: number; factsCount: number; tokensUsed: number; }>; }; channelC: { synced: number; skipped: number; errors: number; }; channelD: { documentsCount: number; filesWritten: number; }; channelF: { filesWritten: number; totalTokens: number; }; totalTokensUsed: number; duration: number; }; }>; /** * 加载知识条目(active + staging + high-confidence pending) * * M2 六态状态机: staging/active/evolving 均为 CONSUMABLE 状态 */ _loadEntries(): Promise<KnowledgeEntryProps[]>; /** * KnowledgeService.list() 返回值提取条目数组 */ _extractItems(result: unknown): KnowledgeEntryProps[]; /** * kind 分类知识条目 * dev-document 类型单独分流,不进入 Channel A/B 压缩 */ _classify(entries: KnowledgeEntryProps[]): { rules: KnowledgeEntryProps[]; patterns: KnowledgeEntryProps[]; facts: KnowledgeEntryProps[]; documents: KnowledgeEntryProps[]; }; /** * 排序 质量分 + 统计使用量 */ _rank(entries: KnowledgeEntryProps[]): KnowledgeEntryProps[]; /** * 计算排名分 */ _rankScore(entry: KnowledgeEntryProps): number; /** * Channel A 生成 */ _generateChannelA(rules: KnowledgeEntryProps[]): { filePath: string; tokensUsed: number; rulesCount: number; } | { rulesCount: number; tokensUsed: number; filePath: null; }; /** * Channel B 生成(patterns + facts) * @param patterns kind='pattern' 的知识条目 * @param [facts=[]] kind='fact' 的知识条目 */ _generateChannelB(patterns: KnowledgeEntryProps[], facts?: KnowledgeEntryProps[]): { topicCount: number; patternsCount: number; factsCount: number; totalTokens: number; topics: Record<string, { patternsCount: number; factsCount: number; tokensUsed: number; }>; }; /** * Channel B+ Call Graph Architecture Rules (Phase 5.2) * 从调用图拓扑分析架构分层,生成 architecture smart rule * @returns |null} */ _generateCallGraphArchitectureRules(): { insightsCount: number; tokensUsed: number; filePath: string; } | null; /** * 从文件路径中提取层级目录 (第一或第二级有意义的目录) */ _extractLayerDir(filePath: string): string | null; /** * Channel C 生成 */ _generateChannelC(): Promise<{ synced: number; builtinSynced: number; projectSynced: number; skipped: number; errors: number; details: { synced: string[]; skipped: string[]; errors: string[]; builtinSynced: string[]; }; }>; /** * Channel D Dev Documents 生成 * knowledgeType='dev-document' 的条目以原始 MD 写入 * .cursor/skills/autosnippet-devdocs/references/ 目录 */ _generateChannelD(documents: KnowledgeEntryProps[]): { documentsCount: number; filesWritten: number; filePaths: string[]; }; /** * Channel F Agent Instructions 生成 * 生成 AGENTS.md / CLAUDE.md / .github/copilot-instructions.md */ _generateChannelF(rules: KnowledgeEntryProps[], patterns: KnowledgeEntryProps[]): { filesWritten: number; totalTokens: number; files: { agents: string; claude: string; copilot: string; }; } | { filesWritten: number; totalTokens: number; files: { agents?: undefined; claude?: undefined; copilot?: undefined; }; }; /** * 文件名安全 slug */ _slugify(text: string): string; /** * 镜像 .cursor/ 交付物料到目标 IDE 目录(Qoder / Trae 等兼容 IDE) * 只复制 autosnippet- 前缀的文件/目录,不触碰用户自定义内容 * @param targetDirName 目标目录名,如 '.qoder' '.trae' */ _mirrorToIDE(targetDirName: string): void; /** * 递归复制目录 */ _copyDirRecursive(src: string, dest: string): void; /** * 从项目路径推断项目名称 */ _inferProjectName(projectRoot: string): string; } export default CursorDeliveryPipeline;