@autobe/agent 0.8.0 → 0.9.1

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 (91) hide show
  1. package/lib/AutoBeAgent.d.ts +183 -12
  2. package/lib/AutoBeAgent.js +247 -65
  3. package/lib/AutoBeAgent.js.map +1 -1
  4. package/lib/constants/AutoBeSystemPromptConstant.d.ts +4 -3
  5. package/lib/constants/AutoBeSystemPromptConstant.js.map +1 -1
  6. package/lib/context/AutoBeContext.d.ts +2 -2
  7. package/lib/factory/index.d.ts +0 -1
  8. package/lib/factory/index.js +0 -1
  9. package/lib/factory/index.js.map +1 -1
  10. package/lib/index.mjs +1195 -834
  11. package/lib/index.mjs.map +1 -1
  12. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js +1 -1
  13. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js.map +1 -1
  14. package/lib/orchestrate/interface/orchestrateInterface.js +1 -1
  15. package/lib/orchestrate/interface/orchestrateInterface.js.map +1 -1
  16. package/lib/orchestrate/prisma/orchestratePrisma.js +1 -1
  17. package/lib/orchestrate/prisma/orchestratePrisma.js.map +1 -1
  18. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js +1 -1
  19. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js.map +1 -1
  20. package/lib/orchestrate/test/compileTestScenario.d.ts +5 -0
  21. package/lib/orchestrate/test/compileTestScenario.js +56 -0
  22. package/lib/orchestrate/test/compileTestScenario.js.map +1 -0
  23. package/lib/orchestrate/test/filterTestFileName.d.ts +1 -0
  24. package/lib/orchestrate/test/filterTestFileName.js +13 -0
  25. package/lib/orchestrate/test/filterTestFileName.js.map +1 -0
  26. package/lib/orchestrate/test/orchestrateTest.js +10 -11
  27. package/lib/orchestrate/test/orchestrateTest.js.map +1 -1
  28. package/lib/orchestrate/test/orchestrateTestCorrect.d.ts +2 -2
  29. package/lib/orchestrate/test/orchestrateTestCorrect.js +91 -73
  30. package/lib/orchestrate/test/orchestrateTestCorrect.js.map +1 -1
  31. package/lib/orchestrate/test/orchestrateTestScenario.d.ts +2 -2
  32. package/lib/orchestrate/test/orchestrateTestScenario.js +616 -237
  33. package/lib/orchestrate/test/orchestrateTestScenario.js.map +1 -1
  34. package/lib/orchestrate/test/orchestrateTestWrite.d.ts +4 -0
  35. package/lib/orchestrate/test/{orchestrateTestProgress.js → orchestrateTestWrite.js} +37 -51
  36. package/lib/orchestrate/test/orchestrateTestWrite.js.map +1 -0
  37. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.d.ts +123 -0
  38. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.js +3 -0
  39. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.js.map +1 -0
  40. package/lib/orchestrate/test/structures/IAutoBeTestScenarioArtifacts.d.ts +5 -0
  41. package/lib/orchestrate/test/structures/IAutoBeTestScenarioArtifacts.js +3 -0
  42. package/lib/orchestrate/test/structures/IAutoBeTestScenarioArtifacts.js.map +1 -0
  43. package/lib/orchestrate/test/transformTestCorrectHistories.d.ts +2 -1
  44. package/lib/orchestrate/test/transformTestCorrectHistories.js +4 -4
  45. package/lib/orchestrate/test/transformTestCorrectHistories.js.map +1 -1
  46. package/lib/orchestrate/test/transformTestScenarioHistories.d.ts +1 -2
  47. package/lib/orchestrate/test/transformTestScenarioHistories.js +1 -77
  48. package/lib/orchestrate/test/transformTestScenarioHistories.js.map +1 -1
  49. package/lib/orchestrate/test/transformTestWriteHistories.d.ts +7 -0
  50. package/lib/orchestrate/test/transformTestWriteHistories.js +47 -0
  51. package/lib/orchestrate/test/transformTestWriteHistories.js.map +1 -0
  52. package/lib/structures/IAutoBeConfig.d.ts +48 -10
  53. package/lib/structures/IAutoBeProps.d.ts +87 -0
  54. package/lib/structures/IAutoBeVendor.d.ts +64 -22
  55. package/lib/utils/backoffRetry.d.ts +7 -0
  56. package/lib/utils/backoffRetry.js +73 -0
  57. package/lib/utils/backoffRetry.js.map +1 -0
  58. package/lib/utils/types/BackoffOptions.d.ts +12 -0
  59. package/lib/utils/types/BackoffOptions.js +3 -0
  60. package/lib/utils/types/BackoffOptions.js.map +1 -0
  61. package/package.json +4 -4
  62. package/src/AutoBeAgent.ts +251 -51
  63. package/src/constants/AutoBeSystemPromptConstant.ts +4 -3
  64. package/src/context/AutoBeContext.ts +7 -2
  65. package/src/factory/index.ts +0 -1
  66. package/src/orchestrate/analyze/AutoBeAnalyzeAgent.ts +1 -1
  67. package/src/orchestrate/interface/orchestrateInterface.ts +1 -1
  68. package/src/orchestrate/prisma/orchestratePrisma.ts +1 -0
  69. package/src/orchestrate/prisma/orchestratePrismaCorrect.ts +4 -2
  70. package/src/orchestrate/test/compileTestScenario.ts +63 -0
  71. package/src/orchestrate/test/filterTestFileName.ts +9 -0
  72. package/src/orchestrate/test/orchestrateTest.ts +11 -17
  73. package/src/orchestrate/test/orchestrateTestCorrect.ts +152 -100
  74. package/src/orchestrate/test/orchestrateTestScenario.ts +195 -151
  75. package/src/orchestrate/test/{orchestrateTestProgress.ts → orchestrateTestWrite.ts} +29 -44
  76. package/src/orchestrate/test/structures/IAutoBeTestScenarioApplication.ts +132 -0
  77. package/src/orchestrate/test/structures/IAutoBeTestScenarioArtifacts.ts +5 -0
  78. package/src/orchestrate/test/transformTestCorrectHistories.ts +4 -4
  79. package/src/orchestrate/test/transformTestScenarioHistories.ts +0 -79
  80. package/src/orchestrate/test/transformTestWriteHistories.ts +53 -0
  81. package/src/structures/IAutoBeConfig.ts +48 -10
  82. package/src/structures/IAutoBeProps.ts +91 -0
  83. package/src/structures/IAutoBeVendor.ts +64 -22
  84. package/src/utils/backoffRetry.ts +84 -0
  85. package/src/utils/types/BackoffOptions.ts +15 -0
  86. package/lib/orchestrate/test/orchestrateTestProgress.d.ts +0 -4
  87. package/lib/orchestrate/test/orchestrateTestProgress.js.map +0 -1
  88. package/lib/orchestrate/test/transformTestProgressHistories.d.ts +0 -2
  89. package/lib/orchestrate/test/transformTestProgressHistories.js +0 -47
  90. package/lib/orchestrate/test/transformTestProgressHistories.js.map +0 -1
  91. package/src/orchestrate/test/transformTestProgressHistories.ts +0 -51
