@autobe/agent 0.15.0 → 0.16.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 (97) hide show
  1. package/lib/AutoBeAgent.js +2 -2
  2. package/lib/AutoBeAgent.js.map +1 -1
  3. package/lib/AutoBeMockAgent.d.ts +1 -0
  4. package/lib/AutoBeMockAgent.js +18 -4
  5. package/lib/AutoBeMockAgent.js.map +1 -1
  6. package/lib/constants/AutoBeSystemPromptConstant.d.ts +3 -3
  7. package/lib/factory/getAutoBeGenerated.js +2 -1
  8. package/lib/factory/getAutoBeGenerated.js.map +1 -1
  9. package/lib/index.mjs +739 -577
  10. package/lib/index.mjs.map +1 -1
  11. package/lib/orchestrate/analyze/AutoBeAnalyzeFileSystem.d.ts +0 -15
  12. package/lib/orchestrate/analyze/AutoBeAnalyzeFileSystem.js +0 -3
  13. package/lib/orchestrate/analyze/AutoBeAnalyzeFileSystem.js.map +1 -1
  14. package/lib/orchestrate/analyze/orchestrateAnalyze.js +19 -12
  15. package/lib/orchestrate/analyze/orchestrateAnalyze.js.map +1 -1
  16. package/lib/orchestrate/analyze/orchestrateAnalyzeComposer.d.ts +1 -2
  17. package/lib/orchestrate/analyze/orchestrateAnalyzeComposer.js +3 -5
  18. package/lib/orchestrate/analyze/orchestrateAnalyzeComposer.js.map +1 -1
  19. package/lib/orchestrate/analyze/orchestrateAnalyzeReviewer.d.ts +7 -1
  20. package/lib/orchestrate/analyze/orchestrateAnalyzeReviewer.js +363 -4
  21. package/lib/orchestrate/analyze/orchestrateAnalyzeReviewer.js.map +1 -1
  22. package/lib/orchestrate/analyze/orchestrateAnalyzeWrite.d.ts +3 -3
  23. package/lib/orchestrate/analyze/orchestrateAnalyzeWrite.js +3 -118
  24. package/lib/orchestrate/analyze/orchestrateAnalyzeWrite.js.map +1 -1
  25. package/lib/orchestrate/analyze/transformAnalyzeReviewerHistories.js +1 -1
  26. package/lib/orchestrate/analyze/transformAnalyzeReviewerHistories.js.map +1 -1
  27. package/lib/orchestrate/analyze/writeDocumentUntilReviewPassed.d.ts +11 -4
  28. package/lib/orchestrate/analyze/writeDocumentUntilReviewPassed.js +61 -45
  29. package/lib/orchestrate/analyze/writeDocumentUntilReviewPassed.js.map +1 -1
  30. package/lib/orchestrate/prisma/transformPrismaComponentsHistories.js +17 -10
  31. package/lib/orchestrate/prisma/transformPrismaComponentsHistories.js.map +1 -1
  32. package/lib/orchestrate/realize/ProviderCodeComparator.d.ts +5 -0
  33. package/lib/orchestrate/realize/ProviderCodeComparator.js +16 -0
  34. package/lib/orchestrate/realize/ProviderCodeComparator.js.map +1 -0
  35. package/lib/orchestrate/realize/orchestrateRealize.js +41 -53
  36. package/lib/orchestrate/realize/orchestrateRealize.js.map +1 -1
  37. package/lib/orchestrate/realize/orchestrateRealizeAuthorization.js +13 -87
  38. package/lib/orchestrate/realize/orchestrateRealizeAuthorization.js.map +1 -1
  39. package/lib/orchestrate/realize/orchestrateRealizeAuthorizationCorrect.js +32 -43
  40. package/lib/orchestrate/realize/orchestrateRealizeAuthorizationCorrect.js.map +1 -1
  41. package/lib/orchestrate/realize/orchestrateRealizeCoder.d.ts +3 -2
  42. package/lib/orchestrate/realize/orchestrateRealizeCoder.js +25 -39
  43. package/lib/orchestrate/realize/orchestrateRealizeCoder.js.map +1 -1
  44. package/lib/orchestrate/realize/structures/IAutoBeRealizeAuthorizationApplication.d.ts +15 -15
  45. package/lib/orchestrate/realize/structures/IAutoBeRealizeAuthorizationCorrectApplication.d.ts +11 -17
  46. package/lib/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.d.ts +4 -2
  47. package/lib/orchestrate/realize/structures/IAutoBeRealizeCompile.d.ts +21 -17
  48. package/lib/orchestrate/realize/transformRealizeAuthorization.js +5 -9
  49. package/lib/orchestrate/realize/transformRealizeAuthorization.js.map +1 -1
  50. package/lib/orchestrate/realize/transformRealizeAuthorizationCorrectHistories.js +9 -0
  51. package/lib/orchestrate/realize/transformRealizeAuthorizationCorrectHistories.js.map +1 -1
  52. package/lib/orchestrate/realize/transformRealizeCoderHistories.d.ts +3 -2
  53. package/lib/orchestrate/realize/transformRealizeCoderHistories.js +58 -27
  54. package/lib/orchestrate/realize/transformRealizeCoderHistories.js.map +1 -1
  55. package/lib/orchestrate/realize/utils/AutoBeRealizeAuthorizationFileSystem.d.ts +5 -0
  56. package/lib/orchestrate/realize/utils/AutoBeRealizeAuthorizationFileSystem.js +10 -0
  57. package/lib/orchestrate/realize/utils/AutoBeRealizeAuthorizationFileSystem.js.map +1 -0
  58. package/lib/orchestrate/realize/utils/AutoBeRealizeAuthorizationReplaceImport.d.ts +4 -0
  59. package/lib/orchestrate/realize/utils/AutoBeRealizeAuthorizationReplaceImport.js +38 -0
  60. package/lib/orchestrate/realize/utils/AutoBeRealizeAuthorizationReplaceImport.js.map +1 -0
  61. package/lib/orchestrate/realize/utils/replaceImportStatements.d.ts +2 -1
  62. package/lib/orchestrate/realize/utils/replaceImportStatements.js +15 -2
  63. package/lib/orchestrate/realize/utils/replaceImportStatements.js.map +1 -1
  64. package/lib/orchestrate/realize/writeCodeUntilCompilePassed.d.ts +9 -2
  65. package/lib/orchestrate/realize/writeCodeUntilCompilePassed.js +158 -100
  66. package/lib/orchestrate/realize/writeCodeUntilCompilePassed.js.map +1 -1
  67. package/lib/orchestrate/test/orchestrateTest.js +1 -1
  68. package/lib/orchestrate/test/orchestrateTest.js.map +1 -1
  69. package/package.json +6 -6
  70. package/src/AutoBeAgent.ts +1 -1
  71. package/src/AutoBeMockAgent.ts +20 -6
  72. package/src/constants/AutoBeSystemPromptConstant.ts +3 -3
  73. package/src/factory/getAutoBeGenerated.ts +2 -1
  74. package/src/orchestrate/analyze/AutoBeAnalyzeFileSystem.ts +0 -15
  75. package/src/orchestrate/analyze/orchestrateAnalyze.ts +17 -17
  76. package/src/orchestrate/analyze/orchestrateAnalyzeComposer.ts +4 -7
  77. package/src/orchestrate/analyze/orchestrateAnalyzeReviewer.ts +100 -6
  78. package/src/orchestrate/analyze/orchestrateAnalyzeWrite.ts +5 -21
  79. package/src/orchestrate/analyze/writeDocumentUntilReviewPassed.ts +76 -59
  80. package/src/orchestrate/prisma/transformPrismaComponentsHistories.ts +17 -10
  81. package/src/orchestrate/realize/ProviderCodeComparator.ts +15 -0
  82. package/src/orchestrate/realize/orchestrateRealize.ts +54 -59
  83. package/src/orchestrate/realize/orchestrateRealizeAuthorization.ts +12 -120
  84. package/src/orchestrate/realize/orchestrateRealizeAuthorizationCorrect.ts +21 -5
  85. package/src/orchestrate/realize/orchestrateRealizeCoder.ts +10 -9
  86. package/src/orchestrate/realize/structures/IAutoBeRealizeAuthorizationApplication.ts +15 -15
  87. package/src/orchestrate/realize/structures/IAutoBeRealizeAuthorizationCorrectApplication.ts +11 -18
  88. package/src/orchestrate/realize/structures/IAutoBeRealizeCoderApplication.ts +4 -2
  89. package/src/orchestrate/realize/structures/IAutoBeRealizeCompile.ts +24 -17
  90. package/src/orchestrate/realize/transformRealizeAuthorization.ts +5 -9
  91. package/src/orchestrate/realize/transformRealizeAuthorizationCorrectHistories.ts +9 -0
  92. package/src/orchestrate/realize/transformRealizeCoderHistories.ts +73 -25
  93. package/src/orchestrate/realize/utils/AutoBeRealizeAuthorizationFileSystem.ts +9 -0
  94. package/src/orchestrate/realize/utils/AutoBeRealizeAuthorizationReplaceImport.ts +64 -0
  95. package/src/orchestrate/realize/utils/replaceImportStatements.ts +41 -2
  96. package/src/orchestrate/realize/writeCodeUntilCompilePassed.ts +219 -145
  97. package/src/orchestrate/test/orchestrateTest.ts +1 -1
