@autobe/agent 0.9.2 → 0.10.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.
Files changed (175) hide show
  1. package/lib/AutoBeAgent.js +11 -4
  2. package/lib/AutoBeAgent.js.map +1 -1
  3. package/lib/constants/AutoBeSystemPromptConstant.d.ts +6 -6
  4. package/lib/context/AutoBeTokenUsage.d.ts +15 -1
  5. package/lib/context/AutoBeTokenUsage.js +56 -1
  6. package/lib/context/AutoBeTokenUsage.js.map +1 -1
  7. package/lib/factory/createAutoBeApplication.js +288 -643
  8. package/lib/factory/createAutoBeApplication.js.map +1 -1
  9. package/lib/index.mjs +5057 -7211
  10. package/lib/index.mjs.map +1 -1
  11. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js +82 -319
  12. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js.map +1 -1
  13. package/lib/orchestrate/analyze/AutoBeAnalyzeReviewer.js +0 -1
  14. package/lib/orchestrate/analyze/AutoBeAnalyzeReviewer.js.map +1 -1
  15. package/lib/orchestrate/analyze/orchestrateAnalyze.js +95 -266
  16. package/lib/orchestrate/analyze/orchestrateAnalyze.js.map +1 -1
  17. package/lib/orchestrate/facade/transformFacadeStateMessage.js +2 -2
  18. package/lib/orchestrate/facade/transformFacadeStateMessage.js.map +1 -1
  19. package/lib/orchestrate/index.d.ts +2 -2
  20. package/lib/orchestrate/index.js +4 -4
  21. package/lib/orchestrate/index.js.map +1 -1
  22. package/lib/orchestrate/interface/orchestrateInterfaceComplement.js +56 -142
  23. package/lib/orchestrate/interface/orchestrateInterfaceComplement.js.map +1 -1
  24. package/lib/orchestrate/interface/orchestrateInterfaceComponents.js +195 -199
  25. package/lib/orchestrate/interface/orchestrateInterfaceComponents.js.map +1 -1
  26. package/lib/orchestrate/interface/orchestrateInterfaceEndpoints.js +75 -172
  27. package/lib/orchestrate/interface/orchestrateInterfaceEndpoints.js.map +1 -1
  28. package/lib/orchestrate/interface/orchestrateInterfaceOperations.js +772 -1097
  29. package/lib/orchestrate/interface/orchestrateInterfaceOperations.js.map +1 -1
  30. package/lib/orchestrate/interface/transformInterfaceHistories.js +2 -0
  31. package/lib/orchestrate/interface/transformInterfaceHistories.js.map +1 -1
  32. package/lib/orchestrate/prisma/orchestratePrismaComponent.js +64 -175
  33. package/lib/orchestrate/prisma/orchestratePrismaComponent.js.map +1 -1
  34. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js +552 -1073
  35. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js.map +1 -1
  36. package/lib/orchestrate/prisma/orchestratePrismaSchema.js +571 -1119
  37. package/lib/orchestrate/prisma/orchestratePrismaSchema.js.map +1 -1
  38. package/lib/orchestrate/prisma/transformPrismaComponentsHistories.js +9 -0
  39. package/lib/orchestrate/prisma/transformPrismaComponentsHistories.js.map +1 -1
  40. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.js +8 -0
  41. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.js.map +1 -1
  42. package/lib/orchestrate/realize/orchestrateRealize.d.ts +11 -0
  43. package/lib/orchestrate/realize/orchestrateRealize.js +109 -0
  44. package/lib/orchestrate/realize/orchestrateRealize.js.map +1 -0
  45. package/lib/orchestrate/realize/orchestrateRealizeCoder.d.ts +25 -0
  46. package/lib/orchestrate/realize/orchestrateRealizeCoder.js +337 -0
  47. package/lib/orchestrate/realize/orchestrateRealizeCoder.js.map +1 -0
  48. package/lib/orchestrate/realize/orchestrateRealizeIntegrator.d.ts +52 -0
  49. package/lib/orchestrate/realize/orchestrateRealizeIntegrator.js +57 -0
  50. package/lib/orchestrate/realize/orchestrateRealizeIntegrator.js.map +1 -0
  51. package/lib/orchestrate/realize/orchestrateRealizePlanner.d.ts +80 -0
  52. package/lib/orchestrate/realize/orchestrateRealizePlanner.js +53 -0
  53. package/lib/orchestrate/realize/orchestrateRealizePlanner.js.map +1 -0
  54. package/lib/orchestrate/realize/orchestrateRealizeValidator.d.ts +46 -0
  55. package/lib/orchestrate/realize/orchestrateRealizeValidator.js +37 -0
  56. package/lib/orchestrate/realize/orchestrateRealizeValidator.js.map +1 -0
  57. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.d.ts +33 -0
  58. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.js +3 -0
  59. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.js.map +1 -0
  60. package/lib/orchestrate/realize/transformRealizeCoderHistories.d.ts +5 -0
  61. package/lib/orchestrate/realize/transformRealizeCoderHistories.js +127 -0
  62. package/lib/orchestrate/realize/transformRealizeCoderHistories.js.map +1 -0
  63. package/lib/orchestrate/test/compile/completeTestCode.d.ts +2 -0
  64. package/lib/orchestrate/test/compile/completeTestCode.js +21 -0
  65. package/lib/orchestrate/test/compile/completeTestCode.js.map +1 -0
  66. package/lib/orchestrate/test/{filterTestFileName.js → compile/filterTestFileName.js} +1 -1
  67. package/lib/orchestrate/test/compile/filterTestFileName.js.map +1 -0
  68. package/lib/orchestrate/test/compile/getTestExternalDeclarations.d.ts +3 -0
  69. package/lib/orchestrate/test/compile/getTestExternalDeclarations.js +27 -0
  70. package/lib/orchestrate/test/compile/getTestExternalDeclarations.js.map +1 -0
  71. package/lib/orchestrate/test/compile/getTestScenarioArtifacts.d.ts +5 -0
  72. package/lib/orchestrate/test/{compileTestScenario.js → compile/getTestScenarioArtifacts.js} +10 -5
  73. package/lib/orchestrate/test/compile/getTestScenarioArtifacts.js.map +1 -0
  74. package/lib/orchestrate/test/orchestrateTest.js +14 -9
  75. package/lib/orchestrate/test/orchestrateTest.js.map +1 -1
  76. package/lib/orchestrate/test/orchestrateTestCorrect.d.ts +3 -2
  77. package/lib/orchestrate/test/orchestrateTestCorrect.js +150 -448
  78. package/lib/orchestrate/test/orchestrateTestCorrect.js.map +1 -1
  79. package/lib/orchestrate/test/orchestrateTestScenario.js +272 -530
  80. package/lib/orchestrate/test/orchestrateTestScenario.js.map +1 -1
  81. package/lib/orchestrate/test/orchestrateTestWrite.d.ts +3 -2
  82. package/lib/orchestrate/test/orchestrateTestWrite.js +139 -90
  83. package/lib/orchestrate/test/orchestrateTestWrite.js.map +1 -1
  84. package/lib/orchestrate/test/structures/IAutoBeTestCorrectApplication.d.ts +121 -0
  85. package/lib/orchestrate/test/structures/IAutoBeTestCorrectApplication.js +3 -0
  86. package/lib/orchestrate/test/structures/IAutoBeTestCorrectApplication.js.map +1 -0
  87. package/lib/orchestrate/test/structures/IAutoBeTestFunction.d.ts +8 -0
  88. package/lib/{utils/types/BackoffOptions.js → orchestrate/test/structures/IAutoBeTestFunction.js} +1 -1
  89. package/lib/orchestrate/test/structures/IAutoBeTestFunction.js.map +1 -0
  90. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.d.ts +14 -2
  91. package/lib/orchestrate/test/structures/IAutoBeTestWriteApplication.d.ts +112 -0
  92. package/lib/orchestrate/test/structures/IAutoBeTestWriteApplication.js +3 -0
  93. package/lib/orchestrate/test/structures/IAutoBeTestWriteApplication.js.map +1 -0
  94. package/lib/orchestrate/test/structures/IAutoBeTestWriteResult.d.ts +7 -0
  95. package/lib/orchestrate/test/structures/IAutoBeTestWriteResult.js +3 -0
  96. package/lib/orchestrate/test/structures/IAutoBeTestWriteResult.js.map +1 -0
  97. package/lib/orchestrate/test/transformTestCorrectHistories.d.ts +3 -2
  98. package/lib/orchestrate/test/transformTestCorrectHistories.js +28 -67
  99. package/lib/orchestrate/test/transformTestCorrectHistories.js.map +1 -1
  100. package/lib/orchestrate/test/transformTestWriteHistories.d.ts +5 -4
  101. package/lib/orchestrate/test/transformTestWriteHistories.js +168 -43
  102. package/lib/orchestrate/test/transformTestWriteHistories.js.map +1 -1
  103. package/lib/structures/IAutoBeConfig.d.ts +11 -0
  104. package/lib/utils/backoffRetry.d.ts +4 -7
  105. package/lib/utils/backoffRetry.js +19 -37
  106. package/lib/utils/backoffRetry.js.map +1 -1
  107. package/lib/utils/forceRetry.d.ts +1 -0
  108. package/lib/{orchestrate/orchestrateRealize.js → utils/forceRetry.js} +15 -8
  109. package/lib/utils/forceRetry.js.map +1 -0
  110. package/package.json +8 -7
  111. package/src/AutoBeAgent.ts +17 -3
  112. package/src/constants/AutoBeSystemPromptConstant.ts +6 -6
  113. package/src/context/AutoBeTokenUsage.ts +85 -1
  114. package/src/factory/createAutoBeApplication.ts +2 -3
  115. package/src/orchestrate/analyze/AutoBeAnalyzeAgent.ts +8 -3
  116. package/src/orchestrate/analyze/AutoBeAnalyzeReviewer.ts +0 -1
  117. package/src/orchestrate/analyze/orchestrateAnalyze.ts +6 -5
  118. package/src/orchestrate/facade/transformFacadeStateMessage.ts +2 -1
  119. package/src/orchestrate/index.ts +2 -2
  120. package/src/orchestrate/interface/orchestrateInterfaceComplement.ts +4 -3
  121. package/src/orchestrate/interface/orchestrateInterfaceComponents.ts +26 -23
  122. package/src/orchestrate/interface/orchestrateInterfaceEndpoints.ts +6 -4
  123. package/src/orchestrate/interface/orchestrateInterfaceOperations.ts +14 -11
  124. package/src/orchestrate/interface/transformInterfaceHistories.ts +2 -0
  125. package/src/orchestrate/prisma/orchestratePrismaComponent.ts +10 -5
  126. package/src/orchestrate/prisma/orchestratePrismaCorrect.ts +11 -5
  127. package/src/orchestrate/prisma/orchestratePrismaSchema.ts +16 -8
  128. package/src/orchestrate/prisma/transformPrismaComponentsHistories.ts +9 -0
  129. package/src/orchestrate/prisma/transformPrismaSchemaHistories.ts +8 -0
  130. package/src/orchestrate/realize/orchestrateRealize.ts +169 -0
  131. package/src/orchestrate/realize/orchestrateRealizeCoder.ts +156 -0
  132. package/src/orchestrate/realize/orchestrateRealizeIntegrator.ts +75 -0
  133. package/src/orchestrate/realize/orchestrateRealizePlanner.ts +115 -0
  134. package/src/orchestrate/realize/orchestrateRealizeValidator.ts +64 -0
  135. package/src/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.ts +36 -0
  136. package/src/orchestrate/realize/transformRealizeCoderHistories.ts +136 -0
  137. package/src/orchestrate/test/compile/completeTestCode.ts +35 -0
  138. package/src/orchestrate/test/{filterTestFileName.ts → compile/filterTestFileName.ts} +1 -1
  139. package/src/orchestrate/test/compile/getTestExternalDeclarations.ts +24 -0
  140. package/src/orchestrate/test/{compileTestScenario.ts → compile/getTestScenarioArtifacts.ts} +16 -8
  141. package/src/orchestrate/test/experimental/orchestrateTestCorrect.ast +240 -0
  142. package/src/orchestrate/test/experimental/orchestrateTestWrite.ast +316 -0
  143. package/src/orchestrate/test/experimental/transformTestCorrectHistories.ast +52 -0
  144. package/src/orchestrate/test/orchestrateTest.ts +33 -16
  145. package/src/orchestrate/test/orchestrateTestCorrect.ts +109 -497
  146. package/src/orchestrate/test/orchestrateTestScenario.ts +102 -71
  147. package/src/orchestrate/test/orchestrateTestWrite.ts +55 -181
  148. package/src/orchestrate/test/structures/IAutoBeTestCorrectApplication.ts +126 -0
  149. package/src/orchestrate/test/structures/IAutoBeTestFunction.ts +10 -0
  150. package/src/orchestrate/test/structures/IAutoBeTestScenarioApplication.ts +14 -2
  151. package/src/orchestrate/test/structures/IAutoBeTestWriteApplication.ts +117 -0
  152. package/src/orchestrate/test/structures/IAutoBeTestWriteResult.ts +9 -0
  153. package/src/orchestrate/test/transformTestCorrectHistories.ts +38 -71
  154. package/src/orchestrate/test/transformTestWriteHistories.ts +88 -46
  155. package/src/structures/IAutoBeConfig.ts +9 -0
  156. package/src/utils/backoffRetry.ts +25 -36
  157. package/src/utils/forceRetry.ts +13 -0
  158. package/lib/factory/invertOpenApiDocument.d.ts +0 -3
  159. package/lib/factory/invertOpenApiDocument.js +0 -51
  160. package/lib/factory/invertOpenApiDocument.js.map +0 -1
  161. package/lib/orchestrate/orchestrateRealize.d.ts +0 -5
  162. package/lib/orchestrate/orchestrateRealize.js.map +0 -1
  163. package/lib/orchestrate/test/compileTestScenario.d.ts +0 -5
  164. package/lib/orchestrate/test/compileTestScenario.js.map +0 -1
  165. package/lib/orchestrate/test/filterTestFileName.js.map +0 -1
  166. package/lib/utils/StringUtil.d.ts +0 -4
  167. package/lib/utils/StringUtil.js +0 -43
  168. package/lib/utils/StringUtil.js.map +0 -1
  169. package/lib/utils/types/BackoffOptions.d.ts +0 -12
  170. package/lib/utils/types/BackoffOptions.js.map +0 -1
  171. package/src/factory/invertOpenApiDocument.ts +0 -63
  172. package/src/orchestrate/orchestrateRealize.ts +0 -18
  173. package/src/utils/StringUtil.ts +0 -45
  174. package/src/utils/types/BackoffOptions.ts +0 -15
  175. /package/lib/orchestrate/test/{filterTestFileName.d.ts → compile/filterTestFileName.d.ts} +0 -0
