@autobe/agent 0.9.1 → 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 (185) hide show
  1. package/lib/AutoBeAgent.js +16 -5
  2. package/lib/AutoBeAgent.js.map +1 -1
  3. package/lib/constants/AutoBeSystemPromptConstant.d.ts +6 -4
  4. package/lib/constants/AutoBeSystemPromptConstant.js.map +1 -1
  5. package/lib/context/AutoBeTokenUsage.d.ts +15 -1
  6. package/lib/context/AutoBeTokenUsage.js +56 -1
  7. package/lib/context/AutoBeTokenUsage.js.map +1 -1
  8. package/lib/context/IAutoBeApplicationProps.d.ts +0 -61
  9. package/lib/factory/createAutoBeApplication.js +298 -773
  10. package/lib/factory/createAutoBeApplication.js.map +1 -1
  11. package/lib/index.mjs +5116 -7271
  12. package/lib/index.mjs.map +1 -1
  13. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js +82 -319
  14. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js.map +1 -1
  15. package/lib/orchestrate/analyze/AutoBeAnalyzeReviewer.js +0 -1
  16. package/lib/orchestrate/analyze/AutoBeAnalyzeReviewer.js.map +1 -1
  17. package/lib/orchestrate/analyze/orchestrateAnalyze.js +97 -294
  18. package/lib/orchestrate/analyze/orchestrateAnalyze.js.map +1 -1
  19. package/lib/orchestrate/facade/transformFacadeStateMessage.js +2 -2
  20. package/lib/orchestrate/facade/transformFacadeStateMessage.js.map +1 -1
  21. package/lib/orchestrate/index.d.ts +2 -2
  22. package/lib/orchestrate/index.js +4 -4
  23. package/lib/orchestrate/index.js.map +1 -1
  24. package/lib/orchestrate/interface/orchestrateInterface.js +9 -3
  25. package/lib/orchestrate/interface/orchestrateInterface.js.map +1 -1
  26. package/lib/orchestrate/interface/orchestrateInterfaceComplement.js +56 -142
  27. package/lib/orchestrate/interface/orchestrateInterfaceComplement.js.map +1 -1
  28. package/lib/orchestrate/interface/orchestrateInterfaceComponents.js +195 -199
  29. package/lib/orchestrate/interface/orchestrateInterfaceComponents.js.map +1 -1
  30. package/lib/orchestrate/interface/orchestrateInterfaceEndpoints.js +75 -172
  31. package/lib/orchestrate/interface/orchestrateInterfaceEndpoints.js.map +1 -1
  32. package/lib/orchestrate/interface/orchestrateInterfaceOperations.js +772 -1097
  33. package/lib/orchestrate/interface/orchestrateInterfaceOperations.js.map +1 -1
  34. package/lib/orchestrate/interface/transformInterfaceHistories.js +2 -0
  35. package/lib/orchestrate/interface/transformInterfaceHistories.js.map +1 -1
  36. package/lib/orchestrate/prisma/orchestratePrismaComponent.js +64 -175
  37. package/lib/orchestrate/prisma/orchestratePrismaComponent.js.map +1 -1
  38. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js +552 -1073
  39. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js.map +1 -1
  40. package/lib/orchestrate/prisma/orchestratePrismaSchema.js +571 -1119
  41. package/lib/orchestrate/prisma/orchestratePrismaSchema.js.map +1 -1
  42. package/lib/orchestrate/prisma/transformPrismaComponentsHistories.js +9 -0
  43. package/lib/orchestrate/prisma/transformPrismaComponentsHistories.js.map +1 -1
  44. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.js +8 -0
  45. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.js.map +1 -1
  46. package/lib/orchestrate/realize/orchestrateRealize.d.ts +11 -0
  47. package/lib/orchestrate/realize/orchestrateRealize.js +109 -0
  48. package/lib/orchestrate/realize/orchestrateRealize.js.map +1 -0
  49. package/lib/orchestrate/realize/orchestrateRealizeCoder.d.ts +25 -0
  50. package/lib/orchestrate/realize/orchestrateRealizeCoder.js +337 -0
  51. package/lib/orchestrate/realize/orchestrateRealizeCoder.js.map +1 -0
  52. package/lib/orchestrate/realize/orchestrateRealizeIntegrator.d.ts +52 -0
  53. package/lib/orchestrate/realize/orchestrateRealizeIntegrator.js +57 -0
  54. package/lib/orchestrate/realize/orchestrateRealizeIntegrator.js.map +1 -0
  55. package/lib/orchestrate/realize/orchestrateRealizePlanner.d.ts +80 -0
  56. package/lib/orchestrate/realize/orchestrateRealizePlanner.js +53 -0
  57. package/lib/orchestrate/realize/orchestrateRealizePlanner.js.map +1 -0
  58. package/lib/orchestrate/realize/orchestrateRealizeValidator.d.ts +46 -0
  59. package/lib/orchestrate/realize/orchestrateRealizeValidator.js +37 -0
  60. package/lib/orchestrate/realize/orchestrateRealizeValidator.js.map +1 -0
  61. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.d.ts +33 -0
  62. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.js +3 -0
  63. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.js.map +1 -0
  64. package/lib/orchestrate/realize/transformRealizeCoderHistories.d.ts +5 -0
  65. package/lib/orchestrate/realize/transformRealizeCoderHistories.js +127 -0
  66. package/lib/orchestrate/realize/transformRealizeCoderHistories.js.map +1 -0
  67. package/lib/orchestrate/test/compile/completeTestCode.d.ts +2 -0
  68. package/lib/orchestrate/test/compile/completeTestCode.js +21 -0
  69. package/lib/orchestrate/test/compile/completeTestCode.js.map +1 -0
  70. package/lib/orchestrate/test/{filterTestFileName.js → compile/filterTestFileName.js} +1 -1
  71. package/lib/orchestrate/test/compile/filterTestFileName.js.map +1 -0
  72. package/lib/orchestrate/test/compile/getTestExternalDeclarations.d.ts +3 -0
  73. package/lib/orchestrate/test/compile/getTestExternalDeclarations.js +27 -0
  74. package/lib/orchestrate/test/compile/getTestExternalDeclarations.js.map +1 -0
  75. package/lib/orchestrate/test/compile/getTestScenarioArtifacts.d.ts +5 -0
  76. package/lib/orchestrate/test/{compileTestScenario.js → compile/getTestScenarioArtifacts.js} +11 -5
  77. package/lib/orchestrate/test/compile/getTestScenarioArtifacts.js.map +1 -0
  78. package/lib/orchestrate/test/orchestrateTest.js +14 -9
  79. package/lib/orchestrate/test/orchestrateTest.js.map +1 -1
  80. package/lib/orchestrate/test/orchestrateTestCorrect.d.ts +3 -2
  81. package/lib/orchestrate/test/orchestrateTestCorrect.js +150 -349
  82. package/lib/orchestrate/test/orchestrateTestCorrect.js.map +1 -1
  83. package/lib/orchestrate/test/orchestrateTestScenario.js +323 -566
  84. package/lib/orchestrate/test/orchestrateTestScenario.js.map +1 -1
  85. package/lib/orchestrate/test/orchestrateTestWrite.d.ts +3 -2
  86. package/lib/orchestrate/test/orchestrateTestWrite.js +139 -76
  87. package/lib/orchestrate/test/orchestrateTestWrite.js.map +1 -1
  88. package/lib/orchestrate/test/structures/IAutoBeTestCorrectApplication.d.ts +121 -0
  89. package/lib/orchestrate/test/structures/IAutoBeTestCorrectApplication.js +3 -0
  90. package/lib/orchestrate/test/structures/IAutoBeTestCorrectApplication.js.map +1 -0
  91. package/lib/orchestrate/test/structures/IAutoBeTestFunction.d.ts +8 -0
  92. package/lib/{utils/types/BackoffOptions.js → orchestrate/test/structures/IAutoBeTestFunction.js} +1 -1
  93. package/lib/orchestrate/test/structures/IAutoBeTestFunction.js.map +1 -0
  94. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.d.ts +32 -22
  95. package/lib/orchestrate/test/structures/IAutoBeTestScenarioArtifacts.d.ts +2 -0
  96. package/lib/orchestrate/test/structures/IAutoBeTestWriteApplication.d.ts +112 -0
  97. package/lib/orchestrate/test/structures/IAutoBeTestWriteApplication.js +3 -0
  98. package/lib/orchestrate/test/structures/IAutoBeTestWriteApplication.js.map +1 -0
  99. package/lib/orchestrate/test/structures/IAutoBeTestWriteResult.d.ts +7 -0
  100. package/lib/orchestrate/test/structures/IAutoBeTestWriteResult.js +3 -0
  101. package/lib/orchestrate/test/structures/IAutoBeTestWriteResult.js.map +1 -0
  102. package/lib/orchestrate/test/transformTestCorrectHistories.d.ts +3 -2
  103. package/lib/orchestrate/test/transformTestCorrectHistories.js +28 -41
  104. package/lib/orchestrate/test/transformTestCorrectHistories.js.map +1 -1
  105. package/lib/orchestrate/test/transformTestWriteHistories.d.ts +5 -4
  106. package/lib/orchestrate/test/transformTestWriteHistories.js +169 -32
  107. package/lib/orchestrate/test/transformTestWriteHistories.js.map +1 -1
  108. package/lib/structures/IAutoBeConfig.d.ts +11 -0
  109. package/lib/structures/IAutoBeProps.d.ts +12 -1
  110. package/lib/utils/backoffRetry.d.ts +4 -7
  111. package/lib/utils/backoffRetry.js +19 -37
  112. package/lib/utils/backoffRetry.js.map +1 -1
  113. package/lib/utils/forceRetry.d.ts +1 -0
  114. package/lib/{orchestrate/orchestrateRealize.js → utils/forceRetry.js} +15 -8
  115. package/lib/utils/forceRetry.js.map +1 -0
  116. package/package.json +8 -8
  117. package/src/AutoBeAgent.ts +26 -4
  118. package/src/constants/AutoBeSystemPromptConstant.ts +6 -4
  119. package/src/context/AutoBeTokenUsage.ts +85 -1
  120. package/src/context/IAutoBeApplicationProps.ts +0 -62
  121. package/src/factory/createAutoBeApplication.ts +2 -3
  122. package/src/orchestrate/analyze/AutoBeAnalyzeAgent.ts +8 -3
  123. package/src/orchestrate/analyze/AutoBeAnalyzeReviewer.ts +0 -1
  124. package/src/orchestrate/analyze/orchestrateAnalyze.ts +8 -37
  125. package/src/orchestrate/facade/transformFacadeStateMessage.ts +2 -1
  126. package/src/orchestrate/index.ts +2 -2
  127. package/src/orchestrate/interface/orchestrateInterface.ts +7 -0
  128. package/src/orchestrate/interface/orchestrateInterfaceComplement.ts +4 -3
  129. package/src/orchestrate/interface/orchestrateInterfaceComponents.ts +26 -23
  130. package/src/orchestrate/interface/orchestrateInterfaceEndpoints.ts +6 -4
  131. package/src/orchestrate/interface/orchestrateInterfaceOperations.ts +14 -11
  132. package/src/orchestrate/interface/transformInterfaceHistories.ts +2 -0
  133. package/src/orchestrate/prisma/orchestratePrismaComponent.ts +10 -5
  134. package/src/orchestrate/prisma/orchestratePrismaCorrect.ts +11 -5
  135. package/src/orchestrate/prisma/orchestratePrismaSchema.ts +16 -8
  136. package/src/orchestrate/prisma/transformPrismaComponentsHistories.ts +9 -0
  137. package/src/orchestrate/prisma/transformPrismaSchemaHistories.ts +8 -0
  138. package/src/orchestrate/realize/orchestrateRealize.ts +169 -0
  139. package/src/orchestrate/realize/orchestrateRealizeCoder.ts +156 -0
  140. package/src/orchestrate/realize/orchestrateRealizeIntegrator.ts +75 -0
  141. package/src/orchestrate/realize/orchestrateRealizePlanner.ts +115 -0
  142. package/src/orchestrate/realize/orchestrateRealizeValidator.ts +64 -0
  143. package/src/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.ts +36 -0
  144. package/src/orchestrate/realize/transformRealizeCoderHistories.ts +136 -0
  145. package/src/orchestrate/test/compile/completeTestCode.ts +35 -0
  146. package/src/orchestrate/test/{filterTestFileName.ts → compile/filterTestFileName.ts} +1 -1
  147. package/src/orchestrate/test/compile/getTestExternalDeclarations.ts +24 -0
  148. package/src/orchestrate/test/{compileTestScenario.ts → compile/getTestScenarioArtifacts.ts} +17 -8
  149. package/src/orchestrate/test/experimental/orchestrateTestCorrect.ast +240 -0
  150. package/src/orchestrate/test/experimental/orchestrateTestWrite.ast +316 -0
  151. package/src/orchestrate/test/experimental/transformTestCorrectHistories.ast +52 -0
  152. package/src/orchestrate/test/orchestrateTest.ts +38 -16
  153. package/src/orchestrate/test/orchestrateTestCorrect.ts +111 -338
  154. package/src/orchestrate/test/orchestrateTestScenario.ts +114 -69
  155. package/src/orchestrate/test/orchestrateTestWrite.ts +55 -153
  156. package/src/orchestrate/test/structures/IAutoBeTestCorrectApplication.ts +126 -0
  157. package/src/orchestrate/test/structures/IAutoBeTestFunction.ts +10 -0
  158. package/src/orchestrate/test/structures/IAutoBeTestScenarioApplication.ts +32 -22
  159. package/src/orchestrate/test/structures/IAutoBeTestScenarioArtifacts.ts +3 -0
  160. package/src/orchestrate/test/structures/IAutoBeTestWriteApplication.ts +117 -0
  161. package/src/orchestrate/test/structures/IAutoBeTestWriteResult.ts +9 -0
  162. package/src/orchestrate/test/transformTestCorrectHistories.ts +38 -43
  163. package/src/orchestrate/test/transformTestWriteHistories.ts +89 -35
  164. package/src/structures/IAutoBeConfig.ts +9 -0
  165. package/src/structures/IAutoBeProps.ts +17 -1
  166. package/src/utils/backoffRetry.ts +25 -36
  167. package/src/utils/forceRetry.ts +13 -0
  168. package/lib/factory/invertOpenApiDocument.d.ts +0 -3
  169. package/lib/factory/invertOpenApiDocument.js +0 -51
  170. package/lib/factory/invertOpenApiDocument.js.map +0 -1
  171. package/lib/orchestrate/orchestrateRealize.d.ts +0 -5
  172. package/lib/orchestrate/orchestrateRealize.js.map +0 -1
  173. package/lib/orchestrate/test/compileTestScenario.d.ts +0 -5
  174. package/lib/orchestrate/test/compileTestScenario.js.map +0 -1
  175. package/lib/orchestrate/test/filterTestFileName.js.map +0 -1
  176. package/lib/utils/StringUtil.d.ts +0 -4
  177. package/lib/utils/StringUtil.js +0 -43
  178. package/lib/utils/StringUtil.js.map +0 -1
  179. package/lib/utils/types/BackoffOptions.d.ts +0 -12
  180. package/lib/utils/types/BackoffOptions.js.map +0 -1
  181. package/src/factory/invertOpenApiDocument.ts +0 -63
  182. package/src/orchestrate/orchestrateRealize.ts +0 -18
  183. package/src/utils/StringUtil.ts +0 -45
  184. package/src/utils/types/BackoffOptions.ts +0 -15
  185. /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: 30 });
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(
@@ -71,7 +102,7 @@ export async function orchestrateTestScenario<Model extends ILlmSchema.Model>(
71
102
  endpoint: pg.endpoint,
72
103
  draft: plan.draft,
73
104
  functionName: plan.functionName,
74
- dependencies: plan.dependsOn,
105
+ dependencies: plan.dependencies,
75
106
  } satisfies AutoBeTestScenario;
76
107
  });
