@agiflowai/scaffold-mcp 1.0.3 → 1.0.5
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.
- package/dist/{ScaffoldConfigLoader-DQMCLVGD.cjs → ScaffoldConfigLoader-B-NLy6VP.cjs} +1 -1
- package/dist/{ScaffoldConfigLoader-CI0T6zdG.js → ScaffoldConfigLoader-BDMJNI1o.mjs} +1 -1
- package/dist/ScaffoldConfigLoader-SHk-KEje.mjs +3 -0
- package/dist/{ScaffoldConfigLoader-BrmvENTo.cjs → ScaffoldConfigLoader-Y_SBLPg7.cjs} +0 -1
- package/dist/ScaffoldService-BNOyoqSb.cjs +3 -0
- package/dist/ScaffoldService-BNdfC21Z.mjs +3 -0
- package/dist/{ScaffoldService-DB7-Cyod.js → ScaffoldService-BNuN00Fm.mjs} +8 -8
- package/dist/{ScaffoldService-BwDmXt83.cjs → ScaffoldService-ChzxM0Yc.cjs} +1 -3
- package/dist/TemplateService-BRfzfaZs.mjs +3 -0
- package/dist/{TemplateService-CiZJA06s.js → TemplateService-Cg5QV29n.mjs} +1 -1
- package/dist/{TemplateService-DRubcvS9.cjs → TemplateService-D3ydJR_R.cjs} +0 -2
- package/dist/TemplateService-DqieT1Tq.cjs +3 -0
- package/dist/VariableReplacementService-BWCd-z7X.mjs +3 -0
- package/dist/{VariableReplacementService-D0QnWKUW.cjs → VariableReplacementService-CAjesAYq.cjs} +1 -2
- package/dist/{VariableReplacementService-DRxd9ILB.js → VariableReplacementService-DHIINRnJ.mjs} +5 -5
- package/dist/{VariableReplacementService-CroHkMha.cjs → VariableReplacementService-DKaF2C9l.cjs} +1 -1
- package/dist/cli.cjs +27 -124
- package/dist/{cli.js → cli.mjs} +27 -120
- package/dist/index.cjs +14 -18
- package/dist/{index.d.ts → index.d.mts} +1 -1
- package/dist/{index.js → index.mjs} +14 -16
- package/dist/{stdio-DM_C4xbZ.cjs → stdio-BGj_FLky.cjs} +410 -423
- package/dist/{stdio-BheRzmRj.js → stdio-wAlpLC6l.mjs} +413 -418
- package/package.json +6 -8
- package/dist/ScaffoldConfigLoader-DhthV6xq.js +0 -3
- package/dist/ScaffoldService-B3En_m4t.cjs +0 -3
- package/dist/ScaffoldService-CJ3vNmAj.js +0 -3
- package/dist/TemplateService-BZRt3NI8.cjs +0 -3
- package/dist/TemplateService-DropYdp8.js +0 -3
- package/dist/VariableReplacementService-BAwTGv_R.js +0 -3
- /package/dist/{cli.d.ts → cli.d.mts} +0 -0
|
@@ -1,33 +1,183 @@
|
|
|
1
1
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
2
|
-
const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-
|
|
3
|
-
const require_ScaffoldService = require('./ScaffoldService-
|
|
4
|
-
const require_TemplateService = require('./TemplateService-
|
|
5
|
-
const require_VariableReplacementService = require('./VariableReplacementService-
|
|
6
|
-
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
7
|
-
__agiflowai_aicode_utils = require_chunk.__toESM(__agiflowai_aicode_utils);
|
|
2
|
+
const require_ScaffoldConfigLoader = require('./ScaffoldConfigLoader-Y_SBLPg7.cjs');
|
|
3
|
+
const require_ScaffoldService = require('./ScaffoldService-ChzxM0Yc.cjs');
|
|
4
|
+
const require_TemplateService = require('./TemplateService-D3ydJR_R.cjs');
|
|
5
|
+
const require_VariableReplacementService = require('./VariableReplacementService-CAjesAYq.cjs');
|
|
8
6
|
let node_path = require("node:path");
|
|
9
7
|
node_path = require_chunk.__toESM(node_path);
|
|
10
|
-
let
|
|
11
|
-
__composio_json_schema_to_zod = require_chunk.__toESM(__composio_json_schema_to_zod);
|
|
12
|
-
let fs_extra = require("fs-extra");
|
|
13
|
-
fs_extra = require_chunk.__toESM(fs_extra);
|
|
8
|
+
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
14
9
|
let js_yaml = require("js-yaml");
|
|
15
10
|
js_yaml = require_chunk.__toESM(js_yaml);
|
|
11
|
+
let node_fs = require("node:fs");
|
|
12
|
+
let __composio_json_schema_to_zod = require("@composio/json-schema-to-zod");
|
|
16
13
|
let zod = require("zod");
|
|
17
|
-
zod = require_chunk.__toESM(zod);
|
|
18
|
-
let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
|
|
19
|
-
__modelcontextprotocol_sdk_types_js = require_chunk.__toESM(__modelcontextprotocol_sdk_types_js);
|
|
20
14
|
let node_crypto = require("node:crypto");
|
|
21
|
-
node_crypto = require_chunk.__toESM(node_crypto);
|
|
22
15
|
let __modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
23
|
-
|
|
16
|
+
let __modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
|
|
24
17
|
let express = require("express");
|
|
25
18
|
express = require_chunk.__toESM(express);
|
|
26
19
|
let __modelcontextprotocol_sdk_server_sse_js = require("@modelcontextprotocol/sdk/server/sse.js");
|
|
27
|
-
__modelcontextprotocol_sdk_server_sse_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_sse_js);
|
|
28
20
|
let __modelcontextprotocol_sdk_server_stdio_js = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
29
|
-
__modelcontextprotocol_sdk_server_stdio_js = require_chunk.__toESM(__modelcontextprotocol_sdk_server_stdio_js);
|
|
30
21
|
|
|
22
|
+
//#region src/services/BoilerplateGeneratorService.ts
|
|
23
|
+
/**
|
|
24
|
+
* Service for generating boilerplate configurations in scaffold.yaml files
|
|
25
|
+
*/
|
|
26
|
+
var BoilerplateGeneratorService = class {
|
|
27
|
+
templatesPath;
|
|
28
|
+
constructor(templatesPath) {
|
|
29
|
+
this.templatesPath = templatesPath;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Custom YAML dumper that forces literal block style (|) for description and instruction fields
|
|
33
|
+
*/
|
|
34
|
+
dumpYamlWithLiteralBlocks(config) {
|
|
35
|
+
const LiteralBlockType = new js_yaml.Type("tag:yaml.org,2002:str", {
|
|
36
|
+
kind: "scalar",
|
|
37
|
+
construct: (data) => data,
|
|
38
|
+
represent: (data) => {
|
|
39
|
+
return data;
|
|
40
|
+
},
|
|
41
|
+
defaultStyle: "|"
|
|
42
|
+
});
|
|
43
|
+
const LITERAL_SCHEMA = js_yaml.DEFAULT_SCHEMA.extend([LiteralBlockType]);
|
|
44
|
+
const processedConfig = this.processConfigForLiteralBlocks(config);
|
|
45
|
+
return js_yaml.dump(processedConfig, {
|
|
46
|
+
schema: LITERAL_SCHEMA,
|
|
47
|
+
indent: 2,
|
|
48
|
+
lineWidth: -1,
|
|
49
|
+
noRefs: true,
|
|
50
|
+
sortKeys: false,
|
|
51
|
+
styles: { "!!str": "literal" },
|
|
52
|
+
replacer: (key, value) => {
|
|
53
|
+
if ((key === "description" || key === "instruction") && typeof value === "string") return value;
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Process config to ensure description and instruction use literal block style
|
|
60
|
+
*/
|
|
61
|
+
processConfigForLiteralBlocks(config) {
|
|
62
|
+
const processed = JSON.parse(JSON.stringify(config));
|
|
63
|
+
if (processed.boilerplate) processed.boilerplate = processed.boilerplate.map((bp) => {
|
|
64
|
+
const newBp = { ...bp };
|
|
65
|
+
if (newBp.description && typeof newBp.description === "string") newBp.description = this.ensureMultilineFormat(newBp.description);
|
|
66
|
+
if (newBp.instruction && typeof newBp.instruction === "string") newBp.instruction = this.ensureMultilineFormat(newBp.instruction);
|
|
67
|
+
return newBp;
|
|
68
|
+
});
|
|
69
|
+
if (processed.features) processed.features = processed.features.map((feature) => {
|
|
70
|
+
const newFeature = { ...feature };
|
|
71
|
+
if (newFeature.description && typeof newFeature.description === "string") newFeature.description = this.ensureMultilineFormat(newFeature.description);
|
|
72
|
+
if (newFeature.instruction && typeof newFeature.instruction === "string") newFeature.instruction = this.ensureMultilineFormat(newFeature.instruction);
|
|
73
|
+
return newFeature;
|
|
74
|
+
});
|
|
75
|
+
return processed;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Ensure string is properly formatted for YAML literal blocks
|
|
79
|
+
*/
|
|
80
|
+
ensureMultilineFormat(text) {
|
|
81
|
+
return text.trim();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Generate or update a boilerplate configuration in scaffold.yaml
|
|
85
|
+
*/
|
|
86
|
+
async generateBoilerplate(options) {
|
|
87
|
+
const { templateName, boilerplateName, description, instruction, targetFolder, variables, includes = [] } = options;
|
|
88
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
89
|
+
await (0, __agiflowai_aicode_utils.ensureDir)(templatePath);
|
|
90
|
+
const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
|
|
91
|
+
let scaffoldConfig = {};
|
|
92
|
+
if (await (0, __agiflowai_aicode_utils.pathExists)(scaffoldYamlPath)) {
|
|
93
|
+
const yamlContent = await (0, __agiflowai_aicode_utils.readFile)(scaffoldYamlPath, "utf-8");
|
|
94
|
+
scaffoldConfig = js_yaml.load(yamlContent);
|
|
95
|
+
}
|
|
96
|
+
if (!scaffoldConfig.boilerplate) scaffoldConfig.boilerplate = [];
|
|
97
|
+
if (scaffoldConfig.boilerplate.findIndex((b) => b.name === boilerplateName) !== -1) return {
|
|
98
|
+
success: false,
|
|
99
|
+
message: `Boilerplate '${boilerplateName}' already exists in ${scaffoldYamlPath}`
|
|
100
|
+
};
|
|
101
|
+
const requiredVars = variables.filter((v) => v.required).map((v) => v.name);
|
|
102
|
+
const boilerplateDefinition = {
|
|
103
|
+
name: boilerplateName,
|
|
104
|
+
targetFolder,
|
|
105
|
+
description,
|
|
106
|
+
variables_schema: {
|
|
107
|
+
type: "object",
|
|
108
|
+
properties: variables.reduce((acc, v) => {
|
|
109
|
+
acc[v.name] = {
|
|
110
|
+
type: v.type,
|
|
111
|
+
description: v.description
|
|
112
|
+
};
|
|
113
|
+
if (v.default !== void 0) acc[v.name].default = v.default;
|
|
114
|
+
return acc;
|
|
115
|
+
}, {}),
|
|
116
|
+
required: requiredVars,
|
|
117
|
+
additionalProperties: false
|
|
118
|
+
},
|
|
119
|
+
includes: includes.length > 0 ? includes : []
|
|
120
|
+
};
|
|
121
|
+
if (instruction) boilerplateDefinition.instruction = instruction;
|
|
122
|
+
scaffoldConfig.boilerplate.push(boilerplateDefinition);
|
|
123
|
+
await (0, __agiflowai_aicode_utils.writeFile)(scaffoldYamlPath, this.dumpYamlWithLiteralBlocks(scaffoldConfig), "utf-8");
|
|
124
|
+
return {
|
|
125
|
+
success: true,
|
|
126
|
+
message: `Boilerplate '${boilerplateName}' added to ${scaffoldYamlPath}`,
|
|
127
|
+
templatePath,
|
|
128
|
+
scaffoldYamlPath
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* List all templates (directories in templates folder)
|
|
133
|
+
*/
|
|
134
|
+
async listTemplates() {
|
|
135
|
+
return (await (0, __agiflowai_aicode_utils.readdir)(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Check if a template exists
|
|
139
|
+
*/
|
|
140
|
+
async templateExists(templateName) {
|
|
141
|
+
return (0, __agiflowai_aicode_utils.pathExists)(node_path.join(this.templatesPath, templateName));
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Create or update a template file for a boilerplate
|
|
145
|
+
*/
|
|
146
|
+
async createTemplateFile(options) {
|
|
147
|
+
const { templateName, filePath, content, sourceFile, header } = options;
|
|
148
|
+
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
149
|
+
if (!await (0, __agiflowai_aicode_utils.pathExists)(templatePath)) return {
|
|
150
|
+
success: false,
|
|
151
|
+
message: `Template directory '${templateName}' does not exist at ${templatePath}`
|
|
152
|
+
};
|
|
153
|
+
let fileContent = content || "";
|
|
154
|
+
if (sourceFile) {
|
|
155
|
+
if (!await (0, __agiflowai_aicode_utils.pathExists)(sourceFile)) return {
|
|
156
|
+
success: false,
|
|
157
|
+
message: `Source file '${sourceFile}' does not exist`
|
|
158
|
+
};
|
|
159
|
+
fileContent = await (0, __agiflowai_aicode_utils.readFile)(sourceFile, "utf-8");
|
|
160
|
+
}
|
|
161
|
+
if (!fileContent && !sourceFile) return {
|
|
162
|
+
success: false,
|
|
163
|
+
message: "Either content or sourceFile must be provided"
|
|
164
|
+
};
|
|
165
|
+
const templateFilePath = filePath.endsWith(".liquid") ? filePath : `${filePath}.liquid`;
|
|
166
|
+
const fullPath = node_path.join(templatePath, templateFilePath);
|
|
167
|
+
await (0, __agiflowai_aicode_utils.ensureDir)(node_path.dirname(fullPath));
|
|
168
|
+
let finalContent = fileContent;
|
|
169
|
+
if (header) finalContent = `${header}\n\n${fileContent}`;
|
|
170
|
+
await (0, __agiflowai_aicode_utils.writeFile)(fullPath, finalContent, "utf-8");
|
|
171
|
+
return {
|
|
172
|
+
success: true,
|
|
173
|
+
message: "Template file created successfully",
|
|
174
|
+
filePath: templateFilePath,
|
|
175
|
+
fullPath
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
//#endregion
|
|
31
181
|
//#region src/utils/pagination.ts
|
|
32
182
|
var PaginationHelper = class PaginationHelper {
|
|
33
183
|
/**
|
|
@@ -81,28 +231,28 @@ var PaginationHelper = class PaginationHelper {
|
|
|
81
231
|
//#region src/services/FileSystemService.ts
|
|
82
232
|
var FileSystemService = class {
|
|
83
233
|
async pathExists(path$2) {
|
|
84
|
-
return
|
|
234
|
+
return (0, __agiflowai_aicode_utils.pathExists)(path$2);
|
|
85
235
|
}
|
|
86
236
|
async readFile(path$2, encoding = "utf8") {
|
|
87
|
-
return
|
|
237
|
+
return (0, __agiflowai_aicode_utils.readFile)(path$2, encoding);
|
|
88
238
|
}
|
|
89
239
|
async readJson(path$2) {
|
|
90
|
-
return
|
|
240
|
+
return (0, __agiflowai_aicode_utils.readJson)(path$2);
|
|
91
241
|
}
|
|
92
242
|
async writeFile(path$2, content, encoding = "utf8") {
|
|
93
|
-
return
|
|
243
|
+
return (0, __agiflowai_aicode_utils.writeFile)(path$2, content, encoding);
|
|
94
244
|
}
|
|
95
245
|
async ensureDir(path$2) {
|
|
96
|
-
return
|
|
246
|
+
return (0, __agiflowai_aicode_utils.ensureDir)(path$2);
|
|
97
247
|
}
|
|
98
248
|
async copy(src, dest) {
|
|
99
|
-
return
|
|
249
|
+
return (0, __agiflowai_aicode_utils.copy)(src, dest);
|
|
100
250
|
}
|
|
101
251
|
async readdir(path$2) {
|
|
102
|
-
return
|
|
252
|
+
return (0, __agiflowai_aicode_utils.readdir)(path$2);
|
|
103
253
|
}
|
|
104
254
|
async stat(path$2) {
|
|
105
|
-
return
|
|
255
|
+
return (0, __agiflowai_aicode_utils.stat)(path$2);
|
|
106
256
|
}
|
|
107
257
|
};
|
|
108
258
|
|
|
@@ -128,8 +278,8 @@ var BoilerplateService = class {
|
|
|
128
278
|
const templateDirs = await this.discoverTemplateDirectories();
|
|
129
279
|
for (const templatePath of templateDirs) {
|
|
130
280
|
const scaffoldYamlPath = node_path.join(this.templatesPath, templatePath, "scaffold.yaml");
|
|
131
|
-
if (
|
|
132
|
-
const scaffoldContent =
|
|
281
|
+
if ((0, __agiflowai_aicode_utils.pathExistsSync)(scaffoldYamlPath)) try {
|
|
282
|
+
const scaffoldContent = (0, __agiflowai_aicode_utils.readFileSync)(scaffoldYamlPath, "utf8");
|
|
133
283
|
const scaffoldConfig = js_yaml.load(scaffoldContent);
|
|
134
284
|
if (scaffoldConfig.boilerplate) for (const boilerplate of scaffoldConfig.boilerplate) {
|
|
135
285
|
if (!boilerplate.targetFolder) {
|
|
@@ -164,14 +314,14 @@ var BoilerplateService = class {
|
|
|
164
314
|
async discoverTemplateDirectories() {
|
|
165
315
|
const templateDirs = [];
|
|
166
316
|
const findTemplates = (dir, baseDir = "") => {
|
|
167
|
-
if (!
|
|
168
|
-
const items =
|
|
317
|
+
if (!(0, __agiflowai_aicode_utils.pathExistsSync)(dir)) return;
|
|
318
|
+
const items = (0, node_fs.readdirSync)(dir);
|
|
169
319
|
const hasPackageJson = items.includes("package.json") || items.includes("package.json.liquid");
|
|
170
320
|
const hasScaffoldYaml = items.includes("scaffold.yaml");
|
|
171
321
|
if (hasPackageJson && hasScaffoldYaml) templateDirs.push(baseDir);
|
|
172
322
|
for (const item of items) {
|
|
173
323
|
const itemPath = node_path.join(dir, item);
|
|
174
|
-
if (
|
|
324
|
+
if ((0, __agiflowai_aicode_utils.statSync)(itemPath).isDirectory() && !item.startsWith(".") && item !== "node_modules") findTemplates(itemPath, baseDir ? node_path.join(baseDir, item) : item);
|
|
175
325
|
}
|
|
176
326
|
};
|
|
177
327
|
findTemplates(this.templatesPath);
|
|
@@ -305,11 +455,11 @@ var BoilerplateService = class {
|
|
|
305
455
|
};
|
|
306
456
|
|
|
307
457
|
//#endregion
|
|
308
|
-
//#region src/services/
|
|
458
|
+
//#region src/services/ScaffoldGeneratorService.ts
|
|
309
459
|
/**
|
|
310
|
-
* Service for generating
|
|
460
|
+
* Service for generating feature scaffold configurations in scaffold.yaml files
|
|
311
461
|
*/
|
|
312
|
-
var
|
|
462
|
+
var ScaffoldGeneratorService = class {
|
|
313
463
|
templatesPath;
|
|
314
464
|
constructor(templatesPath) {
|
|
315
465
|
this.templatesPath = templatesPath;
|
|
@@ -367,27 +517,26 @@ var BoilerplateGeneratorService = class {
|
|
|
367
517
|
return text.trim();
|
|
368
518
|
}
|
|
369
519
|
/**
|
|
370
|
-
* Generate or update a
|
|
520
|
+
* Generate or update a feature configuration in scaffold.yaml
|
|
371
521
|
*/
|
|
372
|
-
async
|
|
373
|
-
const { templateName,
|
|
522
|
+
async generateFeatureScaffold(options) {
|
|
523
|
+
const { templateName, featureName, description, instruction, variables, includes = [], patterns = [] } = options;
|
|
374
524
|
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
375
|
-
await
|
|
525
|
+
await (0, __agiflowai_aicode_utils.ensureDir)(templatePath);
|
|
376
526
|
const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
|
|
377
527
|
let scaffoldConfig = {};
|
|
378
|
-
if (await
|
|
379
|
-
const yamlContent
|
|
380
|
-
scaffoldConfig = js_yaml.load(yamlContent
|
|
528
|
+
if (await (0, __agiflowai_aicode_utils.pathExists)(scaffoldYamlPath)) {
|
|
529
|
+
const yamlContent = await (0, __agiflowai_aicode_utils.readFile)(scaffoldYamlPath, "utf-8");
|
|
530
|
+
scaffoldConfig = js_yaml.load(yamlContent);
|
|
381
531
|
}
|
|
382
|
-
if (!scaffoldConfig.
|
|
383
|
-
if (scaffoldConfig.
|
|
532
|
+
if (!scaffoldConfig.features) scaffoldConfig.features = [];
|
|
533
|
+
if (scaffoldConfig.features.findIndex((f) => f.name === featureName) !== -1) return {
|
|
384
534
|
success: false,
|
|
385
|
-
message: `
|
|
535
|
+
message: `Feature '${featureName}' already exists in ${scaffoldYamlPath}`
|
|
386
536
|
};
|
|
387
537
|
const requiredVars = variables.filter((v) => v.required).map((v) => v.name);
|
|
388
|
-
const
|
|
389
|
-
name:
|
|
390
|
-
targetFolder,
|
|
538
|
+
const featureDefinition = {
|
|
539
|
+
name: featureName,
|
|
391
540
|
description,
|
|
392
541
|
variables_schema: {
|
|
393
542
|
type: "object",
|
|
@@ -404,13 +553,13 @@ var BoilerplateGeneratorService = class {
|
|
|
404
553
|
},
|
|
405
554
|
includes: includes.length > 0 ? includes : []
|
|
406
555
|
};
|
|
407
|
-
if (instruction)
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
await
|
|
556
|
+
if (instruction) featureDefinition.instruction = instruction;
|
|
557
|
+
if (patterns && patterns.length > 0) featureDefinition.patterns = patterns;
|
|
558
|
+
scaffoldConfig.features.push(featureDefinition);
|
|
559
|
+
await (0, __agiflowai_aicode_utils.writeFile)(scaffoldYamlPath, this.dumpYamlWithLiteralBlocks(scaffoldConfig), "utf-8");
|
|
411
560
|
return {
|
|
412
561
|
success: true,
|
|
413
|
-
message: `
|
|
562
|
+
message: `Feature '${featureName}' added to ${scaffoldYamlPath}`,
|
|
414
563
|
templatePath,
|
|
415
564
|
scaffoldYamlPath
|
|
416
565
|
};
|
|
@@ -419,89 +568,226 @@ var BoilerplateGeneratorService = class {
|
|
|
419
568
|
* List all templates (directories in templates folder)
|
|
420
569
|
*/
|
|
421
570
|
async listTemplates() {
|
|
422
|
-
return (await
|
|
571
|
+
return (await (0, __agiflowai_aicode_utils.readdir)(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
423
572
|
}
|
|
424
573
|
/**
|
|
425
574
|
* Check if a template exists
|
|
426
575
|
*/
|
|
427
576
|
async templateExists(templateName) {
|
|
428
|
-
|
|
429
|
-
return fs_extra.pathExists(templatePath);
|
|
430
|
-
}
|
|
431
|
-
/**
|
|
432
|
-
* Create or update a template file for a boilerplate
|
|
433
|
-
*/
|
|
434
|
-
async createTemplateFile(options) {
|
|
435
|
-
const { templateName, filePath, content, sourceFile, header } = options;
|
|
436
|
-
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
437
|
-
if (!await fs_extra.pathExists(templatePath)) return {
|
|
438
|
-
success: false,
|
|
439
|
-
message: `Template directory '${templateName}' does not exist at ${templatePath}`
|
|
440
|
-
};
|
|
441
|
-
let fileContent = content || "";
|
|
442
|
-
if (sourceFile) {
|
|
443
|
-
if (!await fs_extra.pathExists(sourceFile)) return {
|
|
444
|
-
success: false,
|
|
445
|
-
message: `Source file '${sourceFile}' does not exist`
|
|
446
|
-
};
|
|
447
|
-
fileContent = await fs_extra.readFile(sourceFile, "utf-8");
|
|
448
|
-
}
|
|
449
|
-
if (!fileContent && !sourceFile) return {
|
|
450
|
-
success: false,
|
|
451
|
-
message: "Either content or sourceFile must be provided"
|
|
452
|
-
};
|
|
453
|
-
const templateFilePath = filePath.endsWith(".liquid") ? filePath : `${filePath}.liquid`;
|
|
454
|
-
const fullPath = node_path.join(templatePath, templateFilePath);
|
|
455
|
-
await fs_extra.ensureDir(node_path.dirname(fullPath));
|
|
456
|
-
let finalContent = fileContent;
|
|
457
|
-
if (header) finalContent = `${header}\n\n${fileContent}`;
|
|
458
|
-
await fs_extra.writeFile(fullPath, finalContent, "utf-8");
|
|
459
|
-
return {
|
|
460
|
-
success: true,
|
|
461
|
-
message: "Template file created successfully",
|
|
462
|
-
filePath: templateFilePath,
|
|
463
|
-
fullPath
|
|
464
|
-
};
|
|
577
|
+
return (0, __agiflowai_aicode_utils.pathExists)(node_path.join(this.templatesPath, templateName));
|
|
465
578
|
}
|
|
466
579
|
};
|
|
467
580
|
|
|
468
581
|
//#endregion
|
|
469
|
-
//#region src/
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
isMonolith;
|
|
477
|
-
constructor(templatesPath, isMonolith = false) {
|
|
478
|
-
this.boilerplateGeneratorService = new BoilerplateGeneratorService(templatesPath);
|
|
479
|
-
this.isMonolith = isMonolith;
|
|
582
|
+
//#region src/services/ScaffoldingMethodsService.ts
|
|
583
|
+
var ScaffoldingMethodsService = class {
|
|
584
|
+
templateService;
|
|
585
|
+
constructor(fileSystem, templatesRootPath) {
|
|
586
|
+
this.fileSystem = fileSystem;
|
|
587
|
+
this.templatesRootPath = templatesRootPath;
|
|
588
|
+
this.templateService = new require_TemplateService.TemplateService();
|
|
480
589
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
590
|
+
async listScaffoldingMethods(projectPath, cursor) {
|
|
591
|
+
const absoluteProjectPath = node_path.default.resolve(projectPath);
|
|
592
|
+
const sourceTemplate = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absoluteProjectPath)).sourceTemplate;
|
|
593
|
+
return this.listScaffoldingMethodsByTemplate(sourceTemplate, cursor);
|
|
594
|
+
}
|
|
595
|
+
async listScaffoldingMethodsByTemplate(templateName, cursor) {
|
|
596
|
+
const templatePath = await this.findTemplatePath(templateName);
|
|
597
|
+
if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${templateName}`);
|
|
598
|
+
const fullTemplatePath = node_path.default.join(this.templatesRootPath, templatePath);
|
|
599
|
+
const scaffoldYamlPath = node_path.default.join(fullTemplatePath, "scaffold.yaml");
|
|
600
|
+
if (!await this.fileSystem.pathExists(scaffoldYamlPath)) throw new Error(`scaffold.yaml not found at ${scaffoldYamlPath}`);
|
|
601
|
+
const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
|
|
602
|
+
const architectConfig = js_yaml.default.load(scaffoldContent);
|
|
603
|
+
const methods = [];
|
|
604
|
+
if (architectConfig.features && Array.isArray(architectConfig.features)) architectConfig.features.forEach((feature) => {
|
|
605
|
+
const featureName = feature.name || `scaffold-${templateName}`;
|
|
606
|
+
methods.push({
|
|
607
|
+
name: featureName,
|
|
608
|
+
description: feature.description || "",
|
|
609
|
+
instruction: feature.instruction || "",
|
|
610
|
+
variables_schema: feature.variables_schema || {
|
|
611
|
+
type: "object",
|
|
612
|
+
properties: {},
|
|
613
|
+
required: [],
|
|
614
|
+
additionalProperties: false
|
|
615
|
+
},
|
|
616
|
+
generator: feature.generator
|
|
617
|
+
});
|
|
618
|
+
});
|
|
619
|
+
const paginatedResult = PaginationHelper.paginate(methods, cursor);
|
|
620
|
+
return {
|
|
621
|
+
sourceTemplate: templateName,
|
|
622
|
+
templatePath,
|
|
623
|
+
methods: paginatedResult.items,
|
|
624
|
+
nextCursor: paginatedResult.nextCursor,
|
|
625
|
+
_meta: paginatedResult._meta
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Gets scaffolding methods with instructions rendered using provided variables
|
|
630
|
+
*/
|
|
631
|
+
async listScaffoldingMethodsWithVariables(projectPath, variables, cursor) {
|
|
632
|
+
const result = await this.listScaffoldingMethods(projectPath, cursor);
|
|
633
|
+
const processedMethods = result.methods.map((method) => ({
|
|
634
|
+
...method,
|
|
635
|
+
instruction: method.instruction ? this.processScaffoldInstruction(method.instruction, variables) : void 0
|
|
636
|
+
}));
|
|
637
|
+
return {
|
|
638
|
+
...result,
|
|
639
|
+
methods: processedMethods
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
/**
|
|
643
|
+
* Processes scaffold instruction with template service
|
|
644
|
+
*/
|
|
645
|
+
processScaffoldInstruction(instruction, variables) {
|
|
646
|
+
if (this.templateService.containsTemplateVariables(instruction)) return this.templateService.renderString(instruction, variables);
|
|
647
|
+
return instruction;
|
|
648
|
+
}
|
|
649
|
+
async findTemplatePath(sourceTemplate) {
|
|
650
|
+
const templateDirs = await this.discoverTemplateDirs();
|
|
651
|
+
if (templateDirs.includes(sourceTemplate)) return sourceTemplate;
|
|
652
|
+
for (const templateDir of templateDirs) {
|
|
653
|
+
const templatePath = node_path.default.join(this.templatesRootPath, templateDir);
|
|
654
|
+
const scaffoldYamlPath = node_path.default.join(templatePath, "scaffold.yaml");
|
|
655
|
+
if (await this.fileSystem.pathExists(scaffoldYamlPath)) try {
|
|
656
|
+
const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
|
|
657
|
+
const architectConfig = js_yaml.default.load(scaffoldContent);
|
|
658
|
+
if (architectConfig.boilerplate && Array.isArray(architectConfig.boilerplate)) {
|
|
659
|
+
for (const boilerplate of architectConfig.boilerplate) if (boilerplate.name?.includes(sourceTemplate)) return templateDir;
|
|
660
|
+
}
|
|
661
|
+
} catch (error) {
|
|
662
|
+
__agiflowai_aicode_utils.log.warn(`Failed to read scaffold.yaml at ${scaffoldYamlPath}:`, error);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Resolves the project path, handling both monorepo and monolith cases
|
|
669
|
+
* Uses ProjectConfigResolver to find the correct workspace/project root
|
|
670
|
+
*/
|
|
671
|
+
async resolveProjectPath(projectPath) {
|
|
672
|
+
const absolutePath = node_path.default.resolve(projectPath);
|
|
673
|
+
return (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absolutePath)).workspaceRoot || absolutePath;
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Dynamically discovers all template directories
|
|
677
|
+
* Supports both flat structure (templates/nextjs-15) and nested structure (templates/apps/nextjs-15)
|
|
678
|
+
**/
|
|
679
|
+
async discoverTemplateDirs() {
|
|
680
|
+
const templateDirs = [];
|
|
681
|
+
try {
|
|
682
|
+
const items = await this.fileSystem.readdir(this.templatesRootPath);
|
|
683
|
+
for (const item of items) {
|
|
684
|
+
const itemPath = node_path.default.join(this.templatesRootPath, item);
|
|
685
|
+
if (!(await this.fileSystem.stat(itemPath)).isDirectory()) continue;
|
|
686
|
+
const scaffoldYamlPath = node_path.default.join(itemPath, "scaffold.yaml");
|
|
687
|
+
if (await this.fileSystem.pathExists(scaffoldYamlPath)) {
|
|
688
|
+
templateDirs.push(item);
|
|
689
|
+
continue;
|
|
690
|
+
}
|
|
691
|
+
try {
|
|
692
|
+
const subItems = await this.fileSystem.readdir(itemPath);
|
|
693
|
+
for (const subItem of subItems) {
|
|
694
|
+
const subItemPath = node_path.default.join(itemPath, subItem);
|
|
695
|
+
if (!(await this.fileSystem.stat(subItemPath)).isDirectory()) continue;
|
|
696
|
+
const subScaffoldYamlPath = node_path.default.join(subItemPath, "scaffold.yaml");
|
|
697
|
+
if (await this.fileSystem.pathExists(subScaffoldYamlPath)) {
|
|
698
|
+
const relativePath = node_path.default.join(item, subItem);
|
|
699
|
+
templateDirs.push(relativePath);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
} catch (error) {
|
|
703
|
+
__agiflowai_aicode_utils.log.warn(`Failed to read subdirectories in ${itemPath}:`, error);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
} catch (error) {
|
|
707
|
+
__agiflowai_aicode_utils.log.warn(`Failed to read templates root directory ${this.templatesRootPath}:`, error);
|
|
708
|
+
}
|
|
709
|
+
return templateDirs;
|
|
710
|
+
}
|
|
711
|
+
async useScaffoldMethod(request) {
|
|
712
|
+
const { projectPath, scaffold_feature_name, variables } = request;
|
|
713
|
+
const absoluteProjectPath = await this.resolveProjectPath(projectPath);
|
|
714
|
+
const scaffoldingMethods = await this.listScaffoldingMethods(absoluteProjectPath);
|
|
715
|
+
const method = scaffoldingMethods.methods.find((m) => m.name === scaffold_feature_name);
|
|
716
|
+
if (!method) {
|
|
717
|
+
const availableMethods = scaffoldingMethods.methods.map((m) => m.name).join(", ");
|
|
718
|
+
throw new Error(`Scaffold method '${scaffold_feature_name}' not found. Available methods: ${availableMethods}`);
|
|
719
|
+
}
|
|
720
|
+
const ScaffoldService$1 = (await Promise.resolve().then(() => require("./ScaffoldService-BNOyoqSb.cjs"))).ScaffoldService;
|
|
721
|
+
const ScaffoldConfigLoader$1 = (await Promise.resolve().then(() => require("./ScaffoldConfigLoader-B-NLy6VP.cjs"))).ScaffoldConfigLoader;
|
|
722
|
+
const VariableReplacementService$1 = (await Promise.resolve().then(() => require("./VariableReplacementService-DKaF2C9l.cjs"))).VariableReplacementService;
|
|
723
|
+
const TemplateService$1 = (await Promise.resolve().then(() => require("./TemplateService-DqieT1Tq.cjs"))).TemplateService;
|
|
724
|
+
const templateService = new TemplateService$1();
|
|
725
|
+
const scaffoldConfigLoader = new ScaffoldConfigLoader$1(this.fileSystem, templateService);
|
|
726
|
+
const variableReplacer = new VariableReplacementService$1(this.fileSystem, templateService);
|
|
727
|
+
const scaffoldService = new ScaffoldService$1(this.fileSystem, scaffoldConfigLoader, variableReplacer, this.templatesRootPath);
|
|
728
|
+
const projectName = node_path.default.basename(absoluteProjectPath);
|
|
729
|
+
const result = await scaffoldService.useFeature({
|
|
730
|
+
projectPath: absoluteProjectPath,
|
|
731
|
+
templateFolder: scaffoldingMethods.templatePath,
|
|
732
|
+
featureName: scaffold_feature_name,
|
|
733
|
+
variables: {
|
|
734
|
+
...variables,
|
|
735
|
+
appPath: absoluteProjectPath,
|
|
736
|
+
appName: projectName
|
|
737
|
+
}
|
|
738
|
+
});
|
|
739
|
+
if (!result.success) throw new Error(result.message);
|
|
740
|
+
return {
|
|
741
|
+
success: true,
|
|
742
|
+
message: `
|
|
743
|
+
Successfully scaffolded ${scaffold_feature_name} in ${projectPath}.
|
|
744
|
+
Please follow this **instruction**: \n ${method.instruction ? this.processScaffoldInstruction(method.instruction, variables) : ""}.
|
|
745
|
+
-> Create or update the plan based on the instruction.
|
|
746
|
+
`,
|
|
747
|
+
warnings: result.warnings,
|
|
748
|
+
createdFiles: result.createdFiles,
|
|
749
|
+
existingFiles: result.existingFiles
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
//#endregion
|
|
755
|
+
//#region src/tools/GenerateBoilerplateFileTool.ts
|
|
756
|
+
/**
|
|
757
|
+
* Tool to generate template files for boilerplates and features
|
|
758
|
+
*/
|
|
759
|
+
var GenerateBoilerplateFileTool = class GenerateBoilerplateFileTool {
|
|
760
|
+
static TOOL_NAME = "generate-boilerplate-file";
|
|
761
|
+
boilerplateGeneratorService;
|
|
762
|
+
isMonolith;
|
|
763
|
+
constructor(templatesPath, isMonolith = false) {
|
|
764
|
+
this.boilerplateGeneratorService = new BoilerplateGeneratorService(templatesPath);
|
|
765
|
+
this.isMonolith = isMonolith;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Get the tool definition for MCP
|
|
769
|
+
*/
|
|
770
|
+
getDefinition() {
|
|
771
|
+
const properties = {};
|
|
772
|
+
if (!this.isMonolith) properties.templateName = {
|
|
773
|
+
type: "string",
|
|
774
|
+
description: "Name of the template folder (must already exist)"
|
|
775
|
+
};
|
|
776
|
+
Object.assign(properties, {
|
|
777
|
+
filePath: {
|
|
778
|
+
type: "string",
|
|
779
|
+
description: "Path of the file to create within the template (e.g., \"package.json\", \"src/app/page.tsx\")"
|
|
780
|
+
},
|
|
781
|
+
content: {
|
|
782
|
+
type: "string",
|
|
783
|
+
description: `Content of the template file using Liquid template syntax.
|
|
784
|
+
|
|
785
|
+
LIQUID SYNTAX:
|
|
786
|
+
- Variables: {{ variableName }} - Replaced with actual values
|
|
787
|
+
- Conditionals: {% if condition %}...{% endif %} - Conditional rendering
|
|
788
|
+
- Else: {% if condition %}...{% else %}...{% endif %}
|
|
789
|
+
- Elsif: {% if condition %}...{% elsif other %}...{% endif %}
|
|
790
|
+
- Equality: {% if var == 'value' %}...{% endif %}
|
|
505
791
|
|
|
506
792
|
AVAILABLE FILTERS:
|
|
507
793
|
You can transform variables using these filters with the pipe (|) syntax:
|
|
@@ -922,132 +1208,6 @@ Use this to add custom boilerplate configurations for frameworks not yet support
|
|
|
922
1208
|
}
|
|
923
1209
|
};
|
|
924
1210
|
|
|
925
|
-
//#endregion
|
|
926
|
-
//#region src/services/ScaffoldGeneratorService.ts
|
|
927
|
-
/**
|
|
928
|
-
* Service for generating feature scaffold configurations in scaffold.yaml files
|
|
929
|
-
*/
|
|
930
|
-
var ScaffoldGeneratorService = class {
|
|
931
|
-
templatesPath;
|
|
932
|
-
constructor(templatesPath) {
|
|
933
|
-
this.templatesPath = templatesPath;
|
|
934
|
-
}
|
|
935
|
-
/**
|
|
936
|
-
* Custom YAML dumper that forces literal block style (|) for description and instruction fields
|
|
937
|
-
*/
|
|
938
|
-
dumpYamlWithLiteralBlocks(config) {
|
|
939
|
-
const LiteralBlockType = new js_yaml.Type("tag:yaml.org,2002:str", {
|
|
940
|
-
kind: "scalar",
|
|
941
|
-
construct: (data) => data,
|
|
942
|
-
represent: (data) => {
|
|
943
|
-
return data;
|
|
944
|
-
},
|
|
945
|
-
defaultStyle: "|"
|
|
946
|
-
});
|
|
947
|
-
const LITERAL_SCHEMA = js_yaml.DEFAULT_SCHEMA.extend([LiteralBlockType]);
|
|
948
|
-
const processedConfig = this.processConfigForLiteralBlocks(config);
|
|
949
|
-
return js_yaml.dump(processedConfig, {
|
|
950
|
-
schema: LITERAL_SCHEMA,
|
|
951
|
-
indent: 2,
|
|
952
|
-
lineWidth: -1,
|
|
953
|
-
noRefs: true,
|
|
954
|
-
sortKeys: false,
|
|
955
|
-
styles: { "!!str": "literal" },
|
|
956
|
-
replacer: (key, value) => {
|
|
957
|
-
if ((key === "description" || key === "instruction") && typeof value === "string") return value;
|
|
958
|
-
return value;
|
|
959
|
-
}
|
|
960
|
-
});
|
|
961
|
-
}
|
|
962
|
-
/**
|
|
963
|
-
* Process config to ensure description and instruction use literal block style
|
|
964
|
-
*/
|
|
965
|
-
processConfigForLiteralBlocks(config) {
|
|
966
|
-
const processed = JSON.parse(JSON.stringify(config));
|
|
967
|
-
if (processed.boilerplate) processed.boilerplate = processed.boilerplate.map((bp) => {
|
|
968
|
-
const newBp = { ...bp };
|
|
969
|
-
if (newBp.description && typeof newBp.description === "string") newBp.description = this.ensureMultilineFormat(newBp.description);
|
|
970
|
-
if (newBp.instruction && typeof newBp.instruction === "string") newBp.instruction = this.ensureMultilineFormat(newBp.instruction);
|
|
971
|
-
return newBp;
|
|
972
|
-
});
|
|
973
|
-
if (processed.features) processed.features = processed.features.map((feature) => {
|
|
974
|
-
const newFeature = { ...feature };
|
|
975
|
-
if (newFeature.description && typeof newFeature.description === "string") newFeature.description = this.ensureMultilineFormat(newFeature.description);
|
|
976
|
-
if (newFeature.instruction && typeof newFeature.instruction === "string") newFeature.instruction = this.ensureMultilineFormat(newFeature.instruction);
|
|
977
|
-
return newFeature;
|
|
978
|
-
});
|
|
979
|
-
return processed;
|
|
980
|
-
}
|
|
981
|
-
/**
|
|
982
|
-
* Ensure string is properly formatted for YAML literal blocks
|
|
983
|
-
*/
|
|
984
|
-
ensureMultilineFormat(text) {
|
|
985
|
-
return text.trim();
|
|
986
|
-
}
|
|
987
|
-
/**
|
|
988
|
-
* Generate or update a feature configuration in scaffold.yaml
|
|
989
|
-
*/
|
|
990
|
-
async generateFeatureScaffold(options) {
|
|
991
|
-
const { templateName, featureName, description, instruction, variables, includes = [], patterns = [] } = options;
|
|
992
|
-
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
993
|
-
await fs_extra.ensureDir(templatePath);
|
|
994
|
-
const scaffoldYamlPath = node_path.join(templatePath, "scaffold.yaml");
|
|
995
|
-
let scaffoldConfig = {};
|
|
996
|
-
if (await fs_extra.pathExists(scaffoldYamlPath)) {
|
|
997
|
-
const yamlContent$1 = await fs_extra.readFile(scaffoldYamlPath, "utf-8");
|
|
998
|
-
scaffoldConfig = js_yaml.load(yamlContent$1);
|
|
999
|
-
}
|
|
1000
|
-
if (!scaffoldConfig.features) scaffoldConfig.features = [];
|
|
1001
|
-
if (scaffoldConfig.features.findIndex((f) => f.name === featureName) !== -1) return {
|
|
1002
|
-
success: false,
|
|
1003
|
-
message: `Feature '${featureName}' already exists in ${scaffoldYamlPath}`
|
|
1004
|
-
};
|
|
1005
|
-
const requiredVars = variables.filter((v) => v.required).map((v) => v.name);
|
|
1006
|
-
const featureDefinition = {
|
|
1007
|
-
name: featureName,
|
|
1008
|
-
description,
|
|
1009
|
-
variables_schema: {
|
|
1010
|
-
type: "object",
|
|
1011
|
-
properties: variables.reduce((acc, v) => {
|
|
1012
|
-
acc[v.name] = {
|
|
1013
|
-
type: v.type,
|
|
1014
|
-
description: v.description
|
|
1015
|
-
};
|
|
1016
|
-
if (v.default !== void 0) acc[v.name].default = v.default;
|
|
1017
|
-
return acc;
|
|
1018
|
-
}, {}),
|
|
1019
|
-
required: requiredVars,
|
|
1020
|
-
additionalProperties: false
|
|
1021
|
-
},
|
|
1022
|
-
includes: includes.length > 0 ? includes : []
|
|
1023
|
-
};
|
|
1024
|
-
if (instruction) featureDefinition.instruction = instruction;
|
|
1025
|
-
if (patterns && patterns.length > 0) featureDefinition.patterns = patterns;
|
|
1026
|
-
scaffoldConfig.features.push(featureDefinition);
|
|
1027
|
-
const yamlContent = this.dumpYamlWithLiteralBlocks(scaffoldConfig);
|
|
1028
|
-
await fs_extra.writeFile(scaffoldYamlPath, yamlContent, "utf-8");
|
|
1029
|
-
return {
|
|
1030
|
-
success: true,
|
|
1031
|
-
message: `Feature '${featureName}' added to ${scaffoldYamlPath}`,
|
|
1032
|
-
templatePath,
|
|
1033
|
-
scaffoldYamlPath
|
|
1034
|
-
};
|
|
1035
|
-
}
|
|
1036
|
-
/**
|
|
1037
|
-
* List all templates (directories in templates folder)
|
|
1038
|
-
*/
|
|
1039
|
-
async listTemplates() {
|
|
1040
|
-
return (await fs_extra.readdir(this.templatesPath, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
1041
|
-
}
|
|
1042
|
-
/**
|
|
1043
|
-
* Check if a template exists
|
|
1044
|
-
*/
|
|
1045
|
-
async templateExists(templateName) {
|
|
1046
|
-
const templatePath = node_path.join(this.templatesPath, templateName);
|
|
1047
|
-
return fs_extra.pathExists(templatePath);
|
|
1048
|
-
}
|
|
1049
|
-
};
|
|
1050
|
-
|
|
1051
1211
|
//#endregion
|
|
1052
1212
|
//#region src/tools/GenerateFeatureScaffoldTool.ts
|
|
1053
1213
|
/**
|
|
@@ -1328,179 +1488,6 @@ var ListBoilerplatesTool = class ListBoilerplatesTool {
|
|
|
1328
1488
|
//#region src/instructions/tools/list-scaffolding-methods/description.md?raw
|
|
1329
1489
|
var description_default$1 = "Lists all available scaffolding methods (features) that can be added to an existing project{% if not isMonolith %} or for a specific template{% endif %}.\n\nThis tool:\n{% if isMonolith %}\n- Reads your project's sourceTemplate from toolkit.yaml at workspace root\n{% else %}\n- Reads the project's sourceTemplate from project.json (monorepo) or toolkit.yaml (monolith), OR\n- Directly uses the provided templateName to list available features\n{% endif %}\n- Returns available features for that template type\n- Provides variable schemas for each scaffolding method\n- Shows descriptions of what each method creates\n\nUse this FIRST when adding features to understand:\n- What scaffolding methods are available\n- What variables each method requires\n- What files/features will be generated\n\nExample methods might include:\n- Adding new React routes (for React apps)\n- Creating API endpoints (for backend projects)\n- Adding new components (for frontend projects)\n- Setting up database models (for API projects)\n";
|
|
1330
1490
|
|
|
1331
|
-
//#endregion
|
|
1332
|
-
//#region src/services/ScaffoldingMethodsService.ts
|
|
1333
|
-
var ScaffoldingMethodsService = class {
|
|
1334
|
-
templateService;
|
|
1335
|
-
constructor(fileSystem, templatesRootPath) {
|
|
1336
|
-
this.fileSystem = fileSystem;
|
|
1337
|
-
this.templatesRootPath = templatesRootPath;
|
|
1338
|
-
this.templateService = new require_TemplateService.TemplateService();
|
|
1339
|
-
}
|
|
1340
|
-
async listScaffoldingMethods(projectPath, cursor) {
|
|
1341
|
-
const absoluteProjectPath = node_path.default.resolve(projectPath);
|
|
1342
|
-
const sourceTemplate = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absoluteProjectPath)).sourceTemplate;
|
|
1343
|
-
return this.listScaffoldingMethodsByTemplate(sourceTemplate, cursor);
|
|
1344
|
-
}
|
|
1345
|
-
async listScaffoldingMethodsByTemplate(templateName, cursor) {
|
|
1346
|
-
const templatePath = await this.findTemplatePath(templateName);
|
|
1347
|
-
if (!templatePath) throw new Error(`Template not found for sourceTemplate: ${templateName}`);
|
|
1348
|
-
const fullTemplatePath = node_path.default.join(this.templatesRootPath, templatePath);
|
|
1349
|
-
const scaffoldYamlPath = node_path.default.join(fullTemplatePath, "scaffold.yaml");
|
|
1350
|
-
if (!await this.fileSystem.pathExists(scaffoldYamlPath)) throw new Error(`scaffold.yaml not found at ${scaffoldYamlPath}`);
|
|
1351
|
-
const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
|
|
1352
|
-
const architectConfig = js_yaml.default.load(scaffoldContent);
|
|
1353
|
-
const methods = [];
|
|
1354
|
-
if (architectConfig.features && Array.isArray(architectConfig.features)) architectConfig.features.forEach((feature) => {
|
|
1355
|
-
const featureName = feature.name || `scaffold-${templateName}`;
|
|
1356
|
-
methods.push({
|
|
1357
|
-
name: featureName,
|
|
1358
|
-
description: feature.description || "",
|
|
1359
|
-
instruction: feature.instruction || "",
|
|
1360
|
-
variables_schema: feature.variables_schema || {
|
|
1361
|
-
type: "object",
|
|
1362
|
-
properties: {},
|
|
1363
|
-
required: [],
|
|
1364
|
-
additionalProperties: false
|
|
1365
|
-
},
|
|
1366
|
-
generator: feature.generator
|
|
1367
|
-
});
|
|
1368
|
-
});
|
|
1369
|
-
const paginatedResult = PaginationHelper.paginate(methods, cursor);
|
|
1370
|
-
return {
|
|
1371
|
-
sourceTemplate: templateName,
|
|
1372
|
-
templatePath,
|
|
1373
|
-
methods: paginatedResult.items,
|
|
1374
|
-
nextCursor: paginatedResult.nextCursor,
|
|
1375
|
-
_meta: paginatedResult._meta
|
|
1376
|
-
};
|
|
1377
|
-
}
|
|
1378
|
-
/**
|
|
1379
|
-
* Gets scaffolding methods with instructions rendered using provided variables
|
|
1380
|
-
*/
|
|
1381
|
-
async listScaffoldingMethodsWithVariables(projectPath, variables, cursor) {
|
|
1382
|
-
const result = await this.listScaffoldingMethods(projectPath, cursor);
|
|
1383
|
-
const processedMethods = result.methods.map((method) => ({
|
|
1384
|
-
...method,
|
|
1385
|
-
instruction: method.instruction ? this.processScaffoldInstruction(method.instruction, variables) : void 0
|
|
1386
|
-
}));
|
|
1387
|
-
return {
|
|
1388
|
-
...result,
|
|
1389
|
-
methods: processedMethods
|
|
1390
|
-
};
|
|
1391
|
-
}
|
|
1392
|
-
/**
|
|
1393
|
-
* Processes scaffold instruction with template service
|
|
1394
|
-
*/
|
|
1395
|
-
processScaffoldInstruction(instruction, variables) {
|
|
1396
|
-
if (this.templateService.containsTemplateVariables(instruction)) return this.templateService.renderString(instruction, variables);
|
|
1397
|
-
return instruction;
|
|
1398
|
-
}
|
|
1399
|
-
async findTemplatePath(sourceTemplate) {
|
|
1400
|
-
const templateDirs = await this.discoverTemplateDirs();
|
|
1401
|
-
if (templateDirs.includes(sourceTemplate)) return sourceTemplate;
|
|
1402
|
-
for (const templateDir of templateDirs) {
|
|
1403
|
-
const templatePath = node_path.default.join(this.templatesRootPath, templateDir);
|
|
1404
|
-
const scaffoldYamlPath = node_path.default.join(templatePath, "scaffold.yaml");
|
|
1405
|
-
if (await this.fileSystem.pathExists(scaffoldYamlPath)) try {
|
|
1406
|
-
const scaffoldContent = await this.fileSystem.readFile(scaffoldYamlPath, "utf8");
|
|
1407
|
-
const architectConfig = js_yaml.default.load(scaffoldContent);
|
|
1408
|
-
if (architectConfig.boilerplate && Array.isArray(architectConfig.boilerplate)) {
|
|
1409
|
-
for (const boilerplate of architectConfig.boilerplate) if (boilerplate.name?.includes(sourceTemplate)) return templateDir;
|
|
1410
|
-
}
|
|
1411
|
-
} catch (error) {
|
|
1412
|
-
__agiflowai_aicode_utils.log.warn(`Failed to read scaffold.yaml at ${scaffoldYamlPath}:`, error);
|
|
1413
|
-
}
|
|
1414
|
-
}
|
|
1415
|
-
return null;
|
|
1416
|
-
}
|
|
1417
|
-
/**
|
|
1418
|
-
* Resolves the project path, handling both monorepo and monolith cases
|
|
1419
|
-
* Uses ProjectConfigResolver to find the correct workspace/project root
|
|
1420
|
-
*/
|
|
1421
|
-
async resolveProjectPath(projectPath) {
|
|
1422
|
-
const absolutePath = node_path.default.resolve(projectPath);
|
|
1423
|
-
return (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(absolutePath)).workspaceRoot || absolutePath;
|
|
1424
|
-
}
|
|
1425
|
-
/**
|
|
1426
|
-
* Dynamically discovers all template directories
|
|
1427
|
-
* Supports both flat structure (templates/nextjs-15) and nested structure (templates/apps/nextjs-15)
|
|
1428
|
-
**/
|
|
1429
|
-
async discoverTemplateDirs() {
|
|
1430
|
-
const templateDirs = [];
|
|
1431
|
-
try {
|
|
1432
|
-
const items = await this.fileSystem.readdir(this.templatesRootPath);
|
|
1433
|
-
for (const item of items) {
|
|
1434
|
-
const itemPath = node_path.default.join(this.templatesRootPath, item);
|
|
1435
|
-
if (!(await this.fileSystem.stat(itemPath)).isDirectory()) continue;
|
|
1436
|
-
const scaffoldYamlPath = node_path.default.join(itemPath, "scaffold.yaml");
|
|
1437
|
-
if (await this.fileSystem.pathExists(scaffoldYamlPath)) {
|
|
1438
|
-
templateDirs.push(item);
|
|
1439
|
-
continue;
|
|
1440
|
-
}
|
|
1441
|
-
try {
|
|
1442
|
-
const subItems = await this.fileSystem.readdir(itemPath);
|
|
1443
|
-
for (const subItem of subItems) {
|
|
1444
|
-
const subItemPath = node_path.default.join(itemPath, subItem);
|
|
1445
|
-
if (!(await this.fileSystem.stat(subItemPath)).isDirectory()) continue;
|
|
1446
|
-
const subScaffoldYamlPath = node_path.default.join(subItemPath, "scaffold.yaml");
|
|
1447
|
-
if (await this.fileSystem.pathExists(subScaffoldYamlPath)) {
|
|
1448
|
-
const relativePath = node_path.default.join(item, subItem);
|
|
1449
|
-
templateDirs.push(relativePath);
|
|
1450
|
-
}
|
|
1451
|
-
}
|
|
1452
|
-
} catch (error) {
|
|
1453
|
-
__agiflowai_aicode_utils.log.warn(`Failed to read subdirectories in ${itemPath}:`, error);
|
|
1454
|
-
}
|
|
1455
|
-
}
|
|
1456
|
-
} catch (error) {
|
|
1457
|
-
__agiflowai_aicode_utils.log.warn(`Failed to read templates root directory ${this.templatesRootPath}:`, error);
|
|
1458
|
-
}
|
|
1459
|
-
return templateDirs;
|
|
1460
|
-
}
|
|
1461
|
-
async useScaffoldMethod(request) {
|
|
1462
|
-
const { projectPath, scaffold_feature_name, variables } = request;
|
|
1463
|
-
const absoluteProjectPath = await this.resolveProjectPath(projectPath);
|
|
1464
|
-
const scaffoldingMethods = await this.listScaffoldingMethods(absoluteProjectPath);
|
|
1465
|
-
const method = scaffoldingMethods.methods.find((m) => m.name === scaffold_feature_name);
|
|
1466
|
-
if (!method) {
|
|
1467
|
-
const availableMethods = scaffoldingMethods.methods.map((m) => m.name).join(", ");
|
|
1468
|
-
throw new Error(`Scaffold method '${scaffold_feature_name}' not found. Available methods: ${availableMethods}`);
|
|
1469
|
-
}
|
|
1470
|
-
const ScaffoldService$1 = (await Promise.resolve().then(() => require("./ScaffoldService-B3En_m4t.cjs"))).ScaffoldService;
|
|
1471
|
-
const ScaffoldConfigLoader$1 = (await Promise.resolve().then(() => require("./ScaffoldConfigLoader-DQMCLVGD.cjs"))).ScaffoldConfigLoader;
|
|
1472
|
-
const VariableReplacementService$1 = (await Promise.resolve().then(() => require("./VariableReplacementService-CroHkMha.cjs"))).VariableReplacementService;
|
|
1473
|
-
const TemplateService$1 = (await Promise.resolve().then(() => require("./TemplateService-BZRt3NI8.cjs"))).TemplateService;
|
|
1474
|
-
const templateService = new TemplateService$1();
|
|
1475
|
-
const scaffoldConfigLoader = new ScaffoldConfigLoader$1(this.fileSystem, templateService);
|
|
1476
|
-
const variableReplacer = new VariableReplacementService$1(this.fileSystem, templateService);
|
|
1477
|
-
const scaffoldService = new ScaffoldService$1(this.fileSystem, scaffoldConfigLoader, variableReplacer, this.templatesRootPath);
|
|
1478
|
-
const projectName = node_path.default.basename(absoluteProjectPath);
|
|
1479
|
-
const result = await scaffoldService.useFeature({
|
|
1480
|
-
projectPath: absoluteProjectPath,
|
|
1481
|
-
templateFolder: scaffoldingMethods.templatePath,
|
|
1482
|
-
featureName: scaffold_feature_name,
|
|
1483
|
-
variables: {
|
|
1484
|
-
...variables,
|
|
1485
|
-
appPath: absoluteProjectPath,
|
|
1486
|
-
appName: projectName
|
|
1487
|
-
}
|
|
1488
|
-
});
|
|
1489
|
-
if (!result.success) throw new Error(result.message);
|
|
1490
|
-
return {
|
|
1491
|
-
success: true,
|
|
1492
|
-
message: `
|
|
1493
|
-
Successfully scaffolded ${scaffold_feature_name} in ${projectPath}.
|
|
1494
|
-
Please follow this **instruction**: \n ${method.instruction ? this.processScaffoldInstruction(method.instruction, variables) : ""}.
|
|
1495
|
-
-> Create or update the plan based on the instruction.
|
|
1496
|
-
`,
|
|
1497
|
-
warnings: result.warnings,
|
|
1498
|
-
createdFiles: result.createdFiles,
|
|
1499
|
-
existingFiles: result.existingFiles
|
|
1500
|
-
};
|
|
1501
|
-
}
|
|
1502
|
-
};
|
|
1503
|
-
|
|
1504
1491
|
//#endregion
|
|
1505
1492
|
//#region src/tools/ListScaffoldingMethodsTool.ts
|
|
1506
1493
|
var ListScaffoldingMethodsTool = class ListScaffoldingMethodsTool {
|