@agiflowai/scaffold-mcp 1.1.0 → 1.2.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.
- package/README.md +19 -0
- package/dist/{claudeCode-DNgNiLlL.mjs → claudeCode-DbKOy8W8.mjs} +1 -1
- package/dist/{claudeCode-BxcEboyM.cjs → claudeCode-g1eRidPR.cjs} +1 -1
- package/dist/cli.cjs +195 -17
- package/dist/cli.mjs +196 -18
- package/dist/index.cjs +2 -2
- package/dist/index.d.cts +0 -5
- package/dist/index.d.mts +0 -5
- package/dist/index.mjs +2 -2
- package/dist/{src-oF_UdSBu.cjs → src-BG_X82dw.cjs} +2 -2
- package/dist/{src-BEwgHhCT.mjs → src-DnVktdhD.mjs} +2 -2
- package/dist/{tools-CVSZSirE.cjs → tools-COb9iBtt.cjs} +30 -22
- package/dist/{tools-Cl06aoBi.mjs → tools-Dn5KgBUI.mjs} +26 -23
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -121,6 +121,25 @@ npx @agiflowai/scaffold-mcp scaffold list ./apps/my-app
|
|
|
121
121
|
npx @agiflowai/scaffold-mcp scaffold add scaffold-nextjs-page \
|
|
122
122
|
--project ./apps/my-app \
|
|
123
123
|
--vars '{"pageTitle":"About","nextjsPagePath":"/about"}'
|
|
124
|
+
|
|
125
|
+
# Create template authoring entries (CLI equivalents for admin MCP tools)
|
|
126
|
+
npx @agiflowai/scaffold-mcp boilerplate generate scaffold-vite-app \
|
|
127
|
+
--template vite-react \
|
|
128
|
+
--description "React Vite starter" \
|
|
129
|
+
--target-folder apps \
|
|
130
|
+
--variables '[{"name":"appName","description":"Application name","type":"string","required":true}]'
|
|
131
|
+
|
|
132
|
+
npx @agiflowai/scaffold-mcp scaffold generate scaffold-service \
|
|
133
|
+
--template typescript-lib \
|
|
134
|
+
--description "Generate a service class and unit test" \
|
|
135
|
+
--variables '[{"name":"serviceName","description":"Service name","type":"string","required":true}]'
|
|
136
|
+
|
|
137
|
+
npx @agiflowai/scaffold-mcp template file create src/index.ts \
|
|
138
|
+
--template typescript-lib \
|
|
139
|
+
--content 'export const {{ name | camelCase }} = "{{ name }}";'
|
|
140
|
+
|
|
141
|
+
npx @agiflowai/scaffold-mcp file write .env.local \
|
|
142
|
+
--content 'NEXT_PUBLIC_API_URL=https://api.example.com'
|
|
124
143
|
```
|
|
125
144
|
|
|
126
145
|
---
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-DxdrPlcb.mjs";
|
|
2
|
-
import "./tools-
|
|
2
|
+
import "./tools-Dn5KgBUI.mjs";
|
|
3
3
|
import { n as resolveNewFileWriteTarget, t as formatScaffoldMethodsHookMessage } from "./shared-BVYIN3Is.mjs";
|
|
4
4
|
import { ProjectFinderService, TemplatesManagerService } from "@agiflowai/aicode-utils";
|
|
5
5
|
import path from "node:path";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_ListScaffoldingMethodsTool = require("./ListScaffoldingMethodsTool-CYZtpU-W.cjs");
|
|
2
|
-
require("./tools-
|
|
2
|
+
require("./tools-COb9iBtt.cjs");
|
|
3
3
|
const require_shared = require("./shared-QxPXh-L-.cjs");
|
|
4
4
|
let _agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
5
5
|
let node_path = require("node:path");
|
package/dist/cli.cjs
CHANGED
|
@@ -1,13 +1,54 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const require_ListScaffoldingMethodsTool = require("./ListScaffoldingMethodsTool-CYZtpU-W.cjs");
|
|
3
|
-
const require_src = require("./src-
|
|
4
|
-
const require_tools = require("./tools-
|
|
3
|
+
const require_src = require("./src-BG_X82dw.cjs");
|
|
4
|
+
const require_tools = require("./tools-COb9iBtt.cjs");
|
|
5
5
|
let _agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
6
6
|
let node_path = require("node:path");
|
|
7
7
|
node_path = require_ListScaffoldingMethodsTool.__toESM(node_path, 1);
|
|
8
8
|
let commander = require("commander");
|
|
9
9
|
let _agiflowai_coding_agent_bridge = require("@agiflowai/coding-agent-bridge");
|
|
10
10
|
let _agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
|
|
11
|
+
//#region src/commands/utils.ts
|
|
12
|
+
function parseJsonOption(value, flagName) {
|
|
13
|
+
if (!value) throw new Error(`${flagName} is required`);
|
|
14
|
+
try {
|
|
15
|
+
return JSON.parse(value);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
throw new Error(`Invalid JSON for ${flagName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function resolveTemplatesPath() {
|
|
21
|
+
const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
|
|
22
|
+
if (!templatesDir) throw new Error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
|
|
23
|
+
return templatesDir;
|
|
24
|
+
}
|
|
25
|
+
async function detectMonolithMode() {
|
|
26
|
+
try {
|
|
27
|
+
return (await _agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).type === "monolith";
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async function loadTextOption(config) {
|
|
33
|
+
const { value, filePath, valueFlag, fileFlag, required = false } = config;
|
|
34
|
+
if (value !== void 0 && filePath !== void 0) throw new Error(`Use only one of ${valueFlag} or ${fileFlag}`);
|
|
35
|
+
if (filePath !== void 0) return (0, _agiflowai_aicode_utils.readFile)(filePath, "utf-8");
|
|
36
|
+
if (value !== void 0) return value;
|
|
37
|
+
if (required) throw new Error(`${valueFlag} or ${fileFlag} is required`);
|
|
38
|
+
}
|
|
39
|
+
function collectOption(value, previous = []) {
|
|
40
|
+
return [...previous, value];
|
|
41
|
+
}
|
|
42
|
+
function firstTextContent(result) {
|
|
43
|
+
const firstContent = result.content[0];
|
|
44
|
+
return firstContent?.type === "text" ? firstContent.text : "";
|
|
45
|
+
}
|
|
46
|
+
function assertToolSuccess(result) {
|
|
47
|
+
const text = firstTextContent(result);
|
|
48
|
+
if (result.isError) throw new Error(text || "Tool execution failed");
|
|
49
|
+
return text;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
11
52
|
//#region src/commands/boilerplate.ts
|
|
12
53
|
/**
|
|
13
54
|
* Boilerplate CLI command
|
|
@@ -44,7 +85,7 @@ boilerplateCommand.command("list").description("List all available boilerplate t
|
|
|
44
85
|
process.exit(1);
|
|
45
86
|
}
|
|
46
87
|
});
|
|
47
|
-
boilerplateCommand.command("create <boilerplateName>").description("Create a new project from a boilerplate template").option("-v, --vars <json>", "JSON string containing variables for the boilerplate").option("-m, --monolith", "Create as monolith project at workspace root with toolkit.yaml (default: false, creates as monorepo with project.json)").option("-t, --target-folder <path>", "Override target folder (defaults to boilerplate targetFolder for monorepo, workspace root for monolith)").option("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
|
|
88
|
+
boilerplateCommand.command("create <boilerplateName>").description("Create a new project from a boilerplate template").option("-v, --vars <json>", "JSON string containing variables for the boilerplate").option("-m, --monolith", "Create as monolith project at workspace root with toolkit.yaml (default: false, creates as monorepo with project.json)").option("-t, --target-folder <path>", "Override target folder (defaults to boilerplate targetFolder for monorepo, workspace root for monolith)").option("--marker <tag>", "Custom scaffold marker tag to inject into generated code files").option("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
|
|
48
89
|
try {
|
|
49
90
|
const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
|
|
50
91
|
if (!templatesDir) {
|
|
@@ -94,7 +135,8 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
94
135
|
boilerplateName,
|
|
95
136
|
variables,
|
|
96
137
|
monolith: options.monolith,
|
|
97
|
-
targetFolderOverride: options.targetFolder
|
|
138
|
+
targetFolderOverride: options.targetFolder,
|
|
139
|
+
marker: options.marker
|
|
98
140
|
});
|
|
99
141
|
if (result.success) {
|
|
100
142
|
_agiflowai_aicode_utils.messages.success("Project created successfully!");
|
|
@@ -121,6 +163,42 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
121
163
|
process.exit(1);
|
|
122
164
|
}
|
|
123
165
|
});
|
|
166
|
+
boilerplateCommand.command("generate <boilerplateName>").description("Create a new boilerplate configuration in a template's scaffold.yaml").option("-t, --template <name>", "Template name (optional in monolith mode)").option("--description <text>", "Boilerplate description").option("--description-file <path>", "Read boilerplate description from a file").option("--instruction <text>", "Detailed boilerplate instructions").option("--instruction-file <path>", "Read detailed boilerplate instructions from a file").option("--target-folder <path>", "Target folder for generated projects").option("--variables <json>", "JSON array of variable definitions: [{\"name\":\"appName\",\"description\":\"App name\",\"type\":\"string\",\"required\":true}]").option("-i, --include <path>", "Template include path (repeatable)", collectOption, []).action(async (boilerplateName, options) => {
|
|
167
|
+
try {
|
|
168
|
+
const templatesPath = await resolveTemplatesPath();
|
|
169
|
+
const isMonolith = await detectMonolithMode();
|
|
170
|
+
const description = await loadTextOption({
|
|
171
|
+
value: options.description,
|
|
172
|
+
filePath: options.descriptionFile,
|
|
173
|
+
valueFlag: "--description",
|
|
174
|
+
fileFlag: "--description-file",
|
|
175
|
+
required: true
|
|
176
|
+
});
|
|
177
|
+
const instruction = await loadTextOption({
|
|
178
|
+
value: options.instruction,
|
|
179
|
+
filePath: options.instructionFile,
|
|
180
|
+
valueFlag: "--instruction",
|
|
181
|
+
fileFlag: "--instruction-file"
|
|
182
|
+
});
|
|
183
|
+
const variables = parseJsonOption(options.variables, "--variables");
|
|
184
|
+
if (!Array.isArray(variables)) throw new Error("--variables must be a JSON array");
|
|
185
|
+
const targetFolder = options.targetFolder ?? (isMonolith ? "." : void 0);
|
|
186
|
+
if (!targetFolder) throw new Error("--target-folder is required outside monolith mode");
|
|
187
|
+
const result = await new require_tools.GenerateBoilerplateTool(templatesPath, isMonolith).execute({
|
|
188
|
+
templateName: options.template,
|
|
189
|
+
boilerplateName,
|
|
190
|
+
description: description ?? "",
|
|
191
|
+
instruction,
|
|
192
|
+
targetFolder,
|
|
193
|
+
variables,
|
|
194
|
+
includes: options.include ?? []
|
|
195
|
+
});
|
|
196
|
+
_agiflowai_aicode_utils.print.info(assertToolSuccess(result));
|
|
197
|
+
} catch (error) {
|
|
198
|
+
_agiflowai_aicode_utils.print.error("Error generating boilerplate:", error instanceof Error ? error.message : String(error));
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
124
202
|
boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
|
|
125
203
|
try {
|
|
126
204
|
const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
|
|
@@ -146,6 +224,28 @@ boilerplateCommand.command("info <boilerplateName>").description("Show detailed
|
|
|
146
224
|
}
|
|
147
225
|
});
|
|
148
226
|
//#endregion
|
|
227
|
+
//#region src/commands/file.ts
|
|
228
|
+
const fileCommand$1 = new commander.Command("file").description("Workspace file utilities");
|
|
229
|
+
fileCommand$1.command("write <filePath>").description("Write content to a file inside the current workspace").option("--content <text>", "Content to write").option("--content-file <path>", "Read content to write from a file").action(async (filePath, options) => {
|
|
230
|
+
try {
|
|
231
|
+
const content = await loadTextOption({
|
|
232
|
+
value: options.content,
|
|
233
|
+
filePath: options.contentFile,
|
|
234
|
+
valueFlag: "--content",
|
|
235
|
+
fileFlag: "--content-file",
|
|
236
|
+
required: true
|
|
237
|
+
});
|
|
238
|
+
const result = await new require_tools.WriteToFileTool().execute({
|
|
239
|
+
file_path: filePath,
|
|
240
|
+
content
|
|
241
|
+
});
|
|
242
|
+
_agiflowai_aicode_utils.print.info(assertToolSuccess(result));
|
|
243
|
+
} catch (error) {
|
|
244
|
+
_agiflowai_aicode_utils.print.error("Error writing file:", error instanceof Error ? error.message : String(error));
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
//#endregion
|
|
149
249
|
//#region src/commands/mcp-serve.ts
|
|
150
250
|
/**
|
|
151
251
|
* MCP Serve Command
|
|
@@ -299,13 +399,6 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
|
|
|
299
399
|
const scaffoldCommand = new commander.Command("scaffold").description("Add features to existing projects");
|
|
300
400
|
scaffoldCommand.command("list [projectPath]").description("List available scaffolding methods for a project or template").option("-t, --template <name>", "Template name (e.g., nextjs-15, typescript-mcp-package)").option("-c, --cursor <cursor>", "Pagination cursor for next page").action(async (projectPath, options) => {
|
|
301
401
|
try {
|
|
302
|
-
if (!projectPath && !options.template) {
|
|
303
|
-
_agiflowai_aicode_utils.messages.error("Either projectPath or --template option must be provided");
|
|
304
|
-
_agiflowai_aicode_utils.messages.hint("Examples:");
|
|
305
|
-
_agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold list ./my-project");
|
|
306
|
-
_agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold list --template nextjs-15");
|
|
307
|
-
process.exit(1);
|
|
308
|
-
}
|
|
309
402
|
const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
|
|
310
403
|
if (!templatesDir) {
|
|
311
404
|
_agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
|
|
@@ -314,15 +407,16 @@ scaffoldCommand.command("list [projectPath]").description("List available scaffo
|
|
|
314
407
|
const scaffoldingMethodsService = new require_ListScaffoldingMethodsTool.ScaffoldingMethodsService(new require_ListScaffoldingMethodsTool.FileSystemService(), templatesDir);
|
|
315
408
|
let result;
|
|
316
409
|
let displayName;
|
|
317
|
-
if (projectPath) {
|
|
318
|
-
const
|
|
410
|
+
if (projectPath || !options.template) {
|
|
411
|
+
const inputProjectPath = projectPath ?? process.cwd();
|
|
412
|
+
const absolutePath = node_path.default.resolve(inputProjectPath);
|
|
319
413
|
if (!await _agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(absolutePath)) {
|
|
320
414
|
_agiflowai_aicode_utils.messages.error(`No project configuration found in ${absolutePath}`);
|
|
321
415
|
_agiflowai_aicode_utils.messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root\nOr use --template option to list methods for a specific template");
|
|
322
416
|
process.exit(1);
|
|
323
417
|
}
|
|
324
418
|
result = await scaffoldingMethodsService.listScaffoldingMethods(absolutePath, options.cursor);
|
|
325
|
-
displayName = projectPath;
|
|
419
|
+
displayName = projectPath ?? absolutePath;
|
|
326
420
|
} else {
|
|
327
421
|
result = await scaffoldingMethodsService.listScaffoldingMethodsByTemplate(options.template, options.cursor);
|
|
328
422
|
displayName = `template: ${options.template}`;
|
|
@@ -351,7 +445,7 @@ scaffoldCommand.command("list [projectPath]").description("List available scaffo
|
|
|
351
445
|
process.exit(1);
|
|
352
446
|
}
|
|
353
447
|
});
|
|
354
|
-
scaffoldCommand.command("add <featureName>").description("Add a feature to an existing project").option("-p, --project <path>", "Project path", process.cwd()).option("-v, --vars <json>", "JSON string containing variables for the feature").option("--verbose", "Enable verbose logging").action(async (featureName, options) => {
|
|
448
|
+
scaffoldCommand.command("add <featureName>").description("Add a feature to an existing project").option("-p, --project <path>", "Project path", process.cwd()).option("-v, --vars <json>", "JSON string containing variables for the feature").option("--marker <tag>", "Custom scaffold marker tag to inject into generated code files").option("--verbose", "Enable verbose logging").action(async (featureName, options) => {
|
|
355
449
|
try {
|
|
356
450
|
const projectPath = node_path.default.resolve(options.project);
|
|
357
451
|
if (!await _agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
|
|
@@ -408,9 +502,17 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
408
502
|
const result = await scaffoldingMethodsService.useScaffoldMethod({
|
|
409
503
|
projectPath,
|
|
410
504
|
scaffold_feature_name: featureName,
|
|
411
|
-
variables
|
|
505
|
+
variables,
|
|
506
|
+
marker: options.marker
|
|
412
507
|
});
|
|
413
508
|
if (result.success) {
|
|
509
|
+
const scaffoldId = (0, _agiflowai_aicode_utils.generateStableId)(6);
|
|
510
|
+
if (result.createdFiles && result.createdFiles.length > 0) await require_tools.writePendingScaffoldLog({
|
|
511
|
+
scaffoldId,
|
|
512
|
+
projectPath,
|
|
513
|
+
featureName,
|
|
514
|
+
generatedFiles: result.createdFiles
|
|
515
|
+
});
|
|
414
516
|
_agiflowai_aicode_utils.messages.success("✅ Feature added successfully!");
|
|
415
517
|
if (result.createdFiles && result.createdFiles.length > 0) {
|
|
416
518
|
_agiflowai_aicode_utils.print.header("\n📁 Created files:");
|
|
@@ -424,6 +526,7 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
424
526
|
_agiflowai_aicode_utils.print.debug(` - ${warning}`);
|
|
425
527
|
});
|
|
426
528
|
}
|
|
529
|
+
_agiflowai_aicode_utils.print.debug(`\nSCAFFOLD_ID:${scaffoldId}`);
|
|
427
530
|
_agiflowai_aicode_utils.print.header("\n📋 Next steps:");
|
|
428
531
|
_agiflowai_aicode_utils.print.debug(" - Review the generated files");
|
|
429
532
|
_agiflowai_aicode_utils.print.debug(" - Update imports if necessary");
|
|
@@ -437,6 +540,40 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
437
540
|
process.exit(1);
|
|
438
541
|
}
|
|
439
542
|
});
|
|
543
|
+
scaffoldCommand.command("generate <featureName>").description("Create a new feature scaffold configuration in a template's scaffold.yaml").option("-t, --template <name>", "Template name (optional in monolith mode)").option("--description <text>", "Feature description").option("--description-file <path>", "Read feature description from a file").option("--instruction <text>", "Detailed feature instructions").option("--instruction-file <path>", "Read detailed feature instructions from a file").option("--variables <json>", "JSON array of variable definitions: [{\"name\":\"featureName\",\"description\":\"Feature name\",\"type\":\"string\",\"required\":true}]").option("-i, --include <path>", "Template include path (repeatable)", collectOption, []).option("--pattern <glob>", "File pattern this scaffold applies to (repeatable)", collectOption, []).action(async (featureName, options) => {
|
|
544
|
+
try {
|
|
545
|
+
const templatesPath = await resolveTemplatesPath();
|
|
546
|
+
const isMonolith = await detectMonolithMode();
|
|
547
|
+
const description = await loadTextOption({
|
|
548
|
+
value: options.description,
|
|
549
|
+
filePath: options.descriptionFile,
|
|
550
|
+
valueFlag: "--description",
|
|
551
|
+
fileFlag: "--description-file",
|
|
552
|
+
required: true
|
|
553
|
+
});
|
|
554
|
+
const instruction = await loadTextOption({
|
|
555
|
+
value: options.instruction,
|
|
556
|
+
filePath: options.instructionFile,
|
|
557
|
+
valueFlag: "--instruction",
|
|
558
|
+
fileFlag: "--instruction-file"
|
|
559
|
+
});
|
|
560
|
+
const variables = parseJsonOption(options.variables, "--variables");
|
|
561
|
+
if (!Array.isArray(variables)) throw new Error("--variables must be a JSON array");
|
|
562
|
+
const result = await new require_tools.GenerateFeatureScaffoldTool(templatesPath, isMonolith).execute({
|
|
563
|
+
templateName: options.template,
|
|
564
|
+
featureName,
|
|
565
|
+
description: description ?? "",
|
|
566
|
+
instruction,
|
|
567
|
+
variables,
|
|
568
|
+
includes: options.include ?? [],
|
|
569
|
+
patterns: options.pattern ?? []
|
|
570
|
+
});
|
|
571
|
+
_agiflowai_aicode_utils.print.info(assertToolSuccess(result));
|
|
572
|
+
} catch (error) {
|
|
573
|
+
_agiflowai_aicode_utils.print.error("Error generating feature scaffold:", error instanceof Error ? error.message : String(error));
|
|
574
|
+
process.exit(1);
|
|
575
|
+
}
|
|
576
|
+
});
|
|
440
577
|
scaffoldCommand.command("info <featureName>").description("Show detailed information about a scaffold method").option("-p, --project <path>", "Project path").option("-t, --template <name>", "Template name (e.g., nextjs-15, typescript-mcp-package)").action(async (featureName, options) => {
|
|
441
578
|
try {
|
|
442
579
|
if (!options.project && !options.template) {
|
|
@@ -575,7 +712,7 @@ const hookCommand = new commander.Command("hook").description("Execute scaffold
|
|
|
575
712
|
const resolvedAdapterConfig = Object.keys(adapterConfig).length > 0 ? adapterConfig : void 0;
|
|
576
713
|
if (!isHookMethod(hookMethod)) process.exit(0);
|
|
577
714
|
if (agent === _agiflowai_coding_agent_bridge.CLAUDE_CODE) {
|
|
578
|
-
const hookModule = await Promise.resolve().then(() => require("./claudeCode-
|
|
715
|
+
const hookModule = await Promise.resolve().then(() => require("./claudeCode-g1eRidPR.cjs"));
|
|
579
716
|
const claudeCallbacks = [];
|
|
580
717
|
if (hookModule.UseScaffoldMethodHook) {
|
|
581
718
|
const hookInstance = new hookModule.UseScaffoldMethodHook();
|
|
@@ -606,6 +743,45 @@ const hookCommand = new commander.Command("hook").description("Execute scaffold
|
|
|
606
743
|
}
|
|
607
744
|
});
|
|
608
745
|
//#endregion
|
|
746
|
+
//#region src/commands/template.ts
|
|
747
|
+
const templateCommand = new commander.Command("template").description("Manage scaffold template authoring assets");
|
|
748
|
+
const fileCommand = new commander.Command("file").description("Manage template files");
|
|
749
|
+
fileCommand.command("create <filePath>").description("Create or update a Liquid template file for a boilerplate or feature").option("-t, --template <name>", "Template name (optional in monolith mode)").option("--content <text>", "Template file content").option("--content-file <path>", "Read template file content from a file").option("--source-file <path>", "Copy content from an existing source file").option("--header <text>", "Header comment to prepend to the template file").option("--header-file <path>", "Read header comment from a file").action(async (filePath, options) => {
|
|
750
|
+
try {
|
|
751
|
+
if ([
|
|
752
|
+
options.content !== void 0,
|
|
753
|
+
options.contentFile !== void 0,
|
|
754
|
+
options.sourceFile !== void 0
|
|
755
|
+
].filter(Boolean).length !== 1) throw new Error("Use exactly one of --content, --content-file, or --source-file");
|
|
756
|
+
const templatesPath = await resolveTemplatesPath();
|
|
757
|
+
const isMonolith = await detectMonolithMode();
|
|
758
|
+
const content = await loadTextOption({
|
|
759
|
+
value: options.content,
|
|
760
|
+
filePath: options.contentFile,
|
|
761
|
+
valueFlag: "--content",
|
|
762
|
+
fileFlag: "--content-file"
|
|
763
|
+
});
|
|
764
|
+
const header = await loadTextOption({
|
|
765
|
+
value: options.header,
|
|
766
|
+
filePath: options.headerFile,
|
|
767
|
+
valueFlag: "--header",
|
|
768
|
+
fileFlag: "--header-file"
|
|
769
|
+
});
|
|
770
|
+
const result = await new require_tools.GenerateBoilerplateFileTool(templatesPath, isMonolith).execute({
|
|
771
|
+
templateName: options.template,
|
|
772
|
+
filePath,
|
|
773
|
+
content,
|
|
774
|
+
sourceFile: options.sourceFile,
|
|
775
|
+
header
|
|
776
|
+
});
|
|
777
|
+
_agiflowai_aicode_utils.print.info(assertToolSuccess(result));
|
|
778
|
+
} catch (error) {
|
|
779
|
+
_agiflowai_aicode_utils.print.error("Error creating template file:", error instanceof Error ? error.message : String(error));
|
|
780
|
+
process.exit(1);
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
templateCommand.addCommand(fileCommand);
|
|
784
|
+
//#endregion
|
|
609
785
|
//#region src/cli.ts
|
|
610
786
|
/**
|
|
611
787
|
* Main entry point
|
|
@@ -616,6 +792,8 @@ async function main() {
|
|
|
616
792
|
program.addCommand(mcpServeCommand);
|
|
617
793
|
program.addCommand(boilerplateCommand);
|
|
618
794
|
program.addCommand(scaffoldCommand);
|
|
795
|
+
program.addCommand(templateCommand);
|
|
796
|
+
program.addCommand(fileCommand$1);
|
|
619
797
|
program.addCommand(hookCommand);
|
|
620
798
|
await program.parseAsync(process.argv);
|
|
621
799
|
}
|
package/dist/cli.mjs
CHANGED
|
@@ -1,12 +1,53 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as createServer, i as StdioTransportHandler, n as HttpTransportHandler, o as version, r as SseTransportHandler, t as TransportMode } from "./src-
|
|
2
|
+
import { a as createServer, i as StdioTransportHandler, n as HttpTransportHandler, o as version, r as SseTransportHandler, t as TransportMode } from "./src-DnVktdhD.mjs";
|
|
3
3
|
import { n as ScaffoldingMethodsService, s as FileSystemService } from "./ListScaffoldingMethodsTool-DxdrPlcb.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { ProjectConfigResolver, TemplatesManagerService, icons, messages, print, sections } from "@agiflowai/aicode-utils";
|
|
4
|
+
import { c as GenerateBoilerplateFileTool, o as GenerateFeatureScaffoldTool, r as writePendingScaffoldLog, s as GenerateBoilerplateTool, t as WriteToFileTool, u as BoilerplateService } from "./tools-Dn5KgBUI.mjs";
|
|
5
|
+
import { ProjectConfigResolver, TemplatesManagerService, generateStableId, icons, messages, print, readFile, sections } from "@agiflowai/aicode-utils";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import { CLAUDE_CODE, GEMINI_CLI, SUPPORTED_LLM_TOOLS, isValidLlmTool } from "@agiflowai/coding-agent-bridge";
|
|
9
9
|
import { ClaudeCodeAdapter, GeminiCliAdapter, parseHookType } from "@agiflowai/hooks-adapter";
|
|
10
|
+
//#region src/commands/utils.ts
|
|
11
|
+
function parseJsonOption(value, flagName) {
|
|
12
|
+
if (!value) throw new Error(`${flagName} is required`);
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(value);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
throw new Error(`Invalid JSON for ${flagName}: ${error instanceof Error ? error.message : String(error)}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function resolveTemplatesPath() {
|
|
20
|
+
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
21
|
+
if (!templatesDir) throw new Error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
|
|
22
|
+
return templatesDir;
|
|
23
|
+
}
|
|
24
|
+
async function detectMonolithMode() {
|
|
25
|
+
try {
|
|
26
|
+
return (await ProjectConfigResolver.resolveProjectConfig(process.cwd())).type === "monolith";
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function loadTextOption(config) {
|
|
32
|
+
const { value, filePath, valueFlag, fileFlag, required = false } = config;
|
|
33
|
+
if (value !== void 0 && filePath !== void 0) throw new Error(`Use only one of ${valueFlag} or ${fileFlag}`);
|
|
34
|
+
if (filePath !== void 0) return readFile(filePath, "utf-8");
|
|
35
|
+
if (value !== void 0) return value;
|
|
36
|
+
if (required) throw new Error(`${valueFlag} or ${fileFlag} is required`);
|
|
37
|
+
}
|
|
38
|
+
function collectOption(value, previous = []) {
|
|
39
|
+
return [...previous, value];
|
|
40
|
+
}
|
|
41
|
+
function firstTextContent(result) {
|
|
42
|
+
const firstContent = result.content[0];
|
|
43
|
+
return firstContent?.type === "text" ? firstContent.text : "";
|
|
44
|
+
}
|
|
45
|
+
function assertToolSuccess(result) {
|
|
46
|
+
const text = firstTextContent(result);
|
|
47
|
+
if (result.isError) throw new Error(text || "Tool execution failed");
|
|
48
|
+
return text;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
10
51
|
//#region src/commands/boilerplate.ts
|
|
11
52
|
/**
|
|
12
53
|
* Boilerplate CLI command
|
|
@@ -43,7 +84,7 @@ boilerplateCommand.command("list").description("List all available boilerplate t
|
|
|
43
84
|
process.exit(1);
|
|
44
85
|
}
|
|
45
86
|
});
|
|
46
|
-
boilerplateCommand.command("create <boilerplateName>").description("Create a new project from a boilerplate template").option("-v, --vars <json>", "JSON string containing variables for the boilerplate").option("-m, --monolith", "Create as monolith project at workspace root with toolkit.yaml (default: false, creates as monorepo with project.json)").option("-t, --target-folder <path>", "Override target folder (defaults to boilerplate targetFolder for monorepo, workspace root for monolith)").option("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
|
|
87
|
+
boilerplateCommand.command("create <boilerplateName>").description("Create a new project from a boilerplate template").option("-v, --vars <json>", "JSON string containing variables for the boilerplate").option("-m, --monolith", "Create as monolith project at workspace root with toolkit.yaml (default: false, creates as monorepo with project.json)").option("-t, --target-folder <path>", "Override target folder (defaults to boilerplate targetFolder for monorepo, workspace root for monolith)").option("--marker <tag>", "Custom scaffold marker tag to inject into generated code files").option("--verbose", "Enable verbose logging").action(async (boilerplateName, options) => {
|
|
47
88
|
try {
|
|
48
89
|
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
49
90
|
if (!templatesDir) {
|
|
@@ -93,7 +134,8 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
93
134
|
boilerplateName,
|
|
94
135
|
variables,
|
|
95
136
|
monolith: options.monolith,
|
|
96
|
-
targetFolderOverride: options.targetFolder
|
|
137
|
+
targetFolderOverride: options.targetFolder,
|
|
138
|
+
marker: options.marker
|
|
97
139
|
});
|
|
98
140
|
if (result.success) {
|
|
99
141
|
messages.success("Project created successfully!");
|
|
@@ -120,6 +162,42 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
120
162
|
process.exit(1);
|
|
121
163
|
}
|
|
122
164
|
});
|
|
165
|
+
boilerplateCommand.command("generate <boilerplateName>").description("Create a new boilerplate configuration in a template's scaffold.yaml").option("-t, --template <name>", "Template name (optional in monolith mode)").option("--description <text>", "Boilerplate description").option("--description-file <path>", "Read boilerplate description from a file").option("--instruction <text>", "Detailed boilerplate instructions").option("--instruction-file <path>", "Read detailed boilerplate instructions from a file").option("--target-folder <path>", "Target folder for generated projects").option("--variables <json>", "JSON array of variable definitions: [{\"name\":\"appName\",\"description\":\"App name\",\"type\":\"string\",\"required\":true}]").option("-i, --include <path>", "Template include path (repeatable)", collectOption, []).action(async (boilerplateName, options) => {
|
|
166
|
+
try {
|
|
167
|
+
const templatesPath = await resolveTemplatesPath();
|
|
168
|
+
const isMonolith = await detectMonolithMode();
|
|
169
|
+
const description = await loadTextOption({
|
|
170
|
+
value: options.description,
|
|
171
|
+
filePath: options.descriptionFile,
|
|
172
|
+
valueFlag: "--description",
|
|
173
|
+
fileFlag: "--description-file",
|
|
174
|
+
required: true
|
|
175
|
+
});
|
|
176
|
+
const instruction = await loadTextOption({
|
|
177
|
+
value: options.instruction,
|
|
178
|
+
filePath: options.instructionFile,
|
|
179
|
+
valueFlag: "--instruction",
|
|
180
|
+
fileFlag: "--instruction-file"
|
|
181
|
+
});
|
|
182
|
+
const variables = parseJsonOption(options.variables, "--variables");
|
|
183
|
+
if (!Array.isArray(variables)) throw new Error("--variables must be a JSON array");
|
|
184
|
+
const targetFolder = options.targetFolder ?? (isMonolith ? "." : void 0);
|
|
185
|
+
if (!targetFolder) throw new Error("--target-folder is required outside monolith mode");
|
|
186
|
+
const result = await new GenerateBoilerplateTool(templatesPath, isMonolith).execute({
|
|
187
|
+
templateName: options.template,
|
|
188
|
+
boilerplateName,
|
|
189
|
+
description: description ?? "",
|
|
190
|
+
instruction,
|
|
191
|
+
targetFolder,
|
|
192
|
+
variables,
|
|
193
|
+
includes: options.include ?? []
|
|
194
|
+
});
|
|
195
|
+
print.info(assertToolSuccess(result));
|
|
196
|
+
} catch (error) {
|
|
197
|
+
print.error("Error generating boilerplate:", error instanceof Error ? error.message : String(error));
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
});
|
|
123
201
|
boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
|
|
124
202
|
try {
|
|
125
203
|
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
@@ -145,6 +223,28 @@ boilerplateCommand.command("info <boilerplateName>").description("Show detailed
|
|
|
145
223
|
}
|
|
146
224
|
});
|
|
147
225
|
//#endregion
|
|
226
|
+
//#region src/commands/file.ts
|
|
227
|
+
const fileCommand$1 = new Command("file").description("Workspace file utilities");
|
|
228
|
+
fileCommand$1.command("write <filePath>").description("Write content to a file inside the current workspace").option("--content <text>", "Content to write").option("--content-file <path>", "Read content to write from a file").action(async (filePath, options) => {
|
|
229
|
+
try {
|
|
230
|
+
const content = await loadTextOption({
|
|
231
|
+
value: options.content,
|
|
232
|
+
filePath: options.contentFile,
|
|
233
|
+
valueFlag: "--content",
|
|
234
|
+
fileFlag: "--content-file",
|
|
235
|
+
required: true
|
|
236
|
+
});
|
|
237
|
+
const result = await new WriteToFileTool().execute({
|
|
238
|
+
file_path: filePath,
|
|
239
|
+
content
|
|
240
|
+
});
|
|
241
|
+
print.info(assertToolSuccess(result));
|
|
242
|
+
} catch (error) {
|
|
243
|
+
print.error("Error writing file:", error instanceof Error ? error.message : String(error));
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
//#endregion
|
|
148
248
|
//#region src/commands/mcp-serve.ts
|
|
149
249
|
/**
|
|
150
250
|
* MCP Serve Command
|
|
@@ -298,13 +398,6 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
298
398
|
const scaffoldCommand = new Command("scaffold").description("Add features to existing projects");
|
|
299
399
|
scaffoldCommand.command("list [projectPath]").description("List available scaffolding methods for a project or template").option("-t, --template <name>", "Template name (e.g., nextjs-15, typescript-mcp-package)").option("-c, --cursor <cursor>", "Pagination cursor for next page").action(async (projectPath, options) => {
|
|
300
400
|
try {
|
|
301
|
-
if (!projectPath && !options.template) {
|
|
302
|
-
messages.error("Either projectPath or --template option must be provided");
|
|
303
|
-
messages.hint("Examples:");
|
|
304
|
-
print.debug(" scaffold-mcp scaffold list ./my-project");
|
|
305
|
-
print.debug(" scaffold-mcp scaffold list --template nextjs-15");
|
|
306
|
-
process.exit(1);
|
|
307
|
-
}
|
|
308
401
|
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
309
402
|
if (!templatesDir) {
|
|
310
403
|
messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
|
|
@@ -313,15 +406,16 @@ scaffoldCommand.command("list [projectPath]").description("List available scaffo
|
|
|
313
406
|
const scaffoldingMethodsService = new ScaffoldingMethodsService(new FileSystemService(), templatesDir);
|
|
314
407
|
let result;
|
|
315
408
|
let displayName;
|
|
316
|
-
if (projectPath) {
|
|
317
|
-
const
|
|
409
|
+
if (projectPath || !options.template) {
|
|
410
|
+
const inputProjectPath = projectPath ?? process.cwd();
|
|
411
|
+
const absolutePath = path.resolve(inputProjectPath);
|
|
318
412
|
if (!await ProjectConfigResolver.hasConfiguration(absolutePath)) {
|
|
319
413
|
messages.error(`No project configuration found in ${absolutePath}`);
|
|
320
414
|
messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root\nOr use --template option to list methods for a specific template");
|
|
321
415
|
process.exit(1);
|
|
322
416
|
}
|
|
323
417
|
result = await scaffoldingMethodsService.listScaffoldingMethods(absolutePath, options.cursor);
|
|
324
|
-
displayName = projectPath;
|
|
418
|
+
displayName = projectPath ?? absolutePath;
|
|
325
419
|
} else {
|
|
326
420
|
result = await scaffoldingMethodsService.listScaffoldingMethodsByTemplate(options.template, options.cursor);
|
|
327
421
|
displayName = `template: ${options.template}`;
|
|
@@ -350,7 +444,7 @@ scaffoldCommand.command("list [projectPath]").description("List available scaffo
|
|
|
350
444
|
process.exit(1);
|
|
351
445
|
}
|
|
352
446
|
});
|
|
353
|
-
scaffoldCommand.command("add <featureName>").description("Add a feature to an existing project").option("-p, --project <path>", "Project path", process.cwd()).option("-v, --vars <json>", "JSON string containing variables for the feature").option("--verbose", "Enable verbose logging").action(async (featureName, options) => {
|
|
447
|
+
scaffoldCommand.command("add <featureName>").description("Add a feature to an existing project").option("-p, --project <path>", "Project path", process.cwd()).option("-v, --vars <json>", "JSON string containing variables for the feature").option("--marker <tag>", "Custom scaffold marker tag to inject into generated code files").option("--verbose", "Enable verbose logging").action(async (featureName, options) => {
|
|
354
448
|
try {
|
|
355
449
|
const projectPath = path.resolve(options.project);
|
|
356
450
|
if (!await ProjectConfigResolver.hasConfiguration(projectPath)) {
|
|
@@ -407,9 +501,17 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
407
501
|
const result = await scaffoldingMethodsService.useScaffoldMethod({
|
|
408
502
|
projectPath,
|
|
409
503
|
scaffold_feature_name: featureName,
|
|
410
|
-
variables
|
|
504
|
+
variables,
|
|
505
|
+
marker: options.marker
|
|
411
506
|
});
|
|
412
507
|
if (result.success) {
|
|
508
|
+
const scaffoldId = generateStableId(6);
|
|
509
|
+
if (result.createdFiles && result.createdFiles.length > 0) await writePendingScaffoldLog({
|
|
510
|
+
scaffoldId,
|
|
511
|
+
projectPath,
|
|
512
|
+
featureName,
|
|
513
|
+
generatedFiles: result.createdFiles
|
|
514
|
+
});
|
|
413
515
|
messages.success("✅ Feature added successfully!");
|
|
414
516
|
if (result.createdFiles && result.createdFiles.length > 0) {
|
|
415
517
|
print.header("\n📁 Created files:");
|
|
@@ -423,6 +525,7 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
423
525
|
print.debug(` - ${warning}`);
|
|
424
526
|
});
|
|
425
527
|
}
|
|
528
|
+
print.debug(`\nSCAFFOLD_ID:${scaffoldId}`);
|
|
426
529
|
print.header("\n📋 Next steps:");
|
|
427
530
|
print.debug(" - Review the generated files");
|
|
428
531
|
print.debug(" - Update imports if necessary");
|
|
@@ -436,6 +539,40 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
436
539
|
process.exit(1);
|
|
437
540
|
}
|
|
438
541
|
});
|
|
542
|
+
scaffoldCommand.command("generate <featureName>").description("Create a new feature scaffold configuration in a template's scaffold.yaml").option("-t, --template <name>", "Template name (optional in monolith mode)").option("--description <text>", "Feature description").option("--description-file <path>", "Read feature description from a file").option("--instruction <text>", "Detailed feature instructions").option("--instruction-file <path>", "Read detailed feature instructions from a file").option("--variables <json>", "JSON array of variable definitions: [{\"name\":\"featureName\",\"description\":\"Feature name\",\"type\":\"string\",\"required\":true}]").option("-i, --include <path>", "Template include path (repeatable)", collectOption, []).option("--pattern <glob>", "File pattern this scaffold applies to (repeatable)", collectOption, []).action(async (featureName, options) => {
|
|
543
|
+
try {
|
|
544
|
+
const templatesPath = await resolveTemplatesPath();
|
|
545
|
+
const isMonolith = await detectMonolithMode();
|
|
546
|
+
const description = await loadTextOption({
|
|
547
|
+
value: options.description,
|
|
548
|
+
filePath: options.descriptionFile,
|
|
549
|
+
valueFlag: "--description",
|
|
550
|
+
fileFlag: "--description-file",
|
|
551
|
+
required: true
|
|
552
|
+
});
|
|
553
|
+
const instruction = await loadTextOption({
|
|
554
|
+
value: options.instruction,
|
|
555
|
+
filePath: options.instructionFile,
|
|
556
|
+
valueFlag: "--instruction",
|
|
557
|
+
fileFlag: "--instruction-file"
|
|
558
|
+
});
|
|
559
|
+
const variables = parseJsonOption(options.variables, "--variables");
|
|
560
|
+
if (!Array.isArray(variables)) throw new Error("--variables must be a JSON array");
|
|
561
|
+
const result = await new GenerateFeatureScaffoldTool(templatesPath, isMonolith).execute({
|
|
562
|
+
templateName: options.template,
|
|
563
|
+
featureName,
|
|
564
|
+
description: description ?? "",
|
|
565
|
+
instruction,
|
|
566
|
+
variables,
|
|
567
|
+
includes: options.include ?? [],
|
|
568
|
+
patterns: options.pattern ?? []
|
|
569
|
+
});
|
|
570
|
+
print.info(assertToolSuccess(result));
|
|
571
|
+
} catch (error) {
|
|
572
|
+
print.error("Error generating feature scaffold:", error instanceof Error ? error.message : String(error));
|
|
573
|
+
process.exit(1);
|
|
574
|
+
}
|
|
575
|
+
});
|
|
439
576
|
scaffoldCommand.command("info <featureName>").description("Show detailed information about a scaffold method").option("-p, --project <path>", "Project path").option("-t, --template <name>", "Template name (e.g., nextjs-15, typescript-mcp-package)").action(async (featureName, options) => {
|
|
440
577
|
try {
|
|
441
578
|
if (!options.project && !options.template) {
|
|
@@ -574,7 +711,7 @@ const hookCommand = new Command("hook").description("Execute scaffold hooks for
|
|
|
574
711
|
const resolvedAdapterConfig = Object.keys(adapterConfig).length > 0 ? adapterConfig : void 0;
|
|
575
712
|
if (!isHookMethod(hookMethod)) process.exit(0);
|
|
576
713
|
if (agent === CLAUDE_CODE) {
|
|
577
|
-
const hookModule = await import("./claudeCode-
|
|
714
|
+
const hookModule = await import("./claudeCode-DbKOy8W8.mjs");
|
|
578
715
|
const claudeCallbacks = [];
|
|
579
716
|
if (hookModule.UseScaffoldMethodHook) {
|
|
580
717
|
const hookInstance = new hookModule.UseScaffoldMethodHook();
|
|
@@ -605,6 +742,45 @@ const hookCommand = new Command("hook").description("Execute scaffold hooks for
|
|
|
605
742
|
}
|
|
606
743
|
});
|
|
607
744
|
//#endregion
|
|
745
|
+
//#region src/commands/template.ts
|
|
746
|
+
const templateCommand = new Command("template").description("Manage scaffold template authoring assets");
|
|
747
|
+
const fileCommand = new Command("file").description("Manage template files");
|
|
748
|
+
fileCommand.command("create <filePath>").description("Create or update a Liquid template file for a boilerplate or feature").option("-t, --template <name>", "Template name (optional in monolith mode)").option("--content <text>", "Template file content").option("--content-file <path>", "Read template file content from a file").option("--source-file <path>", "Copy content from an existing source file").option("--header <text>", "Header comment to prepend to the template file").option("--header-file <path>", "Read header comment from a file").action(async (filePath, options) => {
|
|
749
|
+
try {
|
|
750
|
+
if ([
|
|
751
|
+
options.content !== void 0,
|
|
752
|
+
options.contentFile !== void 0,
|
|
753
|
+
options.sourceFile !== void 0
|
|
754
|
+
].filter(Boolean).length !== 1) throw new Error("Use exactly one of --content, --content-file, or --source-file");
|
|
755
|
+
const templatesPath = await resolveTemplatesPath();
|
|
756
|
+
const isMonolith = await detectMonolithMode();
|
|
757
|
+
const content = await loadTextOption({
|
|
758
|
+
value: options.content,
|
|
759
|
+
filePath: options.contentFile,
|
|
760
|
+
valueFlag: "--content",
|
|
761
|
+
fileFlag: "--content-file"
|
|
762
|
+
});
|
|
763
|
+
const header = await loadTextOption({
|
|
764
|
+
value: options.header,
|
|
765
|
+
filePath: options.headerFile,
|
|
766
|
+
valueFlag: "--header",
|
|
767
|
+
fileFlag: "--header-file"
|
|
768
|
+
});
|
|
769
|
+
const result = await new GenerateBoilerplateFileTool(templatesPath, isMonolith).execute({
|
|
770
|
+
templateName: options.template,
|
|
771
|
+
filePath,
|
|
772
|
+
content,
|
|
773
|
+
sourceFile: options.sourceFile,
|
|
774
|
+
header
|
|
775
|
+
});
|
|
776
|
+
print.info(assertToolSuccess(result));
|
|
777
|
+
} catch (error) {
|
|
778
|
+
print.error("Error creating template file:", error instanceof Error ? error.message : String(error));
|
|
779
|
+
process.exit(1);
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
templateCommand.addCommand(fileCommand);
|
|
783
|
+
//#endregion
|
|
608
784
|
//#region src/cli.ts
|
|
609
785
|
/**
|
|
610
786
|
* Main entry point
|
|
@@ -615,6 +791,8 @@ async function main() {
|
|
|
615
791
|
program.addCommand(mcpServeCommand);
|
|
616
792
|
program.addCommand(boilerplateCommand);
|
|
617
793
|
program.addCommand(scaffoldCommand);
|
|
794
|
+
program.addCommand(templateCommand);
|
|
795
|
+
program.addCommand(fileCommand$1);
|
|
618
796
|
program.addCommand(hookCommand);
|
|
619
797
|
await program.parseAsync(process.argv);
|
|
620
798
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_ListScaffoldingMethodsTool = require("./ListScaffoldingMethodsTool-CYZtpU-W.cjs");
|
|
3
|
-
const require_src = require("./src-
|
|
4
|
-
const require_tools = require("./tools-
|
|
3
|
+
const require_src = require("./src-BG_X82dw.cjs");
|
|
4
|
+
const require_tools = require("./tools-COb9iBtt.cjs");
|
|
5
5
|
exports.BoilerplateGeneratorService = require_tools.BoilerplateGeneratorService;
|
|
6
6
|
exports.BoilerplateService = require_tools.BoilerplateService;
|
|
7
7
|
exports.FileSystemService = require_ListScaffoldingMethodsTool.FileSystemService;
|
package/dist/index.d.cts
CHANGED
|
@@ -267,15 +267,10 @@ declare class UseBoilerplateTool {
|
|
|
267
267
|
//#region src/tools/UseScaffoldMethodTool.d.ts
|
|
268
268
|
declare class UseScaffoldMethodTool {
|
|
269
269
|
static readonly TOOL_NAME = "use-scaffold-method";
|
|
270
|
-
private static readonly TEMP_LOG_DIR;
|
|
271
270
|
private fileSystemService;
|
|
272
271
|
private scaffoldingMethodsService;
|
|
273
272
|
private isMonolith;
|
|
274
273
|
constructor(templatesPath: string, isMonolith?: boolean);
|
|
275
|
-
/**
|
|
276
|
-
* Write scaffold execution info to temp log file for hook processing
|
|
277
|
-
*/
|
|
278
|
-
private writePendingScaffoldLog;
|
|
279
274
|
/**
|
|
280
275
|
* Get the tool definition for MCP
|
|
281
276
|
*/
|
package/dist/index.d.mts
CHANGED
|
@@ -266,15 +266,10 @@ declare class UseBoilerplateTool {
|
|
|
266
266
|
//#region src/tools/UseScaffoldMethodTool.d.ts
|
|
267
267
|
declare class UseScaffoldMethodTool {
|
|
268
268
|
static readonly TOOL_NAME = "use-scaffold-method";
|
|
269
|
-
private static readonly TEMP_LOG_DIR;
|
|
270
269
|
private fileSystemService;
|
|
271
270
|
private scaffoldingMethodsService;
|
|
272
271
|
private isMonolith;
|
|
273
272
|
constructor(templatesPath: string, isMonolith?: boolean);
|
|
274
|
-
/**
|
|
275
|
-
* Write scaffold execution info to temp log file for hook processing
|
|
276
|
-
*/
|
|
277
|
-
private writePendingScaffoldLog;
|
|
278
273
|
/**
|
|
279
274
|
* Get the tool definition for MCP
|
|
280
275
|
*/
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as createServer, i as StdioTransportHandler, n as HttpTransportHandler, r as SseTransportHandler, t as TransportMode } from "./src-
|
|
1
|
+
import { a as createServer, i as StdioTransportHandler, n as HttpTransportHandler, r as SseTransportHandler, t as TransportMode } from "./src-DnVktdhD.mjs";
|
|
2
2
|
import { a as ScaffoldProcessingService, i as ScaffoldService, l as TemplateService, n as ScaffoldingMethodsService, o as ScaffoldConfigLoader, r as VariableReplacementService, s as FileSystemService, t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-DxdrPlcb.mjs";
|
|
3
|
-
import { a as
|
|
3
|
+
import { a as ListBoilerplatesTool, c as GenerateBoilerplateFileTool, d as BoilerplateGeneratorService, i as UseBoilerplateTool, l as ScaffoldGeneratorService, n as UseScaffoldMethodTool, o as GenerateFeatureScaffoldTool, s as GenerateBoilerplateTool, t as WriteToFileTool, u as BoilerplateService } from "./tools-Dn5KgBUI.mjs";
|
|
4
4
|
export { BoilerplateGeneratorService, BoilerplateService, FileSystemService, GenerateBoilerplateFileTool, GenerateBoilerplateTool, GenerateFeatureScaffoldTool, HttpTransportHandler, ListBoilerplatesTool, ListScaffoldingMethodsTool, ScaffoldConfigLoader, ScaffoldGeneratorService, ScaffoldProcessingService, ScaffoldService, ScaffoldingMethodsService, SseTransportHandler, StdioTransportHandler, TemplateService, TransportMode, UseBoilerplateTool, UseScaffoldMethodTool, VariableReplacementService, WriteToFileTool, createServer };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_ListScaffoldingMethodsTool = require("./ListScaffoldingMethodsTool-CYZtpU-W.cjs");
|
|
2
|
-
const require_tools = require("./tools-
|
|
2
|
+
const require_tools = require("./tools-COb9iBtt.cjs");
|
|
3
3
|
let _agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
4
4
|
let _modelcontextprotocol_sdk_server_index_js = require("@modelcontextprotocol/sdk/server/index.js");
|
|
5
5
|
let _modelcontextprotocol_sdk_types_js = require("@modelcontextprotocol/sdk/types.js");
|
|
@@ -11,7 +11,7 @@ express = require_ListScaffoldingMethodsTool.__toESM(express, 1);
|
|
|
11
11
|
let node_crypto = require("node:crypto");
|
|
12
12
|
let _modelcontextprotocol_sdk_server_streamableHttp_js = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
13
13
|
//#region package.json
|
|
14
|
-
var version = "1.0
|
|
14
|
+
var version = "1.1.0";
|
|
15
15
|
//#endregion
|
|
16
16
|
//#region src/instructions/server.md?raw
|
|
17
17
|
var server_default = "Use this MCP server to {% if isMonolith %}create your monolith project and add features (pages, components, services, etc.){% else %}create new projects and add features (pages, components, services, etc.){% endif %}.\n\n## Workflow:\n{% if not isMonolith %}\n1. **Creating New Project**: Use `list-boilerplates` → `use-boilerplate`\n2. **Adding Features**: Use `list-scaffolding-methods` → `use-scaffold-method`\n{% else %}\n1. **Creating Project**: Use `use-boilerplate` (boilerplateName auto-detected from `.toolkit/settings.yaml`)\n2. **Adding Features**: Use `list-scaffolding-methods` → `use-scaffold-method`\n{% endif %}\n\n## AI Usage Guidelines:\n{% if not isMonolith %}\n- Always call `list-boilerplates` first when creating new projects to see available options\n{% endif %}\n- Always call `list-scaffolding-methods` first when adding features to understand what's available\n- Follow the exact variable schema provided - validation will fail if required fields are missing\n{% if not isMonolith %}\n- Use kebab-case for project names (e.g., \"my-new-app\")\n{% else %}\n- In monolith mode, parameters like `boilerplateName` and `templateName` are auto-detected from `.toolkit/settings.yaml`\n- You only need to provide `variables` when calling `use-boilerplate` or `use-scaffold-method`\n{% endif %}\n- The tools automatically handle file placement, imports, and code generation\n- Check the returned JSON schemas to understand required vs optional variables\n{% if adminEnabled %}\n\n## Admin Mode (Template Generation):\n\nWhen creating custom boilerplate templates for frameworks not yet supported:\n\n1. **Create Boilerplate Configuration**: Use `generate-boilerplate` to add a new boilerplate entry to a template's scaffold.yaml\n - Specify template name, boilerplate name, description, target folder, and variable schema\n - This creates the scaffold.yaml structure following the nextjs-15 pattern\n - Optional: Add detailed instruction about file purposes and design patterns\n\n2. **Create Feature Configuration**: Use `generate-feature-scaffold` to add a new feature entry to a template's scaffold.yaml\n - Specify template name, feature name, generator, description, and variable schema\n - This creates the scaffold.yaml structure for feature scaffolds (pages, components, etc.)\n - Optional: Add detailed instruction about file purposes and design patterns\n - Optional: Specify patterns to match existing files this feature works with\n\n3. **Create Template Files**: Use `generate-boilerplate-file` to create the actual template files\n - Create files referenced in the boilerplate's or feature's includes array\n - Use {{ variableName }} syntax for Liquid variable placeholders\n - Can copy from existing source files or provide content directly\n - Files automatically get .liquid extension\n\n4. **Test the Template**: Use `list-boilerplates`/`list-scaffolding-methods` and `use-boilerplate`/`use-scaffold-method` to verify your template works\n\nExample workflow for boilerplate:\n```\n1. generate-boilerplate { templateName: \"react-vite\", boilerplateName: \"scaffold-vite-app\", ... }\n2. generate-boilerplate-file { templateName: \"react-vite\", filePath: \"package.json\", content: \"...\" }\n3. generate-boilerplate-file { templateName: \"react-vite\", filePath: \"src/App.tsx\", content: \"...\" }\n4. list-boilerplates (verify it appears)\n5. use-boilerplate { boilerplateName: \"scaffold-vite-app\", variables: {...} }\n```\n\nExample workflow for feature:\n```\n1. generate-feature-scaffold { templateName: \"nextjs-15\", featureName: \"scaffold-nextjs-component\", generator: \"componentGenerator.ts\", ... }\n2. generate-boilerplate-file { templateName: \"nextjs-15\", filePath: \"src/components/Component.tsx\", content: \"...\" }\n3. list-scaffolding-methods (verify it appears)\n4. use-scaffold-method { scaffoldName: \"scaffold-nextjs-component\", variables: {...} }\n```\n{% endif %}\n";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { l as TemplateService, t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-DxdrPlcb.mjs";
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as ListBoilerplatesTool, c as GenerateBoilerplateFileTool, i as UseBoilerplateTool, n as UseScaffoldMethodTool, o as GenerateFeatureScaffoldTool, s as GenerateBoilerplateTool, t as WriteToFileTool } from "./tools-Dn5KgBUI.mjs";
|
|
3
3
|
import { TemplatesManagerService } from "@agiflowai/aicode-utils";
|
|
4
4
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
5
5
|
import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListToolsRequestSchema, isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -10,7 +10,7 @@ import express from "express";
|
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
12
12
|
//#region package.json
|
|
13
|
-
var version = "1.0
|
|
13
|
+
var version = "1.1.0";
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region src/instructions/server.md?raw
|
|
16
16
|
var server_default = "Use this MCP server to {% if isMonolith %}create your monolith project and add features (pages, components, services, etc.){% else %}create new projects and add features (pages, components, services, etc.){% endif %}.\n\n## Workflow:\n{% if not isMonolith %}\n1. **Creating New Project**: Use `list-boilerplates` → `use-boilerplate`\n2. **Adding Features**: Use `list-scaffolding-methods` → `use-scaffold-method`\n{% else %}\n1. **Creating Project**: Use `use-boilerplate` (boilerplateName auto-detected from `.toolkit/settings.yaml`)\n2. **Adding Features**: Use `list-scaffolding-methods` → `use-scaffold-method`\n{% endif %}\n\n## AI Usage Guidelines:\n{% if not isMonolith %}\n- Always call `list-boilerplates` first when creating new projects to see available options\n{% endif %}\n- Always call `list-scaffolding-methods` first when adding features to understand what's available\n- Follow the exact variable schema provided - validation will fail if required fields are missing\n{% if not isMonolith %}\n- Use kebab-case for project names (e.g., \"my-new-app\")\n{% else %}\n- In monolith mode, parameters like `boilerplateName` and `templateName` are auto-detected from `.toolkit/settings.yaml`\n- You only need to provide `variables` when calling `use-boilerplate` or `use-scaffold-method`\n{% endif %}\n- The tools automatically handle file placement, imports, and code generation\n- Check the returned JSON schemas to understand required vs optional variables\n{% if adminEnabled %}\n\n## Admin Mode (Template Generation):\n\nWhen creating custom boilerplate templates for frameworks not yet supported:\n\n1. **Create Boilerplate Configuration**: Use `generate-boilerplate` to add a new boilerplate entry to a template's scaffold.yaml\n - Specify template name, boilerplate name, description, target folder, and variable schema\n - This creates the scaffold.yaml structure following the nextjs-15 pattern\n - Optional: Add detailed instruction about file purposes and design patterns\n\n2. **Create Feature Configuration**: Use `generate-feature-scaffold` to add a new feature entry to a template's scaffold.yaml\n - Specify template name, feature name, generator, description, and variable schema\n - This creates the scaffold.yaml structure for feature scaffolds (pages, components, etc.)\n - Optional: Add detailed instruction about file purposes and design patterns\n - Optional: Specify patterns to match existing files this feature works with\n\n3. **Create Template Files**: Use `generate-boilerplate-file` to create the actual template files\n - Create files referenced in the boilerplate's or feature's includes array\n - Use {{ variableName }} syntax for Liquid variable placeholders\n - Can copy from existing source files or provide content directly\n - Files automatically get .liquid extension\n\n4. **Test the Template**: Use `list-boilerplates`/`list-scaffolding-methods` and `use-boilerplate`/`use-scaffold-method` to verify your template works\n\nExample workflow for boilerplate:\n```\n1. generate-boilerplate { templateName: \"react-vite\", boilerplateName: \"scaffold-vite-app\", ... }\n2. generate-boilerplate-file { templateName: \"react-vite\", filePath: \"package.json\", content: \"...\" }\n3. generate-boilerplate-file { templateName: \"react-vite\", filePath: \"src/App.tsx\", content: \"...\" }\n4. list-boilerplates (verify it appears)\n5. use-boilerplate { boilerplateName: \"scaffold-vite-app\", variables: {...} }\n```\n\nExample workflow for feature:\n```\n1. generate-feature-scaffold { templateName: \"nextjs-15\", featureName: \"scaffold-nextjs-component\", generator: \"componentGenerator.ts\", ... }\n2. generate-boilerplate-file { templateName: \"nextjs-15\", filePath: \"src/components/Component.tsx\", content: \"...\" }\n3. list-scaffolding-methods (verify it appears)\n4. use-scaffold-method { scaffoldName: \"scaffold-nextjs-component\", variables: {...} }\n```\n{% endif %}\n";
|
|
@@ -8,7 +8,6 @@ js_yaml = require_ListScaffoldingMethodsTool.__toESM(js_yaml, 1);
|
|
|
8
8
|
let node_fs = require("node:fs");
|
|
9
9
|
let _composio_json_schema_to_zod = require("@composio/json-schema-to-zod");
|
|
10
10
|
let node_fs_promises = require("node:fs/promises");
|
|
11
|
-
node_fs_promises = require_ListScaffoldingMethodsTool.__toESM(node_fs_promises, 1);
|
|
12
11
|
let node_os = require("node:os");
|
|
13
12
|
node_os = require_ListScaffoldingMethodsTool.__toESM(node_os, 1);
|
|
14
13
|
//#region src/services/BoilerplateGeneratorService.ts
|
|
@@ -1314,10 +1313,27 @@ The boilerplate provides a starting point - you may need to add features or cust
|
|
|
1314
1313
|
}
|
|
1315
1314
|
};
|
|
1316
1315
|
//#endregion
|
|
1316
|
+
//#region src/utils/scaffoldPendingLog.ts
|
|
1317
|
+
async function writePendingScaffoldLog(config) {
|
|
1318
|
+
const { scaffoldId, projectPath, featureName, generatedFiles } = config;
|
|
1319
|
+
try {
|
|
1320
|
+
const logEntry = {
|
|
1321
|
+
timestamp: Date.now(),
|
|
1322
|
+
scaffoldId,
|
|
1323
|
+
projectPath,
|
|
1324
|
+
featureName,
|
|
1325
|
+
generatedFiles,
|
|
1326
|
+
operation: "scaffold"
|
|
1327
|
+
};
|
|
1328
|
+
await (0, node_fs_promises.appendFile)(node_path.join(node_os.tmpdir(), `scaffold-mcp-pending-${scaffoldId}.jsonl`), `${JSON.stringify(logEntry)}\n`, "utf-8");
|
|
1329
|
+
} catch (error) {
|
|
1330
|
+
console.error("Failed to write pending scaffold log:", error);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
//#endregion
|
|
1317
1334
|
//#region src/tools/UseScaffoldMethodTool.ts
|
|
1318
1335
|
var UseScaffoldMethodTool = class UseScaffoldMethodTool {
|
|
1319
1336
|
static TOOL_NAME = "use-scaffold-method";
|
|
1320
|
-
static TEMP_LOG_DIR = node_os.tmpdir();
|
|
1321
1337
|
fileSystemService;
|
|
1322
1338
|
scaffoldingMethodsService;
|
|
1323
1339
|
isMonolith;
|
|
@@ -1327,25 +1343,6 @@ var UseScaffoldMethodTool = class UseScaffoldMethodTool {
|
|
|
1327
1343
|
this.isMonolith = isMonolith;
|
|
1328
1344
|
}
|
|
1329
1345
|
/**
|
|
1330
|
-
* Write scaffold execution info to temp log file for hook processing
|
|
1331
|
-
*/
|
|
1332
|
-
async writePendingScaffoldLog(scaffoldId, projectPath, featureName, generatedFiles) {
|
|
1333
|
-
try {
|
|
1334
|
-
const logEntry = {
|
|
1335
|
-
timestamp: Date.now(),
|
|
1336
|
-
scaffoldId,
|
|
1337
|
-
projectPath,
|
|
1338
|
-
featureName,
|
|
1339
|
-
generatedFiles,
|
|
1340
|
-
operation: "scaffold"
|
|
1341
|
-
};
|
|
1342
|
-
const tempLogFile = node_path.join(UseScaffoldMethodTool.TEMP_LOG_DIR, `scaffold-mcp-pending-${scaffoldId}.jsonl`);
|
|
1343
|
-
await node_fs_promises.appendFile(tempLogFile, `${JSON.stringify(logEntry)}\n`, "utf-8");
|
|
1344
|
-
} catch (error) {
|
|
1345
|
-
console.error("Failed to write pending scaffold log:", error);
|
|
1346
|
-
}
|
|
1347
|
-
}
|
|
1348
|
-
/**
|
|
1349
1346
|
* Get the tool definition for MCP
|
|
1350
1347
|
*/
|
|
1351
1348
|
getDefinition() {
|
|
@@ -1410,7 +1407,12 @@ IMPORTANT:
|
|
|
1410
1407
|
marker
|
|
1411
1408
|
});
|
|
1412
1409
|
const scaffoldId = (0, _agiflowai_aicode_utils.generateStableId)(6);
|
|
1413
|
-
if (result.createdFiles && result.createdFiles.length > 0) await
|
|
1410
|
+
if (result.createdFiles && result.createdFiles.length > 0) await writePendingScaffoldLog({
|
|
1411
|
+
scaffoldId,
|
|
1412
|
+
projectPath: resolvedProjectPath,
|
|
1413
|
+
featureName: scaffold_feature_name,
|
|
1414
|
+
generatedFiles: result.createdFiles
|
|
1415
|
+
});
|
|
1414
1416
|
return { content: [{
|
|
1415
1417
|
type: "text",
|
|
1416
1418
|
text: `${result.message}
|
|
@@ -1575,3 +1577,9 @@ Object.defineProperty(exports, "WriteToFileTool", {
|
|
|
1575
1577
|
return WriteToFileTool;
|
|
1576
1578
|
}
|
|
1577
1579
|
});
|
|
1580
|
+
Object.defineProperty(exports, "writePendingScaffoldLog", {
|
|
1581
|
+
enumerable: true,
|
|
1582
|
+
get: function() {
|
|
1583
|
+
return writePendingScaffoldLog;
|
|
1584
|
+
}
|
|
1585
|
+
});
|
|
@@ -6,7 +6,7 @@ import path from "node:path";
|
|
|
6
6
|
import * as yaml$1 from "js-yaml";
|
|
7
7
|
import { readdirSync } from "node:fs";
|
|
8
8
|
import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
|
|
9
|
-
import
|
|
9
|
+
import { appendFile } from "node:fs/promises";
|
|
10
10
|
import * as os$1 from "node:os";
|
|
11
11
|
//#region src/services/BoilerplateGeneratorService.ts
|
|
12
12
|
/**
|
|
@@ -1311,10 +1311,27 @@ The boilerplate provides a starting point - you may need to add features or cust
|
|
|
1311
1311
|
}
|
|
1312
1312
|
};
|
|
1313
1313
|
//#endregion
|
|
1314
|
+
//#region src/utils/scaffoldPendingLog.ts
|
|
1315
|
+
async function writePendingScaffoldLog(config) {
|
|
1316
|
+
const { scaffoldId, projectPath, featureName, generatedFiles } = config;
|
|
1317
|
+
try {
|
|
1318
|
+
const logEntry = {
|
|
1319
|
+
timestamp: Date.now(),
|
|
1320
|
+
scaffoldId,
|
|
1321
|
+
projectPath,
|
|
1322
|
+
featureName,
|
|
1323
|
+
generatedFiles,
|
|
1324
|
+
operation: "scaffold"
|
|
1325
|
+
};
|
|
1326
|
+
await appendFile(path$1.join(os$1.tmpdir(), `scaffold-mcp-pending-${scaffoldId}.jsonl`), `${JSON.stringify(logEntry)}\n`, "utf-8");
|
|
1327
|
+
} catch (error) {
|
|
1328
|
+
console.error("Failed to write pending scaffold log:", error);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
//#endregion
|
|
1314
1332
|
//#region src/tools/UseScaffoldMethodTool.ts
|
|
1315
1333
|
var UseScaffoldMethodTool = class UseScaffoldMethodTool {
|
|
1316
1334
|
static TOOL_NAME = "use-scaffold-method";
|
|
1317
|
-
static TEMP_LOG_DIR = os$1.tmpdir();
|
|
1318
1335
|
fileSystemService;
|
|
1319
1336
|
scaffoldingMethodsService;
|
|
1320
1337
|
isMonolith;
|
|
@@ -1324,25 +1341,6 @@ var UseScaffoldMethodTool = class UseScaffoldMethodTool {
|
|
|
1324
1341
|
this.isMonolith = isMonolith;
|
|
1325
1342
|
}
|
|
1326
1343
|
/**
|
|
1327
|
-
* Write scaffold execution info to temp log file for hook processing
|
|
1328
|
-
*/
|
|
1329
|
-
async writePendingScaffoldLog(scaffoldId, projectPath, featureName, generatedFiles) {
|
|
1330
|
-
try {
|
|
1331
|
-
const logEntry = {
|
|
1332
|
-
timestamp: Date.now(),
|
|
1333
|
-
scaffoldId,
|
|
1334
|
-
projectPath,
|
|
1335
|
-
featureName,
|
|
1336
|
-
generatedFiles,
|
|
1337
|
-
operation: "scaffold"
|
|
1338
|
-
};
|
|
1339
|
-
const tempLogFile = path$1.join(UseScaffoldMethodTool.TEMP_LOG_DIR, `scaffold-mcp-pending-${scaffoldId}.jsonl`);
|
|
1340
|
-
await fs$1.appendFile(tempLogFile, `${JSON.stringify(logEntry)}\n`, "utf-8");
|
|
1341
|
-
} catch (error) {
|
|
1342
|
-
console.error("Failed to write pending scaffold log:", error);
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
/**
|
|
1346
1344
|
* Get the tool definition for MCP
|
|
1347
1345
|
*/
|
|
1348
1346
|
getDefinition() {
|
|
@@ -1407,7 +1405,12 @@ IMPORTANT:
|
|
|
1407
1405
|
marker
|
|
1408
1406
|
});
|
|
1409
1407
|
const scaffoldId = generateStableId(6);
|
|
1410
|
-
if (result.createdFiles && result.createdFiles.length > 0) await
|
|
1408
|
+
if (result.createdFiles && result.createdFiles.length > 0) await writePendingScaffoldLog({
|
|
1409
|
+
scaffoldId,
|
|
1410
|
+
projectPath: resolvedProjectPath,
|
|
1411
|
+
featureName: scaffold_feature_name,
|
|
1412
|
+
generatedFiles: result.createdFiles
|
|
1413
|
+
});
|
|
1411
1414
|
return { content: [{
|
|
1412
1415
|
type: "text",
|
|
1413
1416
|
text: `${result.message}
|
|
@@ -1512,4 +1515,4 @@ Parameters:
|
|
|
1512
1515
|
}
|
|
1513
1516
|
};
|
|
1514
1517
|
//#endregion
|
|
1515
|
-
export {
|
|
1518
|
+
export { ListBoilerplatesTool as a, GenerateBoilerplateFileTool as c, BoilerplateGeneratorService as d, UseBoilerplateTool as i, ScaffoldGeneratorService as l, UseScaffoldMethodTool as n, GenerateFeatureScaffoldTool as o, writePendingScaffoldLog as r, GenerateBoilerplateTool as s, WriteToFileTool as t, BoilerplateService as u };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agiflowai/scaffold-mcp",
|
|
3
3
|
"description": "MCP server for scaffolding applications with boilerplate templates",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"license": "AGPL-3.0",
|
|
6
6
|
"author": "AgiflowIO",
|
|
7
7
|
"repository": {
|
|
@@ -42,16 +42,16 @@
|
|
|
42
42
|
"commander": "14.0.3",
|
|
43
43
|
"execa": "9.6.1",
|
|
44
44
|
"express": "5.2.1",
|
|
45
|
-
"js-yaml": "4.
|
|
46
|
-
"liquidjs": "10.
|
|
45
|
+
"js-yaml": "4.2.0",
|
|
46
|
+
"liquidjs": "10.27.0",
|
|
47
47
|
"minimatch": "10.2.5",
|
|
48
48
|
"pino": "10.3.1",
|
|
49
49
|
"pino-pretty": "13.1.3",
|
|
50
50
|
"zod": "4.3.6",
|
|
51
|
-
"@agiflowai/aicode-utils": "1.
|
|
52
|
-
"@agiflowai/architect-mcp": "1.
|
|
53
|
-
"@agiflowai/hooks-adapter": "0.1.
|
|
54
|
-
"@agiflowai/coding-agent-bridge": "1.
|
|
51
|
+
"@agiflowai/aicode-utils": "1.2.0",
|
|
52
|
+
"@agiflowai/architect-mcp": "1.2.0",
|
|
53
|
+
"@agiflowai/hooks-adapter": "0.1.1",
|
|
54
|
+
"@agiflowai/coding-agent-bridge": "1.2.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/express": "5.0.6",
|