@autobe/agent
Version:
AI backend server code generator
480 lines • 28.8 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.orchestrateTestPrepareWrite = void 0;
const __typia_transform__validateReport = __importStar(require("typia/lib/internal/_validateReport"));
const __typia_transform__llmApplicationFinalize = __importStar(require("typia/lib/internal/_llmApplicationFinalize"));
const utils_1 = require("@autobe/utils");
const tstl_1 = require("tstl");
const typia_1 = __importDefault(require("typia"));
const uuid_1 = require("uuid");
const AutoBeTokenUsageComponent_1 = require("../../context/AutoBeTokenUsageComponent");
const executeCachedBatch_1 = require("../../utils/executeCachedBatch");
const forceRetry_1 = require("../../utils/forceRetry");
const transformTestPrepareWriteHistory_1 = require("./histories/transformTestPrepareWriteHistory");
const AutoBeTestPrepareProgrammer_1 = require("./programmers/AutoBeTestPrepareProgrammer");
/**
* Orchestrates the generation of test data preparation functions.
*
* This orchestrator analyzes all ICreate DTOs from OpenAPI operations and
* generates intelligent test data preparation functions that:
*
* - Create mock data respecting validation constraints
* - Exclude sensitive/system-managed properties from input parameters
* - Generate realistic test data using @nestia/e2e utilities
* - Support partial input overrides for test customization
*
* The prepare functions enable consistent, maintainable test data generation
* across the entire E2E test suite.
*
* @param ctx AutoBE context containing OpenAPI document and LLM access
* @param instruction User instructions for test data generation context
* @returns Array of generated prepare function definitions
*/
const orchestrateTestPrepareWrite = (ctx, props) => __awaiter(void 0, void 0, void 0, function* () {
const createTypes = [];
for (const [key, value] of Object.entries(props.document.components.schemas))
if (key.endsWith(".ICreate") &&
utils_1.AutoBeOpenApiTypeChecker.isObject(value) === true)
createTypes.push({
key,
value,
});
// Generate prepare functions using LLM in parallel with prompt caching
const result = yield (0, executeCachedBatch_1.executeCachedBatch)(ctx, createTypes.map((entry) => (promptCacheKey) => __awaiter(void 0, void 0, void 0, function* () {
const counter = new tstl_1.Singleton(() => ++props.progress.completed);
try {
const event = yield (0, forceRetry_1.forceRetry)(() => process(ctx, {
document: props.document,
typeName: entry.key,
schema: entry.value,
instruction: props.instruction,
promptCacheKey,
progress: props.progress,
counter,
}));
ctx.dispatch(event);
return {
type: "prepare",
typeName: entry.key,
schema: entry.value,
function: event.function,
};
}
catch (_a) {
counter.get();
return null;
}
})));
// Filter out null results and return successful generations
return result.filter((r) => r !== null);
});
exports.orchestrateTestPrepareWrite = orchestrateTestPrepareWrite;
/** Processes the generation of a single prepare function using LLM. */
function process(ctx, props) {
return __awaiter(this, void 0, void 0, function* () {
var _a, _b, _c, _d, _e;
if (!!props.schema.additionalProperties === false &&
Object.keys(props.schema.properties).length === 0) {
const functionName = AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.getFunctionName(props.typeName);
return {
id: (0, uuid_1.v7)(),
type: "testWrite",
function: {
type: "prepare",
location: `test/prepare/${functionName}.ts`,
content: yield AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.replaceImportStatements({
compiler: yield ctx.compiler(),
typeName: props.typeName,
schemas: props.document.components.schemas,
content: AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.writeNonPropertyCode({
typeName: props.typeName,
schema: props.schema,
}),
}),
typeName: props.typeName,
name: functionName,
},
completed: props.counter.get(),
total: props.progress.total,
step: (_b = (_a = ctx.state().interface) === null || _a === void 0 ? void 0 : _a.step) !== null && _b !== void 0 ? _b : 0,
tokenUsage: new AutoBeTokenUsageComponent_1.AutoBeTokenUsageComponent(),
metric: utils_1.AutoBeFunctionCallingMetricFactory.create(),
created_at: new Date().toISOString(),
};
}
const pointer = {
value: null,
};
// Execute LLM conversation with function calling
const { metric, tokenUsage } = yield ctx.conversate(Object.assign({ source: "testWrite", controller: createController({
dtoTypeName: props.typeName,
schema: props.schema,
build: (app) => {
pointer.value = app;
},
}), enforceFunctionCall: true, promptCacheKey: props.promptCacheKey }, (yield (0, transformTestPrepareWriteHistory_1.transformTestPrepareWriteHistory)(ctx, props))));
// Validate LLM response
if (pointer.value === null) {
props.counter.get();
throw new Error(`Failed to generate prepare function for ${props.typeName}`);
}
const functionName = AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.getFunctionName(props.typeName);
const event = {
id: (0, uuid_1.v7)(),
type: "testWrite",
function: {
type: "prepare",
location: `test/prepare/${functionName}.ts`,
content: yield AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.replaceImportStatements({
compiler: yield ctx.compiler(),
typeName: props.typeName,
schemas: props.document.components.schemas,
content: (_c = pointer.value.revise.final) !== null && _c !== void 0 ? _c : pointer.value.draft,
}),
typeName: props.typeName,
name: functionName,
},
completed: props.counter.get(),
total: props.progress.total,
step: (_e = (_d = ctx.state().interface) === null || _d === void 0 ? void 0 : _d.step) !== null && _e !== void 0 ? _e : 0,
tokenUsage,
metric,
created_at: new Date().toISOString(),
};
return event;
});
}
/** Creates LLM controller for function calling. */
function createController(props) {
const validate = (input) => {
// Basic typia validation
const result = (() => { const _io0 = input => "string" === typeof input.plan && (Array.isArray(input.mappings) && input.mappings.every(elem => "object" === typeof elem && null !== elem && _io1(elem))) && "string" === typeof input.draft && ("object" === typeof input.revise && null !== input.revise && _io2(input.revise)); const _io1 = input => "string" === typeof input.property && "string" === typeof input.how; const _io2 = input => "string" === typeof input.review && (null === input.final || "string" === typeof input.final); const _vo0 = (input, _path, _exceptionable = true) => ["string" === typeof input.plan || _report(_exceptionable, {
path: _path + ".plan",
expected: "string",
value: input.plan
}), (Array.isArray(input.mappings) || _report(_exceptionable, {
path: _path + ".mappings",
expected: "Array<AutoBeTestPrepareMapping>",
value: input.mappings
})) && input.mappings.map((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
path: _path + ".mappings[" + _index2 + "]",
expected: "AutoBeTestPrepareMapping",
value: elem
})) && _vo1(elem, _path + ".mappings[" + _index2 + "]", true && _exceptionable) || _report(_exceptionable, {
path: _path + ".mappings[" + _index2 + "]",
expected: "AutoBeTestPrepareMapping",
value: elem
})).every(flag => flag) || _report(_exceptionable, {
path: _path + ".mappings",
expected: "Array<AutoBeTestPrepareMapping>",
value: input.mappings
}), "string" === typeof input.draft || _report(_exceptionable, {
path: _path + ".draft",
expected: "string",
value: input.draft
}), ("object" === typeof input.revise && null !== input.revise || _report(_exceptionable, {
path: _path + ".revise",
expected: "IAutoBeTestPrepareWriteApplication.IReviseProps",
value: input.revise
})) && _vo2(input.revise, _path + ".revise", true && _exceptionable) || _report(_exceptionable, {
path: _path + ".revise",
expected: "IAutoBeTestPrepareWriteApplication.IReviseProps",
value: input.revise
})].every(flag => flag); const _vo1 = (input, _path, _exceptionable = true) => ["string" === typeof input.property || _report(_exceptionable, {
path: _path + ".property",
expected: "string",
value: input.property
}), "string" === typeof input.how || _report(_exceptionable, {
path: _path + ".how",
expected: "string",
value: input.how
})].every(flag => flag); const _vo2 = (input, _path, _exceptionable = true) => ["string" === typeof input.review || _report(_exceptionable, {
path: _path + ".review",
expected: "string",
value: input.review
}), null === input.final || "string" === typeof input.final || _report(_exceptionable, {
path: _path + ".final",
expected: "(null | string)",
value: input.final
})].every(flag => flag); const __is = input => "object" === typeof input && null !== input && _io0(input); let errors; let _report; return input => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
path: _path + "",
expected: "IAutoBeTestPrepareWriteApplication.IProps",
value: input
})) && _vo0(input, _path + "", true) || _report(true, {
path: _path + "",
expected: "IAutoBeTestPrepareWriteApplication.IProps",
value: input
}))(input, "$input", true);
const success = 0 === errors.length;
return success ? {
success,
data: input
} : {
success,
errors,
data: input
};
}
return {
success: true,
data: input
};
}; })()(input);
if (result.success === false)
return result;
// Custom business logic validation
const errors = AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.validate({
typeName: props.dtoTypeName,
schema: props.schema,
mappings: result.data.mappings,
draft: result.data.draft,
revise: result.data.revise,
});
// // Incorrect template literal syntax validation
// const backtickRegex: RegExp = /`/g;
// const count: number = (
// (result.data.revise.final ?? result.data.draft).match(backtickRegex) ?? []
// ).length;
// if (count % 2 !== 0)
// errors.push({
// path: result.data.revise.final
// ? "$input.request.revise.final"
// : "$input.request.draft",
// expected: "even number of backticks",
// value: count,
// description: "Unmatched backtick in template literal",
// });
return errors.length > 0
? {
success: false,
errors,
data: result.data,
}
: result;
};
const application = __typia_transform__llmApplicationFinalize._llmApplicationFinalize({
functions: [
{
name: "write",
parameters: {
description: "Properties for generating a test data preparation function.\n\nContains the complete specification including narrative plan, property\nmappings, function name, draft implementation, and review/final phases.\n\n------------------------------\n\nDescription of the current {@link IAutoBeTestPrepareWriteApplication.IProps} type:\n\n> Properties for generating a test data preparation function.\n> \n> Contains the complete specification including narrative plan, property\n> mappings, function name, draft implementation, and review/final phases.",
type: "object",
properties: {
plan: {
description: "Narrative plan and analysis strategy.\n\nYour planning should accomplish these objectives:\n\n1. Understand the DTO Structure - Read through the actual DTO type\n carefully, noting property names, types, and validation constraints\n2. Classify Properties - Test-customizable vs auto-generated fields\n3. Plan Data Generation Strategy - Think through how each property should\n generate realistic data\n\nThis reflection helps you avoid omissions and incorrect data generation.",
type: "string"
},
mappings: {
description: "Property-by-property mapping table for complete DTO coverage.\n\nMUST include EVERY property from the DTO schema - no exceptions. Each\nmapping specifies:\n\n- `property`: Exact property name from DTO schema\n- `how`: How to generate the value for that property\n\nThe `mappings` field is your Chain-of-Thought (CoT) mechanism - it forces\nyou to explicitly think through EVERY property before coding, preventing\nomissions and incorrect data generation.\n\nMissing even a single property will cause validation failure and trigger\nregeneration.\n\nThis structured approach:\n\n- Prevents property omissions through systematic coverage\n- Forces explicit decision-making for each property\n- Enables validation before code generation\n- Creates clear documentation of data generation strategy\n\nThe validator will cross-check this list against the actual DTO schema\nand reject incomplete mappings.",
type: "array",
items: {
$ref: "#/$defs/AutoBeTestPrepareMapping"
}
},
draft: {
description: "Initial implementation of the prepare function.\n\nComplete implementation that strictly follows the plan's mapping table.\nEVERY property in the mappings MUST appear in this draft. Implement:\n\n- Function with DeepPartial<ICreate> input parameter (NEVER Partial)\n- All property generation from mappings\n- RandomGenerator utilities for realistic data\n- Proper nested object/array handling with conditional mapping",
type: "string"
},
revise: {
description: "Revision and finalization phase.\n\nReviews the draft implementation and produces the final code with all\nimprovements and corrections applied.",
$ref: "#/$defs/IAutoBeTestPrepareWriteApplication.IReviseProps"
}
},
required: [
"plan",
"mappings",
"draft",
"revise"
],
additionalProperties: false,
$defs: {
AutoBeTestPrepareMapping: {
description: "Property-by-property data generation mapping for test prepare functions.\n\nExplicit mapping ensures complete DTO coverage by documenting generation\nstrategy for each property before implementation.",
type: "object",
properties: {
property: {
description: "Exact property name from the DTO schema.\n\nMust match actual DTO property - no fabricated names allowed.",
type: "string"
},
how: {
description: "Data generation strategy for this property.\n\nExplains how the value will be generated (e.g., \"typia.random with uuid\nformat\", \"RandomGenerator.paragraph with 2-5 sentences\", \"input override or\ndefault generation\").",
type: "string"
}
},
required: [
"property",
"how"
]
},
"IAutoBeTestPrepareWriteApplication.IReviseProps": {
description: "Review and final optimization properties.\n\nContains the critical self-review analysis and the final production-ready\nimplementation with all identified issues corrected.",
type: "object",
properties: {
review: {
description: "Critical review and improvement analysis.\n\nMUST systematically verify using these checklists:\n\n1. Schema Fidelity - Cross-check EVERY property name against the DTO schema,\n verify all properties are generated, no fabricated properties\n2. Type Safety - DeepPartial<> used (not Partial<>), proper typing, correct\n nested handling\n3. Constraint Compliance - String lengths, number bounds, formats, enums\n4. Code Quality - Compilation check, template literal syntax, no errors\n\nIdentify specific issues with reasoning and provide clear fixes. This\ncatches hallucinated properties, missing mappings, and rule violations.",
type: "string"
},
final: {
description: "Final prepare function code with all review improvements applied.\n\nApply ALL fixes identified in the review to produce production-ready\ncode. If review found issues, this MUST contain the corrected\nimplementation.\n\nReturn `null` ONLY if the draft is already perfect and review found zero\nissues.",
anyOf: [
{
type: "null"
},
{
type: "string"
}
]
}
},
required: [
"review",
"final"
]
}
}
},
description: "Generate test data preparation function.\n\nExecutes three-phase generation to create complete prepare function with:\n\n- DeepPartial input for test-time customization\n- RandomGenerator utilities for realistic data generation\n- Proper handling of nested structures (objects and arrays)\n- Constraint compliance (validation rules)\n\nFollows plan \u2192 mappings \u2192 draft \u2192 revise pattern to ensure completeness and\ncorrectness.",
validate: (() => { const _io0 = input => "string" === typeof input.plan && (Array.isArray(input.mappings) && input.mappings.every(elem => "object" === typeof elem && null !== elem && _io1(elem))) && "string" === typeof input.draft && ("object" === typeof input.revise && null !== input.revise && _io2(input.revise)); const _io1 = input => "string" === typeof input.property && "string" === typeof input.how; const _io2 = input => "string" === typeof input.review && (null === input.final || "string" === typeof input.final); const _vo0 = (input, _path, _exceptionable = true) => ["string" === typeof input.plan || _report(_exceptionable, {
path: _path + ".plan",
expected: "string",
value: input.plan
}), (Array.isArray(input.mappings) || _report(_exceptionable, {
path: _path + ".mappings",
expected: "Array<AutoBeTestPrepareMapping>",
value: input.mappings
})) && input.mappings.map((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
path: _path + ".mappings[" + _index2 + "]",
expected: "AutoBeTestPrepareMapping",
value: elem
})) && _vo1(elem, _path + ".mappings[" + _index2 + "]", true && _exceptionable) || _report(_exceptionable, {
path: _path + ".mappings[" + _index2 + "]",
expected: "AutoBeTestPrepareMapping",
value: elem
})).every(flag => flag) || _report(_exceptionable, {
path: _path + ".mappings",
expected: "Array<AutoBeTestPrepareMapping>",
value: input.mappings
}), "string" === typeof input.draft || _report(_exceptionable, {
path: _path + ".draft",
expected: "string",
value: input.draft
}), ("object" === typeof input.revise && null !== input.revise || _report(_exceptionable, {
path: _path + ".revise",
expected: "IAutoBeTestPrepareWriteApplication.IReviseProps",
value: input.revise
})) && _vo2(input.revise, _path + ".revise", true && _exceptionable) || _report(_exceptionable, {
path: _path + ".revise",
expected: "IAutoBeTestPrepareWriteApplication.IReviseProps",
value: input.revise
})].every(flag => flag); const _vo1 = (input, _path, _exceptionable = true) => ["string" === typeof input.property || _report(_exceptionable, {
path: _path + ".property",
expected: "string",
value: input.property
}), "string" === typeof input.how || _report(_exceptionable, {
path: _path + ".how",
expected: "string",
value: input.how
})].every(flag => flag); const _vo2 = (input, _path, _exceptionable = true) => ["string" === typeof input.review || _report(_exceptionable, {
path: _path + ".review",
expected: "string",
value: input.review
}), null === input.final || "string" === typeof input.final || _report(_exceptionable, {
path: _path + ".final",
expected: "(null | string)",
value: input.final
})].every(flag => flag); const __is = input => "object" === typeof input && null !== input && _io0(input); let errors; let _report; return input => {
if (false === __is(input)) {
errors = [];
_report = __typia_transform__validateReport._validateReport(errors);
((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
path: _path + "",
expected: "IAutoBeTestPrepareWriteApplication.IProps",
value: input
})) && _vo0(input, _path + "", true) || _report(true, {
path: _path + "",
expected: "IAutoBeTestPrepareWriteApplication.IProps",
value: input
}))(input, "$input", true);
const success = 0 === errors.length;
return success ? {
success,
data: input
} : {
success,
errors,
data: input
};
}
return {
success: true,
data: input
};
}; })()
}
]
}, {
validate: {
write: validate,
},
});
return {
protocol: "class",
name: "testPrepareWrite",
application,
execute: {
write: (next) => {
props.build(next);
},
},
};
}
//# sourceMappingURL=orchestrateTestPrepareWrite.js.map