@autobe/agent 0.7.3 → 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.
Files changed (100) hide show
  1. package/lib/AutoBeAgent.d.ts +183 -12
  2. package/lib/AutoBeAgent.js +249 -65
  3. package/lib/AutoBeAgent.js.map +1 -1
  4. package/lib/constants/AutoBeSystemPromptConstant.d.ts +5 -4
  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 +1024 -663
  11. package/lib/index.mjs.map +1 -1
  12. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js +7 -8
  13. package/lib/orchestrate/analyze/AutoBeAnalyzeAgent.js.map +1 -1
  14. package/lib/orchestrate/analyze/orchestrateAnalyze.js +2 -5
  15. package/lib/orchestrate/analyze/orchestrateAnalyze.js.map +1 -1
  16. package/lib/orchestrate/interface/orchestrateInterface.js +1 -1
  17. package/lib/orchestrate/interface/orchestrateInterface.js.map +1 -1
  18. package/lib/orchestrate/interface/orchestrateInterfaceComplement.js +6 -8
  19. package/lib/orchestrate/interface/orchestrateInterfaceComplement.js.map +1 -1
  20. package/lib/orchestrate/interface/orchestrateInterfaceComponents.js +9 -6
  21. package/lib/orchestrate/interface/orchestrateInterfaceComponents.js.map +1 -1
  22. package/lib/orchestrate/interface/orchestrateInterfaceEndpoints.js +3 -1
  23. package/lib/orchestrate/interface/orchestrateInterfaceEndpoints.js.map +1 -1
  24. package/lib/orchestrate/interface/orchestrateInterfaceOperations.js +5 -8
  25. package/lib/orchestrate/interface/orchestrateInterfaceOperations.js.map +1 -1
  26. package/lib/orchestrate/prisma/orchestratePrisma.js +1 -1
  27. package/lib/orchestrate/prisma/orchestratePrisma.js.map +1 -1
  28. package/lib/orchestrate/prisma/orchestratePrismaComponent.js +5 -1
  29. package/lib/orchestrate/prisma/orchestratePrismaComponent.js.map +1 -1
  30. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js +3 -6
  31. package/lib/orchestrate/prisma/orchestratePrismaCorrect.js.map +1 -1
  32. package/lib/orchestrate/prisma/orchestratePrismaSchema.js +11 -7
  33. package/lib/orchestrate/prisma/orchestratePrismaSchema.js.map +1 -1
  34. package/lib/orchestrate/prisma/transformPrismaCorrectHistories.js +1 -1
  35. package/lib/orchestrate/prisma/transformPrismaCorrectHistories.js.map +1 -1
  36. package/lib/orchestrate/test/orchestrateTest.js +4 -8
  37. package/lib/orchestrate/test/orchestrateTest.js.map +1 -1
  38. package/lib/orchestrate/test/orchestrateTestCorrect.d.ts +2 -2
  39. package/lib/orchestrate/test/orchestrateTestCorrect.js +90 -60
  40. package/lib/orchestrate/test/orchestrateTestCorrect.js.map +1 -1
  41. package/lib/orchestrate/test/orchestrateTestProgress.d.ts +3 -2
  42. package/lib/orchestrate/test/orchestrateTestProgress.js +75 -50
  43. package/lib/orchestrate/test/orchestrateTestProgress.js.map +1 -1
  44. package/lib/orchestrate/test/orchestrateTestScenario.d.ts +1 -1
  45. package/lib/orchestrate/test/orchestrateTestScenario.js +617 -208
  46. package/lib/orchestrate/test/orchestrateTestScenario.js.map +1 -1
  47. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.d.ts +123 -0
  48. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.js +3 -0
  49. package/lib/orchestrate/test/structures/IAutoBeTestScenarioApplication.js.map +1 -0
  50. package/lib/orchestrate/test/transformTestCorrectHistories.d.ts +2 -1
  51. package/lib/orchestrate/test/transformTestCorrectHistories.js +14 -10
  52. package/lib/orchestrate/test/transformTestCorrectHistories.js.map +1 -1
  53. package/lib/orchestrate/test/transformTestProgressHistories.d.ts +7 -1
  54. package/lib/orchestrate/test/transformTestProgressHistories.js +20 -20
  55. package/lib/orchestrate/test/transformTestProgressHistories.js.map +1 -1
  56. package/lib/orchestrate/test/transformTestScenarioHistories.d.ts +1 -2
  57. package/lib/orchestrate/test/transformTestScenarioHistories.js +1 -77
  58. package/lib/orchestrate/test/transformTestScenarioHistories.js.map +1 -1
  59. package/lib/structures/IAutoBeConfig.d.ts +48 -10
  60. package/lib/structures/IAutoBeProps.d.ts +87 -0
  61. package/lib/structures/IAutoBeVendor.d.ts +64 -22
  62. package/lib/utils/backoffRetry.d.ts +7 -0
  63. package/lib/utils/backoffRetry.js +73 -0
  64. package/lib/utils/backoffRetry.js.map +1 -0
  65. package/lib/utils/enforceToolCall.d.ts +3 -0
  66. package/lib/utils/enforceToolCall.js +13 -0
  67. package/lib/utils/enforceToolCall.js.map +1 -0
  68. package/lib/utils/types/BackoffOptions.d.ts +12 -0
  69. package/lib/utils/types/BackoffOptions.js +3 -0
  70. package/lib/utils/types/BackoffOptions.js.map +1 -0
  71. package/package.json +5 -5
  72. package/src/AutoBeAgent.ts +252 -52
  73. package/src/constants/AutoBeSystemPromptConstant.ts +5 -4
  74. package/src/context/AutoBeContext.ts +7 -2
  75. package/src/factory/index.ts +0 -1
  76. package/src/orchestrate/analyze/AutoBeAnalyzeAgent.ts +5 -10
  77. package/src/orchestrate/analyze/orchestrateAnalyze.ts +2 -6
  78. package/src/orchestrate/interface/orchestrateInterface.ts +1 -1
  79. package/src/orchestrate/interface/orchestrateInterfaceComplement.ts +12 -11
  80. package/src/orchestrate/interface/orchestrateInterfaceComponents.ts +7 -6
  81. package/src/orchestrate/interface/orchestrateInterfaceEndpoints.ts +2 -1
  82. package/src/orchestrate/interface/orchestrateInterfaceOperations.ts +4 -9
  83. package/src/orchestrate/prisma/orchestratePrisma.ts +1 -0
  84. package/src/orchestrate/prisma/orchestratePrismaComponent.ts +4 -1
  85. package/src/orchestrate/prisma/orchestratePrismaCorrect.ts +6 -7
  86. package/src/orchestrate/prisma/orchestratePrismaSchema.ts +10 -7
  87. package/src/orchestrate/test/orchestrateTest.ts +6 -13
  88. package/src/orchestrate/test/orchestrateTestCorrect.ts +127 -78
  89. package/src/orchestrate/test/orchestrateTestProgress.ts +88 -47
  90. package/src/orchestrate/test/orchestrateTestScenario.ts +194 -105
  91. package/src/orchestrate/test/structures/IAutoBeTestScenarioApplication.ts +132 -0
  92. package/src/orchestrate/test/transformTestCorrectHistories.ts +14 -10
  93. package/src/orchestrate/test/transformTestProgressHistories.ts +25 -22
  94. package/src/orchestrate/test/transformTestScenarioHistories.ts +0 -79
  95. package/src/structures/IAutoBeConfig.ts +48 -10
  96. package/src/structures/IAutoBeProps.ts +91 -0
  97. package/src/structures/IAutoBeVendor.ts +64 -22
  98. package/src/utils/backoffRetry.ts +84 -0
  99. package/src/utils/enforceToolCall.ts +13 -0
  100. package/src/utils/types/BackoffOptions.ts +15 -0
