autosnippet
Version:
Extract code patterns into a knowledge base for AI coding assistants
136 lines (135 loc) • 8.49 kB
TypeScript
/**
* insight-producer.js — Insight Producer 领域函数
*
* 从旧 ProducerAgent.js 提取的纯领域逻辑:
* - Producer System Prompt
* - 工具白名单
* - 预算常量
* - Prompt 构建器 (v1 + v2)
* - 代码上下文注入 (evidenceMap → prompt section)
* - 拒绝率门控 (producerRejectionGateEvaluator)
*
* 被 PipelineStrategy 的 bootstrap preset 直接引用。
* 不再包含任何 Agent 类 — Agent 由 AgentRuntime + PipelineStrategy 驱动。
*
* @module insight-producer
*/
import type { EvidenceEntry } from './EvidenceCollector.js';
/** AnalysisReport 最小接口 (v1) */
interface AnalysisReportLike {
analysisText: string;
referencedFiles: string[];
}
/** AnalysisArtifact 最小接口 (v2) */
interface AnalysisArtifactLike extends AnalysisReportLike {
findings: Array<{
finding: string;
evidence?: string;
importance: number;
}>;
evidenceMap?: Map<string, EvidenceEntry>;
negativeSignals: Array<{
searchPattern: string;
implication: string;
}>;
}
/** 维度配置 */
interface DimConfig {
id: string;
label: string;
allowedKnowledgeTypes?: string[];
outputType?: string;
}
/** 项目基本信息 */
interface ProjectInfo {
name: string;
}
/** reactLoop 返回值 (门控评估用) */
interface ReactLoopResult {
toolCalls?: ToolCallRecord[];
}
/** 工具调用记录 */
interface ToolCallRecord {
tool?: string;
name?: string;
result?: string | {
status?: string;
reason?: string;
};
}
/** 门控策略上下文 */
interface GateStrategyContext {
submitToolNames?: string[];
[key: string]: unknown;
}
export declare const PRODUCER_SYSTEM_PROMPT = "\u4F60\u662F\u77E5\u8BC6\u7BA1\u7406\u4E13\u5BB6\u3002\u4F60\u4F1A\u6536\u5230\u4E00\u6BB5\u4EE3\u7801\u5206\u6790\u6587\u672C\uFF0C\u9700\u8981\u5C06\u5176\u4E2D\u7684\u77E5\u8BC6\u70B9\u8F6C\u5316\u4E3A\u7ED3\u6784\u5316\u7684\u77E5\u8BC6\u5019\u9009\u3002\n\n\u6838\u5FC3\u539F\u5219: \u5206\u6790\u6587\u672C\u5DF2\u7ECF\u5305\u542B\u4E86\u6240\u6709\u53D1\u73B0\uFF0C\u4F60\u7684\u552F\u4E00\u5DE5\u4F5C\u662F\u5C06\u5B83\u4EEC\u683C\u5F0F\u5316\u4E3A submit_knowledge \u8C03\u7528\u3002\n\n\u6BCF\u4E2A\u5019\u9009\u5FC5\u987B:\n1. \u6709\u6E05\u6670\u7684\u6807\u9898 (\u63CF\u8FF0\u77E5\u8BC6\u70B9\u7684\u6838\u5FC3\uFF0C\u4F7F\u7528\u9879\u76EE\u771F\u5B9E\u7C7B\u540D\uFF0C\u4E0D\u4EE5\u9879\u76EE\u540D\u5F00\u5934)\n2. \u6709\u9879\u76EE\u7279\u5199\u98CE\u683C\u7684\u6B63\u6587 (content.markdown \u5B57\u6BB5\uFF0C\u7ED3\u5408\u4EE3\u7801\u5C55\u793A)\n3. \u6807\u6CE8\u76F8\u5173\u6587\u4EF6\u7684\u5B8C\u6574\u76F8\u5BF9\u8DEF\u5F84 + \u884C\u53F7\uFF08\u4ECE\u9879\u76EE\u6839\u76EE\u5F55\u5F00\u59CB\uFF0C\u5982 Packages/AOXNetworkKit/Sources/.../NetworkClient.swift:42\uFF09\n4. \u9009\u62E9\u6B63\u786E\u7684 kind (rule/pattern/fact)\n5. \u63D0\u4F9B\u5B8C\u6574\u7684 Cursor \u4EA4\u4ED8\u5B57\u6BB5 (trigger, doClause, whenClause \u7B49)\n6. \u6807\u6CE8\u6240\u5C5E\u6A21\u5757/\u5305\u540D\uFF08\u5982\u300C\u6240\u5C5E\u6A21\u5757: AOXNetworkKit\u300D\uFF09\uFF0C\u7279\u522B\u662F\u6765\u81EA\u672C\u5730\u5B50\u5305\u7684\u77E5\u8BC6\n\n\u5DE5\u4F5C\u6D41\u7A0B:\n1. \u9605\u8BFB\u5206\u6790\u6587\u672C\uFF0C\u8BC6\u522B\u6BCF\u4E2A\u72EC\u7ACB\u7684\u77E5\u8BC6\u70B9/\u53D1\u73B0\n2. \u7528 read_project_file \u6279\u91CF\u83B7\u53D6\u5173\u952E\u4EE3\u7801\u7247\u6BB5:\n read_project_file({ filePaths: [\"Full/Path/To/FileA.swift\", \"Full/Path/To/FileB.swift\"], maxLines: 80 })\n3. \u7ACB\u523B\u8C03\u7528 submit_knowledge \u63D0\u4EA4\n4. \u91CD\u590D\u76F4\u5230\u5206\u6790\u4E2D\u7684\u6240\u6709\u77E5\u8BC6\u70B9\u90FD\u5DF2\u63D0\u4EA4\n\n\u5173\u952E\u89C4\u5219:\n- \u5206\u6790\u4E2D\u7684\u6BCF\u4E2A\u8981\u70B9/\u6BB5\u843D\u90FD\u5E94\u8F6C\u5316\u4E3A\u81F3\u5C11\u4E00\u4E2A\u5019\u9009\n- read_project_file \u652F\u6301 filePaths \u6570\u7EC4\u6279\u91CF\u8BFB\u53D6\u591A\u4E2A\u6587\u4EF6\uFF0C\u4E00\u6B21\u8C03\u7528\u5B8C\u6210\n- read_project_file \u65F6\u8BFB\u53D6\u8DB3\u591F\u591A\u7684\u884C\u6570\uFF08startLine + maxLines \u81F3\u5C11 30 \u884C\uFF09\n- reasoning.sources \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\uFF0C\u586B\u5199\u6587\u4EF6\u7684\u5B8C\u6574\u76F8\u5BF9\u8DEF\u5F84\u5982 [\"Packages/AOXNetworkKit/Sources/AOXNetworkKit/Client/NetworkClient.swift\"]\uFF08\u7981\u6B62\u53EA\u5199\u6587\u4EF6\u540D\uFF09\n- content.markdown \u4E2D\u7684\u6765\u6E90\u6807\u6CE8\u5FC5\u987B\u4F7F\u7528\u5B8C\u6574\u76F8\u5BF9\u8DEF\u5F84+\u884C\u53F7: (\u6765\u6E90: Full/Path/FileName.ext:\u884C\u53F7)\n- \u5982\u679C\u5206\u6790\u63D0\u5230\u4E86 3 \u4E2A\u6A21\u5F0F\uFF0C\u5C31\u5E94\u8BE5\u63D0\u4EA4 3 \u4E2A\u5019\u9009\uFF0C\u4E0D\u8981\u5408\u5E76\n- \u7981\u6B62: \u4E0D\u8981\u641C\u7D22\u65B0\u6587\u4EF6\u3001\u4E0D\u8981\u505A\u989D\u5916\u5206\u6790\uFF0C\u4E13\u6CE8\u4E8E\u683C\u5F0F\u5316\u548C\u63D0\u4EA4\n- \u3010\u8DE8\u7EF4\u5EA6\u53BB\u91CD\u3011\u6BCF\u6761\u5019\u9009\u5FC5\u987B\u805A\u7126\u5F53\u524D\u7EF4\u5EA6\u72EC\u6709\u7684\u89C6\u89D2\uFF0C\u4E0D\u5F97\u5C06\u540C\u4E00\u77E5\u8BC6\u70B9\u6362\u4E2A\u8BF4\u6CD5\u91CD\u590D\u63D0\u4EA4\u3002\u76F8\u540C\u7684\u7C7B/\u6A21\u5F0F\u53EA\u5728\u6700\u76F8\u5173\u7684\u7EF4\u5EA6\u51FA\u73B0\u4E00\u6B21\uFF0C\u5B81\u53EF\u5C11\u63D0\u4EA4\u4E5F\u4E0D\u8981\u5145\u6570\n\n\u5BB9\u9519\u89C4\u5219:\n- \u5982\u679C read_project_file \u8FD4\u56DE\"\u6587\u4EF6\u4E0D\u5B58\u5728\"\u6216\u9519\u8BEF\uFF0C\u4E0D\u8981\u91CD\u8BD5\u540C\u4E00\u6587\u4EF6\u7684\u5176\u4ED6\u8DEF\u5F84\u53D8\u4F53\n- \u6587\u4EF6\u8BFB\u53D6\u5931\u8D25\u65F6\uFF0C\u76F4\u63A5\u4F7F\u7528\u5206\u6790\u6587\u672C\u4E2D\u5DF2\u6709\u7684\u4EE3\u7801\u548C\u63CF\u8FF0\u6765\u63D0\u4EA4\u5019\u9009\n- \u6C38\u8FDC\u4E0D\u8981\u56E0\u4E3A\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25\u800C\u8DF3\u8FC7\u77E5\u8BC6\u70B9 \u2014 \u5206\u6790\u6587\u672C\u5DF2\u7ECF\u5305\u542B\u8DB3\u591F\u4FE1\u606F\n- \u5148\u63D0\u4EA4\u5019\u9009\uFF0C\u518D\u8003\u8651\u662F\u5426\u9700\u8981\u8BFB\u53D6\u66F4\u591A\u4EE3\u7801\uFF08\u63D0\u4EA4\u4F18\u5148\u4E8E\u9A8C\u8BC1\uFF09";
export declare const PRODUCER_TOOLS: string[];
export declare const PRODUCER_BUDGET: {
maxIterations: number;
searchBudget: number;
searchBudgetGrace: number;
maxSubmits: number;
softSubmitLimit: number;
idleRoundsToExit: number;
};
/**
* 构建 Producer Prompt (v1 — 用于 AnalysisReport)
*
* @param dimConfig { id, label, allowedKnowledgeTypes, outputType }
* @param projectInfo { name }
*/
export declare function buildProducerPrompt(analysisReport: AnalysisReportLike, dimConfig: DimConfig, projectInfo: ProjectInfo): string;
/** Panorama context for Producer */
interface ProducerPanoramaContext {
moduleRole: string | null;
moduleLayer: number | null;
knownGaps: string[];
layerContext: string | null;
}
/** Rescan context for Producer — gap info + existing recipe titles */
interface ProducerRescanContext {
existingRecipes: Array<{
title: string;
trigger: string;
}>;
decayingRecipes?: Array<{
id?: string;
title: string;
trigger: string;
decayReason?: string;
}>;
occupiedTriggers: string[];
gap: number;
existing: number;
}
/**
* 构建 Producer Prompt v2 — 用于 AnalysisArtifact
*
* 相比 v1 增加:
* - §3 结构化发现 (findings)
* - §4 代码证据 (evidenceMap → code context)
* - §5 负空间信号
* - §9 (可选) Rescan 模式约束
* - §M1 (可选) 全景上下文
*/
export declare function buildProducerPromptV2(artifact: AnalysisArtifactLike, dimConfig: DimConfig, projectInfo: ProjectInfo, rescanContext?: ProducerRescanContext | null, panorama?: ProducerPanoramaContext | null): string;
/**
* 从 evidenceMap 构建代码上下文段
*
* 策略: 按代码片段数量排序
* 预算: ≤ 4000 chars (~1000 tokens)
*/
export declare function buildCodeContextSection(evidenceMap: Map<string, EvidenceEntry> | null | undefined): string | null;
/**
* Producer 拒绝率门控 — 面向 PipelineStrategy gate.evaluator
*
* 当 produce 阶段的提交拒绝率过高时触发 retry。
*
* @param source produce 阶段的 reactLoop 返回值
* @returns }
*/
export declare function producerRejectionGateEvaluator(source: ReactLoopResult | null | undefined, _phaseResults: unknown, _strategyContext?: GateStrategyContext): {
action: string;
reason: string;
};
export {};