@@ -92,7 +92,7 @@ export async function getAutoBeGenerated(
92
92
  );
93
93
 
94
94
  // REALIZE
95
- if (state.realize?.step === state.analyze.step)
95
+ if (state.realize?.step === state.analyze.step) {
96
96
  Object.assign<Record<string, string>, Record<string, string>>(ret, {
97
97
  ...Object.fromEntries(
98
98
  state.realize.functions.map((f) => [f.location, f.content]),
@@ -113,6 +113,7 @@ export async function getAutoBeGenerated(
113
113
  authorizations: state.realize.authorizations,
114
114
  })),
115
115
  });
116
+ }
116
117
 
117
118
  // LOGGING
118
119
  Object.assign<Record<string, string>, Record<string, string>>(ret, {
@@ -42,17 +42,6 @@ export interface IAutoBeAnalyzeFileSystem {
42
42
  createOrUpdateFiles(
43
43
  input: ICreateOrUpdateInput,
44
44
  ): Promise<Record<string, string>>;
45
-
46
- /**
47
- * If you decide that you no longer need any reviews, or if the reviewer
48
- * refuses to do so, call abort. This is a function to end document creation
49
- * and review, and to respond to users.
50
- *
51
- * When there is content you are unsure about and need to ask the user a
52
- * question, abort the process and ask the user directly. The reason for
53
- * aborting should be included as the content of the question.
54
- */
55
- abort(input: { reason: string }): "OK";
56
45
  }
57
46
 
58
47
  export class AutoBeAnalyzeFileSystem implements IAutoBeAnalyzeFileSystem {
@@ -66,8 +55,4 @@ export class AutoBeAnalyzeFileSystem implements IAutoBeAnalyzeFileSystem {
66
55
 
67
56
  return this.fileMap;
68
57
  }
69
-
70
- abort(_input: { reason: string }): "OK" {
71
- return "OK";
72
- }
73
58
  }
@@ -8,7 +8,6 @@ import { v4 } from "uuid";
8
8
 
9
9
  import { AutoBeContext } from "../../context/AutoBeContext";
10
10
  import { IAutoBeApplicationProps } from "../../context/IAutoBeApplicationProps";
11
- import { AutoBeAnalyzePointer } from "./AutoBeAnalyzePointer";
12
11
  import { orchestrateAnalyzeComposer } from "./orchestrateAnalyzeComposer";
13
12
  import { IComposeInput } from "./structures/IAutoBeAnalyzeComposerApplication";
14
13
  import { writeDocumentUntilReviewPassed } from "./writeDocumentUntilReviewPassed";
@@ -28,8 +27,11 @@ export const orchestrateAnalyze =
28
27
  created_at,
29
28
  });
