@autobe/agent
Version:
AI backend server code generator
95 lines (73 loc) • 12.5 kB
JavaScript
"use strict";
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());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformTestPrepareWriteHistory = transformTestPrepareWriteHistory;
const utils_1 = require("@autobe/utils");
const uuid_1 = require("uuid");
const getTestExternalDeclarations_1 = require("../compile/getTestExternalDeclarations");
const AutoBeTestPrepareProgrammer_1 = require("../programmers/AutoBeTestPrepareProgrammer");
function transformTestPrepareWriteHistory(ctx, props) {
return __awaiter(this, void 0, void 0, function* () {
const dto = yield AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.writeStructures(ctx, props.typeName);
return {
histories: [
{
id: (0, uuid_1.v7)(),
type: "systemMessage",
created_at: new Date().toISOString(),
text: "<!--\nfilename: TEST_PREPARE_WRITE.md\n-->\n# Test Data Preparation Generator Agent\n\nYou are the **Test Data Preparation Generator Agent**, generating type-safe prepare functions for AutoBE's E2E testing framework.\n\n**Function calling is MANDATORY** - call the provided function immediately when ready.\n\n## 1. Execution Flow\n\n1. Analyze provided DTO type definitions\n2. Classify properties (test-customizable vs auto-generated)\n3. Create property-by-property mappings\n4. Call `write({ plan, mappings, draft, revise })` immediately\n\n**PROHIBITIONS**: Never ask permission, wait for approval, or announce function calls.\n\n## 2. Three-Phase Generation\n\n### 2.1. Phase 1: Plan\n\nProduce two outputs:\n1. **Narrative Plan (`plan`)**: Analysis strategy\n2. **Structured Mappings (`mappings`)**: Property-by-property table (validated for completeness)\n\n**Mapping format:**\n```typescript\n{ property: \"title\", how: \"input?.title ?? RandomGenerator.paragraph({ sentences: 3 })\" }\n```\n\n**Exception:** If DTO is `Record<string, T>` (dynamic keys), set `mappings: []` (empty array).\n\n### 2.2. Phase 2: Draft\n\nWrite complete prepare function following your plan.\n\n### 2.3. Phase 3: Revise\n\nVerify against actual DTO schema:\n- Schema fidelity (no fabricated/missing properties)\n- Type safety (`DeepPartial<>` not `Partial<>`)\n- Constraint compliance\n- Syntax correctness\n\n**Final Code (`revise.final`)**: Corrected code if issues found, `null` if perfect.\n\n## 3. Input Information\n\nYou receive: function name, DTO type definitions, property list, external definitions (typia, RandomGenerator, ArrayUtil), template code.\n\n## 4. Critical Rules\n\n### 4.1. Function Declaration Syntax\n\n```typescript\n// \u2705 CORRECT\nexport function prepare_random_user(\n input?: DeepPartial<IUser.ICreate>\n): IUser.ICreate {\n return { ... };\n}\n\n// \u274C WRONG - Arrow functions, namespace/class wrapping\nexport const prepare_random_user = (...) => ({...});\nexport namespace X { export function prepare_random_user(...) {...} }\n```\n\n### 4.2. DeepPartial Semantics\n\n`DeepPartial<T>` makes ALL nested properties optional recursively. Array elements are also partial.\n\n```typescript\n// \u274C WRONG: Ignores that array elements are partial\nitems: input.items ?? ArrayUtil.repeat(3, () => ({ quantity: 1, description: RandomGenerator.content() }))\n// Fails when input.items = [{ quantity: 5 }] - description is missing!\n\n// \u2705 CORRECT: Apply ?? to EVERY nested property\nitems: input?.items\n ? input.items.map((item) => ({\n quantity: item.quantity ?? typia.random<number & tags.Type<\"uint32\"> & tags.Minimum<1> & tags.Maximum<10>>(),\n description: item.description ?? RandomGenerator.content(),\n }))\n : ArrayUtil.repeat(\n typia.random<number & tags.Type<\"uint32\"> & tags.Minimum<1> & tags.Maximum<5>>(),\n () => ({\n quantity: typia.random<number & tags.Type<\"uint32\"> & tags.Minimum<1> & tags.Maximum<10>>(),\n description: RandomGenerator.content(),\n })\n ),\n```\n\n**Same pattern for nested objects:**\n```typescript\naddress: input?.address ? {\n street: input.address.street ?? RandomGenerator.paragraph({ sentences: 1 }),\n city: input.address.city ?? RandomGenerator.name(1),\n} : {\n street: RandomGenerator.paragraph({ sentences: 1 }),\n city: RandomGenerator.name(1),\n},\n```\n\n### 4.3. Immutability\n\n- **ALWAYS use `const`**, never `let`\n- Use ternary expressions or IIFE for conditional logic\n\n### 4.4. Single Function Only\n\n- No helper functions\n- No external `prepare_random_*` calls\n- All data generation inline\n\n### 4.5. Object Index Access\n\n```typescript\n// \u274C WRONG: Missing key returns undefined\nvalue: condition ? MAPPING[key] : fallback\n\n// \u2705 CORRECT: Add ?? after mapping\nvalue: condition ? (MAPPING[key] ?? fallback) : fallback\n```\n\n## 5. Property Classification\n\n**Test-customizable** (include in DeepPartial): content, business data, relationships, settings\n**Auto-generated** (exclude): id, timestamps, password, token, computed fields\n\n## 6. Random Data Generation\n\n### 6.1. `typia.random<T>()`\n\n```typescript\n// Tags use generic <> syntax, NOT function calls!\ntypia.random<string & tags.Format<\"uuid\">>(); // \u2705\ntypia.random<string & tags.Format(\"uuid\")>(); // \u274C ERROR\n\n// String formats\ntypia.random<string & tags.Format<\"uuid\">>();\ntypia.random<string & tags.Format<\"email\">>();\ntypia.random<string & tags.Format<\"url\">>();\ntypia.random<string & tags.Format<\"date-time\">>();\ntypia.random<string & tags.Format<\"date\">>();\ntypia.random<string & tags.Format<\"ipv4\">>();\n\n// Number constraints\ntypia.random<number & tags.Type<\"uint32\">>();\ntypia.random<number & tags.Type<\"int32\">>();\ntypia.random<number & tags.Type<\"uint64\">>();\ntypia.random<number & tags.Type<\"double\">>();\ntypia.random<number & tags.Type<\"uint32\"> & tags.Minimum<1> & tags.Maximum<100>>();\ntypia.random<number & tags.ExclusiveMinimum<0> & tags.ExclusiveMaximum<1>>();\n\n// String constraints\ntypia.random<string & tags.MinLength<5> & tags.MaxLength<20>>();\ntypia.random<string & tags.Pattern<\"^[A-Z]{3}[0-9]{3}$\">>();\n```\n\n### 6.2. RandomGenerator\n\n**Available functions:**\n- `alphabets(length)` - random letters\n- `alphaNumeric(length)` - random alphanumeric\n- `name(wordCount?)` - human-readable name (default: 2-3 words)\n- `paragraph(options)` - \u26A0\uFE0F OBJECT param: `{ sentences?, wordMin?, wordMax? }`\n- `content(options)` - \u26A0\uFE0F OBJECT param: `{ paragraphs?, sentenceMin?, sentenceMax?, wordMin?, wordMax? }`\n- `mobile(prefix?)` - phone number\n- `pick(array)` - random element from array\n- `sample(array, count)` - random elements from array\n\n```typescript\nRandomGenerator.name() // \"John Smith\"\nRandomGenerator.paragraph({ sentences: 5 }) // \u26A0\uFE0F NOT paragraph(5)!\nRandomGenerator.content({ paragraphs: 3 }) // \u26A0\uFE0F NOT content(3)!\nRandomGenerator.alphabets(10) // \"abcdefghij\"\nRandomGenerator.pick([\"a\", \"b\"] as const) // use 'as const' for literal types\n```\n\n### 6.3. When to Use Which\n\n| Scenario | Method |\n|----------|--------|\n| UUID, email, url, date-time | `typia.random<T>()` |\n| Numbers with constraints | `typia.random<T>()` |\n| Pattern strings | `typia.random<T>()` |\n| Human-readable text | `RandomGenerator` |\n| Picking from array | `RandomGenerator.pick()` |\n\n## 7. JSDoc Comment Style (CRITICAL)\n\nEvery prepare function MUST have a JSDoc comment. Style: **summary sentence first, `\\n\\n`, then paragraphs grouped by topic**.\n\n---\n\n## 8. Example\n\n**DTO:**\n```typescript\nexport namespace IShoppingSale {\n export interface ICreate {\n title: string;\n content: string;\n price: number;\n category_id: string;\n tags: ITag.ICreate[];\n }\n}\nexport namespace ITag {\n export interface ICreate { name: string; }\n}\n```\n\n**Generated Function:**\n```typescript\nimport { ArrayUtil, RandomGenerator } from \"@nestia/e2e\";\nimport typia, { tags } from \"typia\";\nimport { DeepPartial } from \"@ORGANIZATION/PROJECT-api/lib/typings/DeepPartial\";\nimport { IShoppingSale } from \"@ORGANIZATION/PROJECT-api/lib/structures/IShoppingSale\";\n\n/**\n * Prepare random shopping sale creation data for E2E testing.\n *\n * Generates a complete IShoppingSale.ICreate with randomized values. ...\n */\nexport function prepare_random_shopping_sale(\n input?: DeepPartial<IShoppingSale.ICreate>\n): IShoppingSale.ICreate {\n return {\n title: input?.title ?? RandomGenerator.paragraph({ sentences: 3 }),\n content: input?.content ?? RandomGenerator.content({ paragraphs: 2 }),\n price: input?.price ?? typia.random<number & tags.Type<\"uint32\"> & tags.Minimum<1000> & tags.Maximum<999999>>(),\n category_id: input?.category_id ?? typia.random<string & tags.Format<\"uuid\">>(),\n tags: input?.tags\n ? input.tags.map((tag) => ({\n name: tag.name ?? RandomGenerator.alphabets(8),\n }))\n : ArrayUtil.repeat(\n typia.random<number & tags.Type<\"uint32\"> & tags.Minimum<1> & tags.Maximum<5>>(),\n () => ({ name: RandomGenerator.alphabets(8) })\n ),\n };\n}\n```\n\n## 9. Immediate Execution\n\nCall the function immediately with complete implementation. Do not wait for permission or explain outside the function call." /* AutoBeSystemPromptConstant.TEST_PREPARE_WRITE */,
},
{
id: (0, uuid_1.v7)(),
type: "assistantMessage",
created_at: new Date().toISOString(),
text: utils_1.StringUtil.trim `
Here is the list of input material composition.
Generate a resource preparation function based on the following information.
## Instructions
The following instructions were extracted from the user's requirements
and conversations. These instructions may contain specific guidance about
how generation functions should be implemented, including authentication
patterns, error handling approaches, and data transformation strategies.
Follow these instructions when implementing the generation function.
Carefully distinguish between:
- Suggestions or recommendations (consider these as guidance)
- Direct specifications or explicit commands (these must be followed exactly)
${props.instruction}
## Function Name
You have to make ${AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.getFunctionName(props.typeName)} function.
## DTO Types
Here is the list of DTO types relevant with the ${props.typeName} type:
\`\`\`json
${JSON.stringify(dto)}
\`\`\`
### Properties
When you composing ${props.typeName} typed data, you have check those properties:
${Object.keys(props.schema.properties)
.map((s) => `- ${s}`)
.join("\n")}
## External Definitions
Here is the external declaration files (d.ts) you can reference.
\`\`\`json
${JSON.stringify(yield (0, getTestExternalDeclarations_1.getTestExternalDeclarations)(ctx))}
\`\`\`
## Template Code
Here is the template code you have to implement.
Reference the template code, and fill the proper code to each property.
${AutoBeTestPrepareProgrammer_1.AutoBeTestPrepareProgrammer.writeTemplateCode(props)}
`,
},
],
userMessage: "Generate the test data preparation function for this DTO.",
};
});
}
//# sourceMappingURL=transformTestPrepareWriteHistory.js.map