@@ -13,6 +13,7 @@ import { v4 } from "uuid";
13
13
  import { AutoBeSystemPromptConstant } from "../../constants/AutoBeSystemPromptConstant";
14
14
  import { AutoBeContext } from "../../context/AutoBeContext";
15
15
  import { assertSchemaModel } from "../../context/assertSchemaModel";
16
+ import { enforceToolCall } from "../../utils/enforceToolCall";
16
17
  import { transformInterfaceHistories } from "./transformInterfaceHistories";
17
18
 
18
19
  export function orchestrateInterfaceComplement<Model extends ILlmSchema.Model>(
@@ -79,21 +80,21 @@ async function step<Model extends ILlmSchema.Model>(
79
80
  createApplication({
80
81
  model: ctx.model,
81
82
  build: (next) => {
82
- pointer.value = (OpenApiV3_1Emender.convertComponents({
83
- schemas: next,
84
- }).schemas ?? {}) as Record<
85
- string,
86
- AutoBeOpenApi.IJsonSchemaDescriptive
87
- >;
83
+ pointer.value ??= {};
84
+ Object.assign(
85
+ pointer.value,
86
+ (OpenApiV3_1Emender.convertComponents({
87
+ schemas: next,
88
+ }).schemas ?? {}) as Record<
89
+ string,
90
+ AutoBeOpenApi.IJsonSchemaDescriptive
91
+ >,
92
+ );
88
93
  },
89
94
  }),
90
95
  ],
91
96
  });