30
29
 
31
- const pointer: IPointer<IComposeInput | null> = { value: null };
32
- const agentica = orchestrateAnalyzeComposer(ctx, pointer);
30
+ const composeInputPointer: IPointer<IComposeInput | null> = { value: null };
31
+ const agentica = orchestrateAnalyzeComposer(ctx, (v) => {
32
+ composeInputPointer.value = v;
33
+ });
34
+
33
35
  const determined = await agentica
34
36
  .conversate(
35
37
  [
@@ -42,7 +44,9 @@ export const orchestrateAnalyze =
42
44
  const tokenUsage = agentica.getTokenUsage();
43
45
  ctx.usage().record(tokenUsage, ["analyze"]);
44
46
  });
45
- if (pointer.value === null) {
47
+
48
+ const composeInput = composeInputPointer.value;
49
+ if (composeInput === null) {
46
50
  return {
47
51
  id: v4(),
48
52
  text: "Failed to analyze your request. please request again.",
@@ -52,7 +56,7 @@ export const orchestrateAnalyze =
52
56
  };
53
57
  }
54
58
 
55
- const { files: tableOfContents, prefix, roles } = pointer.value;
59
+ const { files: tableOfContents, prefix, roles } = composeInput;
56
60
 
57
61
  if (tableOfContents.length === 0) {
58
62
  const history: AutoBeAssistantMessageHistory = {
@@ -77,17 +81,13 @@ export const orchestrateAnalyze =
77
81
  };
78
82
  const pointers = await Promise.all(
79
83
  tableOfContents.map(async ({ filename }) => {
80
- const pointer: AutoBeAnalyzePointer = { value: { files: {} } };
81
- await writeDocumentUntilReviewPassed(
82
- ctx,
83
- pointer,
84
- tableOfContents,
84
+ return await writeDocumentUntilReviewPassed(ctx, {
85
+ totalFiles: tableOfContents,
85
86
  filename,
86
87
  roles,
87
88
  progress,
88
- retryCount,
89
- );
90
- return pointer;
89
+ retry: retryCount,
90
+ });
91
91
  }),
92
92
  );
93
93
 
@@ -114,7 +114,7 @@ export const orchestrateAnalyze =
114
114
  ctx.dispatch({
115
115
  type: "analyzeComplete",
116
116
  prefix,
117
- files: files,
117
+ files,
118
118
  step,
119
119
  created_at,
120
120
  });
@@ -129,9 +129,9 @@ export const orchestrateAnalyze =
129
129
  completed_at: new Date().toISOString(),
130
130
  };
131
131
  ctx.dispatch({
132
- type: "assistantMessage",
133
- text: determined.find((el) => el.type === "assistantMessage")?.text ?? "",
134
- created_at,
132
+ type: history.type,
133
+ text: history.text,
134
+ created_at: history.created_at,
135
135
  });
136
136
  return history;
137
137
  };
