@autobe/agent 0.3.17 → 0.3.19

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 (25) hide show
  1. package/lib/constants/AutoBeSystemPromptConstant.d.ts +3 -3
  2. package/lib/index.mjs +168 -152
  3. package/lib/index.mjs.map +1 -1
  4. package/lib/orchestrate/prisma/orchestratePrisma.js +2 -47
  5. package/lib/orchestrate/prisma/orchestratePrisma.js.map +1 -1
  6. package/lib/orchestrate/prisma/orchestratePrismaCompiler.d.ts +1 -3
  7. package/lib/orchestrate/prisma/orchestratePrismaCompiler.js +112 -106
  8. package/lib/orchestrate/prisma/orchestratePrismaCompiler.js.map +1 -1
  9. package/lib/orchestrate/prisma/orchestratePrismaSchema.js +1 -1
  10. package/lib/orchestrate/prisma/orchestratePrismaSchema.js.map +1 -1
  11. package/lib/orchestrate/prisma/transformPrismaCompilerHistories.d.ts +2 -2
  12. package/lib/orchestrate/prisma/transformPrismaCompilerHistories.js +22 -24
  13. package/lib/orchestrate/prisma/transformPrismaCompilerHistories.js.map +1 -1
  14. package/lib/orchestrate/prisma/transformPrismaHistories.js +1 -1
  15. package/lib/orchestrate/prisma/transformPrismaHistories.js.map +1 -1
  16. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.d.ts +6 -2
  17. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.js +20 -17
  18. package/lib/orchestrate/prisma/transformPrismaSchemaHistories.js.map +1 -1
  19. package/package.json +4 -4
  20. package/src/constants/AutoBeSystemPromptConstant.ts +3 -3
  21. package/src/orchestrate/prisma/orchestratePrisma.ts +3 -54
  22. package/src/orchestrate/prisma/orchestratePrismaCompiler.ts +174 -94
  23. package/src/orchestrate/prisma/orchestratePrismaSchema.ts +4 -2
  24. package/src/orchestrate/prisma/transformPrismaCompilerHistories.ts +22 -24
  25. package/src/orchestrate/prisma/transformPrismaSchemaHistories.ts +25 -17
@@ -2,7 +2,6 @@ import {
2
2
  AutoBeAssistantMessageHistory,
3
3
  AutoBePrismaComponentsEvent,
4
4
  AutoBePrismaHistory,
5
- IAutoBePrismaCompilerResult,
6
5
  } from "@autobe/interface";
7
6
  import { AutoBePrismaSchemasEvent } from "@autobe/interface/src/events/AutoBePrismaSchemasEvent";
8
7
  import { ILlmSchema } from "@samchon/openapi";
@@ -48,25 +47,20 @@ export const orchestratePrisma =
48
47
  events.map((e) => [e.filename, e.content]),
49
48
  );
50
49
 
51
- const { description, ...compiledResult } = await orchestratePrismaCompiler(
52
- ctx,
53
- files,
54
- );
55
-
56
- const result = processCompilerResult(compiledResult);
57
-
50
+ const result = await orchestratePrismaCompiler(ctx, files);
58
51
  const history: AutoBePrismaHistory = {
59
52
  type: "prisma",
60
53
  id: v4(),
61
54
  created_at: start.toISOString(),
62
55
  completed_at: new Date().toISOString(),
63
56
  reason: props.reason,
64
- description,
57
+ description: "",
65
58
  result: result,
66
59
  step: ctx.state().analyze?.step ?? 0,
67
60
  };
68
61
  ctx.state().prisma = history;
69
62
  ctx.histories().push(history);
63
+
70
64
  if (result.type === "success")
71
65
  ctx.dispatch({
72
66
  type: "prismaComplete",
@@ -76,50 +70,5 @@ export const orchestratePrisma =
76
70
  step: ctx.state().analyze?.step ?? 0,
77
71
  created_at: new Date().toISOString(),
78
72
  });
79
-
80
73
  return history;
81
74
  };