92
- agentica.on("request", async (event) => {
93
- if (event.body.tools) {
94
- event.body.tool_choice = "required";
95
- }
96
- });
97
+ enforceToolCall(agentica);
97
98
 
98
99
  await agentica.conversate("Fill missing schema types please");
99
100
  if (pointer.value === null) {
@@ -10,6 +10,7 @@ import { AutoBeSystemPromptConstant } from "../../constants/AutoBeSystemPromptCo
10
10
  import { AutoBeContext } from "../../context/AutoBeContext";
11
11
  import { assertSchemaModel } from "../../context/assertSchemaModel";
12
12
  import { divideArray } from "../../utils/divideArray";
13
+ import { enforceToolCall } from "../../utils/enforceToolCall";
13
14
  import { transformInterfaceHistories } from "./transformInterfaceHistories";
14
15
 
15
16
  export async function orchestrateInterfaceComponents<
@@ -131,17 +132,17 @@ async function process<Model extends ILlmSchema.Model>(
131
132
  createApplication({
132
133
  model: ctx.model,
133
134
  build: async (components) => {
134
- pointer.value = components;
135
+ pointer.value ??= {
136
+ schemas: {},
137
+ };
138
+ pointer.value.authorization ??= components.authorization;
139
+ Object.assign(pointer.value.schemas, components.schemas);
135
140
  },
136
141
  pointer,
137
142
  }),
138
143
  ],
139
144
  });
140
- agentica.on("request", async (event) => {
141
- if (event.body.tools) {
142
- event.body.tool_choice = "required";
143
- }
144
- });
145
+ enforceToolCall(agentica);
145
146
 
146
147
  const already: string[] = Object.keys(oldbie.schemas);
147
148
  await agentica.conversate(
@@ -48,7 +48,8 @@ export async function orchestrateInterfaceEndpoints<
48
48
  createApplication({
49
49
  model: ctx.model,
50
50
  build: (endpoints) => {
51
- pointer.value = endpoints;
51
+ pointer.value ??= endpoints;
52
+ pointer.value.push(...endpoints);
52
53
  },
53
54
  }),
54
55
  ],
@@ -8,6 +8,7 @@ import { AutoBeSystemPromptConstant } from "../../constants/AutoBeSystemPromptCo
8
8
  import { AutoBeContext } from "../../context/AutoBeContext";
9
9
  import { assertSchemaModel } from "../../context/assertSchemaModel";
10
10
  import { divideArray } from "../../utils/divideArray";
