@autobe/agent 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/AutoBeAgent.d.ts +183 -12
- package/lib/AutoBeAgent.js +245 -65
- package/lib/AutoBeAgent.js.map +1 -1
- package/lib/constants/AutoBeSystemPromptConstant.d.ts +4 -3
- package/lib/constants/AutoBeSystemPromptConstant.js.map +1 -1
- package/lib/context/AutoBeContext.d.ts +2 -2
- package/lib/factory/index.d.ts +0 -1
- package/lib/factory/index.js +0 -1
- package/lib/factory/index.js.map +1 -1
- package/lib/index.mjs +976 -633
- package/lib/index.mjs.map +1 -1
- package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js +1 -1
- package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js.map +1 -1
- package/lib/orchestrate/interface/orchestrateInterface.js +1 -1
- package/lib/orchestrate/interface/orchestrateInterface.js.map +1 -1
- package/lib/orchestrate/prisma/orchestratePrisma.js +1 -1
- package/lib/orchestrate/prisma/orchestratePrisma.js.map +1 -1
- package/lib/orchestrate/prisma/orchestratePrismaCorrect.js +1 -1
- package/lib/orchestrate/prisma/orchestratePrismaCorrect.js.map +1 -1
- package/lib/orchestrate/test/orchestrateTest.js +4 -8
- package/lib/orchestrate/test/orchestrateTest.js.map +1 -1
- package/lib/orchestrate/test/orchestrateTestCorrect.d.ts +2 -2
- package/lib/orchestrate/test/orchestrateTestCorrect.js +89 -57
- package/lib/orchestrate/test/orchestrateTestCorrect.js.map +1 -1
- package/lib/orchestrate/test/orchestrateTestProgress.d.ts +3 -2
- package/lib/orchestrate/test/orchestrateTestProgress.js +73 -46
- package/lib/orchestrate/test/orchestrateTestProgress.js.map +1 -1
- package/lib/orchestrate/test/orchestrateTestScenario.d.ts +2 -2
- package/lib/orchestrate/test/orchestrateTestScenario.js +616 -237
- package/lib/orchestrate/test/orchestrateTestScenario.js.map +1 -1
- package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.d.ts +123 -0
- package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.js +3 -0
- package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.js.map +1 -0
- package/lib/orchestrate/test/transformTestCorrectHistories.d.ts +2 -1
- package/lib/orchestrate/test/transformTestCorrectHistories.js +14 -10
- package/lib/orchestrate/test/transformTestCorrectHistories.js.map +1 -1
- package/lib/orchestrate/test/transformTestProgressHistories.d.ts +7 -1
- package/lib/orchestrate/test/transformTestProgressHistories.js +20 -20
- package/lib/orchestrate/test/transformTestProgressHistories.js.map +1 -1
- package/lib/orchestrate/test/transformTestScenarioHistories.d.ts +1 -2
- package/lib/orchestrate/test/transformTestScenarioHistories.js +1 -77
- package/lib/orchestrate/test/transformTestScenarioHistories.js.map +1 -1
- package/lib/structures/IAutoBeConfig.d.ts +48 -10
- package/lib/structures/IAutoBeProps.d.ts +87 -0
- package/lib/structures/IAutoBeVendor.d.ts +64 -22
- package/lib/utils/backoffRetry.d.ts +7 -0
- package/lib/utils/backoffRetry.js +73 -0
- package/lib/utils/backoffRetry.js.map +1 -0
- package/lib/utils/types/BackoffOptions.d.ts +12 -0
- package/lib/utils/types/BackoffOptions.js +3 -0
- package/lib/utils/types/BackoffOptions.js.map +1 -0
- package/package.json +4 -4
- package/src/AutoBeAgent.ts +248 -52
- package/src/constants/AutoBeSystemPromptConstant.ts +4 -3
- package/src/context/AutoBeContext.ts +7 -2
- package/src/factory/index.ts +0 -1
- package/src/orchestrate/analyze/AutoBeAnalyzeAgent.ts +1 -1
- package/src/orchestrate/interface/orchestrateInterface.ts +1 -1
- package/src/orchestrate/prisma/orchestratePrisma.ts +1 -0
- package/src/orchestrate/prisma/orchestratePrismaCorrect.ts +4 -2
- package/src/orchestrate/test/orchestrateTest.ts +6 -13
- package/src/orchestrate/test/orchestrateTestCorrect.ts +125 -72
- package/src/orchestrate/test/orchestrateTestProgress.ts +86 -42
- package/src/orchestrate/test/orchestrateTestScenario.ts +192 -151
- package/src/orchestrate/test/structures/IAutoBeTestScenarioApplication.ts +132 -0
- package/src/orchestrate/test/transformTestCorrectHistories.ts +14 -10
- package/src/orchestrate/test/transformTestProgressHistories.ts +25 -22
- package/src/orchestrate/test/transformTestScenarioHistories.ts +0 -79
- package/src/structures/IAutoBeConfig.ts +48 -10
- package/src/structures/IAutoBeProps.ts +91 -0
- package/src/structures/IAutoBeVendor.ts +64 -22
- package/src/utils/backoffRetry.ts +84 -0
- package/src/utils/types/BackoffOptions.ts +15 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { IAgenticaController, MicroAgentica } from "@agentica/core";
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
AutoBeOpenApi,
|
|
4
|
+
AutoBeTestScenarioEvent,
|
|
4
5
|
AutoBeTestValidateEvent,
|
|
6
|
+
AutoBeTestWriteEvent,
|
|
5
7
|
IAutoBeTypeScriptCompilerResult,
|
|
6
8
|
} from "@autobe/interface";
|
|
7
9
|
import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
|
|
@@ -10,32 +12,49 @@ import typia from "typia";
|
|
|
10
12
|
|
|
11
13
|
import { AutoBeContext } from "../../context/AutoBeContext";
|
|
12
14
|
import { assertSchemaModel } from "../../context/assertSchemaModel";
|
|
15
|
+
import { randomBackoffRetry } from "../../utils/backoffRetry";
|
|
13
16
|
import { enforceToolCall } from "../../utils/enforceToolCall";
|
|
17
|
+
import { filterDocument } from "./orchestrateTestProgress";
|
|
14
18
|
import { transformTestCorrectHistories } from "./transformTestCorrectHistories";
|
|
15
19
|
|
|
16
20
|
export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
|
|
17
21
|
ctx: AutoBeContext<Model>,
|
|
18
|
-
codes:
|
|
22
|
+
codes: AutoBeTestWriteEvent[],
|
|
23
|
+
scenarios: AutoBeTestScenarioEvent.IScenario[],
|
|
19
24
|
life: number = 4,
|
|
20
25
|
): Promise<AutoBeTestValidateEvent> {
|
|
26
|
+
const scenarioMap: Map<string, AutoBeTestScenarioEvent.IScenario> = new Map();
|
|
27
|
+
codes.forEach(({ filename }, index) => {
|
|
28
|
+
scenarioMap.set(filename, scenarios[index]);
|
|
29
|
+
});
|
|
30
|
+
|
|
21
31
|
// 1) Build map of new test files from progress events
|
|
22
|
-
const testFiles =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
const testFiles: Record<string, string> = codes
|
|
33
|
+
.map(({ filename, content }) => {
|
|
34
|
+
return {
|
|
35
|
+
[`test/features/api/${filename}`]: content,
|
|
36
|
+
};
|
|
37
|
+
})
|
|
38
|
+
.reduce<Record<string, string>>((acc, cur) => Object.assign(acc, cur), {});
|
|
28
39
|
|
|
29
40
|
// 2) Keep only files outside the test directory from current state
|
|
30
|
-
const retainedFiles = Object.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
|
|
41
|
+
const retainedFiles: Record<string, string> = Object.entries(
|
|
42
|
+
ctx.state().interface?.files ?? {},
|
|
43
|
+
)
|
|
44
|
+
.filter(([filename]) => {
|
|
45
|
+
return !filename.startsWith("test/features/api");
|
|
46
|
+
})
|
|
47
|
+
.map(([filename, content]) => {
|
|
48
|
+
return { [filename]: content };
|
|
49
|
+
})
|
|
50
|
+
.reduce<Record<string, string>>((acc, cur) => Object.assign(acc, cur), {});
|
|
35
51
|
|
|
36
52
|
// 3) Merge and filter: keep .ts/.json, drop anything under "benchmark"
|
|
37
|
-
const mergedFiles = {
|
|
38
|
-
|
|
53
|
+
const mergedFiles: Record<string, string> = {
|
|
54
|
+
...retainedFiles,
|
|
55
|
+
...testFiles,
|
|
56
|
+
};
|
|
57
|
+
const files: Record<string, string> = Object.fromEntries(
|
|
39
58
|
Object.entries(mergedFiles).filter(
|
|
40
59
|
([filename]) =>
|
|
41
60
|
(filename.endsWith(".ts") && !filename.startsWith("test/benchmark/")) ||
|
|
@@ -44,7 +63,12 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
|
|
|
44
63
|
);
|
|
45
64
|
|
|
46
65
|
// 4) Ask the LLM to correct the filtered file set
|
|
47
|
-
const response = await step(
|
|
66
|
+
const response: AutoBeTestValidateEvent = await step(
|
|
67
|
+
ctx,
|
|
68
|
+
files,
|
|
69
|
+
scenarioMap,
|
|
70
|
+
life,
|
|
71
|
+
);
|
|
48
72
|
|
|
49
73
|
// 5) Combine original + corrected files and dispatch event
|
|
50
74
|
const event: AutoBeTestValidateEvent = {
|
|
@@ -52,7 +76,6 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
|
|
|
52
76
|
type: "testValidate",
|
|
53
77
|
files: { ...mergedFiles, ...response.files },
|
|
54
78
|
};
|
|
55
|
-
|
|
56
79
|
return event;
|
|
57
80
|
}
|
|
58
81
|
|
|
@@ -74,13 +97,15 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
|
|
|
74
97
|
async function step<Model extends ILlmSchema.Model>(
|
|
75
98
|
ctx: AutoBeContext<Model>,
|
|
76
99
|
files: Record<string, string>,
|
|
100
|
+
scenarioMap: Map<string, AutoBeTestScenarioEvent.IScenario>,
|
|
77
101
|
life: number,
|
|
78
102
|
): Promise<AutoBeTestValidateEvent> {
|
|
79
103
|
// COMPILE TEST CODE
|
|
80
|
-
const result = await ctx.compiler.typescript({
|
|
81
|
-
files,
|
|
82
|
-
});
|
|
83
104
|
|
|
105
|
+
const result: IAutoBeTypeScriptCompilerResult =
|
|
106
|
+
await ctx.compiler.typescript.compile({
|
|
107
|
+
files,
|
|
108
|
+
});
|
|
84
109
|
if (result.type === "success") {
|
|
85
110
|
// SUCCESS
|
|
86
111
|
return {
|
|
@@ -101,7 +126,6 @@ async function step<Model extends ILlmSchema.Model>(
|
|
|
101
126
|
result,
|
|
102
127
|
step: ctx.state().interface?.step ?? 0,
|
|
103
128
|
});
|
|
104
|
-
|
|
105
129
|
throw new Error(JSON.stringify(result.error, null, 2));
|
|
106
130
|
}
|
|
107
131
|
|
|
@@ -155,11 +179,17 @@ async function step<Model extends ILlmSchema.Model>(
|
|
|
155
179
|
};
|
|
156
180
|
|
|
157
181
|
// VALIDATION FAILED
|
|
158
|
-
const validate = await Promise.all(
|
|
182
|
+
const validate: [string, string][] = await Promise.all(
|
|
159
183
|
Object.entries(diagnostics).map(async ([filename, d]) => {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
184
|
+
const scenario: AutoBeTestScenarioEvent.IScenario =
|
|
185
|
+
scenarioMap.get(filename)!;
|
|
186
|
+
const code: string = files[filename];
|
|
187
|
+
const response: ICorrectTestFunctionProps = await process(
|
|
188
|
+
ctx,
|
|
189
|
+
d,
|
|
190
|
+
code,
|
|
191
|
+
scenario,
|
|
192
|
+
);
|
|
163
193
|
ctx.dispatch({
|
|
164
194
|
type: "testCorrect",
|
|
165
195
|
created_at: new Date().toISOString(),
|
|
@@ -176,9 +206,11 @@ async function step<Model extends ILlmSchema.Model>(
|
|
|
176
206
|
}),
|
|
177
207
|
);
|
|
178
208
|
|
|
179
|
-
const newFiles = {
|
|
180
|
-
|
|
181
|
-
|
|
209
|
+
const newFiles: Record<string, string> = {
|
|
210
|
+
...files,
|
|
211
|
+
...Object.fromEntries(validate),
|
|
212
|
+
};
|
|
213
|
+
return step(ctx, newFiles, scenarioMap, life - 1);
|
|
182
214
|
}
|
|
183
215
|
|
|
184
216
|
/**
|
|
@@ -195,26 +227,32 @@ async function process<Model extends ILlmSchema.Model>(
|
|
|
195
227
|
ctx: AutoBeContext<Model>,
|
|
196
228
|
diagnostics: IAutoBeTypeScriptCompilerResult.IDiagnostic[],
|
|
197
229
|
code: string,
|
|
230
|
+
scenario: AutoBeTestScenarioEvent.IScenario,
|
|
198
231
|
): Promise<ICorrectTestFunctionProps> {
|
|
199
232
|
const pointer: IPointer<ICorrectTestFunctionProps | null> = {
|
|
200
233
|
value: null,
|
|
201
234
|
};
|
|
202
235
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
.reduce<Record<string, string>>((acc, [filename, content]) => {
|
|
208
|
-
return Object.assign(acc, { [filename]: content });
|
|
209
|
-
}, {});
|
|
236
|
+
let document: AutoBeOpenApi.IDocument | null = null;
|
|
237
|
+
if (scenario) {
|
|
238
|
+
document = filterDocument(scenario, ctx.state().interface!.document);
|
|
239
|
+
}
|
|
210
240
|
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
241
|
+
// const apiFiles = Object.entries(ctx.state().interface?.files ?? {})
|
|
242
|
+
// .filter(([filename]) => {
|
|
243
|
+
// return filename.startsWith("src/api/");
|
|
244
|
+
// })
|
|
245
|
+
// .reduce<Record<string, string>>((acc, [filename, content]) => {
|
|
246
|
+
// return Object.assign(acc, { [filename]: content });
|
|
247
|
+
// }, {});
|
|
248
|
+
|
|
249
|
+
// const dtoFiles = Object.entries(ctx.state().interface?.files ?? {})
|
|
250
|
+
// .filter(([filename]) => {
|
|
251
|
+
// return filename.startsWith("src/api/structures/");
|
|
252
|
+
// })
|
|
253
|
+
// .reduce<Record<string, string>>((acc, [filename, content]) => {
|
|
254
|
+
// return Object.assign(acc, { [filename]: content });
|
|
255
|
+
// }, {});
|
|
218
256
|
|
|
219
257
|
const agentica = new MicroAgentica({
|
|
220
258
|
model: ctx.model,
|
|
@@ -222,7 +260,7 @@ async function process<Model extends ILlmSchema.Model>(
|
|
|
222
260
|
config: {
|
|
223
261
|
...(ctx.config ?? {}),
|
|
224
262
|
},
|
|
225
|
-
histories: transformTestCorrectHistories(
|
|
263
|
+
histories: transformTestCorrectHistories(document),
|
|
226
264
|
controllers: [
|
|
227
265
|
createApplication({
|
|
228
266
|
model: ctx.model,
|
|
@@ -231,38 +269,53 @@ async function process<Model extends ILlmSchema.Model>(
|
|
|
231
269
|
},
|
|
232
270
|
}),
|
|
233
271
|
],
|
|
272
|
+
tokenUsage: ctx.usage(),
|
|
234
273
|
});
|
|
235
274
|
enforceToolCall(agentica);
|
|
236
275
|
|
|
237
|
-
await
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
await randomBackoffRetry(async () => {
|
|
277
|
+
await agentica.conversate(
|
|
278
|
+
[
|
|
279
|
+
"Fix the compilation error in the provided code.",
|
|
280
|
+
"",
|
|
281
|
+
"## Original Code",
|
|
282
|
+
"```typescript",
|
|
283
|
+
code,
|
|
284
|
+
"```",
|
|
285
|
+
"",
|
|
286
|
+
diagnostics.map((diagnostic) => {
|
|
287
|
+
if (diagnostic.start === undefined || diagnostic.length === undefined)
|
|
288
|
+
return "";
|
|
289
|
+
|
|
290
|
+
const checkDtoRegexp = `Cannot find module '@ORGANIZATION/template-api/lib/structures/IBbsArticleComment' or its corresponding type declarations.`;
|
|
291
|
+
const [group] = [
|
|
292
|
+
...checkDtoRegexp.matchAll(
|
|
293
|
+
/Cannot find module '(.*lib\/structures\/.*)'/g,
|
|
294
|
+
),
|
|
295
|
+
];
|
|
296
|
+
|
|
297
|
+
const [_, filename] = group ?? [];
|
|
298
|
+
|
|
299
|
+
return [
|
|
300
|
+
"## Error Information",
|
|
301
|
+
`- Position: Characters ${diagnostic.start} to ${diagnostic.start + diagnostic.length}`,
|
|
302
|
+
`- Error Message: ${diagnostic.messageText}`,
|
|
303
|
+
`- Problematic Code: \`${code.substring(diagnostic.start, diagnostic.start + diagnostic.length)}\``,
|
|
304
|
+
filename
|
|
305
|
+
? `The type files located under **/lib/structures are declared in '@ORGANIZATION/PROJECT-api/lib/structures'.\n` +
|
|
306
|
+
`Note: '@ORGANIZATION/PROJECT-api' must be written exactly as is and should not be replaced.\n`
|
|
307
|
+
: "",
|
|
308
|
+
].join("\n");
|
|
309
|
+
}),
|
|
310
|
+
"## Instructions",
|
|
311
|
+
"1. Focus on the specific error location and message",
|
|
312
|
+
"2. Provide the corrected TypeScript code",
|
|
313
|
+
"3. Ensure the fix resolves the compilation error",
|
|
314
|
+
"",
|
|
315
|
+
"Return only the fixed code without explanations.",
|
|
316
|
+
].join("\n"),
|
|
317
|
+
);
|
|
318
|
+
});
|
|
266
319
|
if (pointer.value === null) throw new Error("Failed to modify test code.");
|
|
267
320
|
return pointer.value;
|
|
268
321
|
}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { IAgenticaController, MicroAgentica } from "@agentica/core";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
AutoBeOpenApi,
|
|
4
|
+
AutoBeTestScenarioEvent,
|
|
5
|
+
AutoBeTestWriteEvent,
|
|
6
|
+
} from "@autobe/interface";
|
|
7
|
+
import {
|
|
8
|
+
ILlmApplication,
|
|
9
|
+
ILlmSchema,
|
|
10
|
+
OpenApiTypeChecker,
|
|
11
|
+
} from "@samchon/openapi";
|
|
4
12
|
import { IPointer } from "tstl";
|
|
5
13
|
import typia from "typia";
|
|
6
14
|
|
|
@@ -11,22 +19,21 @@ import { transformTestProgressHistories } from "./transformTestProgressHistories
|
|
|
11
19
|
|
|
12
20
|
export async function orchestrateTestProgress<Model extends ILlmSchema.Model>(
|
|
13
21
|
ctx: AutoBeContext<Model>,
|
|
14
|
-
scenarios:
|
|
15
|
-
): Promise<
|
|
22
|
+
scenarios: AutoBeTestScenarioEvent.IScenario[],
|
|
23
|
+
): Promise<AutoBeTestWriteEvent[]> {
|
|
16
24
|
const start: Date = new Date();
|
|
17
25
|
let complete: number = 0;
|
|
18
26
|
|
|
19
|
-
const events:
|
|
27
|
+
const events: AutoBeTestWriteEvent[] = await Promise.all(
|
|
20
28
|
/**
|
|
21
|
-
* Generate test code for each scenario. Maps through
|
|
22
|
-
*
|
|
23
|
-
*
|
|
29
|
+
* Generate test code for each scenario. Maps through plans array to create
|
|
30
|
+
* individual test code implementations. Each scenario is processed to
|
|
31
|
+
* generate corresponding test code and progress events.
|
|
24
32
|
*/
|
|
25
33
|
scenarios.map(async (scenario) => {
|
|
26
34
|
const code: ICreateTestCodeProps = await process(ctx, scenario);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
type: "testProgress",
|
|
35
|
+
const event: AutoBeTestWriteEvent = {
|
|
36
|
+
type: "testWrite",
|
|
30
37
|
created_at: start.toISOString(),
|
|
31
38
|
filename: `${code.domain}/${scenario.functionName}.ts`,
|
|
32
39
|
content: code.content,
|
|
@@ -54,27 +61,20 @@ export async function orchestrateTestProgress<Model extends ILlmSchema.Model>(
|
|
|
54
61
|
*/
|
|
55
62
|
async function process<Model extends ILlmSchema.Model>(
|
|
56
63
|
ctx: AutoBeContext<Model>,
|
|
57
|
-
scenario:
|
|
64
|
+
scenario: AutoBeTestScenarioEvent.IScenario,
|
|
58
65
|
): Promise<ICreateTestCodeProps> {
|
|
59
66
|
const pointer: IPointer<ICreateTestCodeProps | null> = {
|
|
60
67
|
value: null,
|
|
61
68
|
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const dtoFiles = Object.entries(ctx.state().interface?.files ?? {})
|
|
72
|
-
.filter(([filename]) => {
|
|
73
|
-
return filename.startsWith("src/api/structures/");
|
|
74
|
-
})
|
|
75
|
-
.reduce<Record<string, string>>((acc, [filename, content]) => {
|
|
76
|
-
return Object.assign(acc, { [filename]: content });
|
|
77
|
-
}, {});
|
|
69
|
+
const document: AutoBeOpenApi.IDocument = filterDocument(
|
|
70
|
+
scenario,
|
|
71
|
+
ctx.state().interface!.document,
|
|
72
|
+
);
|
|
73
|
+
const files: [string, string][] = Object.entries(
|
|
74
|
+
await ctx.compiler.interface.compile(document),
|
|
75
|
+
);
|
|
76
|
+
const filter = (prefix: string) =>
|
|
77
|
+
Object.fromEntries(files.filter(([key]) => key.startsWith(prefix)));
|
|
78
78
|
|
|
79
79
|
const agentica = new MicroAgentica({
|
|
80
80
|
model: ctx.model,
|
|
@@ -82,7 +82,12 @@ async function process<Model extends ILlmSchema.Model>(
|
|
|
82
82
|
config: {
|
|
83
83
|
...(ctx.config ?? {}),
|
|
84
84
|
},
|
|
85
|
-
histories: transformTestProgressHistories(
|
|
85
|
+
histories: transformTestProgressHistories({
|
|
86
|
+
scenario: scenario,
|
|
87
|
+
dto: filter("src/api/structures"),
|
|
88
|
+
sdk: filter("src/api/functional"),
|
|
89
|
+
e2e: filter("test/features"),
|
|
90
|
+
}),
|
|
86
91
|
controllers: [
|
|
87
92
|
createApplication({
|
|
88
93
|
model: ctx.model,
|
|
@@ -91,22 +96,61 @@ async function process<Model extends ILlmSchema.Model>(
|
|
|
91
96
|
},
|
|
92
97
|
}),
|
|
93
98
|
],
|
|
99
|
+
tokenUsage: ctx.usage(),
|
|
94
100
|
});
|
|
95
101
|
enforceToolCall(agentica);
|
|
96
102
|
|
|
97
|
-
await agentica.conversate(
|
|
98
|
-
[
|
|
99
|
-
"Create test code for below scenario:",
|
|
100
|
-
"",
|
|
101
|
-
"```json",
|
|
102
|
-
JSON.stringify(scenario, null, 2),
|
|
103
|
-
"```",
|
|
104
|
-
].join("\n"),
|
|
105
|
-
);
|
|
103
|
+
await agentica.conversate("Create e2e test functions.");
|
|
106
104
|
if (pointer.value === null) throw new Error("Failed to create test code.");
|
|
107
105
|
return pointer.value;
|
|
108
106
|
}
|
|
109
107
|
|
|
108
|
+
export function filterDocument(
|
|
109
|
+
scenario: AutoBeTestScenarioEvent.IScenario,
|
|
110
|
+
document: AutoBeOpenApi.IDocument,
|
|
111
|
+
): AutoBeOpenApi.IDocument {
|
|
112
|
+
const operations: AutoBeOpenApi.IOperation[] = document.operations.filter(
|
|
113
|
+
(op) => {
|
|
114
|
+
if (
|
|
115
|
+
scenario.endpoint.method === op.method &&
|
|
116
|
+
scenario.endpoint.path === op.path
|
|
117
|
+
) {
|
|
118
|
+
return true;
|
|
119
|
+
} else if (
|
|
120
|
+
scenario.dependencies.some(
|
|
121
|
+
(dp) =>
|
|
122
|
+
dp.endpoint.method === op.method && dp.endpoint.path === op.path,
|
|
123
|
+
)
|
|
124
|
+
) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
);
|
|
129
|
+
const components: AutoBeOpenApi.IComponents = {
|
|
130
|
+
schemas: {},
|
|
131
|
+
};
|
|
132
|
+
const visit = (typeName: string) => {
|
|
133
|
+
OpenApiTypeChecker.visit({
|
|
134
|
+
components: document.components,
|
|
135
|
+
schema: { $ref: `#/components/schemas/${typeName}` },
|
|
136
|
+
closure: (s) => {
|
|
137
|
+
if (OpenApiTypeChecker.isReference(s)) {
|
|
138
|
+
const key: string = s.$ref.split("/").pop()!;
|
|
139
|
+
components.schemas[key] = document.components.schemas[key];
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
};
|
|
144
|
+
for (const op of operations) {
|
|
145
|
+
if (op.requestBody) visit(op.requestBody.typeName);
|
|
146
|
+
if (op.responseBody) visit(op.responseBody.typeName);
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
operations,
|
|
150
|
+
components,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
110
154
|
function createApplication<Model extends ILlmSchema.Model>(props: {
|
|
111
155
|
model: Model;
|
|
112
156
|
build: (next: ICreateTestCodeProps) => void;
|
|
@@ -178,7 +222,7 @@ interface ICreateTestCodeProps {
|
|
|
178
222
|
* #### Execution Strategy
|
|
179
223
|
*
|
|
180
224
|
* - Outline step-by-step test execution flow
|
|
181
|
-
* - Plan error handling and exception
|
|
225
|
+
* - Plan error handling and exception plans
|
|
182
226
|
* - Define cleanup and teardown procedures
|
|
183
227
|
* - Identify dependencies and prerequisites
|
|
184
228
|
*
|
|
@@ -188,12 +232,12 @@ interface ICreateTestCodeProps {
|
|
|
188
232
|
* 1. Prepare valid article data with required fields
|
|
189
233
|
* 2. Execute POST request to create article
|
|
190
234
|
* 3. Validate response structure and data integrity
|
|
191
|
-
* 4. Test error
|
|
235
|
+
* 4. Test error plans (missing fields, invalid data)
|
|
192
236
|
* 5. Verify database state changes
|
|
193
|
-
* 6. Reconsider the
|
|
237
|
+
* 6. Reconsider the scenario if it doesn't follow the Test Generation
|
|
194
238
|
* Guildelines.
|
|
195
239
|
*/
|
|
196
|
-
|
|
240
|
+
scenario: string;
|
|
197
241
|
|
|
198
242
|
/**
|
|
199
243
|
* Functional domain classification for test organization.
|