82
-
83
- /**
84
- * Process the compiler result to generate the main Prisma schema file.
85
- *
86
- * If the compiler result is a success, the main Prisma schema file will be
87
- * generated.
88
- *
89
- * @param result - The compiler result to process.
90
- * @returns The processed compiler result with the main Prisma schema file.
91
- */
92
- function processCompilerResult(
93
- result: IAutoBePrismaCompilerResult,
94
- ): IAutoBePrismaCompilerResult {
95
- const content = `
96
- generator client {
97
- provider = "prisma-client-js"
98
- previewFeatures = ["postgresqlExtensions", "views"]
99
- binaryTargets = ["native", "linux-musl-arm64-openssl-3.0.x"]
100
- }
101
-
102
- datasource db {
103
- provider = "postgresql"
104
- url = env("DATABASE_URL")
105
- extensions = []
106
- }
107
-
108
- generator markdown {
109
- provider = "prisma-markdown"
110
- output = "../docs/ERD.md"
111
- }
112
- `;
113
-
114
- if (result.type === "success") {
115
- return {
116
- ...result,
117
- schemas: {
118
- ...result.schemas,
119
- "main.prisma": content,
120
- },
121
- };
122
- }
123
-
124
- return result;
125
- }
@@ -6,15 +6,40 @@ import typia from "typia";
6
6
 
7
7
  import { AutoBeContext } from "../../context/AutoBeContext";
8
8
  import { assertSchemaModel } from "../../context/assertSchemaModel";
9
+ import { StringUtil } from "../../utils/StringUtil";
9
10
  import { transformPrismaCompilerHistories } from "./transformPrismaCompilerHistories";
10
11
 
