@autobe/agent
Version:
AI backend server code generator
262 lines (244 loc) • 8.38 kB
text/typescript
import { IAgenticaController, MicroAgentica } from "@agentica/core";
import { AutoBeTest, AutoBeTestProgressEvent } from "@autobe/interface";
import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
import { IPointer } from "tstl";
import typia from "typia";
import { AutoBeContext } from "../../context/AutoBeContext";
import { assertSchemaModel } from "../../context/assertSchemaModel";
import { enforceToolCall } from "../../utils/enforceToolCall";
import { transformTestProgressHistories } from "./transformTestProgressHistories";
export async function orchestrateTestProgress<Model extends ILlmSchema.Model>(
ctx: AutoBeContext<Model>,
scenarios: AutoBeTest.Scenario[],
): Promise<AutoBeTestProgressEvent[]> {
const start: Date = new Date();
let complete: number = 0;
const events: AutoBeTestProgressEvent[] = await Promise.all(
/**
* Generate test code for each scenario. Maps through scenarios array to
* create individual test code implementations. Each scenario is processed
* to generate corresponding test code and progress events.
*/
scenarios.map(async (scenario) => {
const code: ICreateTestCodeProps = await process(ctx, scenario);
const event: AutoBeTestProgressEvent = {
type: "testProgress",
created_at: start.toISOString(),
filename: `${code.domain}/${scenario.functionName}.ts`,
content: code.content,
completed: ++complete,
total: scenarios.length,
step: ctx.state().interface?.step ?? 0,
};
ctx.dispatch(event);
return event;
}),
);
return events;
}
/**
* Process function that generates test code for each individual scenario. Takes
* the AutoBeContext and scenario information as input and uses MicroAgentica to
* generate appropriate test code through LLM interaction.
*
* @param ctx - The AutoBeContext containing model, vendor and configuration
* @param scenario - The test scenario information to generate code for
* @returns Promise resolving to ICreateTestCodeProps containing the generated
* test code
*/
async function process<Model extends ILlmSchema.Model>(
ctx: AutoBeContext<Model>,
scenario: AutoBeTest.Scenario,
): Promise<ICreateTestCodeProps> {
const pointer: IPointer<ICreateTestCodeProps | null> = {
value: null,
};
const apiFiles = Object.entries(ctx.state().interface?.files ?? {})
.filter(([filename]) => {
return filename.startsWith("src/api/");
})
.reduce<Record<string, string>>((acc, [filename, content]) => {
return Object.assign(acc, { [filename]: content });
}, {});
const dtoFiles = Object.entries(ctx.state().interface?.files ?? {})
.filter(([filename]) => {
return filename.startsWith("src/api/structures/");
})
.reduce<Record<string, string>>((acc, [filename, content]) => {
return Object.assign(acc, { [filename]: content });
}, {});
const agentica = new MicroAgentica({
model: ctx.model,
vendor: ctx.vendor,
config: {
...(ctx.config ?? {}),
},
histories: transformTestProgressHistories(apiFiles, dtoFiles),
controllers: [
createApplication({
model: ctx.model,
build: (next) => {
pointer.value = next;
},
}),
],
});
enforceToolCall(agentica);
await agentica.conversate(
[
"Create test code for below scenario:",
"",
"```json",
JSON.stringify(scenario, null, 2),
"```",
].join("\n"),
);
if (pointer.value === null) throw new Error("Failed to create test code.");
return pointer.value;
}
function createApplication<Model extends ILlmSchema.Model>(props: {
model: Model;
build: (next: ICreateTestCodeProps) => void;
}): IAgenticaController.IClass<Model> {
assertSchemaModel(props.model);
const application: ILlmApplication<Model> = collection[
props.model
] as unknown as ILlmApplication<Model>;
return {
protocol: "class",
name: "Create Test Code",
application,
execute: {
createTestCode: (next) => {
props.build(next);
},
} satisfies IApplication,
};
}
const claude = typia.llm.application<
IApplication,
"claude",
{
reference: true;
}
>();
const collection = {
chatgpt: typia.llm.application<
IApplication,
"chatgpt",
{ reference: true }
>(),
claude,
llama: claude,
deepseek: claude,
"3.1": claude,
"3.0": typia.llm.application<IApplication, "3.0">(),
};
interface IApplication {
createTestCode(props: ICreateTestCodeProps): void;
}
interface ICreateTestCodeProps {
/**
* Strategic approach for test implementation.
*
* Define the high-level strategy and logical flow for testing the given
* scenario. Focus on test methodology, data preparation, and assertion
* strategy.
*
* ### Critical Requirements
*
* - Must follow the Test Generation Guildelines.
* - Must Planning the test code Never occur the typescript compile error.
*
* ### Planning Elements:
*
* #### Test Methodology
*
* - Identify test scenario type (CRUD operation, authentication flow,
* validation test)
* - Define test data requirements and preparation strategy
* - Plan positive/negative test cases and edge cases
* - Design assertion logic and validation points
*
* #### Execution Strategy
*
* - Outline step-by-step test execution flow
* - Plan error handling and exception scenarios
* - Define cleanup and teardown procedures
* - Identify dependencies and prerequisites
*
* ### Example Plan:
*
* Test Strategy: Article Creation Validation
* 1. Prepare valid article data with required fields
* 2. Execute POST request to create article
* 3. Validate response structure and data integrity
* 4. Test error scenarios (missing fields, invalid data)
* 5. Verify database state changes
* 6. Reconsider the plan if it doesn't follow the Test Generation
* Guildelines.
*/
plan: string;
/**
* Functional domain classification for test organization.
*
* Determines file structure and test categorization based on API
* functionality. Used for organizing tests into logical groups and directory
* hierarchies.
*
* ### Naming Rules:
*
* - Lowercase English words only
* - Singular nouns (e.g., "article", "user", "comment")
* - Kebab-case for compound words (e.g., "user-profile", "payment-method")
* - Match primary API resource being tested
* - Domain Name must be named only one word.
*
* ### Domain Examples:
*
* - `article` → Article management operations
* - `comment` → Comment-related functionality
* - `auth` → Authentication and authorization
* - `user` → User management operations
* - `payment` → Payment processing
* - `notification` → Notification system
*/
domain: string;
/**
* Complete TypeScript E2E test implementation.
*
* Generate fully functional, compilation-error-free test code following
*
* @nestia/e2e framework conventions and TypeScript best practices.
*
* ### Technical Implementation Requirements:
*
* #### Import Declarations
* ```typescript
* import api from "@ORGANIZATION/PROJECT-api";
* import { ITargetType } from "@ORGANIZATION/PROJECT-api/lib/structures/[path]";
* import { TestValidator } from "@nestia/e2e";
* import typia from "typia";
* ```
* - Must use exact `@ORGANIZATION/PROJECT-api` module path
* - Include `@ORGANIZATION` prefix in all API-related imports
* - Import specific DTO types from correct structure paths
*
* #### Code Quality Standards
* - Zero TypeScript compilation errors (mandatory)
* - Explicit type annotations for all variables
* - Proper async/await patterns throughout
* - Comprehensive error handling
* - Clean, readable code structure
* - Consistent formatting and naming conventions
*
* ### Critical Error Prevention
* - Verify all import paths are correct and accessible
* - Ensure type compatibility between variables and assignments
* - Include all required object properties and methods
* - Validate API function signatures and parameter types
* - Confirm proper generic type usage
* - Test async function declarations and Promise handling
*/
content: string;
}