UNPKG

@autobe/agent

Version:

AI backend server code generator

173 lines (161 loc) 6.42 kB
import { AutoBeOpenApi, AutoBeProgressEventBase, AutoBeRealizeCollectorFunction, } from "@autobe/interface"; import { AutoBeOpenApiTypeChecker } from "@autobe/utils"; import typia, { ILlmApplication, IValidation } from "typia"; import { AutoBeContext } from "../../context/AutoBeContext"; import { AutoBePreliminaryController } from "../common/AutoBePreliminaryController"; import { orchestrateRealizeCorrectOverall } from "./correct/orchestrateRealizeCorrectOverall"; import { transformRealizeCollectorCorrectHistory } from "./histories/transformRealizeCollectorCorrectHistory"; import { AutoBeRealizeCollectorProgrammer } from "./programmers/AutoBeRealizeCollectorProgrammer"; import { IAutoBeRealizeCollectorCorrectApplication } from "./structures/IAutoBeRealizeCollectorCorrectApplication"; import { IAutoBeRealizeFunctionResult } from "./structures/IAutoBeRealizeFunctionResult"; export const orchestrateRealizeCollectorCorrectOverall = async ( ctx: AutoBeContext, props: { functions: AutoBeRealizeCollectorFunction[]; progress: AutoBeProgressEventBase; }, ): Promise<IAutoBeRealizeFunctionResult<AutoBeRealizeCollectorFunction>[]> => { const document: AutoBeOpenApi.IDocument = ctx.state().interface!.document; const getNeighbors = ( func: AutoBeRealizeCollectorFunction, ): AutoBeRealizeCollectorFunction[] => { const visited: Set<string> = new Set(); AutoBeOpenApiTypeChecker.visit({ components: document.components, schema: { $ref: `#/components/schemas/${func.plan.dtoTypeName}` }, closure: (next) => { if (AutoBeOpenApiTypeChecker.isReference(next)) { const key: string = next.$ref.split("/").pop()!; visited.add(key); } }, }); return props.functions.filter( (y) => y.plan.dtoTypeName !== func.plan.dtoTypeName && visited.has(y.plan.dtoTypeName), ); }; return await orchestrateRealizeCorrectOverall(ctx, { programmer: { location: "src/collectors", // Recalculate template for corrected collector function template: (func) => AutoBeRealizeCollectorProgrammer.writeTemplate({ plan: func.plan, body: document.components.schemas[func.plan.dtoTypeName], model: ctx .state() .database!.result.data.files.map((f) => f.models) .flat() .find((m) => m.name === func.plan.databaseSchemaName)!, application: ctx.state().database!.result.data, }), // Replace import statements using Collector-specific programmer replaceImportStatements: async (next) => { return await AutoBeRealizeCollectorProgrammer.replaceImportStatements( ctx, { dtoTypeName: next.function.plan.dtoTypeName, schemas: document.components.schemas, code: next.code, }, ); }, // No additional files needed for collectors (unlike operations) additional: (_functions) => ({}), // Create preliminary controller with only databaseSchemas support preliminary: (next) => new AutoBePreliminaryController<"databaseSchemas">({ source: next.source, application: typia.json.application<IAutoBeRealizeCollectorCorrectApplication>(), kinds: ["databaseSchemas"], dispatch: (e) => ctx.dispatch(e), state: ctx.state(), local: { databaseSchemas: ctx .state() .database!.result.data.files.map((f) => f.models) .flat() .filter((m) => m.name === next.function.plan.databaseSchemaName), }, }), // Transform history using Collector-specific transformer histories: (next) => transformRealizeCollectorCorrectHistory(ctx, { function: next.function, neighbors: getNeighbors(next.function), failures: next.failures, preliminary: next.preliminary, }), // Create controller with Collector-specific validation controller: (next) => { const validate: Validator = (input) => { const result: IValidation<IAutoBeRealizeCollectorCorrectApplication.IProps> = typia.validate<IAutoBeRealizeCollectorCorrectApplication.IProps>( input, ); if (result.success === false) return result; else if (result.data.request.type !== "write") return next.preliminary.validate({ thinking: result.data.thinking, request: result.data.request, }); // Validate collector-specific constraints const errors: IValidation.IError[] = AutoBeRealizeCollectorProgrammer.validate({ plan: next.function.plan, mappings: result.data.request.mappings, neighbors: props.functions.map((f) => f.plan), draft: result.data.request.draft, revise: result.data.request.revise, application: ctx.state().database!.result.data, }); return errors.length ? { success: false, errors, data: result.data, } : result; }; const application: ILlmApplication = next.preliminary.fixApplication( typia.llm.application<IAutoBeRealizeCollectorCorrectApplication>({ validate: { process: validate, }, }), ); AutoBeRealizeCollectorProgrammer.fixApplication({ definition: application, application: ctx.state().database!.result.data, model: ctx .state() .database!.result.data.files.map((f) => f.models) .flat() .find((m) => m.name === next.function.plan.databaseSchemaName)!, }); return { protocol: "class", name: next.source, application, execute: { process: (v) => { if (v.request.type === "write") next.build(v.request); }, } satisfies IAutoBeRealizeCollectorCorrectApplication, }; }, }, functions: props.functions, progress: props.progress, }); }; type Validator = ( input: unknown, ) => IValidation<IAutoBeRealizeCollectorCorrectApplication.IProps>;