11
- export async function orchestratePrismaCompiler<Model extends ILlmSchema.Model>(
12
+ export function orchestratePrismaCompiler<Model extends ILlmSchema.Model>(
12
13
  ctx: AutoBeContext<Model>,
13
14
  files: Record<string, string>,
14
- retry: number = 10,
15
- ): Promise<IAutoBePrismaCompilerResult & { description: string }> {
16
- const pointer: IPointer<IModifyPrismaSchemaFilesProps> = {
17
- value: { files, description: "" },
15
+ retry: number = 5,
16
+ ): Promise<IAutoBePrismaCompilerResult> {
17
+ files["main.prisma"] = MAIN_PRISMA_FILE;
18
+ return step(ctx, files, retry);
19
+ }
20
+
21
+ async function step<Model extends ILlmSchema.Model>(
22
+ ctx: AutoBeContext<Model>,
23
+ files: Record<string, string>,
24
+ life: number,
25
+ ): Promise<IAutoBePrismaCompilerResult> {
26
+ // TRY COMPILATION
27
+ const result: IAutoBePrismaCompilerResult = await ctx.compiler.prisma({
28
+ files,
29
+ });
30
+ if (result.type !== "failure" || life <= 0) return result;
31
+
32
+ // VALIDATION FAILED
33
+ ctx.dispatch({
34
+ type: "prismaValidate",
35
+ schemas: files,
36
+ result,
37
+ step: ctx.state().analyze?.step ?? 0,
38
+ created_at: new Date().toISOString(),
39
+ });
40
+
41
+ const pointer: IPointer<IModifyPrismaSchemaFilesProps | null> = {
42
+ value: null,
18
43
  };
19
44
  const agentica: MicroAgentica<Model> = new MicroAgentica({
20
45
  model: ctx.model,
@@ -22,7 +47,7 @@ export async function orchestratePrismaCompiler<Model extends ILlmSchema.Model>(
22
47
  config: {
23
48
  ...(ctx.config ?? {}),
24
49
  },
25
- histories: transformPrismaCompilerHistories(ctx.state(), files),
50
+ histories: transformPrismaCompilerHistories(files, result),
26
51
  tokenUsage: ctx.usage(),
27
52
  controllers: [
28
53
  createApplication({
@@ -33,77 +58,43 @@ export async function orchestratePrismaCompiler<Model extends ILlmSchema.Model>(
33
58
  }),
34
59
  ],
35
60
  });
36
-
37
61
  agentica.on("request", (event) => {
38
62
  if (event.body.tools) {
39
63
  event.body.tool_choice = "required";
40
64
  }
41
65
  });
42
66
 
43
- let result: IAutoBePrismaCompilerResult;
44
-
45
- for (let i: number = 0; i < retry; ++i) {
46
- result = await ctx.compiler.prisma({
47
- files: pointer.value?.files ?? files,
48
- });
49
-
50
- if (result.type !== "failure") break;
51
- ctx.dispatch({
52
- type: "prismaValidate",
53
- schemas: files,
54
- result,
55
- step: ctx.state().analyze?.step ?? 0,
56
- created_at: new Date().toISOString(),
57
- });
58
-
59
- await agentica.conversate(
60
- [
61
- "The Prisma schema files have compilation errors that must be fixed. You MUST provide complete, corrected files.",
62
- "",
63
- "============================================== CURRENT FILES ==============================================",
64
- "",
65
- ...Object.entries(pointer.value?.files ?? files).flatMap(
66
- ([filename, content]) => [`### ${filename} ###`, content, ""],
67
- ),
68
- "",
69
- "============================================== COMPILATION ERRORS ==============================================",
70
- "",
71
- result.reason,
72
- "",
73
- "============================================== REQUIREMENTS ==============================================",
74
- "",
75
- "CRITICAL: You must call the modifyPrismaSchemaFiles function with:",
76
- "",
77
- "1. **COMPLETE file contents** - Do NOT truncate or abbreviate any content",
78
- "2. **ALL files** - Every file from the input must be included in the output",
79
- "3. **Fixed errors** - Resolve all compilation errors shown above",
80
- "4. **Preserved structure** - Keep all models, fields, relationships, and comments",
81
- "5. **Proper syntax** - Ensure valid Prisma schema syntax",
82
- "",
83
- "IMPORTANT NOTES:",
84
- "- Include the ENTIRE content of each file, not summaries or truncated versions",
85
- "- Maintain all existing relationships between models",
86
- "- Keep all field definitions, attributes, and indexes",
87
- "- Preserve all comments and documentation",
88
- "- Fix ONLY the compilation errors, don't make unnecessary changes",
89
- "",
90
- "Example of what NOT to do:",
91
- "```",
92
- "// ... (truncated for brevity)",
93
- "// ... other fields and relationships",
94
- "// ... unchanged ...",
95
- "```",
96
- "",
97
- "You must provide the COMPLETE file content for each file.",
98
- ].join("\n"),
99
- );
67
+ // REQUEST CORRECTION
68
+ await agentica.conversate(
69
+ StringUtil.trim`
70
+ Resolve the compilation errors in the provided Prisma schema files.
100
71
 
101
- if (i === retry - 1) {
102
- throw new Error("Prisma schema compiler failed");
103
- }
72
+ Don't remake every schema files. Fix only some of the files that have
73
+ compilation errors. You MUST provide complete, corrected files.
74
+ `,
75
+ );
76
+ if (pointer.value === null) {
77
+ console.error(
78
+ "Unreachable error: PrismaCompilerAgent.pointer.value is null",
79
+ );
80
+ return result; // unreachable
104
81
  }
105
82
 
106
- return { ...result!, description: pointer.value.description };
83
+ ctx.dispatch({
84
+ type: "prismaCorrect",
85
+ input: files,
86
+ failure: result,
87
+ correction: pointer.value.files,
88
+ planning: pointer.value.planning,
89
+ step: ctx.state().analyze?.step ?? 0,
90
+ created_at: new Date().toISOString(),
91
+ });
92
+
93
+ const newFiles: Record<string, string> = {
94
+ ...files,
95
+ ...pointer.value.files,
96
+ };
97
+ return step(ctx, newFiles, life - 1);
107
98
  }
108
99
 
109
100
  function createApplication<Model extends ILlmSchema.Model>(props: {
@@ -146,49 +137,138 @@ const collection = {
146
137
 
147
138
  interface IApplication {
148
139
  /**
149
- * Fixes compilation errors in Prisma schema files.
140
+ * Fixes Prisma compilation errors while preserving ALL existing comments,
141
+ * documentation, and schema structure.
142
+ *
143
+ * ## Core Rules
150
144
  *
151
- * CRITICAL: This function must return COMPLETE file contents, not truncated
152
- * versions.
145
+ * 1. Fix ONLY compilation errors - never remove comments/documentation
146
+ * 2. Apply minimal changes - preserve original design and relationships
147
+ * 3. Return COMPLETE files - no truncation allowed
148
+ * 4. NEVER use mapping names in @relation directives
153
149
  *
154
- * Responsibilities:
150
+ * ## Preservation Requirements
155
151
  *
156
- * 1. Analyze compilation errors in the provided schema files
157
- * 2. Fix all syntax and structural issues
158
- * 3. Return COMPLETE corrected files (no truncation or abbreviation)
159
- * 4. Preserve all existing models, relationships, and business logic
160
- * 5. Maintain proper cross-file references and dependencies
152
+ * - Keep ALL comments (`//` and `///`)
153
+ * - Keep ALL field/model documentation
154
+ * - Keep business logic and architectural patterns
155
+ * - Remove description comments only when erasing properties/relationships
161
156
  *
162
- * @param props Contains files to fix and requires complete file contents in
163
- * response
157
+ * ## Fix Strategy
158
+ *
159
+ * - Resolve syntax/relationship errors without changing structure
160
+ * - Remove mapping names from @relation directives if present
161
+ * - Add missing foreign keys/constraints while preserving documentation
164
162
  */
165
163
  modifyPrismaSchemaFiles(props: IModifyPrismaSchemaFilesProps): void;
166
164
  }
167
165
 
168
166
  interface IModifyPrismaSchemaFilesProps {
169
167
  /**
170
- * COMPLETE Prisma schema files with ALL content included.
168
+ * Detailed execution plan for fixing Prisma compilation errors.
169
+ *
170
+ * 🎯 Purpose: Enable systematic reasoning and step-by-step error resolution
171
+ * approach
172
+ *
173
+ * 📋 Required Planning Content:
174
+ *
175
+ * 1. **Error Analysis Summary**
176
+ *
177
+ * - List all identified compilation errors with their locations
178
+ * - Categorize errors by type (syntax, relationships, types, constraints)
179
+ * - Identify root causes and error interdependencies
180
+ * 2. **Fix Strategy Overview**
171
181
  *
172
- * CRITICAL REQUIREMENTS:
182
+ * - Prioritize fixes based on dependencies (fix foundational errors first)
183
+ * - Outline minimal changes needed for each error
184
+ * - Identify potential impact on other schema parts
185
+ * 3. **Step-by-Step Fix Plan**
173
186
  *
174
- * - Each file must contain the ENTIRE schema content
175
- * - Do NOT truncate, abbreviate, or use placeholders like "... unchanged ..."
176
- * - Include ALL models, fields, relationships, indexes, and comments
177
- * - Maintain exact same file organization and naming
187
+ * - File-by-file modification plan with specific changes
188
+ * - Exact line numbers or sections to be modified
189
+ * - New code additions or corrections to be applied
190
+ * - Verification steps to ensure fixes don't break other parts
191
+ * 4. **Preservation Checklist**
178
192
  *
179
- * File organization patterns:
193
+ * - Confirm which comments/documentation must be preserved
194
+ * - List relationships and business logic to maintain unchanged
195
+ * - Identify cross-file dependencies that must remain intact
196
+ * 5. **Risk Assessment**
180
197
  *
181
- * - Main.prisma: Configuration, datasource, generators
182
- * - Schema-XX-domain.prisma: Complete domain-specific models with ALL fields
198
+ * - Potential side effects of each planned fix
199
+ * - Validation points to check after applying fixes
200
+ * - Rollback considerations if fixes introduce new issues
183
201
  *
184
- * Key = filename (e.g., "main.prisma", "schema-01-core.prisma") Value =
185
- * COMPLETE file content (no truncation allowed)
202
+ * 💡 Example Planning Structure:
203
+ *
204
+ * ## Error Analysis
205
+ * - Error 1: Missing foreign key field 'userId' in Post model (schema-02-posts.prisma:15)
206
+ * - Error 2: Invalid @relation reference to non-existent 'User.posts' (schema-01-users.prisma:8)
207
+ *
208
+ * ## Fix Strategy
209
+ * 1. Add missing 'userId String' field to Post model
210
+ * 2. Update @relation mapping in User model to reference correct field
211
+ *
212
+ * ## Detailed Steps
213
+ * 1. schema-02-posts.prisma: Add 'userId String' after line 14
214
+ * 2. schema-01-users.prisma: Fix @relation(fields: [userId], references: [id])
215
+ *
216
+ * ## Preservation Notes
217
+ * - Keep all existing comments in Post model
218
+ * - Maintain User model documentation
219
+ * - Preserve existing indexes and constraints
186
220
  */
187
- files: Record<string, string>;
221
+ planning: string;
188
222
 
189
223
  /**
190
- * Brief description of what was fixed or modified in the schema files. Should
191
- * summarize the changes made to resolve compilation errors.
224
+ * Original Prisma schema files that contain compilation errors and need
225
+ * correction.
226
+ *
227
+ * 📥 Input Structure:
228
+ *
229
+ * - Key: filename (e.g., "schema-01-users.prisma")
230
+ * - Value: COMPLETE original file content with compilation errors
231
+ *
232
+ * 🔍 Expected Input File Types:
233
+ *
234
+ * - Domain-specific schema files: "schema-XX-domain.prisma" → Contains complete
235
+ * model definitions for specific business domains
236
+ *
237
+ * 📝 Input File Content Analysis:
238
+ *
239
+ * - All models with their complete field definitions
240
+ * - All relationships (@relation directives with field mappings)
241
+ * - All indexes, constraints, and unique identifiers
242
+ * - All enums and their complete value sets
243
+ * - All comments and documentation
244
+ * - Cross-file model references and dependencies
245
+ *
246
+ * ⚠️ Input Processing Notes:
247
+ *
248
+ * - Files may contain syntax errors, type mismatches, or missing references
249
+ * - Some models might reference non-existent fields or models
250
+ * - Relationship mappings might be incorrect or incomplete
251
+ * - Foreign key fields might be missing or incorrectly defined
252
+ * - Cross-file dependencies might be broken or circular
192
253
  */
193
- description: string;
254
+ files: Record<string, string>;
194
255
  }
256
+
257
+ const MAIN_PRISMA_FILE = StringUtil.trim`
258
+ generator client {
259
+ provider = "prisma-client-js"
260
+ previewFeatures = ["postgresqlExtensions", "views"]
261
+ binaryTargets = ["native", "linux-musl-arm64-openssl-3.0.x"]
262
+ }
263
+
264
+ datasource db {
265
+ provider = "postgresql"
266
+ url = env("DATABASE_URL")
267
+ extensions = []
268
+ }
269
+
270
+ generator markdown {
271
+ provider = "prisma-markdown"
272
+ output = "../docs/ERD.md"
273
+ }
274
+ `;
@@ -44,7 +44,9 @@ export async function orchestratePrismaSchemas<Model extends ILlmSchema.Model>(
44
44
 
45
45
  async function process<Model extends ILlmSchema.Model>(
46
46
  ctx: AutoBeContext<Model>,
47
- component: { filename: string; tables: string[] } & {
47
+ component: {
48
+ filename: string;
49
+ tables: string[];
48
50
  entireTables: string[];
49
51
  },
50
52
  ): Promise<IMakePrismaSchemaFilesProps> {
@@ -57,7 +59,7 @@ async function process<Model extends ILlmSchema.Model>(
57
59
  config: {
58
60
  ...(ctx.config ?? {}),
59
61
  },
60
- histories: transformPrismaSchemaHistories(ctx.state()),
62
+ histories: transformPrismaSchemaHistories(ctx.state().analyze!, component),
61
63
  tokenUsage: ctx.usage(),
62
64
  controllers: [
63
65
  createApplication({
@@ -1,25 +1,14 @@
1
1
  import { IAgenticaHistoryJson } from "@agentica/core";
2
+ import { IAutoBePrismaCompilerResult } from "@autobe/interface";
2
3
 
3
4
  import { AutoBeSystemPromptConstant } from "../../constants/AutoBeSystemPromptConstant";
4
- import { AutoBeState } from "../../context/AutoBeState";
5
5
 
6
6
  export const transformPrismaCompilerHistories = (
7
- state: AutoBeState,
8
7
  files: Record<string, string>,
8
+ result: IAutoBePrismaCompilerResult.IFailure,
9
9
  ): Array<
10
10
  IAgenticaHistoryJson.IAssistantMessage | IAgenticaHistoryJson.ISystemMessage
11
11
  > => {
12
- if (state.analyze === null)
13
- return [
14
- {
15
- type: "systemMessage",
16
- text: [
17
- "Requirement analysis is not yet completed.",
18
- "Don't call any tool function,",
19
- "but say to process the requirement analysis.",
20
- ].join(" "),
21
- },
22
- ];
23
12
  return [
24
13
  {
25
14
  type: "systemMessage",
@@ -30,19 +19,28 @@ export const transformPrismaCompilerHistories = (
30
19
  text: [
31
20
  "Below are the current schema files that failed compilation:",
32
21
  "",
33
- "============================================== CURRENT SCHEMA FILES ==============================================",
22
+ "```json",
23
+ JSON.stringify(files),
24
+ "```",
25
+ ].join("\n"),
26
+ },
27
+ {
28
+ type: "assistantMessage",
29
+ text: [
30
+ `Here is the compiler error message. Please fix the schema files`,
31
+ `referencing the error message.`,
34
32
  "",
35
- Object.entries(files)
36
- .map(([filename, content]) => {
37
- return [
38
- `// =============================================================================`,
39
- `// FILE: ${filename}`,
40
- `// =============================================================================`,
41
- content,
42
- ].join("\n");
43
- })
44
- .join("\n\n"),
33
+ result.reason,
34
+ ].join("\n"),
35
+ },
36
+ {
37
+ type: "systemMessage",
38
+ text: [
39
+ "Before fixing the schema files,",
40
+ "study about Prisma schema language",
41
+ "from the best practices and examples",
45
42
  "",
43
+ AutoBeSystemPromptConstant.PRISMA_EXAMPLE,
46
44
  ].join("\n"),
47
45
  },
48
46
  ];
@@ -1,32 +1,32 @@
1
1
  import { IAgenticaHistoryJson } from "@agentica/core";
2
+ import { AutoBeAnalyzeHistory } from "@autobe/interface";
2
3
 
3
4
  import { AutoBeSystemPromptConstant } from "../../constants/AutoBeSystemPromptConstant";
4
- import { AutoBeState } from "../../context/AutoBeState";
5
5
 
6
6
  export const transformPrismaSchemaHistories = (
7
- state: AutoBeState,
7
+ analyze: AutoBeAnalyzeHistory,
8
+ component: {
9
+ filename: string;
10
+ tables: string[];
11
+ entireTables: string[];
12
+ },
8
13
  ): Array<
9
14
  IAgenticaHistoryJson.IAssistantMessage | IAgenticaHistoryJson.ISystemMessage
10
15
  > => {
11
- if (state.analyze === null)
12
- return [
13
- {
14
- type: "systemMessage",
15
- text: [
16
- "Requirement analysis is not yet completed.",
17
- "Don't call any tool function,",
18
- "but say to process the requirement analysis.",
19
- ].join(" "),
20
- },
21
- ];
22
16
  return [
23
17
  {
24
18
  type: "systemMessage",
25
19
  text: AutoBeSystemPromptConstant.PRISMA_SCHEMA,
26
20
  },
27
21
  {
28
- type: "assistantMessage",
29
- text: AutoBeSystemPromptConstant.PRISMA_EXAMPLE,
22
+ type: "systemMessage",
23
+ text: [
24
+ "Before making prisma schema files,",
25
+ "learn about the prisma schema language",
26
+ "from the best practices and examples",
27
+ "",
28
+ AutoBeSystemPromptConstant.PRISMA_EXAMPLE,
29
+ ].join("\n"),
30
30
  },
31
31
  {
32
32
  type: "assistantMessage",
@@ -37,13 +37,21 @@ export const transformPrismaSchemaHistories = (
37
37
  "referencing below requirement analysis report.",
38
38
  "",
39
39
  "## User Request",
40
- state.analyze.reason,
40
+ analyze.reason,
41
41
  "",
42
42
  `## Requirement Analysis Report`,
43
43
  "",
44
44
  "```json",
45
- JSON.stringify(state.analyze.files),
45
+ JSON.stringify(analyze.files),
46
46
  "```",
47
+ "",
48
+ "## Context",
49
+ "",
50
+ ` - Target filename: ${component.filename}`,
51
+ ` - Tables what you have to make:`,
52
+ ...component.tables.map((table) => ` - ${table}`),
53
+ ` - Entire tables you can reference:`,
54
+ ...component.entireTables.map((table) => ` - ${table}`),
47
55
  ].join("\n"),
48
56
  },
49
57
  ];