@autobe/agent
Version:
AI backend server code generator
162 lines (152 loc) • 5.28 kB
text/typescript
import {
AutoBeAssistantMessageHistory,
AutoBeOpenApi,
AutoBeProgressEventBase,
AutoBeTestAuthorizeFunction,
AutoBeTestCompleteEvent,
AutoBeTestFunction,
AutoBeTestGenerateFunction,
AutoBeTestHistory,
AutoBeTestOperationFunction,
AutoBeTestPrepareFunction,
AutoBeTestScenario,
IAutoBeCompiler,
} from "@autobe/interface";
import { v7 } from "uuid";
import { AutoBeContext } from "../../context/AutoBeContext";
import { predicateStateMessage } from "../../utils/predicateStateMessage";
import { IAutoBeFacadeApplicationProps } from "../facade/histories/IAutoBeFacadeApplicationProps";
import { orchestrateTestAuthorize } from "./orchestrateTestAuthorize";
import { orchestrateTestGenerate } from "./orchestrateTestGenerate";
import { orchestrateTestOperation } from "./orchestrateTestOperation";
import { orchestrateTestPrepare } from "./orchestrateTestPrepare";
import { orchestrateTestScenario } from "./orchestrateTestScenario";
import { AutoBeTestAuthorizeProgrammer } from "./programmers/AutoBeTestAuthorizeProgrammer";
import { AutoBeTestGenerateProgrammer } from "./programmers/AutoBeTestGenerateProgrammer";
import { AutoBeTestPrepareProgrammer } from "./programmers/AutoBeTestPrepareProgrammer";
export const orchestrateTest =
(ctx: AutoBeContext) =>
async (
props: IAutoBeFacadeApplicationProps,
): Promise<AutoBeAssistantMessageHistory | AutoBeTestHistory> => {
// PREDICATION
const start: Date = new Date();
const predicate: string | null = predicateStateMessage(ctx.state(), "test");
if (predicate !== null)
return ctx.assistantMessage({
type: "assistantMessage",
id: v7(),
created_at: start.toISOString(),
text: predicate,
completed_at: new Date().toISOString(),
});
ctx.dispatch({
type: "testStart",
id: v7(),
created_at: start.toISOString(),
reason: props.instruction,
step: ctx.state().analyze?.step ?? 0,
});
const document: AutoBeOpenApi.IDocument | undefined =
ctx.state().interface?.document;
if (document === undefined)
throw new Error("No document found. Please check the logs.");
else if (document.operations.length === 0)
return ctx.assistantMessage({
id: v7(),
type: "assistantMessage",
created_at: start.toISOString(),
completed_at: new Date().toISOString(),
text:
"Unable to write test code because there are no Operations, " +
"please check if the Interface agent is called.",
});
// SCENARIO PLANNING
const scenarios: AutoBeTestScenario[] = await orchestrateTestScenario(
ctx,
props.instruction,
);
if (scenarios.length === 0)
throw new Error("No scenarios generated. Please check the logs.");
const writeProgress: AutoBeProgressEventBase = {
completed: 0,
total:
AutoBeTestAuthorizeProgrammer.size(document) +
AutoBeTestPrepareProgrammer.size(document) +
AutoBeTestGenerateProgrammer.size(document) +
scenarios.length,
};
const correctProgress: AutoBeProgressEventBase = {
total: 0,
completed: 0,
};
// AUTHORIZE
const authorizes: AutoBeTestAuthorizeFunction[] =
await orchestrateTestAuthorize(ctx, {
instruction: props.instruction,
document,
writeProgress,
validateProgress: correctProgress,
});
// DATA COMPOSER
const prepares: AutoBeTestPrepareFunction[] = await orchestrateTestPrepare(
ctx,
{
instruction: props.instruction,
document,
writeProgress,
validateProgress: correctProgress,
},
);
// GENERATOR FUNCTIONS (C of CRUD)
const generates: AutoBeTestGenerateFunction[] =
await orchestrateTestGenerate(ctx, {
instruction: props.instruction,
document,
prepares,
writeProgress,
validateProgress: correctProgress,
});
// ACTUAL TEST FUNCTION
const operations: AutoBeTestOperationFunction[] =
await orchestrateTestOperation(ctx, {
instruction: props.instruction,
document,
scenarios,
authorizes,
prepares,
generates,
writeProgress,
validateProgress: correctProgress,
});
// FINALIZE WITH COMPILATION
const compiler: IAutoBeCompiler = await ctx.compiler();
const functions: AutoBeTestFunction[] = [
...authorizes,
...prepares,
...generates,
...operations,
];
return ctx.dispatch({
type: "testComplete",
id: v7(),
functions,
compiled: await compiler.typescript.compile({
files: Object.fromEntries([
...Object.entries(
await ctx.files({
dbms: "sqlite",
}),
).filter(
([key]) =>
key.endsWith(".ts") && key.startsWith("test/features") === false,
),
...functions.map((f) => [f.location, f.content]),
]),
}),
aggregates: ctx.getCurrentAggregates("test"),
step: ctx.state().analyze?.step ?? 0,
elapsed: new Date().getTime() - start.getTime(),
created_at: new Date().toISOString(),
} satisfies AutoBeTestCompleteEvent);
};