11
+ import { enforceToolCall } from "../../utils/enforceToolCall";
11
12
  import { OpenApiEndpointComparator } from "./OpenApiEndpointComparator";
12
13
  import { transformInterfaceHistories } from "./transformInterfaceHistories";
13
14
 
@@ -105,17 +106,13 @@ async function process<Model extends ILlmSchema.Model>(
105
106
  createApplication({
106
107
  model: ctx.model,
107
108
  build: (endpoints) => {
108
- pointer.value = endpoints;
109
+ pointer.value ??= [];
110
+ pointer.value.push(...endpoints);
109
111
  },
110
- pointer,
111
112
  }),
112
113
  ],
113
114
  });
114
- agentica.on("request", async (event) => {
115
- if (event.body.tools) {
116
- event.body.tool_choice = "required";
117
- }
118
- });
115
+ enforceToolCall(agentica);
119
116
  await agentica.conversate(
120
117
  [
121
118
  "Make API operations for below endpoints:",
@@ -132,7 +129,6 @@ async function process<Model extends ILlmSchema.Model>(
132
129
  function createApplication<Model extends ILlmSchema.Model>(props: {
133
130
  model: Model;
134
131
  build: (operations: AutoBeOpenApi.IOperation[]) => void;
135
- pointer: IPointer<AutoBeOpenApi.IOperation[] | null>;
136
132
  }): IAgenticaController.IClass<Model> {
137
133
  assertSchemaModel(props.model);
138
134
 
@@ -143,7 +139,6 @@ function createApplication<Model extends ILlmSchema.Model>(props: {
143
139
  const result: IValidation<IMakeOperationProps> =
144
140
  typia.validate<IMakeOperationProps>(next);
145
141
  if (result.success === false) return result;
146
- props.pointer.value = result.data.operations;
147
142
 
148
143
  const errors: IValidation.IError[] = [];
149
144
  result.data.operations.forEach((op, i) => {
@@ -51,6 +51,7 @@ export const orchestratePrisma =
51
51
  );
52
52
  const schemas: Record<string, string> = await ctx.compiler.prisma.write(
53
53
  result.data,
54
+ "postgres",
54
55
  );
55
56
  const history: AutoBePrismaHistory = {
56
57
  type: "prisma",
@@ -40,7 +40,10 @@ export async function orchestratePrismaComponents<
40
40
  createApplication({
41
41
  model: ctx.model,
42
42
  build: (next) => {
43
- pointer.value = next;
43
+ pointer.value ??= {
44
+ components: [],
45
+ };
46
+ pointer.value.components.push(...next.components);
44
47
  },
45
48
  }),
46
49
  ],
@@ -6,6 +6,7 @@ import typia from "typia";
6
6
 
7
7
  import { AutoBeContext } from "../../context/AutoBeContext";
8
8
  import { assertSchemaModel } from "../../context/assertSchemaModel";
9
+ import { enforceToolCall } from "../../utils/enforceToolCall";
9
10
  import { transformPrismaCorrectHistories } from "./transformPrismaCorrectHistories";
10
11
 
11
12
  export function orchestratePrismaCorrect<Model extends ILlmSchema.Model>(
@@ -36,8 +37,10 @@ async function step<Model extends ILlmSchema.Model>(
36
37
  else if (life <= 0) return result; // FAILURE
37
38
 
38
39
  // VALIDATION FAILED
39
- const schemas: Record<string, string> =
40
- await ctx.compiler.prisma.write(application);
40
+ const schemas: Record<string, string> = await ctx.compiler.prisma.write(
41
+ application,
42
+ "postgres",
43
+ );
41
44
  ctx.dispatch({
42
45
  type: "prismaValidate",
43
46
  result,
@@ -69,11 +72,7 @@ async function step<Model extends ILlmSchema.Model>(
69
72
  }),
70
73
  ],
71
74
  });
72
- agentica.on("request", (event) => {
73
- if (event.body.tools) {
74
- event.body.tool_choice = "required";
75
- }
76
- });
75
+ enforceToolCall(agentica);
77
76
 
78
77
  // REQUEST CORRECTION
79
78
  await agentica.conversate(
@@ -7,6 +7,7 @@ import typia from "typia";
7
7
 
8
8
  import { AutoBeContext } from "../../context/AutoBeContext";
9
9
  import { assertSchemaModel } from "../../context/assertSchemaModel";
10
+ import { enforceToolCall } from "../../utils/enforceToolCall";
10
11
  import { transformPrismaSchemaHistories } from "./transformPrismaSchemaHistories";
11
12
 
12
13
  export async function orchestratePrismaSchemas<Model extends ILlmSchema.Model>(
@@ -64,17 +65,19 @@ async function process<Model extends ILlmSchema.Model>(
64
65
  createApplication({
65
66
  model: ctx.model,
66
67
  build: (next) => {
67
- pointer.value = next;
68
- pointer.value.file.filename = component.filename;
68
+ pointer.value ??= {
69
+ file: {
70
+ filename: component.filename,
71
+ namespace: next.file.namespace,
72
+ models: [],
73
+ },
74
+ };
75
+ pointer.value.file.models.push(...next.file.models);
69
76
  },
70
77
  }),
71
78
  ],
72
79
  });
73
- agentica.on("request", async (event) => {
74
- if (event.body.tools) {
75
- event.body.tool_choice = "required";
76
- }
77
- });
80
+ enforceToolCall(agentica);
78
81
  await agentica.conversate("Make prisma schema file please");
79
82
  if (pointer.value === null)
80
83
  throw new Error("Unreachable code: Prisma Schema not generated");
@@ -1,9 +1,8 @@
1
1
  import {
2
2
  AutoBeAssistantMessageHistory,
3
3
  AutoBeTestHistory,
4
- AutoBeTestProgressEvent,
4
+ AutoBeTestWriteEvent,
5
5
  } from "@autobe/interface";
6
- import { AutoBeTestScenarioEvent } from "@autobe/interface/src/events/AutoBeTestScenarioEvent";
7
6
  import { ILlmSchema } from "@samchon/openapi";
8
7
  import { v4 } from "uuid";
9
8
 
@@ -44,22 +43,16 @@ export const orchestrateTest =
44
43
  return history;
45
44
  }
46
45
 
47
- // SCENARIOS
48
- const scenarioEvent: AutoBeTestScenarioEvent =
49
- await orchestrateTestScenario(ctx);
46
+ // PLAN
47
+ const { scenarios } = await orchestrateTestScenario(ctx);
50
48
 
51
- const scenarios = scenarioEvent.scenarios
52
- .map((scenario) => {
53
- return scenario.scenarios;
54
- })
55
- .flat();
56
-
57
- const codes: AutoBeTestProgressEvent[] = await orchestrateTestProgress(
49
+ // TEST CODE
50
+ const codes: AutoBeTestWriteEvent[] = await orchestrateTestProgress(
58
51
  ctx,
59
52
  scenarios,
60
53
  );
61
54
 
62
- const correct = await orchestrateTestCorrect(ctx, codes);
55
+ const correct = await orchestrateTestCorrect(ctx, codes, scenarios);
63
56
 
64
57
  const history: AutoBeTestHistory = {
65
58
  type: "test",
@@ -1,7 +1,9 @@
1
1
  import { IAgenticaController, MicroAgentica } from "@agentica/core";
2
2
  import {
3
- AutoBeTestProgressEvent,
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,31 +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";
16
+ import { enforceToolCall } from "../../utils/enforceToolCall";
17
+ import { filterDocument } from "./orchestrateTestProgress";
13
18
  import { transformTestCorrectHistories } from "./transformTestCorrectHistories";
14
19
 
15
20
  export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
16
21
  ctx: AutoBeContext<Model>,
17
- codes: AutoBeTestProgressEvent[],
22
+ codes: AutoBeTestWriteEvent[],
23
+ scenarios: AutoBeTestScenarioEvent.IScenario[],
18
24
  life: number = 4,
19
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
+
20
31
  // 1) Build map of new test files from progress events
21
- const testFiles = Object.fromEntries(
22
- codes.map(({ filename, content }) => [
23
- `test/features/api/${filename}`,
24
- content,
25
- ]),
26
- );
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), {});
27
39
 
28
40
  // 2) Keep only files outside the test directory from current state
29
- const retainedFiles = Object.fromEntries(
30
- Object.entries(ctx.state().interface?.files ?? {}).filter(
31
- ([filename]) => !filename.startsWith("test/features/api"),
32
- ),
33
- );
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), {});
34
51
 
35
52
  // 3) Merge and filter: keep .ts/.json, drop anything under "benchmark"
36
- const mergedFiles = { ...retainedFiles, ...testFiles };
37
- const files = Object.fromEntries(
53
+ const mergedFiles: Record<string, string> = {
54
+ ...retainedFiles,
55
+ ...testFiles,
56
+ };
57
+ const files: Record<string, string> = Object.fromEntries(
38
58
  Object.entries(mergedFiles).filter(
39
59
  ([filename]) =>
40
60
  (filename.endsWith(".ts") && !filename.startsWith("test/benchmark/")) ||
@@ -43,7 +63,12 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
43
63
  );
44
64
 
45
65
  // 4) Ask the LLM to correct the filtered file set
46
- const response = await step(ctx, files, life);
66
+ const response: AutoBeTestValidateEvent = await step(
67
+ ctx,
68
+ files,
69
+ scenarioMap,
70
+ life,
71
+ );
47
72
 
48
73
  // 5) Combine original + corrected files and dispatch event
49
74
  const event: AutoBeTestValidateEvent = {
@@ -51,7 +76,6 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
51
76
  type: "testValidate",
52
77
  files: { ...mergedFiles, ...response.files },
53
78
  };
54
-
55
79
  return event;
56
80
  }
57
81
 
@@ -73,13 +97,15 @@ export async function orchestrateTestCorrect<Model extends ILlmSchema.Model>(
73
97
  async function step<Model extends ILlmSchema.Model>(
74
98
  ctx: AutoBeContext<Model>,
75
99
  files: Record<string, string>,
100
+ scenarioMap: Map<string, AutoBeTestScenarioEvent.IScenario>,
76
101
  life: number,
77
102
  ): Promise<AutoBeTestValidateEvent> {
78
103
  // COMPILE TEST CODE
79
- const result = await ctx.compiler.typescript({
80
- files,
81
- });
82
104
 
105
+ const result: IAutoBeTypeScriptCompilerResult =
106
+ await ctx.compiler.typescript.compile({
107
+ files,
108
+ });
83
109
  if (result.type === "success") {
84
110
  // SUCCESS
85
111
  return {
@@ -100,7 +126,6 @@ async function step<Model extends ILlmSchema.Model>(
100
126
  result,
101
127
  step: ctx.state().interface?.step ?? 0,
102
128
  });
103
-
104
129
  throw new Error(JSON.stringify(result.error, null, 2));
105
130
  }
106
131
 
@@ -154,11 +179,17 @@ async function step<Model extends ILlmSchema.Model>(
154
179
  };
155
180
 
156
181
  // VALIDATION FAILED
157
- const validate = await Promise.all(
182
+ const validate: [string, string][] = await Promise.all(
158
183
  Object.entries(diagnostics).map(async ([filename, d]) => {
159
- const code = files[filename];
160
- const response = await process(ctx, d, code);
161
-
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
+ );
162
193
  ctx.dispatch({
163
194
  type: "testCorrect",
164
195
  created_at: new Date().toISOString(),
@@ -175,9 +206,11 @@ async function step<Model extends ILlmSchema.Model>(
175
206
  }),
176
207
  );
177
208
 
178
- const newFiles = { ...files, ...Object.fromEntries(validate) };
179
-
180
- return step(ctx, newFiles, life - 1);
209
+ const newFiles: Record<string, string> = {
210
+ ...files,
211
+ ...Object.fromEntries(validate),
212
+ };
213
+ return step(ctx, newFiles, scenarioMap, life - 1);
181
214
  }
182
215
 
183
216
  /**
@@ -194,26 +227,32 @@ async function process<Model extends ILlmSchema.Model>(
194
227
  ctx: AutoBeContext<Model>,
195
228
  diagnostics: IAutoBeTypeScriptCompilerResult.IDiagnostic[],
196
229
  code: string,
230
+ scenario: AutoBeTestScenarioEvent.IScenario,
197
231
  ): Promise<ICorrectTestFunctionProps> {
198
232
  const pointer: IPointer<ICorrectTestFunctionProps | null> = {
199
233
  value: null,
200
234
  };
201
235
 
202
- const apiFiles = Object.entries(ctx.state().interface?.files ?? {})
203
- .filter(([filename]) => {
204
- return filename.startsWith("src/api/");
205
- })
206
- .reduce<Record<string, string>>((acc, [filename, content]) => {
207
- return Object.assign(acc, { [filename]: content });
208
- }, {});
236
+ let document: AutoBeOpenApi.IDocument | null = null;
237
+ if (scenario) {
238
+ document = filterDocument(scenario, ctx.state().interface!.document);
239
+ }
209
240
 
210
- const dtoFiles = Object.entries(ctx.state().interface?.files ?? {})
211
- .filter(([filename]) => {
212
- return filename.startsWith("src/api/structures/");
213
- })
214
- .reduce<Record<string, string>>((acc, [filename, content]) => {
215
- return Object.assign(acc, { [filename]: content });
216
- }, {});
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
+ // }, {});
217
256
 
218
257
  const agentica = new MicroAgentica({
219
258
  model: ctx.model,
@@ -221,7 +260,7 @@ async function process<Model extends ILlmSchema.Model>(
221
260
  config: {
222
261
  ...(ctx.config ?? {}),
223
262
  },
224
- histories: transformTestCorrectHistories(apiFiles, dtoFiles),
263
+ histories: transformTestCorrectHistories(document),
225
264
  controllers: [
226
265
  createApplication({
227
266
  model: ctx.model,
@@ -230,44 +269,54 @@ async function process<Model extends ILlmSchema.Model>(
230
269
  },
231
270
  }),
232
271
  ],
272
+ tokenUsage: ctx.usage(),
233
273
  });
234
-
235
- agentica.on("request", async (event) => {
236
- if (event.body.tools) event.body.tool_choice = "required";
274
+ enforceToolCall(agentica);
275
+
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
+ );
237
318
  });
238
-
239
- await agentica.conversate(
240
- [
241
- "Fix the compilation error in the provided code.",
242
- "",
243
- "## Original Code",
244
- "```typescript",
245
- code,
246
- "```",
247
- "",
248
- diagnostics.map((diagnostic) => {
249
- if (diagnostic.start === undefined || diagnostic.length === undefined)
250
- return "";
251
-
252
- return [
253
- "## Error Information",
254
- `- Position: Characters ${diagnostic.start} to ${diagnostic.start + diagnostic.length}`,
255
- `- Error Message: ${diagnostic.messageText}`,
256
- `- Problematic Code: \`${code.substring(diagnostic.start, diagnostic.start + diagnostic.length)}\``,
257
- "",
258
- ].join("\n");
259
- }),
260
- "## Instructions",
261
- "1. Focus on the specific error location and message",
262
- "2. Provide the corrected TypeScript code",
263
- "3. Ensure the fix resolves the compilation error",
264
- "",
265
- "Return only the fixed code without explanations.",
266
- ].join("\n"),
267
- );
268
-
269
319
  if (pointer.value === null) throw new Error("Failed to modify test code.");
270
-
271
320
  return pointer.value;
272
321
  }
273
322