UNPKG

@autobe/agent

Version:

AI backend server code generator

617 lines (589 loc) 20.4 kB
import { AgenticaExecuteHistory, MicroAgenticaHistory } from "@agentica/core"; import { AutoBeDatabase, AutoBeEventSource, AutoBeOpenApi, AutoBePreliminaryKind, AutoBeRealizeCollectorFunction, AutoBeRealizeTransformerFunction, } from "@autobe/interface"; import { OpenApiTypeChecker } from "@typia/utils"; import { IPointer } from "tstl"; import typia from "typia"; import { v7 } from "uuid"; import { AutoBeContext } from "../../context/AutoBeContext"; import { AutoBePreliminaryController } from "./AutoBePreliminaryController"; import { complementPreliminaryCollection } from "./internal/complementPreliminaryCollection"; import { IAutoBePreliminaryRequest } from "./structures/AutoBePreliminaryRequest"; import { IAnalysisSectionEntry } from "./structures/IAnalysisSectionEntry"; import { IAutoBePreliminaryCollection } from "./structures/IAutoBePreliminaryCollection"; import { IAutoBePreliminaryComplete } from "./structures/IAutoBePreliminaryComplete"; export const orchestratePreliminary = async < Kind extends AutoBePreliminaryKind, >( ctx: AutoBeContext, props: { source_id: string; source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; histories: MicroAgenticaHistory[]; preliminary: AutoBePreliminaryController<Kind>; completed: IPointer<boolean>; trial: number; }, ): Promise<void> => { const executes: AgenticaExecuteHistory[] = props.histories.filter( (h) => h.type === "execute", ); if (executes.length === 0) { // Some vendors (notably certain Qwen/OpenRouter routes) occasionally return // an empty turn where only the user message is recorded. Treat it as a // transient no-op so the outer RAG loop can retry instead of failing fast. if (props.histories.every((h) => h.type === "userMessage")) return; throw new Error("Failed to function calling from the preliminary step."); } for (const exec of executes) { // COMPLETE if (typia.is<{ request: IAutoBePreliminaryComplete }>(exec.arguments)) { props.completed.value ||= true; } // ANALYSIS else if (isAnalysisSections(props.preliminary, exec.arguments)) { const ps: AutoBePreliminaryController<"analysisSections"> = props.preliminary; orchestrateAnalysisSections(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: ps.getAll().analysisSections, local: ps.getLocal().analysisSections, arguments: exec.arguments, previous: false, }); props.preliminary.advanceAnalysisPage(); } else if (isPreviousAnalysisSections(props.preliminary, exec.arguments)) { const ps: AutoBePreliminaryController<"previousAnalysisSections"> = props.preliminary; orchestrateAnalysisSections(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: ps.getAll().previousAnalysisSections, local: ps.getLocal().previousAnalysisSections, arguments: exec.arguments, previous: true, }); props.preliminary.advanceAnalysisPage(); } // PRISMA SCHEMAS else if (isPrismaSchemas(props.preliminary, exec.arguments)) { const pp: AutoBePreliminaryController<"databaseSchemas"> = props.preliminary; orchestratePrismaSchemas(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: pp.getAll().databaseSchemas, local: pp.getLocal().databaseSchemas, arguments: exec.arguments, previous: false, }); } else if (isPreviousPrismaSchemas(props.preliminary, exec.arguments)) { const pp: AutoBePreliminaryController<"previousDatabaseSchemas"> = props.preliminary; orchestratePrismaSchemas(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: pp.getAll().previousDatabaseSchemas, local: pp.getLocal().previousDatabaseSchemas, arguments: exec.arguments, previous: true, }); } // INTERFACE OPERATIONS else if (isInterfaceOperations(props.preliminary, exec.arguments)) { const pi: AutoBePreliminaryController<"interfaceOperations"> = props.preliminary; orchestrateInterfaceOperations(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: pi.getAll().interfaceOperations, local: pi.getLocal().interfaceOperations, arguments: exec.arguments, previous: false, }); } else if ( isPreviousInterfaceOperations(props.preliminary, exec.arguments) ) { const pi: AutoBePreliminaryController<"previousInterfaceOperations"> = props.preliminary; orchestrateInterfaceOperations(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: pi.getAll().previousInterfaceOperations, local: pi.getLocal().previousInterfaceOperations, arguments: exec.arguments, previous: true, }); } // INTERFACE SCHEMAS else if (isInterfaceSchemas(props.preliminary, exec.arguments)) { const ps: AutoBePreliminaryController<"interfaceSchemas"> = props.preliminary; orchestrateInterfaceSchemas(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: ps.getAll().interfaceSchemas, local: ps.getLocal().interfaceSchemas, arguments: exec.arguments, previous: false, }); } else if (isPreviousInterfaceSchemas(props.preliminary, exec.arguments)) { const ps: AutoBePreliminaryController<"previousInterfaceSchemas"> = props.preliminary; orchestrateInterfaceSchemas(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: ps.getAll().previousInterfaceSchemas, local: ps.getLocal().previousInterfaceSchemas, arguments: exec.arguments, previous: true, }); } // REALIZE COLLECTORS else if (isRealizeCollectors(props.preliminary, exec.arguments)) { const rc: AutoBePreliminaryController<"realizeCollectors"> = props.preliminary; orchestrateRealizeCollectors(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: rc.getAll().realizeCollectors, local: rc.getLocal().realizeCollectors, arguments: exec.arguments, }); } // REALIZE TRANSFORMERS else if (isRealizeTransformers(props.preliminary, exec.arguments)) { const rt: AutoBePreliminaryController<"realizeTransformers"> = props.preliminary; orchestrateRealizeTransformers(ctx, { source: props.source, source_id: props.source_id, trial: props.trial, all: rt.getAll().realizeTransformers, local: rt.getLocal().realizeTransformers, arguments: exec.arguments, }); } } complementPreliminaryCollection({ kinds: props.preliminary.getKinds(), all: props.preliminary.getAll() as IAutoBePreliminaryCollection, local: props.preliminary.getLocal() as IAutoBePreliminaryCollection, prerequisite: false, }); }; /* ----------------------------------------------------------- TYPE CHECKERS ----------------------------------------------------------- */ const isAnalysisSections = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"analysisSections"> => typia.is<IAutoBePreliminaryRequest<"analysisSections">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "analysisSections"> >()[0] ] !== undefined; const isPreviousAnalysisSections = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"previousAnalysisSections"> => typia.is<IAutoBePreliminaryRequest<"previousAnalysisSections">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "previousAnalysisSections"> >()[0] ] !== undefined; const isPrismaSchemas = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"databaseSchemas"> => typia.is<IAutoBePreliminaryRequest<"databaseSchemas">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "databaseSchemas"> >()[0] ] !== undefined; const isPreviousPrismaSchemas = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"previousDatabaseSchemas"> => typia.is<IAutoBePreliminaryRequest<"previousDatabaseSchemas">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "previousDatabaseSchemas"> >()[0] ] !== undefined; const isInterfaceOperations = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"interfaceOperations"> => typia.is<IAutoBePreliminaryRequest<"interfaceOperations">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "interfaceOperations"> >()[0] ] !== undefined; const isPreviousInterfaceOperations = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"previousInterfaceOperations"> => typia.is<IAutoBePreliminaryRequest<"previousInterfaceOperations">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "previousInterfaceOperations"> >()[0] ] !== undefined; const isInterfaceSchemas = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"interfaceSchemas"> => typia.is<IAutoBePreliminaryRequest<"interfaceSchemas">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "interfaceSchemas"> >()[0] ] !== undefined; const isPreviousInterfaceSchemas = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"previousInterfaceSchemas"> => typia.is<IAutoBePreliminaryRequest<"previousInterfaceSchemas">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "previousInterfaceSchemas"> >()[0] ] !== undefined; const isRealizeCollectors = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"realizeCollectors"> => typia.is<IAutoBePreliminaryRequest<"realizeCollectors">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "realizeCollectors"> >()[0] ] !== undefined; const isRealizeTransformers = ( // biome-ignore lint: intended preliminary: AutoBePreliminaryController<any>, input: unknown, ): preliminary is AutoBePreliminaryController<"realizeTransformers"> => typia.is<IAutoBePreliminaryRequest<"realizeTransformers">>(input) && preliminary.getAll()[ typia.misc.literals< Extract<keyof IAutoBePreliminaryCollection, "realizeTransformers"> >()[0] ] !== undefined; /* ----------------------------------------------------------- ORCHESTRATORS ----------------------------------------------------------- */ const orchestrateAnalysisSections = ( ctx: AutoBeContext, props: { source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; source_id: string; trial: number; all: IAnalysisSectionEntry[]; local: IAnalysisSectionEntry[]; arguments: unknown; previous: boolean; }, ): void => { if (props.previous) { if ( false === typia.is<IAutoBePreliminaryRequest<"previousAnalysisSections">>( props.arguments, ) ) return; } else if ( false === typia.is<IAutoBePreliminaryRequest<"analysisSections">>(props.arguments) ) return; const existing: number[] = props.local.map((s) => s.id); for (const sectionId of props.arguments.request.sectionIds) { const section: IAnalysisSectionEntry | undefined = props.all.find( (s) => s.id === sectionId, ); if (section === undefined) continue; else if (props.local.find((s) => s.id === sectionId) === undefined) props.local.push(section); } ctx.dispatch({ type: "preliminaryAcquire", id: v7(), function: props.previous ? "previousAnalysisSections" : "analysisSections", source: props.source, source_id: props.source_id, // biome-ignore lint/suspicious/noExplicitAny: conditional type narrowing not available at dispatch site existing: existing as any, // biome-ignore lint/suspicious/noExplicitAny: conditional type narrowing not available at dispatch site requested: props.arguments.request.sectionIds as any, trial: props.trial, created_at: new Date().toISOString(), }); }; const orchestratePrismaSchemas = ( ctx: AutoBeContext, props: { source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; source_id: string; trial: number; all: AutoBeDatabase.IModel[]; local: AutoBeDatabase.IModel[]; arguments: unknown; previous: boolean; }, ): void => { if (props.previous) { if ( false === typia.is<IAutoBePreliminaryRequest<"previousDatabaseSchemas">>( props.arguments, ) ) return; } else if ( false === typia.is<IAutoBePreliminaryRequest<"databaseSchemas">>(props.arguments) ) return; const existing: string[] = props.local.map((m) => m.name); for (const name of props.arguments.request.schemaNames) { const model: AutoBeDatabase.IModel | undefined = props.all.find( (m) => m.name === name, ); if (model === undefined) continue; else if (props.local.find((m) => m.name === name) === undefined) props.local.push(model); } ctx.dispatch({ type: "preliminaryAcquire", id: v7(), function: props.previous ? "previousDatabaseSchemas" : "databaseSchemas", source: props.source, source_id: props.source_id, existing, requested: props.arguments.request.schemaNames, trial: props.trial, created_at: new Date().toISOString(), }); }; const orchestrateInterfaceOperations = ( ctx: AutoBeContext, props: { source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; source_id: string; trial: number; all: AutoBeOpenApi.IOperation[]; local: AutoBeOpenApi.IOperation[]; arguments: unknown; previous: boolean; }, ): void => { if (props.previous) { if ( false === typia.is<IAutoBePreliminaryRequest<"previousInterfaceOperations">>( props.arguments, ) ) return; } else if ( false === typia.is<IAutoBePreliminaryRequest<"interfaceOperations">>(props.arguments) ) return; const existing: AutoBeOpenApi.IEndpoint[] = props.local.map((o) => ({ method: o.method, path: o.path, })); for (const endpoint of props.arguments.request.endpoints) { if ( props.local.find( (v) => v.method === endpoint.method && v.path === endpoint.path, ) !== undefined ) continue; // duplicated const operation: AutoBeOpenApi.IOperation | undefined = props.all.find( (v) => v.method === endpoint.method && v.path === endpoint.path, ); if (operation !== undefined) props.local.push(operation); } ctx.dispatch({ type: "preliminaryAcquire", id: v7(), function: props.previous ? "previousInterfaceOperations" : "interfaceOperations", source: props.source, source_id: props.source_id, existing, requested: props.arguments.request.endpoints, trial: props.trial, created_at: new Date().toISOString(), }); }; const orchestrateInterfaceSchemas = ( ctx: AutoBeContext, props: { source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; source_id: string; trial: number; all: Record<string, AutoBeOpenApi.IJsonSchemaDescriptive>; local: Record<string, AutoBeOpenApi.IJsonSchemaDescriptive>; arguments: unknown; previous: boolean; }, dispatch: boolean = true, ): void => { if (props.previous) { if ( false === typia.is<IAutoBePreliminaryRequest<"previousInterfaceSchemas">>( props.arguments, ) ) return; } else if ( false === typia.is<IAutoBePreliminaryRequest<"interfaceSchemas">>(props.arguments) ) return; const existing: string[] = Object.keys(props.local); const collected: Record<string, AutoBeOpenApi.IJsonSchemaDescriptive> = {}; for (const key of props.arguments.request.typeNames) { OpenApiTypeChecker.visit({ components: { schemas: props.all, }, schema: { $ref: `#/components/schemas/${key}` }, closure: (next) => { if (OpenApiTypeChecker.isReference(next)) { const last: string = next.$ref.split("/").pop()!; if (props.all[last] !== undefined) collected[last] = props.all[last]; } }, }); } Object.assign(props.local, collected); if (dispatch === true) ctx.dispatch({ type: "preliminaryAcquire", id: v7(), function: props.previous ? "previousInterfaceSchemas" : "interfaceSchemas", source: props.source, source_id: props.source_id, existing, requested: props.arguments.request.typeNames, trial: props.trial, created_at: new Date().toISOString(), }); }; const orchestrateRealizeCollectors = ( ctx: AutoBeContext, props: { source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; source_id: string; trial: number; all: AutoBeRealizeCollectorFunction[]; local: AutoBeRealizeCollectorFunction[]; arguments: unknown; }, ): void => { if ( false === typia.is<IAutoBePreliminaryRequest<"realizeCollectors">>(props.arguments) ) return; const existing: string[] = props.local.map((c) => c.plan.dtoTypeName); for (const dtoTypeName of props.arguments.request.dtoTypeNames) { const collector: AutoBeRealizeCollectorFunction | undefined = props.all.find((c) => c.plan.dtoTypeName === dtoTypeName); if (collector === undefined) continue; else if ( props.local.find((c) => c.plan.dtoTypeName === dtoTypeName) === undefined ) props.local.push(collector); } ctx.dispatch({ type: "preliminaryAcquire", id: v7(), function: "realizeCollectors", source: props.source, source_id: props.source_id, existing, requested: props.arguments.request.dtoTypeNames, trial: props.trial, created_at: new Date().toISOString(), }); }; const orchestrateRealizeTransformers = ( ctx: AutoBeContext, props: { source: Exclude<AutoBeEventSource, "facade" | "preliminaryAcquire">; source_id: string; trial: number; all: AutoBeRealizeTransformerFunction[]; local: AutoBeRealizeTransformerFunction[]; arguments: unknown; }, ): void => { if ( false === typia.is<IAutoBePreliminaryRequest<"realizeTransformers">>(props.arguments) ) return; const existing: string[] = props.local.map((t) => t.plan.dtoTypeName); for (const dtoTypeName of props.arguments.request.dtoTypeNames) { const transformer: AutoBeRealizeTransformerFunction | undefined = props.all.find((t) => t.plan.dtoTypeName === dtoTypeName); if ( transformer !== undefined && existing.find((e) => e === dtoTypeName) === undefined ) props.local.push(transformer); } ctx.dispatch({ type: "preliminaryAcquire", id: v7(), function: "realizeTransformers", source: props.source, source_id: props.source_id, existing, requested: props.arguments.request.dtoTypeNames, trial: props.trial, created_at: new Date().toISOString(), }); };