@@ -1,6 +1,5 @@
1
1
  import { IAgenticaController, MicroAgentica } from "@agentica/core";
2
2
  import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
3
- import { IPointer } from "tstl";
4
3
  import typia from "typia";
5
4
  import { v4 } from "uuid";
6
5
 
@@ -15,14 +14,12 @@ import {
15
14
 
16
15
  export const orchestrateAnalyzeComposer = <Model extends ILlmSchema.Model>(
17
16
  ctx: AutoBeContext<Model>,
18
- pointer: IPointer<IComposeInput | null>,
17
+ setComposeInput: (value: IComposeInput) => void,
19
18
  ) => {
20
19
  const controller = createController<Model>({
21
20
  model: ctx.model,
22
21
  execute: new AutoBeAnalyzeComposerApplication(),
23
- build: (value: IComposeInput) => {
24
- pointer.value = value;
25
- },
22
+ preExecute: setComposeInput,
26
23
  });
27
24
 
28
25
  const agent = new MicroAgentica({
@@ -78,7 +75,7 @@ class AutoBeAnalyzeComposerApplication
78
75
  function createController<Model extends ILlmSchema.Model>(props: {
79
76
  model: Model;
80
77
  execute: AutoBeAnalyzeComposerApplication;
81
- build: (input: IComposeInput) => void;
78
+ preExecute: (input: IComposeInput) => void;
82
79
  }): IAgenticaController.IClass<Model> {
83
80
  assertSchemaModel(props.model);
84
81
  const application: ILlmApplication<Model> = collection[
@@ -90,7 +87,7 @@ function createController<Model extends ILlmSchema.Model>(props: {
90
87
  application,
91
88
  execute: {
92
89
  compose: (input) => {
93
- props.build(input);
90
+ props.preExecute(input);
94
91
  return props.execute.compose(input);
95
92
  },
96
93
  } satisfies IAutoBeAnalyzeComposerApplication,
@@ -1,10 +1,22 @@
1
- import { MicroAgentica } from "@agentica/core";
2
- import { ILlmSchema } from "@samchon/openapi";
1
+ import { IAgenticaController, MicroAgentica } from "@agentica/core";
2
+ import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
3
+ import { IPointer } from "tstl";
4
+ import typia from "typia";
3
5
 
4
6
  import { AutoBeContext } from "../../context/AutoBeContext";
7
+ import { assertSchemaModel } from "../../context/assertSchemaModel";
5
8
  import { enforceToolCall } from "../../utils/enforceToolCall";
6
9
  import { transformAnalyzeReviewerHistories } from "./transformAnalyzeReviewerHistories";
7
10
 
11
+ export type IOrchestrateAnalyzeReviewerResult =
12
+ | {
13
+ type: "reject";
14
+ value: string;
15
+ }
16
+ | {
17
+ type: "accept";
18
+ };
19
+
8
20
  export const orchestrateAnalyzeReviewer = async <
9
21
  Model extends ILlmSchema.Model,
10
22
  >(
@@ -13,11 +25,24 @@ export const orchestrateAnalyzeReviewer = async <
13
25
  /** Total file names */
14
26
  files: Record<string, string>;
15
27
  },
16
- ): Promise<string | null> => {
28
+ ): Promise<IOrchestrateAnalyzeReviewerResult> => {
29
+ const fnCalled: IPointer<IOrchestrateAnalyzeReviewerResult> = {
30
+ value: {
31
+ type: "reject",
32
+ value: "reviewer is not working because of unknown reason.",
33
+ },
34
+ };
35
+
36
+ const controller = createController({
37
+ model: ctx.model,
38
+ setResult: (result: IOrchestrateAnalyzeReviewerResult) => {
39
+ fnCalled.value = result;
40
+ },
41
+ });
17
42
  const agent = new MicroAgentica({
18
43
  model: ctx.model,
19
44
  vendor: ctx.vendor,
20
- controllers: [],
45
+ controllers: [controller],
21
46
  config: {
22
47
  ...ctx.config,
23
48
  executor: {
@@ -29,9 +54,78 @@ export const orchestrateAnalyzeReviewer = async <
29
54
  enforceToolCall(agent);
30
55
 
31
56
  const command = `proceed with the review of these files only.` as const;
32
- const histories = await agent.conversate(command).finally(() => {
57
+ await agent.conversate(command).finally(() => {
33
58
  const tokenUsage = agent.getTokenUsage();
34
59
  ctx.usage().record(tokenUsage, ["analyze"]);
35
60
  });
36
- return histories.find((h) => h.type === "assistantMessage")?.text ?? null;
61
+
62
+ return fnCalled.value;
63
+ };
64
+
65
+ interface IAutoBeAnalyzerReviewerSystem {
66
+ /**
67
+ * If there is anything that needs to be modified, you can call it, This
68
+ * function is to reject the document for to try rewriting document with your
69
+ * advice or suggestion.
70
+ */
71
+ reject(input: {
72
+ /**
73
+ * The reason why you reject the document and the suggestion for the
74
+ * modification. You can write the reason in detail.
75
+ */
76
+ reason: string;
77
+ }): "OK" | Promise<"OK">;
78
+
79
+ /**
80
+ * If you decide that you no longer need any reviews, call accept. This is a
81
+ * function to end document creation and review, and to respond to users.
82
+ */
83
+ accept(): "OK" | Promise<"OK">;
84
+ }
85
+
86
+ function createController<Model extends ILlmSchema.Model>(props: {
87
+ model: Model;
88
+ setResult: (result: IOrchestrateAnalyzeReviewerResult) => void;
89
+ }): IAgenticaController.IClass<Model> {
90
+ assertSchemaModel(props.model);
91
+ const application: ILlmApplication<Model> = collection[
92
+ props.model
93
+ ] as unknown as ILlmApplication<Model>;
94
+ return {
95
+ protocol: "class",
96
+ name: "Reviewer",
97
+ application,
98
+ execute: {
99
+ accept: async () => {
100
+ props.setResult({
101
+ type: "accept",
102
+ });
103
+ return "OK" as const;
104
+ },
105
+ reject: async (input) => {
106
+ props.setResult({
107
+ type: "reject",
108
+ value: input.reason,
109
+ });
110
+ return "OK" as const;
111
+ },
112
+ } satisfies IAutoBeAnalyzerReviewerSystem,
113
+ };
114
+ }
115
+
116
+ const claude = typia.llm.application<
117
+ IAutoBeAnalyzerReviewerSystem,
118
+ "claude",
119
+ { reference: true }
120
+ >();
121
+ const collection = {
122
+ chatgpt: typia.llm.application<
123
+ IAutoBeAnalyzerReviewerSystem,
124
+ "chatgpt",
125
+ { reference: true }
126
+ >(),
127
+ claude,
128
+ llama: claude,
129
+ deepseek: claude,
130
+ "3.1": claude,
37
131
  };
@@ -1,7 +1,6 @@
1
1
  import { IAgenticaController, MicroAgentica } from "@agentica/core";
2
2
  import { AutoBeAnalyzeRole } from "@autobe/interface";
3
3
  import { ILlmApplication, ILlmSchema } from "@samchon/openapi";
4
- import { IPointer } from "tstl";
5
4
  import typia from "typia";
6
5
 
7
6
  import { AutoBeContext } from "../../context/AutoBeContext";
@@ -12,10 +11,7 @@ import {
12
11
  IAutoBeAnalyzeFileSystem,
13
12
  IFile,
14
13
  } from "./AutoBeAnalyzeFileSystem";
15
- import {
16
- AutoBEAnalyzeFileMap,
17
- AutoBeAnalyzePointer,
18
- } from "./AutoBeAnalyzePointer";
14
+ import { AutoBEAnalyzeFileMap } from "./AutoBeAnalyzePointer";
19
15
  import { transformAnalyzeWriteHistories } from "./transformAnalyzeWriteHistories";
20
16
 
21
17
  export const orchestrateAnalyzeWrite = <Model extends ILlmSchema.Model>(
@@ -26,18 +22,13 @@ export const orchestrateAnalyzeWrite = <Model extends ILlmSchema.Model>(
26
22
  targetFile: string;
27
23
  roles: AutoBeAnalyzeRole[];
28
24
  review: string | null;
25
+ setDocument: (v: AutoBEAnalyzeFileMap) => void;
29
26
  },
30
- pointer: AutoBeAnalyzePointer,
31
- isAborted: IPointer<boolean>,
32
27
  ): MicroAgentica<Model> => {
33
28
  const controller = createController<Model>({
34
29
  model: ctx.model,
35
30
  execute: new AutoBeAnalyzeFileSystem({ [input.targetFile]: "" as const }),
36
- build: async (files: AutoBEAnalyzeFileMap) => {
37
- pointer.value ??= { files: {} };
38
- Object.assign(pointer.value.files, files);
39
- },
40
- abort: () => (isAborted.value = true),
31
+ setDocument: input.setDocument,
41
32
  });
42
33
 
43
34
  const agent = new MicroAgentica({
@@ -59,8 +50,7 @@ export const orchestrateAnalyzeWrite = <Model extends ILlmSchema.Model>(
59
50
  function createController<Model extends ILlmSchema.Model>(props: {
60
51
  model: Model;
61
52
  execute: AutoBeAnalyzeFileSystem;
62
- build: (input: AutoBEAnalyzeFileMap) => void;
63
- abort: () => void;
53
+ setDocument: (v: AutoBEAnalyzeFileMap) => void;
64
54
  }): IAgenticaController.IClass<Model> {
65
55
  assertSchemaModel(props.model);
66
56
  const application: ILlmApplication<Model> = collection[
@@ -71,15 +61,9 @@ function createController<Model extends ILlmSchema.Model>(props: {
71
61
  name: "Planning",
72
62
  application,
73
63
  execute: {
74
- abort: (input) => {
75
- const response = props.execute.abort(input);
76
- props.abort();
77
-
78
- return response;
79
- },
80
64
  createOrUpdateFiles: async (input) => {
81
65
  const fileMap = await props.execute.createOrUpdateFiles(input);
82
- props.build(fileMap);
66
+ props.setDocument(fileMap);
83
67
  return fileMap;
84
68
  },
85
69
  } satisfies IAutoBeAnalyzeFileSystem,
@@ -1,10 +1,12 @@
1
1
  import { AutoBeAnalyzeRole } from "@autobe/interface";
2
2
  import { ILlmSchema } from "@samchon/openapi";
3
- import { IPointer } from "tstl";
4
3
 
5
4
  import { AutoBeContext } from "../../context/AutoBeContext";
6
5
  import { IFile } from "./AutoBeAnalyzeFileSystem";
7
- import { AutoBeAnalyzePointer } from "./AutoBeAnalyzePointer";
6
+ import {
7
+ AutoBEAnalyzeFileMap,
8
+ AutoBeAnalyzePointer,
9
+ } from "./AutoBeAnalyzePointer";
8
10
  import { orchestrateAnalyzeReviewer } from "./orchestrateAnalyzeReviewer";
9
11
  import { orchestrateAnalyzeWrite } from "./orchestrateAnalyzeWrite";
10
12
 
@@ -12,68 +14,83 @@ export async function writeDocumentUntilReviewPassed<
12
14
  Model extends ILlmSchema.Model,
13
15
  >(
14
16
  ctx: AutoBeContext<Model>,
15
- pointer: AutoBeAnalyzePointer,
16
- totalFiles: Pick<IFile, "filename" | "reason">[],
17
- filename: string,
18
- roles: AutoBeAnalyzeRole[],
19
- progress: { total: number; completed: number },
20
- retry = 3,
17
+ props: {
18
+ totalFiles: Pick<IFile, "filename" | "reason">[];
19
+ filename: string;
20
+ roles: AutoBeAnalyzeRole[];
21
+ progress: { total: number; completed: number };
22
+ retry?: number;
23
+ prevReview?: string;
24
+ },
21
25
  ): Promise<AutoBeAnalyzePointer> {
22
- const isAborted: IPointer<boolean> = { value: false };
23
- let review: string | null = null;
24
- for (let i = 0; i < retry; i++) {
25
- if (isAborted.value === true) {
26
- return pointer;
27
- }
26
+ const retry = props.retry ?? 3;
27
+ const pointer: { value: { files: AutoBEAnalyzeFileMap } } = {
28
+ value: { files: {} },
29
+ };
28
30
 
29
- // Write the document until the review is passed.
30
- const write = "Write Document OR Abort." as const;
31
- const writer = orchestrateAnalyzeWrite(
32
- ctx,
33
- {
34
- totalFiles: totalFiles,
35
- roles: roles,
36
- targetFile: filename,
37
- review,
38
- },
39
- pointer,
40
- isAborted,
41
- );
31
+ /**
32
+ * `retry` means the number of times to retry the review. so if `retry` is -1,
33
+ * it means not execute this logic.
34
+ */
35
+ if (retry === -1) {
36
+ return pointer;
37
+ }
38
+
39
+ let isToolCalled = false;
40
+ const writer = orchestrateAnalyzeWrite(ctx, {
41
+ totalFiles: props.totalFiles,
42
+ roles: props.roles,
43
+ targetFile: props.filename,
44
+ review: props.prevReview ?? "",
45
+ setDocument: (v) => {
46
+ isToolCalled = true;
47
+ pointer.value = { files: { ...pointer.value?.files, ...v } };
48
+ },
49
+ });
50
+ await writer.conversate("Write Document.").finally(() => {
51
+ const tokenUsage = writer.getTokenUsage();
52
+ ctx.usage().record(tokenUsage, ["analyze"]);
53
+ });
42
54
 
43
- await writer.conversate(review ?? write).finally(() => {
44
- const tokenUsage = writer.getTokenUsage();
45
- ctx.usage().record(tokenUsage, ["analyze"]);
46
- });
55
+ if (isToolCalled === false) {
56
+ throw new Error("Failed to write document by unknown reason.");
57
+ }
47
58
 
48
- if (pointer.value === null) {
49
- throw new Error("Failed to write document by unknown reason.");
50
- }
59
+ ctx.dispatch({
60
+ type: "analyzeWrite",
61
+ files: {
62
+ ...pointer.value?.files,
63
+ },
64
+ total: props.progress.total,
65
+ completed: ++props.progress.completed,
66
+ step: ctx.state().analyze?.step ?? 0,
67
+ created_at: new Date().toISOString(),
68
+ });
51
69
 
52
- ctx.dispatch({
53
- type: "analyzeWrite",
54
- files: {
55
- ...pointer.value.files,
56
- },
57
- total: progress.total,
58
- completed: ++progress.completed,
59
- step: ctx.state().analyze?.step ?? 0,
60
- created_at: new Date().toISOString(),
61
- });
70
+ const reviewResult = await orchestrateAnalyzeReviewer(ctx, pointer.value);
62
71
 
63
- // Do review
64
- review = await orchestrateAnalyzeReviewer(ctx, pointer.value);
65
- if (review !== null)
66
- ctx.dispatch({
67
- type: "analyzeReview",
68
- files: {
69
- ...pointer.value.files,
70
- },
71
- review,
72
- total: progress.total,
73
- completed: progress.completed,
74
- step: ctx.state().analyze?.step ?? 0,
75
- created_at: new Date().toISOString(),
76
- });
72
+ if (reviewResult.type === "accept") {
73
+ return pointer;
77
74
  }
78
- return pointer;
75
+
76
+ ctx.dispatch({
77
+ type: "analyzeReview",
78
+ files: {
79
+ ...pointer.value.files,
80
+ },
81
+ review: reviewResult.value,
82
+ total: props.progress.total,
83
+ completed: props.progress.completed,
84
+ step: ctx.state().analyze?.step ?? 0,
85
+ created_at: new Date().toISOString(),
86
+ });
87
+
88
+ return await writeDocumentUntilReviewPassed(ctx, {
89
+ totalFiles: props.totalFiles,
90
+ filename: props.filename,
91
+ roles: props.roles,
92
+ progress: props.progress,
93
+ retry: retry - 1,
94
+ prevReview: reviewResult.value,
95
+ });
79
96
  }
@@ -40,9 +40,6 @@ export const transformPrismaComponentsHistories = (
40
40
  "Call the provided tool function to generate Prisma DB schema",
41
41
  "referencing below requirement analysis report.",
42
42
  "",
43
- "## User Request",
44
- state.analyze.reason,
45
- "",
46
43
  `## Requirement Analysis Report`,
47
44
  "",
48
45
  "```json",
@@ -69,14 +66,24 @@ export const transformPrismaComponentsHistories = (
69
66
  "",
70
67
  "* `mv_shopping_daily_stats`",
71
68
  "",
72
- "## User Role Handling",
73
- "",
74
- "If the Requirement Analysis Report contains User Role information, **do not normalize** user roles into a single table.",
75
- "Instead, create separate tables for each distinct role mentioned in the requirements.",
76
- "",
77
- "For example, if the requirements mention User, Admin, and Moderator roles:",
78
69
  "",
79
- "* Create separate tables: `User`, `Admin`, `Moderator` (or with prefix: `shopping_user`, `shopping_admin`, `shopping_moderator`)",
70
+ state.analyze.roles.length > 0
71
+ ? [
72
+ "## User Role Handling",
73
+ "",
74
+ `The Requirement Analysis Report contains the following user roles: ${state.analyze.roles.join(", ")}.`,
75
+ "",
76
+ "**Do not normalize** user roles into a single table.",
77
+ "Instead, create separate tables for each distinct role mentioned in the requirements.",
78
+ "",
79
+ "Create separate tables for each role:",
80
+ "",
81
+ state.analyze.roles
82
+ .map((role) => `* ${prefix}_${role.name.toLowerCase()}`)
83
+ .join("\n"),
84
+ "",
85
+ ].join("\n")
86
+ : "",
80
87
  ].join("\n"),
81
88
  },
82
89
  ];
@@ -0,0 +1,15 @@
1
+ import { AutoBeOpenApi } from "@autobe/interface";
2
+ import { hash } from "tstl";
3
+
4
+ export namespace ProviderCodeComparator {
5
+ export function hashCode(e: AutoBeOpenApi.IEndpoint): number {
6
+ return hash(e.path, e.method);
7
+ }
8
+
9
+ export function equals(
10
+ x: AutoBeOpenApi.IEndpoint,
11
+ y: AutoBeOpenApi.IEndpoint,
12
+ ): boolean {
13
+ return x.path === y.path && x.method === y.method;
14
+ }
15
+ }