UNPKG

@autobe/agent

Version:

AI backend server code generator

202 lines (177 loc) 6.9 kB
import { AutoBeAnalyze, AutoBeAnalyzeScenarioEvent, AutoBeAnalyzeWriteModuleEvent, AutoBeAnalyzeWriteSectionEvent, AutoBeAnalyzeWriteUnitEvent, } from "@autobe/interface"; import { StringUtil } from "@autobe/utils"; import { v7 } from "uuid"; import YAML from "yaml"; import { AutoBeSystemPromptConstant } from "../../../constants/AutoBeSystemPromptConstant"; import { AutoBeContext } from "../../../context/AutoBeContext"; import { IAutoBeOrchestrateHistory } from "../../../structures/IAutoBeOrchestrateHistory"; import { AutoBePreliminaryController } from "../../common/AutoBePreliminaryController"; /** * Transform histories for cross-file lightweight review of section metadata. * * This transformer provides ONLY section titles, keywords, and purposes from * ALL files — NOT full content. This keeps the input well within context limits * even with hundreds of sections. */ export const transformAnalyzeSectionCrossFileReviewHistory = ( _ctx: AutoBeContext, props: { scenario: AutoBeAnalyzeScenarioEvent; allFileSummaries: Array<{ file: AutoBeAnalyze.IFileScenario; moduleEvent: AutoBeAnalyzeWriteModuleEvent; unitEvents: AutoBeAnalyzeWriteUnitEvent[]; sectionEvents: AutoBeAnalyzeWriteSectionEvent[][]; status: "approved" | "rewritten" | "new"; }>; mechanicalViolationSummary?: string; fileDecisions?: import("../utils/detectDecisionConflicts").IFileDecisions[]; preliminary: null | AutoBePreliminaryController< "previousAnalysisSections" | "complete" >; }, ): IAutoBeOrchestrateHistory => { return { histories: [ { id: v7(), created_at: new Date().toISOString(), type: "systemMessage", text: AutoBeSystemPromptConstant.ANALYZE_SECTION_CROSS_FILE_REVIEW, }, ...(props.preliminary?.getHistories() ?? []), { id: v7(), created_at: new Date().toISOString(), type: "assistantMessage", text: StringUtil.trim` ## Language The language of the document is ${JSON.stringify(props.scenario.language ?? "en-US")}. ## All Files' Section Metadata for Cross-File Consistency Review Below is lightweight metadata (titles, keywords, purposes) from ALL files. Full content has already been validated in per-file review. ${props.allFileSummaries .map( ( { file, moduleEvent, unitEvents, sectionEvents, status }, fileIndex, ) => ` --- ## File ${fileIndex + 1}: ${file.filename} [Status: ${status === "approved" ? "✅ Previously Approved" : status === "rewritten" ? "🔄 Rewritten" : "🆕 New"}] **Title**: ${moduleEvent.title} **Summary**: ${moduleEvent.summary} ${sectionEvents .map((sectionsForModule, moduleIndex) => { const moduleSection = moduleEvent.moduleSections[moduleIndex]; const unitEvent = unitEvents[moduleIndex]; return ` ### Module ${moduleIndex + 1}: ${moduleSection?.title ?? "Unknown"} ${sectionsForModule .map((sectionEvent, unitIndex) => { const unitSection = unitEvent?.unitSections[unitIndex]; return ` #### Unit ${moduleIndex + 1}.${unitIndex + 1}: ${unitSection?.title ?? "Unknown"} **Keywords**: ${unitSection?.keywords?.join(", ") ?? "None"} Sections: ${sectionEvent.sectionSections .map((section) => { const attrKeys = extractYamlAttributeKeys(section.content); return `- **${section.title}**${attrKeys ? ` [attrs: ${attrKeys}]` : ""}`; }) .join("\n")} `; }) .join("\n")} `; }) .join("\n")} `, ) .join("\n")} ${ props.mechanicalViolationSummary ? ` ## Mechanical Validation Results (Already Addressed Separately) The following mechanical issues have been detected and will be patched separately. You do NOT need to flag these — focus only on semantic/logical consistency: ${props.mechanicalViolationSummary} ` : "" } ${ props.fileDecisions && props.fileDecisions.length > 0 ? ` ## Extracted Key Decisions Per File Below are the key behavioral decisions extracted from each file. Use these to verify cross-file consistency — same topic+decision should have the same value across files. ${props.fileDecisions .filter((fd) => fd.decisions.length > 0) .map( (fd) => `**${fd.filename}**:\n${fd.decisions.map((d) => `- ${d.topic}.${d.decision} = "${d.value}" — ${d.evidence.slice(0, 100)}`).join("\n")}`, ) .join("\n\n")} ` : "" } ## Cross-File Semantic Consistency Criteria Focus ONLY on issues requiring human-like judgment: 1. Are there logical contradictions between files? 2. Is terminology aligned (same concepts = same terms)? 3. Are authentication/authorization models compatible across files? 4. Are there features described in one file that conflict with another? 5. Do any files invent features not in the scenario? `, }, ], userMessage: "Review ALL files' section metadata for cross-file consistency and provide per-file approved/rejected verdicts.", }; }; // ─── Internal helpers ─── const YAML_CODE_BLOCK_REGEX = /```yaml\n([\s\S]*?)```/g; const BACKTICK_ENTITY_FIELD_REGEX = /`(\w+\.\w+)`/g; /** * Extract Entity.attribute keys from YAML spec blocks and backtick references. * * Returns a compact comma-separated string of attribute keys (e.g., * "User.status, User.email, Todo.title") for lightweight cross-file * visibility. */ const extractYamlAttributeKeys = (content: string): string => { const keys: Set<string> = new Set(); // Extract from YAML spec blocks const yamlMatches = content.matchAll(YAML_CODE_BLOCK_REGEX); for (const match of yamlMatches) { const yamlContent = match[1] ?? ""; try { const parsed = YAML.parse(yamlContent); if ( parsed && typeof parsed === "object" && typeof parsed.entity === "string" && Array.isArray(parsed.attributes) ) { for (const attr of parsed.attributes) { if (attr && typeof attr.name === "string") { keys.add(`${parsed.entity}.${attr.name}`); } } } } catch { // skip parse errors } } // Extract from backtick `Entity.field` references const backtickMatches = content.matchAll(BACKTICK_ENTITY_FIELD_REGEX); for (const match of backtickMatches) { keys.add(match[1]!); } return [...keys].join(", "); };