77
108
  }),
@@ -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,10 +157,12 @@ 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<
164
+ IAgenticaHistoryJson.IAssistantMessage | IAgenticaHistoryJson.ISystemMessage
165
+ > => [
127
166
  {
128
167
  id: v4(),
129
168
  created_at: new Date().toISOString(),
@@ -135,17 +174,24 @@ const createHistoryProperties = (
135
174
  created_at: new Date().toISOString(),
136
175
  type: "systemMessage",
137
176
  text: [
177
+ "# Operations",
138
178
  "Below are the full operations. Please refer to this.",
139
179
  "Your role is to draft all test cases for each given Operation.",
140
180
  "It is also permissible to write multiple test codes on a single endpoint.",
141
181
  "However, rather than meaningless tests, business logic tests should be written and an E2E test situation should be assumed.",
142
182
  "",
183
+ "Please carefully analyze each operation to identify all dependencies required for testing.",
184
+ "For example, if you want to test liking and then deleting a post,",
185
+ "you might think to test post creation, liking, and unlike operations.",
186
+ "However, even if not explicitly mentioned, user registration and login are essential prerequisites.",
187
+ "Pay close attention to IDs and related values in the API,",
188
+ "and ensure you identify all dependencies between endpoints.",
189
+ "",
143
190
  "```json",
144
191
  JSON.stringify(
145
- operations.map((el) => ({
146
- path: el.path,
147
- method: el.method,
148
- summary: el.summary,
192
+ entire.map((el) => ({
193
+ ...el,
194
+ specification: undefined,
149
195
  })),
150
196
  ),
151
197
  "```",
@@ -174,6 +220,8 @@ const createHistoryProperties = (
174
220
 
175
221
  function createApplication<Model extends ILlmSchema.Model>(props: {
176
222
  model: Model;
223
+ endpointNotFound: string;
224
+ dict: HashMap<AutoBeOpenApi.IEndpoint, AutoBeOpenApi.IOperation>;
177
225
  build: (next: IAutoBeTestScenarioApplication.IProps) => void;
178
226
  }): IAgenticaController.IClass<Model> {
179
227
  assertSchemaModel(props.model);
@@ -187,55 +235,53 @@ function createApplication<Model extends ILlmSchema.Model>(props: {
187
235
  typia.validate<IAutoBeTestScenarioApplication.IProps>(next);
188
236
  if (result.success === false) return result;
189
237
 
190
- const errors: IValidation.IError[] = [];
191
- result.data.scenarioGroups.forEach((pg, i, arr) => {
192
- arr.forEach((target, j) => {
193
- if (
194
- i !== j &&
195
- target.endpoint.method === pg.endpoint.method &&
196
- target.endpoint.path === pg.endpoint.path
197
- ) {
198
- if (
199
- !errors.some(
200
- (el) =>
201
- el.path !== `planGroups[${j}].path` &&
202
- el.value !== target.endpoint.path,
203
- )
204
- ) {
205
- errors.push({
206
- path: `planGroups[${j}].path`,
207
- expected: `planGroup's {method + path} cannot duplicated.`,
208
- value: target.endpoint.path,
209
- });
210
- }
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
+ });
211
252
 
212
- if (
213
- !errors.some(
214
- (el) =>
215
- el.path !== `planGroups[${j}].method` &&
216
- el.value !== target.endpoint.method,
217
- )
218
- ) {
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)
219
266
  errors.push({
220
- path: `planGroups[${j}].method`,
221
- expected: `planGroup's {method + path} cannot duplicated.`,
222
- 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,
223
271
  });
224
- }
225
- }
272
+ });
226
273
  });
227
274
  });
228
-
229
- if (errors.length !== 0) {
230
- console.log(JSON.stringify(errors, null, 2), "errors");
231
- return {
232
- success: false,
233
- errors,
234
- data: next,
235
- };
236
- }
237
-
238
- 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
+ };
239
285
  };
240
286
  return {
241
287
  protocol: "class",
@@ -266,5 +312,4 @@ const collection = {
266
312
  llama: claude,
267
313
  deepseek: claude,
268
314
  "3.1": claude,
269
- "3.0": typia.llm.application<IAutoBeTestScenarioApplication, "3.0">(),
270
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,51 +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
103
  return pointer.value;
93
104
  }
94
105
 
95
106
  function createApplication<Model extends ILlmSchema.Model>(props: {
96
107
  model: Model;
97
- build: (next: ICreateTestCodeProps) => void;
108
+ artifacts: IAutoBeTestScenarioArtifacts;
109
+ build: (next: IAutoBeTestWriteApplication.IProps) => void;
98
110
  }): IAgenticaController.IClass<Model> {
99
111
  assertSchemaModel(props.model);
100
112
 
@@ -106,15 +118,17 @@ function createApplication<Model extends ILlmSchema.Model>(props: {
106
118
  name: "Create Test Code",
107
119
  application,
108
120
  execute: {
109
- createTestCode: (next) => {
121
+ write: (next) => {
122
+ next.draft = completeTestCode(props.artifacts, next.draft);
123
+ next.final = completeTestCode(props.artifacts, next.final);
110
124
  props.build(next);
111
125
  },
112
- } satisfies IApplication,
126
+ } satisfies IAutoBeTestWriteApplication,
113
127
  };
114
128
  }
115
129
 
116
130
  const claude = typia.llm.application<
117
- IApplication,
131
+ IAutoBeTestWriteApplication,
118
132
  "claude",
119
133
  {
120
134
  reference: true;
@@ -122,7 +136,7 @@ const claude = typia.llm.application<
122
136
  >();
123
137
  const collection = {
124
138
  chatgpt: typia.llm.application<
125
- IApplication,
139
+ IAutoBeTestWriteApplication,
126
140
  "chatgpt",
127
141
  { reference: true }
128
142
  >(),
@@ -130,117 +144,5 @@ const collection = {
130
144
  llama: claude,
131
145
  deepseek: claude,
132
146
  "3.1": claude,
133
- "3.0": typia.llm.application<IApplication, "3.0">(),
147
+ "3.0": typia.llm.application<IAutoBeTestWriteApplication, "3.0">(),
134
148
  };
135
-
136
- interface IApplication {
137
- createTestCode(props: ICreateTestCodeProps): void;
138
- }
139
-
140
- interface ICreateTestCodeProps {
141
- /**
142
- * Strategic approach for test implementation.
143
- *
144
- * Define the high-level strategy and logical flow for testing the given
145
- * scenario. Focus on test methodology, data preparation, and assertion
146
- * strategy.
147
- *
148
- * ### Critical Requirements
149
- *
150
- * - Must follow the Test Generation Guildelines.
151
- * - Must Planning the test code Never occur the typescript compile error.
152
- *
153
- * ### Planning Elements:
154
- *
155
- * #### Test Methodology
156
- *
157
- * - Identify test scenario type (CRUD operation, authentication flow,
158
- * validation test)
159
- * - Define test data requirements and preparation strategy
160
- * - Plan positive/negative test cases and edge cases
161
- * - Design assertion logic and validation points
162
- *
163
- * #### Execution Strategy
164
- *
165
- * - Outline step-by-step test execution flow
166
- * - Plan error handling and exception plans
167
- * - Define cleanup and teardown procedures
168
- * - Identify dependencies and prerequisites
169
- *
170
- * ### Example Plan:
171
- *
172
- * Test Strategy: Article Creation Validation
173
- * 1. Prepare valid article data with required fields
174
- * 2. Execute POST request to create article
175
- * 3. Validate response structure and data integrity
176
- * 4. Test error plans (missing fields, invalid data)
177
- * 5. Verify database state changes
178
- * 6. Reconsider the scenario if it doesn't follow the Test Generation
179
- * Guildelines.
180
- */
181
- scenario: string;
182
-
183
- /**
184
- * Functional domain classification for test organization.
185
- *
186
- * Determines file structure and test categorization based on API
187
- * functionality. Used for organizing tests into logical groups and directory
188
- * hierarchies.
189
- *
190
- * ### Naming Rules:
191
- *
192
- * - Lowercase English words only
193
- * - Singular nouns (e.g., "article", "user", "comment")
194
- * - Kebab-case for compound words (e.g., "user-profile", "payment-method")
195
- * - Match primary API resource being tested
196
- * - Domain Name must be named only one word.
197
- *
198
- * ### Domain Examples:
199
- *
200
- * - `article` → Article management operations
201
- * - `comment` → Comment-related functionality
202
- * - `auth` → Authentication and authorization
203
- * - `user` → User management operations
204
- * - `payment` → Payment processing
205
- * - `notification` → Notification system
206
- */
207
- domain: string;
208
-
209
- /**
210
- * Complete TypeScript E2E test implementation.
211
- *
212
- * Generate fully functional, compilation-error-free test code following
213
- *
214
- * @nestia/e2e framework conventions and TypeScript best practices.
215
- *
216
- * ### Technical Implementation Requirements:
217
- *
218
- * #### Import Declarations
219
- * ```typescript
220
- * import api from "@ORGANIZATION/PROJECT-api";
221
- * import { ITargetType } from "@ORGANIZATION/PROJECT-api/lib/structures/[path]";
222
- * import { TestValidator } from "@nestia/e2e";
223
- * import typia from "typia";
224
- * ```
225
- * - Must use exact `@ORGANIZATION/PROJECT-api` module path
226
- * - Include `@ORGANIZATION` prefix in all API-related imports
227
- * - Import specific DTO types from correct structure paths
228
- *
229
- * #### Code Quality Standards
230
- * - Zero TypeScript compilation errors (mandatory)
231
- * - Explicit type annotations for all variables
232
- * - Proper async/await patterns throughout
233
- * - Comprehensive error handling
234
- * - Clean, readable code structure
235
- * - Consistent formatting and naming conventions
236
- *
237
- * ### Critical Error Prevention
238
- * - Verify all import paths are correct and accessible
239
- * - Ensure type compatibility between variables and assignments
240
- * - Include all required object properties and methods
241
- * - Validate API function signatures and parameter types
242
- * - Confirm proper generic type usage
243
- * - Test async function declarations and Promise handling
244
- */
245
- content: string;
246
- }