@agiflowai/scaffold-mcp 1.0.27 → 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/{ListScaffoldingMethodsTool-DBwZzJTA.cjs → ListScaffoldingMethodsTool-CYZtpU-W.cjs} +109 -126
- package/dist/{ListScaffoldingMethodsTool-D6BkKQyK.mjs → ListScaffoldingMethodsTool-DxdrPlcb.mjs} +32 -44
- package/dist/{claudeCode-Dozuzn4S.mjs → claudeCode-DbKOy8W8.mjs} +7 -10
- package/dist/{claudeCode-B6CWgRYJ.cjs → claudeCode-g1eRidPR.cjs} +54 -57
- package/dist/cli.cjs +329 -157
- package/dist/cli.mjs +202 -30
- package/dist/{geminiCli-COS3X1P7.cjs → geminiCli--s1Qy7ZP.cjs} +35 -37
- package/dist/{geminiCli-CzgQDDMl.mjs → geminiCli-CcrZEqsz.mjs} +3 -5
- package/dist/index.cjs +5 -5
- package/dist/index.d.cts +3 -12
- package/dist/index.d.mts +3 -14
- package/dist/index.mjs +4 -5
- package/dist/{shared-oDx2Btq0.mjs → shared-BVYIN3Is.mjs} +4 -10
- package/dist/{shared-fkWett9D.cjs → shared-QxPXh-L-.cjs} +17 -23
- package/dist/{src-DuOmlC4n.cjs → src-BG_X82dw.cjs} +59 -77
- package/dist/{src-CSfEg-8i.mjs → src-DnVktdhD.mjs} +12 -30
- package/dist/{tools-DsnQImJ1.cjs → tools-COb9iBtt.cjs} +132 -130
- package/dist/{tools-t-HMGLVh.mjs → tools-Dn5KgBUI.mjs} +38 -41
- package/package.json +22 -22
package/dist/cli.mjs
CHANGED
|
@@ -1,13 +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-
|
|
3
|
-
import { n as ScaffoldingMethodsService, s as FileSystemService } from "./ListScaffoldingMethodsTool-
|
|
4
|
-
import {
|
|
5
|
-
import { ProjectConfigResolver, TemplatesManagerService, icons, messages, print, sections } from "@agiflowai/aicode-utils";
|
|
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
|
+
import { n as ScaffoldingMethodsService, s as FileSystemService } from "./ListScaffoldingMethodsTool-DxdrPlcb.mjs";
|
|
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
|
-
|
|
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
|
|
11
51
|
//#region src/commands/boilerplate.ts
|
|
12
52
|
/**
|
|
13
53
|
* Boilerplate CLI command
|
|
@@ -44,7 +84,7 @@ boilerplateCommand.command("list").description("List all available boilerplate t
|
|
|
44
84
|
process.exit(1);
|
|
45
85
|
}
|
|
46
86
|
});
|
|
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) => {
|
|
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) => {
|
|
48
88
|
try {
|
|
49
89
|
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
50
90
|
if (!templatesDir) {
|
|
@@ -65,9 +105,9 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
65
105
|
let allBoilerplates = [];
|
|
66
106
|
let cursor;
|
|
67
107
|
do {
|
|
68
|
-
const result
|
|
69
|
-
allBoilerplates = allBoilerplates.concat(result
|
|
70
|
-
cursor = result
|
|
108
|
+
const result = await boilerplateService.listBoilerplates(cursor);
|
|
109
|
+
allBoilerplates = allBoilerplates.concat(result.boilerplates);
|
|
110
|
+
cursor = result.nextCursor;
|
|
71
111
|
} while (cursor);
|
|
72
112
|
messages.error(`Boilerplate '${boilerplateName}' not found.`);
|
|
73
113
|
print.warning(`Available boilerplates: ${allBoilerplates.map((b) => b.name).join(", ")}`);
|
|
@@ -94,7 +134,8 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
94
134
|
boilerplateName,
|
|
95
135
|
variables,
|
|
96
136
|
monolith: options.monolith,
|
|
97
|
-
targetFolderOverride: options.targetFolder
|
|
137
|
+
targetFolderOverride: options.targetFolder,
|
|
138
|
+
marker: options.marker
|
|
98
139
|
});
|
|
99
140
|
if (result.success) {
|
|
100
141
|
messages.success("Project created successfully!");
|
|
@@ -121,6 +162,42 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
|
|
|
121
162
|
process.exit(1);
|
|
122
163
|
}
|
|
123
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
|
+
});
|
|
124
201
|
boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
|
|
125
202
|
try {
|
|
126
203
|
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
@@ -145,7 +222,28 @@ boilerplateCommand.command("info <boilerplateName>").description("Show detailed
|
|
|
145
222
|
process.exit(1);
|
|
146
223
|
}
|
|
147
224
|
});
|
|
148
|
-
|
|
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
|
+
});
|
|
149
247
|
//#endregion
|
|
150
248
|
//#region src/commands/mcp-serve.ts
|
|
151
249
|
/**
|
|
@@ -292,7 +390,6 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
292
390
|
process.exit(1);
|
|
293
391
|
}
|
|
294
392
|
});
|
|
295
|
-
|
|
296
393
|
//#endregion
|
|
297
394
|
//#region src/commands/scaffold.ts
|
|
298
395
|
/**
|
|
@@ -301,13 +398,6 @@ const mcpServeCommand = new Command("mcp-serve").description("Start MCP server w
|
|
|
301
398
|
const scaffoldCommand = new Command("scaffold").description("Add features to existing projects");
|
|
302
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) => {
|
|
303
400
|
try {
|
|
304
|
-
if (!projectPath && !options.template) {
|
|
305
|
-
messages.error("Either projectPath or --template option must be provided");
|
|
306
|
-
messages.hint("Examples:");
|
|
307
|
-
print.debug(" scaffold-mcp scaffold list ./my-project");
|
|
308
|
-
print.debug(" scaffold-mcp scaffold list --template nextjs-15");
|
|
309
|
-
process.exit(1);
|
|
310
|
-
}
|
|
311
401
|
const templatesDir = await TemplatesManagerService.findTemplatesPath();
|
|
312
402
|
if (!templatesDir) {
|
|
313
403
|
messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
|
|
@@ -316,15 +406,16 @@ scaffoldCommand.command("list [projectPath]").description("List available scaffo
|
|
|
316
406
|
const scaffoldingMethodsService = new ScaffoldingMethodsService(new FileSystemService(), templatesDir);
|
|
317
407
|
let result;
|
|
318
408
|
let displayName;
|
|
319
|
-
if (projectPath) {
|
|
320
|
-
const
|
|
409
|
+
if (projectPath || !options.template) {
|
|
410
|
+
const inputProjectPath = projectPath ?? process.cwd();
|
|
411
|
+
const absolutePath = path.resolve(inputProjectPath);
|
|
321
412
|
if (!await ProjectConfigResolver.hasConfiguration(absolutePath)) {
|
|
322
413
|
messages.error(`No project configuration found in ${absolutePath}`);
|
|
323
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");
|
|
324
415
|
process.exit(1);
|
|
325
416
|
}
|
|
326
417
|
result = await scaffoldingMethodsService.listScaffoldingMethods(absolutePath, options.cursor);
|
|
327
|
-
displayName = projectPath;
|
|
418
|
+
displayName = projectPath ?? absolutePath;
|
|
328
419
|
} else {
|
|
329
420
|
result = await scaffoldingMethodsService.listScaffoldingMethodsByTemplate(options.template, options.cursor);
|
|
330
421
|
displayName = `template: ${options.template}`;
|
|
@@ -353,7 +444,7 @@ scaffoldCommand.command("list [projectPath]").description("List available scaffo
|
|
|
353
444
|
process.exit(1);
|
|
354
445
|
}
|
|
355
446
|
});
|
|
356
|
-
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) => {
|
|
357
448
|
try {
|
|
358
449
|
const projectPath = path.resolve(options.project);
|
|
359
450
|
if (!await ProjectConfigResolver.hasConfiguration(projectPath)) {
|
|
@@ -410,9 +501,17 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
410
501
|
const result = await scaffoldingMethodsService.useScaffoldMethod({
|
|
411
502
|
projectPath,
|
|
412
503
|
scaffold_feature_name: featureName,
|
|
413
|
-
variables
|
|
504
|
+
variables,
|
|
505
|
+
marker: options.marker
|
|
414
506
|
});
|
|
415
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
|
+
});
|
|
416
515
|
messages.success("✅ Feature added successfully!");
|
|
417
516
|
if (result.createdFiles && result.createdFiles.length > 0) {
|
|
418
517
|
print.header("\n📁 Created files:");
|
|
@@ -426,6 +525,7 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
426
525
|
print.debug(` - ${warning}`);
|
|
427
526
|
});
|
|
428
527
|
}
|
|
528
|
+
print.debug(`\nSCAFFOLD_ID:${scaffoldId}`);
|
|
429
529
|
print.header("\n📋 Next steps:");
|
|
430
530
|
print.debug(" - Review the generated files");
|
|
431
531
|
print.debug(" - Update imports if necessary");
|
|
@@ -439,6 +539,40 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
|
|
|
439
539
|
process.exit(1);
|
|
440
540
|
}
|
|
441
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
|
+
});
|
|
442
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) => {
|
|
443
577
|
try {
|
|
444
578
|
if (!options.project && !options.template) {
|
|
@@ -496,7 +630,6 @@ scaffoldCommand.command("info <featureName>").description("Show detailed informa
|
|
|
496
630
|
process.exit(1);
|
|
497
631
|
}
|
|
498
632
|
});
|
|
499
|
-
|
|
500
633
|
//#endregion
|
|
501
634
|
//#region src/commands/hook.ts
|
|
502
635
|
/**
|
|
@@ -578,7 +711,7 @@ const hookCommand = new Command("hook").description("Execute scaffold hooks for
|
|
|
578
711
|
const resolvedAdapterConfig = Object.keys(adapterConfig).length > 0 ? adapterConfig : void 0;
|
|
579
712
|
if (!isHookMethod(hookMethod)) process.exit(0);
|
|
580
713
|
if (agent === CLAUDE_CODE) {
|
|
581
|
-
const hookModule = await import("./claudeCode-
|
|
714
|
+
const hookModule = await import("./claudeCode-DbKOy8W8.mjs");
|
|
582
715
|
const claudeCallbacks = [];
|
|
583
716
|
if (hookModule.UseScaffoldMethodHook) {
|
|
584
717
|
const hookInstance = new hookModule.UseScaffoldMethodHook();
|
|
@@ -593,7 +726,7 @@ const hookCommand = new Command("hook").description("Execute scaffold hooks for
|
|
|
593
726
|
if (claudeCallbacks.length === 0) process.exit(0);
|
|
594
727
|
await new ClaudeCodeAdapter().executeMultiple(claudeCallbacks, resolvedAdapterConfig);
|
|
595
728
|
} else if (agent === GEMINI_CLI) {
|
|
596
|
-
const hookModule = await import("./geminiCli-
|
|
729
|
+
const hookModule = await import("./geminiCli-CcrZEqsz.mjs");
|
|
597
730
|
const geminiCallbacks = [];
|
|
598
731
|
if (hookModule.UseScaffoldMethodHook) {
|
|
599
732
|
const hookInstance = new hookModule.UseScaffoldMethodHook();
|
|
@@ -608,7 +741,45 @@ const hookCommand = new Command("hook").description("Execute scaffold hooks for
|
|
|
608
741
|
process.exit(1);
|
|
609
742
|
}
|
|
610
743
|
});
|
|
611
|
-
|
|
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);
|
|
612
783
|
//#endregion
|
|
613
784
|
//#region src/cli.ts
|
|
614
785
|
/**
|
|
@@ -620,10 +791,11 @@ async function main() {
|
|
|
620
791
|
program.addCommand(mcpServeCommand);
|
|
621
792
|
program.addCommand(boilerplateCommand);
|
|
622
793
|
program.addCommand(scaffoldCommand);
|
|
794
|
+
program.addCommand(templateCommand);
|
|
795
|
+
program.addCommand(fileCommand$1);
|
|
623
796
|
program.addCommand(hookCommand);
|
|
624
797
|
await program.parseAsync(process.argv);
|
|
625
798
|
}
|
|
626
799
|
main();
|
|
627
|
-
|
|
628
800
|
//#endregion
|
|
629
|
-
export {
|
|
801
|
+
export {};
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
const require_ListScaffoldingMethodsTool = require(
|
|
2
|
-
const require_shared = require(
|
|
3
|
-
let
|
|
4
|
-
let
|
|
5
|
-
|
|
1
|
+
const require_ListScaffoldingMethodsTool = require("./ListScaffoldingMethodsTool-CYZtpU-W.cjs");
|
|
2
|
+
const require_shared = require("./shared-QxPXh-L-.cjs");
|
|
3
|
+
let _agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
4
|
+
let _agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
|
|
6
5
|
//#region src/hooks/geminiCli/useScaffoldMethod.ts
|
|
7
6
|
/**
|
|
8
7
|
* UseScaffoldMethod Hook class for Gemini CLI
|
|
@@ -24,52 +23,52 @@ var UseScaffoldMethodHook = class {
|
|
|
24
23
|
const filePath = context.tool_input?.file_path;
|
|
25
24
|
const absoluteFilePath = await require_shared.resolveNewFileWriteTarget(context.cwd, context.tool_name, filePath);
|
|
26
25
|
if (!absoluteFilePath || !filePath) return {
|
|
27
|
-
decision:
|
|
26
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
28
27
|
message: "Not a new file write operation"
|
|
29
28
|
};
|
|
30
|
-
const executionLog = new
|
|
29
|
+
const executionLog = new _agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
|
|
31
30
|
const sessionKey = filePath;
|
|
32
31
|
if (await executionLog.hasExecuted({
|
|
33
32
|
filePath: sessionKey,
|
|
34
|
-
decision:
|
|
33
|
+
decision: _agiflowai_hooks_adapter.DECISION_DENY
|
|
35
34
|
})) {
|
|
36
35
|
await executionLog.logExecution({
|
|
37
36
|
filePath: sessionKey,
|
|
38
37
|
operation: "list-scaffold-methods",
|
|
39
|
-
decision:
|
|
38
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP
|
|
40
39
|
});
|
|
41
40
|
return {
|
|
42
|
-
decision:
|
|
41
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
43
42
|
message: "Scaffolding methods already provided in this session"
|
|
44
43
|
};
|
|
45
44
|
}
|
|
46
|
-
const templatesPath = await
|
|
45
|
+
const templatesPath = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
|
|
47
46
|
if (!templatesPath) return {
|
|
48
|
-
decision:
|
|
47
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
49
48
|
message: "Templates folder not found - skipping scaffold method check"
|
|
50
49
|
};
|
|
51
50
|
const tool = new require_ListScaffoldingMethodsTool.ListScaffoldingMethodsTool(templatesPath, false);
|
|
52
|
-
const projectPath = (await new
|
|
51
|
+
const projectPath = (await new _agiflowai_aicode_utils.ProjectFinderService(await _agiflowai_aicode_utils.TemplatesManagerService.getWorkspaceRoot(context.cwd)).findProjectForFile(absoluteFilePath))?.root || context.cwd;
|
|
53
52
|
const result = await tool.execute({ projectPath });
|
|
54
53
|
const firstContent = result.content[0];
|
|
55
54
|
if (firstContent?.type !== "text") return {
|
|
56
|
-
decision:
|
|
55
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
57
56
|
message: "⚠️ Unexpected response type from scaffolding methods tool"
|
|
58
57
|
};
|
|
59
58
|
if (result.isError) {
|
|
60
59
|
await executionLog.logExecution({
|
|
61
60
|
filePath: sessionKey,
|
|
62
61
|
operation: "list-scaffold-methods",
|
|
63
|
-
decision:
|
|
62
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP
|
|
64
63
|
});
|
|
65
64
|
return {
|
|
66
|
-
decision:
|
|
65
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
67
66
|
message: `⚠️ Could not load scaffolding methods: ${firstContent.text}`
|
|
68
67
|
};
|
|
69
68
|
}
|
|
70
69
|
const resultText = firstContent.text;
|
|
71
70
|
if (typeof resultText !== "string") return {
|
|
72
|
-
decision:
|
|
71
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
73
72
|
message: "⚠️ Invalid response format from scaffolding methods tool"
|
|
74
73
|
};
|
|
75
74
|
const data = JSON.parse(resultText);
|
|
@@ -77,10 +76,10 @@ var UseScaffoldMethodHook = class {
|
|
|
77
76
|
await executionLog.logExecution({
|
|
78
77
|
filePath: sessionKey,
|
|
79
78
|
operation: "list-scaffold-methods",
|
|
80
|
-
decision:
|
|
79
|
+
decision: _agiflowai_hooks_adapter.DECISION_DENY
|
|
81
80
|
});
|
|
82
81
|
return {
|
|
83
|
-
decision:
|
|
82
|
+
decision: _agiflowai_hooks_adapter.DECISION_DENY,
|
|
84
83
|
message: "No scaffolding methods are available for this project template. You should write new files directly using the Write tool."
|
|
85
84
|
};
|
|
86
85
|
}
|
|
@@ -88,15 +87,15 @@ var UseScaffoldMethodHook = class {
|
|
|
88
87
|
await executionLog.logExecution({
|
|
89
88
|
filePath: sessionKey,
|
|
90
89
|
operation: "list-scaffold-methods",
|
|
91
|
-
decision:
|
|
90
|
+
decision: _agiflowai_hooks_adapter.DECISION_DENY
|
|
92
91
|
});
|
|
93
92
|
return {
|
|
94
|
-
decision:
|
|
93
|
+
decision: _agiflowai_hooks_adapter.DECISION_DENY,
|
|
95
94
|
message
|
|
96
95
|
};
|
|
97
96
|
} catch (error) {
|
|
98
97
|
return {
|
|
99
|
-
decision:
|
|
98
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
100
99
|
message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
|
|
101
100
|
};
|
|
102
101
|
}
|
|
@@ -110,30 +109,30 @@ var UseScaffoldMethodHook = class {
|
|
|
110
109
|
*/
|
|
111
110
|
async postToolUse(context) {
|
|
112
111
|
try {
|
|
113
|
-
const executionLog = new
|
|
112
|
+
const executionLog = new _agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
|
|
114
113
|
const filePath = context.tool_input?.file_path;
|
|
115
114
|
const actualToolName = context.tool_name === "mcp__one-mcp__use_tool" ? context.tool_input?.toolName : context.tool_name;
|
|
116
115
|
if (actualToolName === "use-scaffold-method") return {
|
|
117
|
-
decision:
|
|
116
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW,
|
|
118
117
|
message: "Scaffold execution logged for progress tracking"
|
|
119
118
|
};
|
|
120
119
|
const operation = extractOperation(actualToolName);
|
|
121
120
|
if (!filePath || operation !== "edit" && operation !== "write") return {
|
|
122
|
-
decision:
|
|
121
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
123
122
|
message: "Not a file edit/write operation"
|
|
124
123
|
};
|
|
125
124
|
const lastScaffoldExecution = await getLastScaffoldExecution(executionLog);
|
|
126
125
|
if (!lastScaffoldExecution) return {
|
|
127
|
-
decision:
|
|
126
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
128
127
|
message: "No scaffold execution found"
|
|
129
128
|
};
|
|
130
129
|
const { scaffoldId, generatedFiles, featureName } = lastScaffoldExecution;
|
|
131
130
|
const fulfilledKey = `scaffold-fulfilled-${scaffoldId}`;
|
|
132
131
|
if (await executionLog.hasExecuted({
|
|
133
132
|
filePath: fulfilledKey,
|
|
134
|
-
decision:
|
|
133
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW
|
|
135
134
|
})) return {
|
|
136
|
-
decision:
|
|
135
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
137
136
|
message: "Scaffold already fulfilled"
|
|
138
137
|
};
|
|
139
138
|
const isScaffoldedFile = generatedFiles.includes(filePath);
|
|
@@ -141,11 +140,11 @@ var UseScaffoldMethodHook = class {
|
|
|
141
140
|
const editKey = `scaffold-edit-${scaffoldId}-${filePath}`;
|
|
142
141
|
if (!await executionLog.hasExecuted({
|
|
143
142
|
filePath: editKey,
|
|
144
|
-
decision:
|
|
143
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW
|
|
145
144
|
})) await executionLog.logExecution({
|
|
146
145
|
filePath: editKey,
|
|
147
146
|
operation: "scaffold-file-edit",
|
|
148
|
-
decision:
|
|
147
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW
|
|
149
148
|
});
|
|
150
149
|
}
|
|
151
150
|
const editedFiles = await getEditedScaffoldFiles(executionLog, scaffoldId);
|
|
@@ -155,17 +154,17 @@ var UseScaffoldMethodHook = class {
|
|
|
155
154
|
await executionLog.logExecution({
|
|
156
155
|
filePath: fulfilledKey,
|
|
157
156
|
operation: "scaffold-fulfilled",
|
|
158
|
-
decision:
|
|
157
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW
|
|
159
158
|
});
|
|
160
159
|
return {
|
|
161
|
-
decision:
|
|
160
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW,
|
|
162
161
|
message: `✅ All scaffold files${featureName ? ` for "${featureName}"` : ""} have been implemented! (${totalFiles}/${totalFiles} files completed)`
|
|
163
162
|
};
|
|
164
163
|
}
|
|
165
164
|
if (isScaffoldedFile) {
|
|
166
165
|
const remainingFilesList = remainingFiles.map((f) => ` - ${f}`).join("\n");
|
|
167
166
|
return {
|
|
168
|
-
decision:
|
|
167
|
+
decision: _agiflowai_hooks_adapter.DECISION_ALLOW,
|
|
169
168
|
message: `
|
|
170
169
|
⚠️ **Scaffold Implementation Progress${featureName ? ` for "${featureName}"` : ""}: ${editedFiles.length}/${totalFiles} files completed**
|
|
171
170
|
|
|
@@ -177,12 +176,12 @@ Don't forget to complete the implementation for all scaffolded files!
|
|
|
177
176
|
};
|
|
178
177
|
}
|
|
179
178
|
return {
|
|
180
|
-
decision:
|
|
179
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
181
180
|
message: "Edited file not part of last scaffold execution"
|
|
182
181
|
};
|
|
183
182
|
} catch (error) {
|
|
184
183
|
return {
|
|
185
|
-
decision:
|
|
184
|
+
decision: _agiflowai_hooks_adapter.DECISION_SKIP,
|
|
186
185
|
message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
|
|
187
186
|
};
|
|
188
187
|
}
|
|
@@ -237,6 +236,5 @@ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
|
|
|
237
236
|
return [];
|
|
238
237
|
}
|
|
239
238
|
}
|
|
240
|
-
|
|
241
239
|
//#endregion
|
|
242
|
-
exports.UseScaffoldMethodHook = UseScaffoldMethodHook;
|
|
240
|
+
exports.UseScaffoldMethodHook = UseScaffoldMethodHook;
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-
|
|
2
|
-
import { n as resolveNewFileWriteTarget, t as formatScaffoldMethodsHookMessage } from "./shared-
|
|
1
|
+
import { t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-DxdrPlcb.mjs";
|
|
2
|
+
import { n as resolveNewFileWriteTarget, t as formatScaffoldMethodsHookMessage } from "./shared-BVYIN3Is.mjs";
|
|
3
3
|
import { ProjectFinderService, TemplatesManagerService } from "@agiflowai/aicode-utils";
|
|
4
4
|
import { DECISION_ALLOW, DECISION_DENY, DECISION_SKIP, ExecutionLogService } from "@agiflowai/hooks-adapter";
|
|
5
|
-
|
|
6
5
|
//#region src/hooks/geminiCli/useScaffoldMethod.ts
|
|
7
6
|
/**
|
|
8
7
|
* UseScaffoldMethod Hook class for Gemini CLI
|
|
@@ -237,6 +236,5 @@ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
|
|
|
237
236
|
return [];
|
|
238
237
|
}
|
|
239
238
|
}
|
|
240
|
-
|
|
241
239
|
//#endregion
|
|
242
|
-
export { UseScaffoldMethodHook };
|
|
240
|
+
export { UseScaffoldMethodHook };
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
const
|
|
4
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_ListScaffoldingMethodsTool = require("./ListScaffoldingMethodsTool-CYZtpU-W.cjs");
|
|
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;
|
|
@@ -24,4 +24,4 @@ exports.UseBoilerplateTool = require_tools.UseBoilerplateTool;
|
|
|
24
24
|
exports.UseScaffoldMethodTool = require_tools.UseScaffoldMethodTool;
|
|
25
25
|
exports.VariableReplacementService = require_ListScaffoldingMethodsTool.VariableReplacementService;
|
|
26
26
|
exports.WriteToFileTool = require_tools.WriteToFileTool;
|
|
27
|
-
exports.createServer = require_src.createServer;
|
|
27
|
+
exports.createServer = require_src.createServer;
|
package/dist/index.d.cts
CHANGED
|
@@ -21,7 +21,7 @@ declare enum TransportMode {
|
|
|
21
21
|
STDIO = "stdio",
|
|
22
22
|
HTTP = "http",
|
|
23
23
|
SSE = "sse",
|
|
24
|
-
CLI = "cli"
|
|
24
|
+
CLI = "cli"
|
|
25
25
|
}
|
|
26
26
|
/**
|
|
27
27
|
* Transport configuration options
|
|
@@ -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
|
*/
|
|
@@ -291,6 +286,7 @@ declare class WriteToFileTool {
|
|
|
291
286
|
static readonly TOOL_NAME = "write-to-file";
|
|
292
287
|
private fileSystemService;
|
|
293
288
|
constructor();
|
|
289
|
+
private resolveWorkspaceFilePath;
|
|
294
290
|
/**
|
|
295
291
|
* Get the tool definition for MCP
|
|
296
292
|
*/
|
|
@@ -712,7 +708,6 @@ declare class FileSystemService implements IFileSystemService {
|
|
|
712
708
|
}
|
|
713
709
|
//#endregion
|
|
714
710
|
//#region src/services/ScaffoldConfigLoader.d.ts
|
|
715
|
-
|
|
716
711
|
declare class ScaffoldConfigLoader implements IScaffoldConfigLoader {
|
|
717
712
|
private fileSystem;
|
|
718
713
|
private templateService;
|
|
@@ -937,11 +932,7 @@ declare class VariableReplacementService implements IVariableReplacementService
|
|
|
937
932
|
//#region src/types/tools.d.ts
|
|
938
933
|
declare const scaffoldArgsSchema: z.ZodObject<{
|
|
939
934
|
appName: z.ZodString;
|
|
940
|
-
},
|
|
941
|
-
appName: string;
|
|
942
|
-
}, {
|
|
943
|
-
appName: string;
|
|
944
|
-
}>;
|
|
935
|
+
}, z.core.$strip>;
|
|
945
936
|
type ScaffoldArgs = z.infer<typeof scaffoldArgsSchema>;
|
|
946
937
|
interface Tool {
|
|
947
938
|
name: string;
|