@@ -8,8 +8,9 @@ import {
8
8
  AutoBeTestScenario,
9
9
  AutoBeTestScenarioEvent,
10
10
  } from "@autobe/interface";
11
+ import { AutoBeEndpointComparator } from "@autobe/utils";
11
12
  import { ILlmApplication, ILlmSchema, IValidation } from "@samchon/openapi";
12
- import { IPointer } from "tstl";
13
+ import { HashMap, IPointer, Pair } from "tstl";
13
14
  import typia from "typia";
14
15
  import { v4 } from "uuid";
15
16
 
@@ -18,37 +19,67 @@ import { AutoBeContext } from "../../context/AutoBeContext";
18
19
  import { assertSchemaModel } from "../../context/assertSchemaModel";
19
20
  import { divideArray } from "../../utils/divideArray";
20
21
  import { enforceToolCall } from "../../utils/enforceToolCall";
22
+ import { forceRetry } from "../../utils/forceRetry";
21
23
  import { IAutoBeTestScenarioApplication } from "./structures/IAutoBeTestScenarioApplication";
22
24
 
23
25
  export async function orchestrateTestScenario<Model extends ILlmSchema.Model>(
24
26
  ctx: AutoBeContext<Model>,
25
27
  ): Promise<AutoBeTestScenarioEvent> {
26
- const operations = ctx.state().interface?.document.operations ?? [];
28
+ const operations: AutoBeOpenApi.IOperation[] =
29
+ ctx.state().interface?.document.operations ?? [];
27
30
  if (operations.length === 0) {
28
31
  throw new Error(
29
32
  "Cannot write test scenarios because these are no operations.",
30
33
  );
31
34
  }
32
35
 
36
+ const dict: HashMap<AutoBeOpenApi.IEndpoint, AutoBeOpenApi.IOperation> =
37
+ new HashMap<AutoBeOpenApi.IEndpoint, AutoBeOpenApi.IOperation>(
38
+ operations.map(
39
+ (op) =>
40
+ new Pair(
41
+ {
42
+ path: op.path,
43
+ method: op.method,
44
+ },
45
+ op,
46
+ ),
47
+ ),
48
+ AutoBeEndpointComparator.hashCode,
49
+ AutoBeEndpointComparator.equals,
50
+ );
51
+ const endpointNotFound: string = [
52
+ `You have to select one of the endpoints below`,
53
+ "",
54
+ " method | path ",
55
+ "--------|------",
56
+ ...operations.map((op) => `\`${op.method}\` | \`${op.path}\``).join("\n"),
57
+ ].join("\n");
58
+
33
59
  const exclude: IAutoBeTestScenarioApplication.IScenarioGroup[] = [];
34
60
  let include: AutoBeOpenApi.IOperation[] = Array.from(operations);
35
61
 
36
62
  do {
37
- const matrix = divideArray({ array: include, capacity: 5 });
38
-
63
+ const matrix: AutoBeOpenApi.IOperation[][] = divideArray({
64
+ array: include,
65
+ capacity: 5,
66
+ });
39
67
  await Promise.all(
40
- matrix.map(async (_include) => {
68
+ matrix.map(async (include) => {
41
69
  exclude.push(
42
- ...(await execute(
43
- ctx,
44
- operations,
45
- _include,
46
- exclude.map((x) => x.endpoint),
70
+ ...(await forceRetry(() =>
71
+ execute(
72
+ ctx,
73
+ dict,
74
+ endpointNotFound,
75
+ operations,
76
+ include,
77
+ exclude.map((x) => x.endpoint),
78
+ ),
47
79
  )),
48
80
  );
49
81
  }),
50
82
  );
51
-
52
83
  include = include.filter((op) => {
53
84
  if (
54
85
  exclude.some(
@@ -81,9 +112,11 @@ export async function orchestrateTestScenario<Model extends ILlmSchema.Model>(
81
112
 
82
113
  const execute = async <Model extends ILlmSchema.Model>(
83
114
  ctx: AutoBeContext<Model>,
84
- ops: AutoBeOpenApi.IOperation[],
85
- include: Pick<AutoBeOpenApi.IOperation, "method" | "path">[],
86
- exclude: Pick<AutoBeOpenApi.IOperation, "method" | "path">[],
115
+ dict: HashMap<AutoBeOpenApi.IEndpoint, AutoBeOpenApi.IOperation>,
116
+ endpointNotFound: string,
117
+ entire: AutoBeOpenApi.IOperation[],
118
+ include: AutoBeOpenApi.IEndpoint[],
119
+ exclude: AutoBeOpenApi.IEndpoint[],
87
120
  ) => {
88
121
  const pointer: IPointer<IAutoBeTestScenarioApplication.IScenarioGroup[]> = {
89
122
  value: [],
@@ -97,11 +130,12 @@ const execute = async <Model extends ILlmSchema.Model>(
97
130
  describe: null,
98
131
  },
99
132
  },
100
- tokenUsage: ctx.usage(),
101
- histories: createHistoryProperties(ops, include, exclude),
133
+ histories: createHistoryProperties(entire, include, exclude),
102
134
  controllers: [
103
135
  createApplication({
104
136
  model: ctx.model,
137
+ endpointNotFound,
138
+ dict,
105
139
  build: (next) => {
106
140
  pointer.value ??= [];
107
141
  pointer.value.push(...next.scenarioGroups);
@@ -111,7 +145,10 @@ const execute = async <Model extends ILlmSchema.Model>(
111
145
  });
112
146
  enforceToolCall(agentica);
113
147
 
114
- await agentica.conversate(`create test scenarios.`);
148
+ await agentica.conversate(`create test scenarios.`).finally(() => {
149
+ const tokenUsage = agentica.getTokenUsage();
150
+ ctx.usage().record(tokenUsage, ["test"]);
151
+ });
115
152
  if (pointer.value.length === 0) {
116
153
  throw new Error("Failed to create test plans.");
117
154
  }
@@ -120,7 +157,7 @@ const execute = async <Model extends ILlmSchema.Model>(
120
157
  };
121
158
 
122
159
  const createHistoryProperties = (
123
- operations: AutoBeOpenApi.IOperation[],
160
+ entire: AutoBeOpenApi.IOperation[],
124
161
  include: Pick<AutoBeOpenApi.IOperation, "method" | "path">[],
125
162
  exclude: Pick<AutoBeOpenApi.IOperation, "method" | "path">[],
126
163
  ): Array<
@@ -152,14 +189,9 @@ const createHistoryProperties = (
152
189
  "",
153
190
  "```json",
154
191
  JSON.stringify(
155
- operations.map((el) => ({
156
- path: el.path,
157
- method: el.method,
158
- summary: el.summary,
159
- description: el.description,
160
- parameters: el.parameters,
161
- requestBody: el.requestBody,
162
- responseBody: el.responseBody,
192
+ entire.map((el) => ({
193
+ ...el,
194
+ specification: undefined,
163
195
  })),
164
196
  ),
165
197
  "```",
@@ -188,6 +220,8 @@ const createHistoryProperties = (
188
220
 
189
221
  function createApplication<Model extends ILlmSchema.Model>(props: {
190
222
  model: Model;
223
+ endpointNotFound: string;
224
+ dict: HashMap<AutoBeOpenApi.IEndpoint, AutoBeOpenApi.IOperation>;
191
225
  build: (next: IAutoBeTestScenarioApplication.IProps) => void;
192
226
  }): IAgenticaController.IClass<Model> {
193
227
  assertSchemaModel(props.model);
@@ -201,55 +235,53 @@ function createApplication<Model extends ILlmSchema.Model>(props: {
201
235
  typia.validate<IAutoBeTestScenarioApplication.IProps>(next);
202
236
  if (result.success === false) return result;
203
237
 
204
- const errors: IValidation.IError[] = [];
205
- result.data.scenarioGroups.forEach((pg, i, arr) => {
206
- arr.forEach((target, j) => {
207
- if (
208
- i !== j &&
209
- target.endpoint.method === pg.endpoint.method &&
210
- target.endpoint.path === pg.endpoint.path
211
- ) {
212
- if (
213
- !errors.some(
214
- (el) =>
215
- el.path !== `planGroups[${j}].path` &&
216
- el.value !== target.endpoint.path,
217
- )
218
- ) {
219
- errors.push({
220
- path: `planGroups[${j}].path`,
221
- expected: `planGroup's {method + path} cannot duplicated.`,
222
- value: target.endpoint.path,
223
- });
224
- }
238
+ // merge to unique scenario groups
239
+ const scenarioGroups: IAutoBeTestScenarioApplication.IScenarioGroup[] = [];
240
+ result.data.scenarioGroups.forEach((sg) => {
241
+ const created = scenarioGroups.find(
242
+ (el) =>
243
+ el.endpoint.method === sg.endpoint.method &&
244
+ el.endpoint.path === sg.endpoint.path,
245
+ );
246
+ if (created) {
247
+ created.scenarios.push(...sg.scenarios);
248
+ } else {
249
+ scenarioGroups.push(sg);
250
+ }
251
+ });
225
252
 
226
- if (
227
- !errors.some(
228
- (el) =>
229
- el.path !== `planGroups[${j}].method` &&
230
- el.value !== target.endpoint.method,
231
- )
232
- ) {
253
+ // validate endpoints
254
+ const errors: IValidation.IError[] = [];
255
+ scenarioGroups.forEach((group, i) => {
256
+ if (props.dict.has(group.endpoint) === false)
257
+ errors.push({
258
+ value: group.endpoint,
259
+ path: `$input.scenarioGroups[${i}].endpoint`,
260
+ expected: "AutoBeOpenApi.IEndpoint",
261
+ description: props.endpointNotFound,
262
+ });
263
+ group.scenarios.forEach((s, j) => {
264
+ s.dependencies.forEach((dep, k) => {
265
+ if (props.dict.has(dep.endpoint) === false)
233
266
  errors.push({
234
- path: `planGroups[${j}].method`,
235
- expected: `planGroup's {method + path} cannot duplicated.`,
236
- value: target.endpoint.method,
267
+ value: dep.endpoint,
268
+ path: `$input.scenarioGroups[${i}].scenarios[${j}].dependencies[${k}].endpoint`,
269
+ expected: "AutoBeOpenApi.IEndpoint",
270
+ description: props.endpointNotFound,
237
271
  });
238
- }
239
- }
272
+ });
240
273
  });
241
274
  });
242
-
243
- if (errors.length !== 0) {
244
- console.log(JSON.stringify(errors, null, 2), "errors");
245
- return {
246
- success: false,
247
- errors,
248
- data: next,
249
- };
250
- }
251
-
252
- return result;
275
+ return errors.length === 0
276
+ ? {
277
+ success: true,
278
+ data: scenarioGroups,
279
+ }
280
+ : {
281
+ success: false,
282
+ data: scenarioGroups,
283
+ errors,
284
+ };
253
285
  };
254
286
  return {
255
287
  protocol: "class",
@@ -280,5 +312,4 @@ const collection = {
280
312
  llama: claude,
281
313
  deepseek: claude,
282
314
  "3.1": claude,
283
- "3.0": typia.llm.application<IAutoBeTestScenarioApplication, "3.0">(),
284
315
  };
@@ -7,40 +7,54 @@ import typia from "typia";
7
7
  import { AutoBeContext } from "../../context/AutoBeContext";
8
8
  import { assertSchemaModel } from "../../context/assertSchemaModel";
9
9
  import { enforceToolCall } from "../../utils/enforceToolCall";
10
- import { compileTestScenario } from "./compileTestScenario";
10
+ import { forceRetry } from "../../utils/forceRetry";
11
+ import { completeTestCode } from "./compile/completeTestCode";
12
+ import { getTestScenarioArtifacts } from "./compile/getTestScenarioArtifacts";
11
13
  import { IAutoBeTestScenarioArtifacts } from "./structures/IAutoBeTestScenarioArtifacts";
14
+ import { IAutoBeTestWriteApplication } from "./structures/IAutoBeTestWriteApplication";
15
+ import { IAutoBeTestWriteResult } from "./structures/IAutoBeTestWriteResult";
12
16
  import { transformTestWriteHistories } from "./transformTestWriteHistories";
13
17
 
14
18
  export async function orchestrateTestWrite<Model extends ILlmSchema.Model>(
15
19
  ctx: AutoBeContext<Model>,
16
20
  scenarios: AutoBeTestScenario[],
17
- ): Promise<AutoBeTestWriteEvent[]> {
21
+ ): Promise<IAutoBeTestWriteResult[]> {
18
22
  const start: Date = new Date();
19
23
  let complete: number = 0;
20
24
 
21
- const events: AutoBeTestWriteEvent[] = await Promise.all(
25
+ return Promise.all(
22
26
  /**
23
27
  * Generate test code for each scenario. Maps through plans array to create
24
28
  * individual test code implementations. Each scenario is processed to
25
29
  * generate corresponding test code and progress events.
26
30
  */
27
- scenarios.map(async (scenario) => {
28
- const code: ICreateTestCodeProps = await process(ctx, scenario);
29
- const event: AutoBeTestWriteEvent = {
30
- type: "testWrite",
31
- created_at: start.toISOString(),
32
- filename: `test/features/api/${code.domain}/${scenario.functionName}.ts`,
33
- content: code.content,
34
- completed: ++complete,
35
- total: scenarios.length,
36
- step: ctx.state().interface?.step ?? 0,
37
- };
38
- ctx.dispatch(event);
39
- return event;
40
- }),
31
+ scenarios.map((scenario) =>
32
+ forceRetry(async () => {
33
+ const artifacts: IAutoBeTestScenarioArtifacts =
34
+ await getTestScenarioArtifacts(ctx, scenario);
35
+ const result: IAutoBeTestWriteApplication.IProps = await process(
36
+ ctx,
37
+ scenario,
38
+ artifacts,
39
+ );
40
+ const event: AutoBeTestWriteEvent = {
41
+ type: "testWrite",
42
+ created_at: start.toISOString(),
43
+ location: `test/features/api/${result.domain}/${scenario.functionName}.ts`,
44
+ ...result,
45
+ completed: ++complete,
46
+ total: scenarios.length,
47
+ step: ctx.state().interface?.step ?? 0,
48
+ };
49
+ ctx.dispatch(event);
50
+ return {
51
+ scenario,
52
+ artifacts,
53
+ event,
54
+ };
55
+ }),
56
+ ),
41
57
  );
42
-
43
- return events;
44
58
  }
45
59
 
46
60
  /**
@@ -50,80 +64,49 @@ export async function orchestrateTestWrite<Model extends ILlmSchema.Model>(
50
64
  *
51
65
  * @param ctx - The AutoBeContext containing model, vendor and configuration
52
66
  * @param scenario - The test scenario information to generate code for
53
- * @returns Promise resolving to ICreateTestCodeProps containing the generated
54
- * test code
67
+ * @param artifacts - The artifacts containing the reference files and schemas
68
+ * @returns Promise resolving to IAutoBeTestWriteApplication.IProps containing
69
+ * the generated test code
55
70
  */
56
71
  async function process<Model extends ILlmSchema.Model>(
57
72
  ctx: AutoBeContext<Model>,
58
73
  scenario: AutoBeTestScenario,
59
- ): Promise<ICreateTestCodeProps> {
60
- const pointer: IPointer<ICreateTestCodeProps | null> = {
74
+ artifacts: IAutoBeTestScenarioArtifacts,
75
+ ): Promise<IAutoBeTestWriteApplication.IProps> {
76
+ const pointer: IPointer<IAutoBeTestWriteApplication.IProps | null> = {
61
77
  value: null,
62
78
  };
63
- const artifacts: IAutoBeTestScenarioArtifacts = await compileTestScenario(
64
- ctx,
65
- scenario,
66
- );
67
-
68
- const agentica = new MicroAgentica({
79
+ const agentica: MicroAgentica<Model> = new MicroAgentica({
69
80
  model: ctx.model,
70
81
  vendor: ctx.vendor,
71
82
  config: {
72
83
  ...(ctx.config ?? {}),
73
84
  },
74
- histories: transformTestWriteHistories({
75
- scenario,
76
- artifacts,
77
- }),
85
+ histories: transformTestWriteHistories(scenario, artifacts),
78
86
  controllers: [
79
87
  createApplication({
80
88
  model: ctx.model,
89
+ artifacts,
81
90
  build: (next) => {
82
91
  pointer.value = next;
83
92
  },
84
93
  }),
85
94
  ],
86
- tokenUsage: ctx.usage(),
87
95
  });
88
96
  enforceToolCall(agentica);
89
97
 
90
- await agentica.conversate("Create e2e test functions.");
98
+ await agentica.conversate("Create e2e test functions.").finally(() => {
99
+ const tokenUsage = agentica.getTokenUsage();
100
+ ctx.usage().record(tokenUsage, ["test"]);
101
+ });
91
102
  if (pointer.value === null) throw new Error("Failed to create test code.");
92
-
93
- const typeReferences: string[] = Array.from(
94
- new Set(
95
- Object.keys(artifacts.document.components.schemas).map(
96
- (key) => key.split(".")[0]!,
97
- ),
98
- ),
99
- );
100
- pointer.value.content = pointer.value.content
101
- .replace(/^[ \t]*import\b[\s\S]*?;[ \t]*$/gm, "")
102
- .trim();
103
- pointer.value.content = [
104
- `import { TestValidator } from "@nestia/e2e";`,
105
- `import typia, { tags } from "typia";`,
106
- "",
107
- `import api from "@ORGANIZATION/PROJECT-api";`,
108
- ...typeReferences.map(
109
- (ref) =>
110
- `import type { ${ref} } from "@ORGANIZATION/PROJECT-api/lib/structures/${ref}";`,
111
- ),
112
- "",
113
- pointer.value.content,
114
- ].join("\n");
115
-
116
- pointer.value.content = pointer.value.content.replaceAll(
117
- 'string & Format<"uuid">',
118
- 'string & tags.Format<"uuid">',
119
- );
120
-
121
103
  return pointer.value;
122
104
  }
123
105
 
124
106
  function createApplication<Model extends ILlmSchema.Model>(props: {
125
107
  model: Model;
126
- build: (next: ICreateTestCodeProps) => void;
108
+ artifacts: IAutoBeTestScenarioArtifacts;
109
+ build: (next: IAutoBeTestWriteApplication.IProps) => void;
127
110
  }): IAgenticaController.IClass<Model> {
128
111
  assertSchemaModel(props.model);
129
112
 
@@ -135,15 +118,17 @@ function createApplication<Model extends ILlmSchema.Model>(props: {
135
118
  name: "Create Test Code",
136
119
  application,
137
120
  execute: {
138
- createTestCode: (next) => {
121
+ write: (next) => {
122
+ next.draft = completeTestCode(props.artifacts, next.draft);
123
+ next.final = completeTestCode(props.artifacts, next.final);
139
124
  props.build(next);
140
125
  },
141
- } satisfies IApplication,
126
+ } satisfies IAutoBeTestWriteApplication,
142
127
  };
143
128
  }
144
129
 
145
130
  const claude = typia.llm.application<
146
- IApplication,
131
+ IAutoBeTestWriteApplication,
147
132
  "claude",
148
133
  {
149
134
  reference: true;
@@ -151,7 +136,7 @@ const claude = typia.llm.application<
151
136
  >();
152
137
  const collection = {
153
138
  chatgpt: typia.llm.application<
154
- IApplication,
139
+ IAutoBeTestWriteApplication,
155
140
  "chatgpt",
156
141
  { reference: true }
157
142
  >(),
@@ -159,116 +144,5 @@ const collection = {
159
144
  llama: claude,
160
145
  deepseek: claude,
161
146
  "3.1": claude,
162
- "3.0": typia.llm.application<IApplication, "3.0">(),
147
+ "3.0": typia.llm.application<IAutoBeTestWriteApplication, "3.0">(),
163
148
  };
164
-
165
- interface IApplication {
166
- createTestCode(props: ICreateTestCodeProps): void;
167
- }
168
-
169
- interface ICreateTestCodeProps {
170
- /**
171
- * Strategic approach for test implementation.
172
- *
173
- * Define the high-level strategy and logical flow for testing the given
174
- * scenario. Focus on test methodology, data preparation, and assertion
175
- * strategy.
176
- *
177
- * ### Critical Requirements
178
- *
179
- * - Must follow the Test Generation Guidelines.
180
- * - Must Planning the test code Never occur the TypeScript compile error.
181
- * - NEVER include import statements in planning or implementation.
182
- *
183
- * ### Planning Elements:
184
- *
185
- * #### Test Methodology
186
- *
187
- * - Identify test scenario type (CRUD operation, authentication flow,
188
- * validation test)
189
- * - Define test data requirements and preparation strategy
190
- * - Plan positive/negative test cases and edge cases
191
- * - Design assertion logic and validation points
192
- *
193
- * #### Execution Strategy
194
- *
195
- * - Outline step-by-step test execution flow
196
- * - Plan error handling and exception plans
197
- * - Define cleanup and teardown procedures
198
- * - Identify dependencies and prerequisites
199
- *
200
- * ### Example Plan:
201
- *
202
- * Test Strategy: Article Creation Validation
203
- * 1. Prepare valid article data with required fields
204
- * 2. Execute POST request to create article
205
- * 3. Validate response structure and data integrity
206
- * 4. Test error plans (missing fields, invalid data)
207
- * 5. Verify database state changes
208
- * 6. Reconsider the scenario if it doesn't follow the Test Generation
209
- * Guidelines.
210
- */
211
- scenario: string;
212
-
213
- /**
214
- * Functional domain classification for test organization.
215
- *
216
- * Determines file structure and test categorization based on API
217
- * functionality. Used for organizing tests into logical groups and directory
218
- * hierarchies.
219
- *
220
- * ### Naming Rules:
221
- *
222
- * - Lowercase English words only
223
- * - Singular nouns (e.g., "article", "user", "comment")
224
- * - Kebab-case for compound words (e.g., "user-profile", "payment-method")
225
- * - Match primary API resource being tested
226
- * - Domain Name must be named only one word.
227
- *
228
- * ### Domain Examples:
229
- *
230
- * - `article` → Article management operations
231
- * - `comment` → Comment-related functionality
232
- * - `auth` → Authentication and authorization
233
- * - `user` → User management operations
234
- * - `payment` → Payment processing
235
- * - `notification` → Notification system
236
- */
237
- domain: string;
238
-
239
- /**
240
- * Complete TypeScript E2E test implementation.
241
- *
242
- * Generate fully functional, compilation-error-free test code following
243
- *
244
- * @nestia/e2e framework conventions and TypeScript best practices.
245
- *
246
- * ### Technical Implementation Requirements:
247
- *
248
- * #### NO IMPORT DECLARATIONS
249
- * - NEVER write any import statements
250
- * - Start code directly with `export async function`
251
- * - All dependencies assumed globally available:
252
- * - `api` for SDK functions
253
- * - `typia` for validation and random data
254
- * - All DTO types (ITargetType, etc.)
255
- * - `TestValidator` for assertions
256
- *
257
- * #### Code Quality Standards
258
- * - Zero TypeScript compilation errors (mandatory)
259
- * - Explicit type annotations for all variables
260
- * - Proper async/await patterns throughout
261
- * - Comprehensive error handling
262
- * - Clean, readable code structure
263
- * - Consistent formatting and naming conventions
264
- *
265
- * ### Critical Error Prevention
266
- * - Verify all API function signatures and parameter types
267
- * - Ensure type compatibility between variables and assignments
268
- * - Include all required object properties and methods
269
- * - Confirm proper generic type usage
270
- * - Test async function declarations and Promise handling
271
- * - NO IMPORT STATEMENTS ANYWHERE IN CODE
272
- */
273
- content: string;
274
- }