@@ -1,7 +1,9 @@
1
1
  import { IAgenticaController, MicroAgentica } from "@agentica/core";
2
2
  import {
3
- AutoBeTestProgressEvent,
3
+ AutoBeTestFile,
4
+ AutoBeTestScenario,
4
5
  AutoBeTestValidateEvent,
6
+ AutoBeTestWriteEvent,
5
7
  IAutoBeTypeScriptCompilerResult,
6
8
  } from "@autobe/interface";
7
9
  import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
@@ -10,49 +12,78 @@ 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 { compileTestScenario } from "./compileTestScenario";
18
+ import { filterTestFileName } from "./filterTestFileName";
19
+ import { IAutoBeTestScenarioArtifacts } from "./structures/IAutoBeTestScenarioArtifacts";
14
20
  import { transformTestCorrectHistories } from "./transformTestCorrectHistories";
15
21
 
16
22
  export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
17
23
  ctx: AutoBeContext<Model>,
18
- codes: AutoBeTestProgressEvent[],
24
+ codes: AutoBeTestWriteEvent[],
25
+ scenarios: AutoBeTestScenario[],
19
26
  life: number = 4,
20
27
  ): Promise<AutoBeTestValidateEvent> {
28
+ const files: AutoBeTestFile[] = codes.map(
29
+ ({ filename, content }, index): AutoBeTestFile => {
30
+ const scenario: AutoBeTestScenario = scenarios[index];
31
+ return { location: filename, content, scenario };
32
+ },
33
+ );
34
+
21
35
  // 1) Build map of new test files from progress events
22
- const testFiles = Object.fromEntries(
23
- codes.map(({ filename, content }) => [
24
- `test/features/api/${filename}`,
25
- content,
26
- ]),
36
+ const testFiles: Record<string, string> = Object.fromEntries(
37
+ codes.map((c) => [c.filename, c.content]),
27
38
  );
28
39
 
29
40
  // 2) Keep only files outside the test directory from current state
30
- const retainedFiles = Object.fromEntries(
31
- Object.entries(ctx.state().interface?.files ?? {}).filter(
32
- ([filename]) => !filename.startsWith("test/features/api"),
41
+ const retainedFiles: Record<string, string> = Object.fromEntries(
42
+ Object.entries(ctx.state().interface?.files ?? {}).filter(([key]) =>
43
+ filterTestFileName(key),
33
44
  ),
34
45
  );
35
46
 
36
47
  // 3) Merge and filter: keep .ts/.json, drop anything under "benchmark"
37
- const mergedFiles = { ...retainedFiles, ...testFiles };
38
- const files = Object.fromEntries(
39
- Object.entries(mergedFiles).filter(
40
- ([filename]) =>
41
- (filename.endsWith(".ts") && !filename.startsWith("test/benchmark/")) ||
42
- filename.endsWith(".json"),
43
- ),
44
- );
48
+ const external = async (
49
+ location: string,
50
+ ): Promise<Record<string, string>> => {
51
+ const content: string | undefined =
52
+ await ctx.compiler.typescript.getExternal(location);
53
+ if (content === undefined) throw new Error(`File not found: ${location}`);
54
+ return { [location]: content };
55
+ };
56
+ const mergedFiles: Record<string, string> = {
57
+ ...retainedFiles,
58
+ ...testFiles,
59
+ ...(await external("node_modules/@nestia/e2e/lib/TestValidator.d.ts")),
60
+ ...(await external("node_modules/@nestia/fetcher/lib/IConnection.d.ts")),
61
+ };
45
62
 
46
63
  // 4) Ask the LLM to correct the filtered file set
47
- const response = await step(ctx, files, life);
64
+ const response: AutoBeTestValidateEvent = await step(
65
+ ctx,
66
+ mergedFiles,
67
+ files,
68
+ life,
69
+ );
48
70
 
49
71
  // 5) Combine original + corrected files and dispatch event
50
72
  const event: AutoBeTestValidateEvent = {
51
73
  ...response,
52
74
  type: "testValidate",
53
- files: { ...mergedFiles, ...response.files },
75
+ files: [
76
+ ...Object.entries(mergedFiles).map(
77
+ ([filename, content]): AutoBeTestFile => {
78
+ return {
79
+ location: filename,
80
+ content,
81
+ };
82
+ },
83
+ ),
84
+ ...response.files,
85
+ ],
54
86
  };
55
-
56
87
  return event;
57
88
  }
58
89
 
@@ -66,27 +97,30 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
66
97
  * all generated test files are syntactically correct and compilable.
67
98
  *
68
99
  * @param ctx AutoBe context object
69
- * @param files Map of files to compile (filename: content)
100
+ * @param entireFiles Map of all files to compile (filename: content)
101
+ * @param testFiles Map of files to compile (filename: content)
70
102
  * @param life Number of remaining retry attempts
71
103
  * @returns Event object containing successful compilation result and modified
72
104
  * files
73
105
  */
74
106
  async function step<Model extends ILlmSchema.Model>(
75
107
  ctx: AutoBeContext<Model>,
76
- files: Record<string, string>,
108
+ entireFiles: Record<string, string>,
109
+ testFiles: AutoBeTestFile[],
77
110
  life: number,
78
111
  ): Promise<AutoBeTestValidateEvent> {
79
112
  // COMPILE TEST CODE
80
- const result = await ctx.compiler.typescript({
81
- files,
82
- });
113
+ const result: IAutoBeTypeScriptCompilerResult =
114
+ await ctx.compiler.typescript.compile({
115
+ files: entireFiles,
116
+ });
83
117
 
84
118
  if (result.type === "success") {
85
119
  // SUCCESS
86
120
  return {
87
121
  type: "testValidate",
88
122
  created_at: new Date().toISOString(),
89
- files,
123
+ files: testFiles,
90
124
  result,
91
125
  step: ctx.state().interface?.step ?? 0,
92
126
  };
@@ -97,11 +131,10 @@ async function step<Model extends ILlmSchema.Model>(
97
131
  ctx.dispatch({
98
132
  type: "testValidate",
99
133
  created_at: new Date().toISOString(),
100
- files,
134
+ files: testFiles,
101
135
  result,
102
136
  step: ctx.state().interface?.step ?? 0,
103
137
  });
104
-
105
138
  throw new Error(JSON.stringify(result.error, null, 2));
106
139
  }
107
140
 
@@ -127,7 +160,7 @@ async function step<Model extends ILlmSchema.Model>(
127
160
  return {
128
161
  type: "testValidate",
129
162
  created_at: new Date().toISOString(),
130
- files,
163
+ files: testFiles,
131
164
  result: {
132
165
  ...result,
133
166
  type: "success",
@@ -140,7 +173,7 @@ async function step<Model extends ILlmSchema.Model>(
140
173
  ctx.dispatch({
141
174
  type: "testValidate",
142
175
  created_at: new Date().toISOString(),
143
- files,
176
+ files: testFiles,
144
177
  result,
145
178
  step: ctx.state().interface?.step ?? 0,
146
179
  });
@@ -149,36 +182,51 @@ async function step<Model extends ILlmSchema.Model>(
149
182
  return {
150
183
  type: "testValidate",
151
184
  created_at: new Date().toISOString(),
152
- files,
185
+ files: testFiles,
153
186
  result,
154
187
  step: ctx.state().interface?.step ?? 0,
155
188
  };
156
189
 
157
190
  // VALIDATION FAILED
158
- const validate = await Promise.all(
159
- Object.entries(diagnostics).map(async ([filename, d]) => {
160
- const code = files[filename];
161
- const response = await process(ctx, d, code);
162
-
163
- ctx.dispatch({
164
- type: "testCorrect",
165
- created_at: new Date().toISOString(),
166
- files: { ...files, [filename]: response.content },
167
- result,
168
- solution: response.solution,
169
- think_without_compile_error: response.think_without_compile_error,
170
- think_again_with_compile_error: response.think_again_with_compile_error,
171
- step: ctx.state().interface?.step ?? 0,
172
- });
173
-
174
- // Return [filename, modified code]
175
- return [filename, response.content];
176
- }),
191
+ const validatedFiles: AutoBeTestFile[] = await Promise.all(
192
+ Object.entries(diagnostics).map(
193
+ async ([filename, d]): Promise<AutoBeTestFile> => {
194
+ const file = testFiles.find((f) => f.location === filename);
195
+ const code: string = file?.content!;
196
+ const scenario = file?.scenario!;
197
+
198
+ const response: ICorrectTestFunctionProps = await process(
199
+ ctx,
200
+ d,
201
+ code,
202
+ scenario,
203
+ );
204
+ ctx.dispatch({
205
+ type: "testCorrect",
206
+ created_at: new Date().toISOString(),
207
+ files: { ...testFiles, [filename]: response.content },
208
+ result,
209
+ solution: response.solution,
210
+ think_without_compile_error: response.think_without_compile_error,
211
+ think_again_with_compile_error:
212
+ response.think_again_with_compile_error,
213
+ step: ctx.state().interface?.step ?? 0,
214
+ });
215
+
216
+ return { location: filename, content: code, scenario: scenario };
217
+ },
218
+ ),
177
219
  );
178
220
 
179
- const newFiles = { ...files, ...Object.fromEntries(validate) };
180
-
181
- return step(ctx, newFiles, life - 1);
221
+ return step(
222
+ ctx,
223
+ entireFiles,
224
+ testFiles.map((f) => {
225
+ const validated = validatedFiles.find((v) => v.location === f.location);
226
+ return validated ? validated : f;
227
+ }),
228
+ life - 1,
229
+ );
182
230
  }
183
231
 
184
232
  /**
@@ -195,26 +243,15 @@ async function process<Model extends ILlmSchema.Model>(
195
243
  ctx: AutoBeContext<Model>,
196
244
  diagnostics: IAutoBeTypeScriptCompilerResult.IDiagnostic[],
197
245
  code: string,
246
+ scenario: AutoBeTestScenario,
198
247
  ): Promise<ICorrectTestFunctionProps> {
199
248
  const pointer: IPointer<ICorrectTestFunctionProps | null> = {
200
249
  value: null,
201
250
  };
202
-
203
- const apiFiles = Object.entries(ctx.state().interface?.files ?? {})
204
- .filter(([filename]) => {
205
- return filename.startsWith("src/api/");
206
- })
207
- .reduce<Record<string, string>>((acc, [filename, content]) => {
208
- return Object.assign(acc, { [filename]: content });
209
- }, {});
210
-
211
- const dtoFiles = Object.entries(ctx.state().interface?.files ?? {})
212
- .filter(([filename]) => {
213
- return filename.startsWith("src/api/structures/");
214
- })
215
- .reduce<Record<string, string>>((acc, [filename, content]) => {
216
- return Object.assign(acc, { [filename]: content });
217
- }, {});
251
+ const artifacts: IAutoBeTestScenarioArtifacts = await compileTestScenario(
252
+ ctx,
253
+ scenario,
254
+ );
218
255
 
219
256
  const agentica = new MicroAgentica({
220
257
  model: ctx.model,
@@ -222,7 +259,7 @@ async function process<Model extends ILlmSchema.Model>(
222
259
  config: {
223
260
  ...(ctx.config ?? {}),
224
261
  },
225
- histories: transformTestCorrectHistories(apiFiles, dtoFiles),
262
+ histories: transformTestCorrectHistories(artifacts),
226
263
  controllers: [
227
264
  createApplication({
228
265
  model: ctx.model,
@@ -231,38 +268,53 @@ async function process<Model extends ILlmSchema.Model>(
231
268
  },
232
269
  }),
233
270
  ],
271
+ tokenUsage: ctx.usage(),
234
272
  });
235
273
  enforceToolCall(agentica);
236
274
 
237
- await agentica.conversate(
238
- [
239
- "Fix the compilation error in the provided code.",
240
- "",
241
- "## Original Code",
242
- "```typescript",
243
- code,
244
- "```",
245
- "",
246
- diagnostics.map((diagnostic) => {
247
- if (diagnostic.start === undefined || diagnostic.length === undefined)
248
- return "";
249
-
250
- return [
251
- "## Error Information",
252
- `- Position: Characters ${diagnostic.start} to ${diagnostic.start + diagnostic.length}`,
253
- `- Error Message: ${diagnostic.messageText}`,
254
- `- Problematic Code: \`${code.substring(diagnostic.start, diagnostic.start + diagnostic.length)}\``,
255
- "",
256
- ].join("\n");
257
- }),
258
- "## Instructions",
259
- "1. Focus on the specific error location and message",
260
- "2. Provide the corrected TypeScript code",
261
- "3. Ensure the fix resolves the compilation error",
262
- "",
263
- "Return only the fixed code without explanations.",
264
- ].join("\n"),
265
- );
275
+ await randomBackoffRetry(async () => {
276
+ await agentica.conversate(
277
+ [
278
+ "Fix the compilation error in the provided code.",
279
+ "",
280
+ "## Original Code",
281
+ "```typescript",
282
+ code,
283
+ "```",
284
+ "",
285
+ diagnostics.map((diagnostic) => {
286
+ if (diagnostic.start === undefined || diagnostic.length === undefined)
287
+ return "";
288
+
289
+ const checkDtoRegexp = `Cannot find module '@ORGANIZATION/template-api/lib/structures/IBbsArticleComment' or its corresponding type declarations.`;
290
+ const [group] = [
291
+ ...checkDtoRegexp.matchAll(
292
+ /Cannot find module '(.*lib\/structures\/.*)'/g,
293
+ ),
294
+ ];
295
+
296
+ const [_, filename] = group ?? [];
297
+
298
+ return [
299
+ "## Error Information",
300
+ `- Position: Characters ${diagnostic.start} to ${diagnostic.start + diagnostic.length}`,
301
+ `- Error Message: ${diagnostic.messageText}`,
302
+ `- Problematic Code: \`${code.substring(diagnostic.start, diagnostic.start + diagnostic.length)}\``,
303
+ filename
304
+ ? `The type files located under **/lib/structures are declared in '@ORGANIZATION/PROJECT-api/lib/structures'.\n` +
305
+ `Note: '@ORGANIZATION/PROJECT-api' must be written exactly as is and should not be replaced.\n`
306
+ : "",
307
+ ].join("\n");
308
+ }),
309
+ "## Instructions",
310
+ "1. Focus on the specific error location and message",
311
+ "2. Provide the corrected TypeScript code",
312
+ "3. Ensure the fix resolves the compilation error",
313
+ "",
314
+ "Return only the fixed code without explanations.",
315
+ ].join("\n"),
316
+ );
317
+ });
266
318
  if (pointer.value === null) throw new Error("Failed to modify test code.");
267
319
  return pointer.value;
268
320
  }