@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/dist/cli.cjs CHANGED
@@ -1,14 +1,54 @@
1
1
  #!/usr/bin/env node
2
- const require_ListScaffoldingMethodsTool = require('./ListScaffoldingMethodsTool-DBwZzJTA.cjs');
3
- const require_src = require('./src-DuOmlC4n.cjs');
4
- const require_tools = require('./tools-DsnQImJ1.cjs');
5
- let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
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
+ let _agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
6
6
  let node_path = require("node:path");
7
- node_path = require_ListScaffoldingMethodsTool.__toESM(node_path);
7
+ node_path = require_ListScaffoldingMethodsTool.__toESM(node_path, 1);
8
8
  let commander = require("commander");
9
- let __agiflowai_coding_agent_bridge = require("@agiflowai/coding-agent-bridge");
10
- let __agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
11
-
9
+ let _agiflowai_coding_agent_bridge = require("@agiflowai/coding-agent-bridge");
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
12
52
  //#region src/commands/boilerplate.ts
13
53
  /**
14
54
  * Boilerplate CLI command
@@ -16,40 +56,40 @@ let __agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
16
56
  const boilerplateCommand = new commander.Command("boilerplate").description("Manage boilerplate templates");
17
57
  boilerplateCommand.command("list").description("List all available boilerplate templates").option("-c, --cursor <cursor>", "Pagination cursor for next page").action(async (options) => {
18
58
  try {
19
- const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
59
+ const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
20
60
  if (!templatesDir) {
21
- __agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
61
+ _agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
22
62
  process.exit(1);
23
63
  }
24
64
  const { boilerplates, nextCursor } = await new require_tools.BoilerplateService(templatesDir).listBoilerplates(options.cursor);
25
65
  if (boilerplates.length === 0) {
26
- __agiflowai_aicode_utils.messages.warning("No boilerplate templates found.");
66
+ _agiflowai_aicode_utils.messages.warning("No boilerplate templates found.");
27
67
  return;
28
68
  }
29
- __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.package} Available Boilerplate Templates:\n`);
69
+ _agiflowai_aicode_utils.print.header(`\n${_agiflowai_aicode_utils.icons.package} Available Boilerplate Templates:\n`);
30
70
  for (const bp of boilerplates) {
31
- __agiflowai_aicode_utils.print.highlight(` ${bp.name}`);
32
- __agiflowai_aicode_utils.print.debug(` ${bp.description}`);
33
- __agiflowai_aicode_utils.print.debug(` Target: ${bp.target_folder}`);
71
+ _agiflowai_aicode_utils.print.highlight(` ${bp.name}`);
72
+ _agiflowai_aicode_utils.print.debug(` ${bp.description}`);
73
+ _agiflowai_aicode_utils.print.debug(` Target: ${bp.target_folder}`);
34
74
  const required = typeof bp.variables_schema === "object" && bp.variables_schema !== null && "required" in bp.variables_schema ? bp.variables_schema.required : [];
35
- if (required && required.length > 0) __agiflowai_aicode_utils.print.debug(` Required: ${required.join(", ")}`);
36
- __agiflowai_aicode_utils.print.newline();
75
+ if (required && required.length > 0) _agiflowai_aicode_utils.print.debug(` Required: ${required.join(", ")}`);
76
+ _agiflowai_aicode_utils.print.newline();
37
77
  }
38
78
  if (nextCursor) {
39
- __agiflowai_aicode_utils.print.newline();
40
- __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.info} More results available. Use --cursor to fetch next page:`);
41
- __agiflowai_aicode_utils.print.debug(` scaffold-mcp boilerplate list --cursor "${nextCursor}"`);
79
+ _agiflowai_aicode_utils.print.newline();
80
+ _agiflowai_aicode_utils.print.info(`${_agiflowai_aicode_utils.icons.info} More results available. Use --cursor to fetch next page:`);
81
+ _agiflowai_aicode_utils.print.debug(` scaffold-mcp boilerplate list --cursor "${nextCursor}"`);
42
82
  }
43
83
  } catch (error) {
44
- __agiflowai_aicode_utils.messages.error("Error listing boilerplates:", error);
84
+ _agiflowai_aicode_utils.messages.error("Error listing boilerplates:", error);
45
85
  process.exit(1);
46
86
  }
47
87
  });
48
- 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) => {
49
89
  try {
50
- const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
90
+ const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
51
91
  if (!templatesDir) {
52
- __agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
92
+ _agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
53
93
  process.exit(1);
54
94
  }
55
95
  const boilerplateService = new require_tools.BoilerplateService(templatesDir);
@@ -57,8 +97,8 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
57
97
  if (options.vars) try {
58
98
  variables = JSON.parse(options.vars);
59
99
  } catch (error) {
60
- __agiflowai_aicode_utils.messages.error("Error parsing variables JSON:", error);
61
- __agiflowai_aicode_utils.messages.hint("Example: --vars '{\"appName\": \"my-app\", \"description\": \"My application\"}'");
100
+ _agiflowai_aicode_utils.messages.error("Error parsing variables JSON:", error);
101
+ _agiflowai_aicode_utils.messages.hint("Example: --vars '{\"appName\": \"my-app\", \"description\": \"My application\"}'");
62
102
  process.exit(1);
63
103
  }
64
104
  const boilerplate = await boilerplateService.getBoilerplate(boilerplateName);
@@ -66,41 +106,42 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
66
106
  let allBoilerplates = [];
67
107
  let cursor;
68
108
  do {
69
- const result$1 = await boilerplateService.listBoilerplates(cursor);
70
- allBoilerplates = allBoilerplates.concat(result$1.boilerplates);
71
- cursor = result$1.nextCursor;
109
+ const result = await boilerplateService.listBoilerplates(cursor);
110
+ allBoilerplates = allBoilerplates.concat(result.boilerplates);
111
+ cursor = result.nextCursor;
72
112
  } while (cursor);
73
- __agiflowai_aicode_utils.messages.error(`Boilerplate '${boilerplateName}' not found.`);
74
- __agiflowai_aicode_utils.print.warning(`Available boilerplates: ${allBoilerplates.map((b) => b.name).join(", ")}`);
113
+ _agiflowai_aicode_utils.messages.error(`Boilerplate '${boilerplateName}' not found.`);
114
+ _agiflowai_aicode_utils.print.warning(`Available boilerplates: ${allBoilerplates.map((b) => b.name).join(", ")}`);
75
115
  process.exit(1);
76
116
  }
77
117
  const required = typeof boilerplate.variables_schema === "object" && boilerplate.variables_schema !== null && "required" in boilerplate.variables_schema ? boilerplate.variables_schema.required : [];
78
118
  const missing = required.filter((key) => !variables[key]);
79
119
  if (missing.length > 0) {
80
- __agiflowai_aicode_utils.messages.error(`Missing required variables: ${missing.join(", ")}`);
81
- __agiflowai_aicode_utils.messages.hint(`Use --vars with a JSON object containing: ${missing.join(", ")}`);
120
+ _agiflowai_aicode_utils.messages.error(`Missing required variables: ${missing.join(", ")}`);
121
+ _agiflowai_aicode_utils.messages.hint(`Use --vars with a JSON object containing: ${missing.join(", ")}`);
82
122
  const exampleVars = {};
83
123
  for (const key of required) if (key === "appName" || key === "packageName") exampleVars[key] = "my-app";
84
124
  else if (key === "description") exampleVars[key] = "My application description";
85
125
  else exampleVars[key] = `<${key}>`;
86
- __agiflowai_aicode_utils.print.debug(`Example: scaffold-mcp boilerplate create ${boilerplateName} --vars '${JSON.stringify(exampleVars)}'`);
126
+ _agiflowai_aicode_utils.print.debug(`Example: scaffold-mcp boilerplate create ${boilerplateName} --vars '${JSON.stringify(exampleVars)}'`);
87
127
  process.exit(1);
88
128
  }
89
129
  if (options.verbose) {
90
- __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.wrench} Boilerplate: ${boilerplateName}`);
91
- __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.chart} Variables: ${JSON.stringify(variables, null, 2)}`);
130
+ _agiflowai_aicode_utils.print.info(`${_agiflowai_aicode_utils.icons.wrench} Boilerplate: ${boilerplateName}`);
131
+ _agiflowai_aicode_utils.print.info(`${_agiflowai_aicode_utils.icons.chart} Variables: ${JSON.stringify(variables, null, 2)}`);
92
132
  }
93
- __agiflowai_aicode_utils.messages.loading(`Creating project from boilerplate '${boilerplateName}'...`);
133
+ _agiflowai_aicode_utils.messages.loading(`Creating project from boilerplate '${boilerplateName}'...`);
94
134
  const result = await boilerplateService.useBoilerplate({
95
135
  boilerplateName,
96
136
  variables,
97
137
  monolith: options.monolith,
98
- targetFolderOverride: options.targetFolder
138
+ targetFolderOverride: options.targetFolder,
139
+ marker: options.marker
99
140
  });
100
141
  if (result.success) {
101
- __agiflowai_aicode_utils.messages.success("Project created successfully!");
102
- __agiflowai_aicode_utils.print.info(result.message);
103
- if (result.createdFiles && result.createdFiles.length > 0) __agiflowai_aicode_utils.sections.createdFiles(result.createdFiles);
142
+ _agiflowai_aicode_utils.messages.success("Project created successfully!");
143
+ _agiflowai_aicode_utils.print.info(result.message);
144
+ if (result.createdFiles && result.createdFiles.length > 0) _agiflowai_aicode_utils.sections.createdFiles(result.createdFiles);
104
145
  const projectName = variables.appName || variables.packageName;
105
146
  if (projectName) {
106
147
  const targetFolder = options.targetFolder || (options.monolith ? "." : boilerplate.target_folder);
@@ -110,43 +151,100 @@ boilerplateCommand.command("create <boilerplateName>").description("Create a new
110
151
  "pnpm install",
111
152
  "pnpm dev"
112
153
  ];
113
- __agiflowai_aicode_utils.sections.nextSteps(steps);
154
+ _agiflowai_aicode_utils.sections.nextSteps(steps);
114
155
  }
115
156
  } else {
116
- __agiflowai_aicode_utils.messages.error(`Failed to create project: ${result.message}`);
157
+ _agiflowai_aicode_utils.messages.error(`Failed to create project: ${result.message}`);
117
158
  process.exit(1);
118
159
  }
119
160
  } catch (error) {
120
- __agiflowai_aicode_utils.messages.error("Error creating project:", error);
161
+ _agiflowai_aicode_utils.messages.error("Error creating project:", error);
121
162
  if (options.verbose) console.error("Stack trace:", error.stack);
122
163
  process.exit(1);
123
164
  }
124
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
+ });
125
202
  boilerplateCommand.command("info <boilerplateName>").description("Show detailed information about a boilerplate template").action(async (boilerplateName) => {
126
203
  try {
127
- const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
204
+ const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
128
205
  if (!templatesDir) {
129
- __agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
206
+ _agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
130
207
  process.exit(1);
131
208
  }
132
209
  const bp = await new require_tools.BoilerplateService(templatesDir).getBoilerplate(boilerplateName);
133
210
  if (!bp) {
134
- __agiflowai_aicode_utils.messages.error(`Boilerplate '${boilerplateName}' not found.`);
211
+ _agiflowai_aicode_utils.messages.error(`Boilerplate '${boilerplateName}' not found.`);
135
212
  process.exit(1);
136
213
  }
137
- __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.package} Boilerplate: ${bp.name}\n`);
138
- __agiflowai_aicode_utils.print.debug(`Description: ${bp.description}`);
139
- __agiflowai_aicode_utils.print.debug(`Template Path: ${bp.template_path}`);
140
- __agiflowai_aicode_utils.print.debug(`Target Folder: ${bp.target_folder}`);
141
- __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.config} Variables Schema:`);
214
+ _agiflowai_aicode_utils.print.header(`\n${_agiflowai_aicode_utils.icons.package} Boilerplate: ${bp.name}\n`);
215
+ _agiflowai_aicode_utils.print.debug(`Description: ${bp.description}`);
216
+ _agiflowai_aicode_utils.print.debug(`Template Path: ${bp.template_path}`);
217
+ _agiflowai_aicode_utils.print.debug(`Target Folder: ${bp.target_folder}`);
218
+ _agiflowai_aicode_utils.print.header(`\n${_agiflowai_aicode_utils.icons.config} Variables Schema:`);
142
219
  console.log(JSON.stringify(bp.variables_schema, null, 2));
143
- if (bp.includes && bp.includes.length > 0) __agiflowai_aicode_utils.sections.list(`${__agiflowai_aicode_utils.icons.folder} Included Files:`, bp.includes);
220
+ if (bp.includes && bp.includes.length > 0) _agiflowai_aicode_utils.sections.list(`${_agiflowai_aicode_utils.icons.folder} Included Files:`, bp.includes);
221
+ } catch (error) {
222
+ _agiflowai_aicode_utils.messages.error("Error getting boilerplate info:", error);
223
+ process.exit(1);
224
+ }
225
+ });
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));
144
243
  } catch (error) {
145
- __agiflowai_aicode_utils.messages.error("Error getting boilerplate info:", error);
244
+ _agiflowai_aicode_utils.print.error("Error writing file:", error instanceof Error ? error.message : String(error));
146
245
  process.exit(1);
147
246
  }
148
247
  });
149
-
150
248
  //#endregion
151
249
  //#region src/commands/mcp-serve.ts
152
250
  /**
@@ -180,7 +278,7 @@ function isRecord(value) {
180
278
  */
181
279
  function parseLlmToolOption(value, flagName) {
182
280
  if (!value) return void 0;
183
- if (!(0, __agiflowai_coding_agent_bridge.isValidLlmTool)(value)) throw new Error(`Invalid ${flagName}: ${value}. Supported: ${__agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`);
281
+ if (!(0, _agiflowai_coding_agent_bridge.isValidLlmTool)(value)) throw new Error(`Invalid ${flagName}: ${value}. Supported: ${_agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`);
184
282
  return value;
185
283
  }
186
284
  /**
@@ -217,12 +315,12 @@ async function startServer(handler) {
217
315
  throw new Error(`Failed to start transport: ${error instanceof Error ? error.message : String(error)}`);
218
316
  }
219
317
  const shutdown = async (signal) => {
220
- __agiflowai_aicode_utils.print.error(`\nReceived ${signal}, shutting down gracefully...`);
318
+ _agiflowai_aicode_utils.print.error(`\nReceived ${signal}, shutting down gracefully...`);
221
319
  try {
222
320
  await handler.stop();
223
321
  process.exit(0);
224
322
  } catch (error) {
225
- __agiflowai_aicode_utils.print.error("Error during shutdown:", error instanceof Error ? error : String(error));
323
+ _agiflowai_aicode_utils.print.error("Error during shutdown:", error instanceof Error ? error : String(error));
226
324
  process.exit(1);
227
325
  }
228
326
  };
@@ -230,23 +328,23 @@ async function startServer(handler) {
230
328
  try {
231
329
  await shutdown("SIGINT");
232
330
  } catch (error) {
233
- __agiflowai_aicode_utils.print.error("Unexpected shutdown error:", error instanceof Error ? error : String(error));
331
+ _agiflowai_aicode_utils.print.error("Unexpected shutdown error:", error instanceof Error ? error : String(error));
234
332
  }
235
333
  });
236
334
  process.on("SIGTERM", async () => {
237
335
  try {
238
336
  await shutdown("SIGTERM");
239
337
  } catch (error) {
240
- __agiflowai_aicode_utils.print.error("Unexpected shutdown error:", error instanceof Error ? error : String(error));
338
+ _agiflowai_aicode_utils.print.error("Unexpected shutdown error:", error instanceof Error ? error : String(error));
241
339
  }
242
340
  });
243
341
  }
244
342
  /**
245
343
  * MCP Serve command
246
344
  */
247
- const mcpServeCommand = new commander.Command("mcp-serve").description("Start MCP server with specified transport").option("-t, --type <type>", "Transport type: stdio, http, or sse").option("-p, --port <port>", "Port to listen on (http/sse only)", (val) => parseInt(val, 10)).option("--host <host>", "Host to bind to (http/sse only)").option("--admin-enable", "Enable admin tools (generate-boilerplate)", false).option("--prompt-as-skill", "Render prompts with skill front matter for Claude Code skills", false).option("--fallback-tool <tool>", `Fallback LLM tool for scaffold operations. Supported: ${__agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`).option("--fallback-tool-config <json>", "JSON config for fallback tool (e.g., '{\"model\":\"claude-sonnet-4-6\"}')").action(async (options) => {
345
+ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MCP server with specified transport").option("-t, --type <type>", "Transport type: stdio, http, or sse").option("-p, --port <port>", "Port to listen on (http/sse only)", (val) => parseInt(val, 10)).option("--host <host>", "Host to bind to (http/sse only)").option("--admin-enable", "Enable admin tools (generate-boilerplate)", false).option("--prompt-as-skill", "Render prompts with skill front matter for Claude Code skills", false).option("--fallback-tool <tool>", `Fallback LLM tool for scaffold operations. Supported: ${_agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`).option("--fallback-tool-config <json>", "JSON config for fallback tool (e.g., '{\"model\":\"claude-sonnet-4-6\"}')").action(async (options) => {
248
346
  try {
249
- const fileConfig = (await __agiflowai_aicode_utils.TemplatesManagerService.readToolkitConfig())?.["scaffold-mcp"]?.["mcp-serve"] ?? {};
347
+ const fileConfig = (await _agiflowai_aicode_utils.TemplatesManagerService.readToolkitConfig())?.["scaffold-mcp"]?.["mcp-serve"] ?? {};
250
348
  const transportType = (options.type ?? fileConfig.type ?? "stdio").toLowerCase();
251
349
  const adminEnable = options.adminEnable || fileConfig.adminEnable || false;
252
350
  const promptAsSkill = options.promptAsSkill || fileConfig.promptAsSkill || false;
@@ -255,9 +353,9 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
255
353
  const fallbackToolConfig = options.fallbackToolConfig ? parseJsonConfig(options.fallbackToolConfig, "--fallback-tool-config") : configuredFallback.config;
256
354
  let isMonolith = false;
257
355
  try {
258
- isMonolith = (await __agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).type === "monolith";
356
+ isMonolith = (await _agiflowai_aicode_utils.ProjectConfigResolver.resolveProjectConfig(process.cwd())).type === "monolith";
259
357
  } catch (error) {
260
- __agiflowai_aicode_utils.print.info(`No project config found, defaulting to monorepo mode: ${error instanceof Error ? error.message : String(error)}`);
358
+ _agiflowai_aicode_utils.print.info(`No project config found, defaulting to monorepo mode: ${error instanceof Error ? error.message : String(error)}`);
261
359
  isMonolith = false;
262
360
  }
263
361
  const serverOptions = {
@@ -285,15 +383,14 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
285
383
  host
286
384
  }));
287
385
  } else {
288
- __agiflowai_aicode_utils.print.error(`Unknown transport type: ${transportType}. Use: stdio, http, or sse`);
386
+ _agiflowai_aicode_utils.print.error(`Unknown transport type: ${transportType}. Use: stdio, http, or sse`);
289
387
  process.exit(1);
290
388
  }
291
389
  } catch (error) {
292
- __agiflowai_aicode_utils.print.error("Failed to start MCP server:", error instanceof Error ? error : String(error));
390
+ _agiflowai_aicode_utils.print.error("Failed to start MCP server:", error instanceof Error ? error : String(error));
293
391
  process.exit(1);
294
392
  }
295
393
  });
296
-
297
394
  //#endregion
298
395
  //#region src/commands/scaffold.ts
299
396
  /**
@@ -302,77 +399,71 @@ const mcpServeCommand = new commander.Command("mcp-serve").description("Start MC
302
399
  const scaffoldCommand = new commander.Command("scaffold").description("Add features to existing projects");
303
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) => {
304
401
  try {
305
- if (!projectPath && !options.template) {
306
- __agiflowai_aicode_utils.messages.error("Either projectPath or --template option must be provided");
307
- __agiflowai_aicode_utils.messages.hint("Examples:");
308
- __agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold list ./my-project");
309
- __agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold list --template nextjs-15");
310
- process.exit(1);
311
- }
312
- const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
402
+ const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
313
403
  if (!templatesDir) {
314
- __agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
404
+ _agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
315
405
  process.exit(1);
316
406
  }
317
407
  const scaffoldingMethodsService = new require_ListScaffoldingMethodsTool.ScaffoldingMethodsService(new require_ListScaffoldingMethodsTool.FileSystemService(), templatesDir);
318
408
  let result;
319
409
  let displayName;
320
- if (projectPath) {
321
- const absolutePath = node_path.default.resolve(projectPath);
322
- if (!await __agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(absolutePath)) {
323
- __agiflowai_aicode_utils.messages.error(`No project configuration found in ${absolutePath}`);
324
- __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");
410
+ if (projectPath || !options.template) {
411
+ const inputProjectPath = projectPath ?? process.cwd();
412
+ const absolutePath = node_path.default.resolve(inputProjectPath);
413
+ if (!await _agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(absolutePath)) {
414
+ _agiflowai_aicode_utils.messages.error(`No project configuration found in ${absolutePath}`);
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");
325
416
  process.exit(1);
326
417
  }
327
418
  result = await scaffoldingMethodsService.listScaffoldingMethods(absolutePath, options.cursor);
328
- displayName = projectPath;
419
+ displayName = projectPath ?? absolutePath;
329
420
  } else {
330
421
  result = await scaffoldingMethodsService.listScaffoldingMethodsByTemplate(options.template, options.cursor);
331
422
  displayName = `template: ${options.template}`;
332
423
  }
333
424
  const methods = result.methods;
334
425
  if (methods.length === 0) {
335
- __agiflowai_aicode_utils.messages.warning(`No scaffolding methods available for ${displayName}.`);
426
+ _agiflowai_aicode_utils.messages.warning(`No scaffolding methods available for ${displayName}.`);
336
427
  return;
337
428
  }
338
- __agiflowai_aicode_utils.print.header(`\n${__agiflowai_aicode_utils.icons.wrench} Available Scaffolding Methods for ${displayName}:\n`);
429
+ _agiflowai_aicode_utils.print.header(`\n${_agiflowai_aicode_utils.icons.wrench} Available Scaffolding Methods for ${displayName}:\n`);
339
430
  for (const method of methods) {
340
- __agiflowai_aicode_utils.print.highlight(` ${method.name}`);
341
- __agiflowai_aicode_utils.print.debug(` ${method.instruction || method.description || "No description available"}`);
342
- if (method.variables_schema.required && method.variables_schema.required.length > 0) __agiflowai_aicode_utils.print.debug(` Required: ${method.variables_schema.required.join(", ")}`);
343
- __agiflowai_aicode_utils.print.newline();
431
+ _agiflowai_aicode_utils.print.highlight(` ${method.name}`);
432
+ _agiflowai_aicode_utils.print.debug(` ${method.instruction || method.description || "No description available"}`);
433
+ if (method.variables_schema.required && method.variables_schema.required.length > 0) _agiflowai_aicode_utils.print.debug(` Required: ${method.variables_schema.required.join(", ")}`);
434
+ _agiflowai_aicode_utils.print.newline();
344
435
  }
345
436
  if (result.nextCursor) {
346
- __agiflowai_aicode_utils.print.newline();
347
- __agiflowai_aicode_utils.print.info(`${__agiflowai_aicode_utils.icons.info} More results available. Use --cursor to fetch next page:`);
437
+ _agiflowai_aicode_utils.print.newline();
438
+ _agiflowai_aicode_utils.print.info(`${_agiflowai_aicode_utils.icons.info} More results available. Use --cursor to fetch next page:`);
348
439
  const cursorOption = `--cursor "${result.nextCursor}"`;
349
- if (projectPath) __agiflowai_aicode_utils.print.debug(` scaffold-mcp scaffold list ${projectPath} ${cursorOption}`);
350
- else __agiflowai_aicode_utils.print.debug(` scaffold-mcp scaffold list --template ${options.template} ${cursorOption}`);
440
+ if (projectPath) _agiflowai_aicode_utils.print.debug(` scaffold-mcp scaffold list ${projectPath} ${cursorOption}`);
441
+ else _agiflowai_aicode_utils.print.debug(` scaffold-mcp scaffold list --template ${options.template} ${cursorOption}`);
351
442
  }
352
443
  } catch (error) {
353
- __agiflowai_aicode_utils.messages.error("Error listing scaffolding methods:", error);
444
+ _agiflowai_aicode_utils.messages.error("Error listing scaffolding methods:", error);
354
445
  process.exit(1);
355
446
  }
356
447
  });
357
- 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) => {
358
449
  try {
359
450
  const projectPath = node_path.default.resolve(options.project);
360
- if (!await __agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
361
- __agiflowai_aicode_utils.messages.error(`No project configuration found in ${projectPath}`);
362
- __agiflowai_aicode_utils.messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root");
451
+ if (!await _agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
452
+ _agiflowai_aicode_utils.messages.error(`No project configuration found in ${projectPath}`);
453
+ _agiflowai_aicode_utils.messages.hint("For monorepo: ensure project.json exists with sourceTemplate field\nFor monolith: ensure toolkit.yaml exists at workspace root");
363
454
  process.exit(1);
364
455
  }
365
456
  let variables = {};
366
457
  if (options.vars) try {
367
458
  variables = JSON.parse(options.vars);
368
459
  } catch (error) {
369
- __agiflowai_aicode_utils.messages.error("Error parsing variables JSON:", error);
370
- __agiflowai_aicode_utils.messages.hint("Example: --vars '{\"componentName\": \"UserProfile\", \"description\": \"User profile component\"}'");
460
+ _agiflowai_aicode_utils.messages.error("Error parsing variables JSON:", error);
461
+ _agiflowai_aicode_utils.messages.hint("Example: --vars '{\"componentName\": \"UserProfile\", \"description\": \"User profile component\"}'");
371
462
  process.exit(1);
372
463
  }
373
- const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
464
+ const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
374
465
  if (!templatesDir) {
375
- __agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
466
+ _agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
376
467
  process.exit(1);
377
468
  }
378
469
  const scaffoldingMethodsService = new require_ListScaffoldingMethodsTool.ScaffoldingMethodsService(new require_ListScaffoldingMethodsTool.FileSystemService(), templatesDir);
@@ -385,73 +476,116 @@ scaffoldCommand.command("add <featureName>").description("Add a feature to an ex
385
476
  } while (cursor);
386
477
  const method = allMethods.find((m) => m.name === featureName);
387
478
  if (!method) {
388
- __agiflowai_aicode_utils.messages.error(`Scaffold method '${featureName}' not found.`);
389
- __agiflowai_aicode_utils.print.warning(`Available methods: ${allMethods.map((m) => m.name).join(", ")}`);
390
- __agiflowai_aicode_utils.print.debug(`Run 'scaffold-mcp scaffold list ${options.project}' to see all available methods`);
479
+ _agiflowai_aicode_utils.messages.error(`Scaffold method '${featureName}' not found.`);
480
+ _agiflowai_aicode_utils.print.warning(`Available methods: ${allMethods.map((m) => m.name).join(", ")}`);
481
+ _agiflowai_aicode_utils.print.debug(`Run 'scaffold-mcp scaffold list ${options.project}' to see all available methods`);
391
482
  process.exit(1);
392
483
  }
393
484
  const required = typeof method.variables_schema === "object" && method.variables_schema !== null && "required" in method.variables_schema ? method.variables_schema.required : [];
394
485
  const missing = required.filter((key) => !variables[key]);
395
486
  if (missing.length > 0) {
396
- __agiflowai_aicode_utils.messages.error(`❌ Missing required variables: ${missing.join(", ")}`);
397
- __agiflowai_aicode_utils.messages.hint(`💡 Use --vars with a JSON object containing: ${missing.join(", ")}`);
487
+ _agiflowai_aicode_utils.messages.error(`❌ Missing required variables: ${missing.join(", ")}`);
488
+ _agiflowai_aicode_utils.messages.hint(`💡 Use --vars with a JSON object containing: ${missing.join(", ")}`);
398
489
  const exampleVars = {};
399
490
  for (const key of required) if (key.includes("Name")) exampleVars[key] = "MyFeature";
400
491
  else if (key === "description") exampleVars[key] = "Feature description";
401
492
  else exampleVars[key] = `<${key}>`;
402
- __agiflowai_aicode_utils.print.debug(`Example: scaffold-mcp scaffold add ${featureName} --project ${options.project} --vars '${JSON.stringify(exampleVars)}'`);
493
+ _agiflowai_aicode_utils.print.debug(`Example: scaffold-mcp scaffold add ${featureName} --project ${options.project} --vars '${JSON.stringify(exampleVars)}'`);
403
494
  process.exit(1);
404
495
  }
405
496
  if (options.verbose) {
406
- __agiflowai_aicode_utils.print.info(`🔧 Feature: ${featureName}`);
407
- __agiflowai_aicode_utils.print.info(`📊 Variables: ${JSON.stringify(variables, null, 2)}`);
408
- __agiflowai_aicode_utils.print.info(`📁 Project Path: ${projectPath}`);
497
+ _agiflowai_aicode_utils.print.info(`🔧 Feature: ${featureName}`);
498
+ _agiflowai_aicode_utils.print.info(`📊 Variables: ${JSON.stringify(variables, null, 2)}`);
499
+ _agiflowai_aicode_utils.print.info(`📁 Project Path: ${projectPath}`);
409
500
  }
410
- __agiflowai_aicode_utils.print.info(`🚀 Adding '${featureName}' to project...`);
501
+ _agiflowai_aicode_utils.print.info(`🚀 Adding '${featureName}' to project...`);
411
502
  const result = await scaffoldingMethodsService.useScaffoldMethod({
412
503
  projectPath,
413
504
  scaffold_feature_name: featureName,
414
- variables
505
+ variables,
506
+ marker: options.marker
415
507
  });
416
508
  if (result.success) {
417
- __agiflowai_aicode_utils.messages.success("✅ Feature added successfully!");
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
+ });
516
+ _agiflowai_aicode_utils.messages.success("✅ Feature added successfully!");
418
517
  if (result.createdFiles && result.createdFiles.length > 0) {
419
- __agiflowai_aicode_utils.print.header("\n📁 Created files:");
518
+ _agiflowai_aicode_utils.print.header("\n📁 Created files:");
420
519
  result.createdFiles.forEach((file) => {
421
- __agiflowai_aicode_utils.print.debug(` - ${file}`);
520
+ _agiflowai_aicode_utils.print.debug(` - ${file}`);
422
521
  });
423
522
  }
424
523
  if (result.warnings && result.warnings.length > 0) {
425
- __agiflowai_aicode_utils.messages.warning("\n⚠️ Warnings:");
524
+ _agiflowai_aicode_utils.messages.warning("\n⚠️ Warnings:");
426
525
  result.warnings.forEach((warning) => {
427
- __agiflowai_aicode_utils.print.debug(` - ${warning}`);
526
+ _agiflowai_aicode_utils.print.debug(` - ${warning}`);
428
527
  });
429
528
  }
430
- __agiflowai_aicode_utils.print.header("\n📋 Next steps:");
431
- __agiflowai_aicode_utils.print.debug(" - Review the generated files");
432
- __agiflowai_aicode_utils.print.debug(" - Update imports if necessary");
433
- __agiflowai_aicode_utils.print.debug(" - Run tests to ensure everything works");
529
+ _agiflowai_aicode_utils.print.debug(`\nSCAFFOLD_ID:${scaffoldId}`);
530
+ _agiflowai_aicode_utils.print.header("\n📋 Next steps:");
531
+ _agiflowai_aicode_utils.print.debug(" - Review the generated files");
532
+ _agiflowai_aicode_utils.print.debug(" - Update imports if necessary");
533
+ _agiflowai_aicode_utils.print.debug(" - Run tests to ensure everything works");
434
534
  } else {
435
- __agiflowai_aicode_utils.messages.error(`❌ Failed to add feature: ${result.message}`);
535
+ _agiflowai_aicode_utils.messages.error(`❌ Failed to add feature: ${result.message}`);
436
536
  process.exit(1);
437
537
  }
438
538
  } catch (error) {
439
- __agiflowai_aicode_utils.messages.error(`❌ Error adding feature: ${error.message}`);
539
+ _agiflowai_aicode_utils.messages.error(`❌ Error adding feature: ${error.message}`);
540
+ process.exit(1);
541
+ }
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));
440
574
  process.exit(1);
441
575
  }
442
576
  });
443
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) => {
444
578
  try {
445
579
  if (!options.project && !options.template) {
446
- __agiflowai_aicode_utils.messages.error("Either --project or --template option must be provided");
447
- __agiflowai_aicode_utils.messages.hint("Examples:");
448
- __agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold info scaffold-route --project ./my-app");
449
- __agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold info scaffold-route --template nextjs-15");
580
+ _agiflowai_aicode_utils.messages.error("Either --project or --template option must be provided");
581
+ _agiflowai_aicode_utils.messages.hint("Examples:");
582
+ _agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold info scaffold-route --project ./my-app");
583
+ _agiflowai_aicode_utils.print.debug(" scaffold-mcp scaffold info scaffold-route --template nextjs-15");
450
584
  process.exit(1);
451
585
  }
452
- const templatesDir = await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
586
+ const templatesDir = await _agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath();
453
587
  if (!templatesDir) {
454
- __agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
588
+ _agiflowai_aicode_utils.messages.error("Templates folder not found. Create a templates folder or specify templatesPath in toolkit.yaml");
455
589
  process.exit(1);
456
590
  }
457
591
  const scaffoldingMethodsService = new require_ListScaffoldingMethodsTool.ScaffoldingMethodsService(new require_ListScaffoldingMethodsTool.FileSystemService(), templatesDir);
@@ -459,9 +593,9 @@ scaffoldCommand.command("info <featureName>").description("Show detailed informa
459
593
  let cursor;
460
594
  if (options.project) {
461
595
  const projectPath = node_path.default.resolve(options.project);
462
- if (!await __agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
463
- __agiflowai_aicode_utils.messages.error(`No project configuration found in ${projectPath}`);
464
- __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 view info for a specific template");
596
+ if (!await _agiflowai_aicode_utils.ProjectConfigResolver.hasConfiguration(projectPath)) {
597
+ _agiflowai_aicode_utils.messages.error(`No project configuration found in ${projectPath}`);
598
+ _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 view info for a specific template");
465
599
  process.exit(1);
466
600
  }
467
601
  do {
@@ -476,28 +610,27 @@ scaffoldCommand.command("info <featureName>").description("Show detailed informa
476
610
  } while (cursor);
477
611
  const method = allMethods.find((m) => m.name === featureName);
478
612
  if (!method) {
479
- __agiflowai_aicode_utils.messages.error(`❌ Scaffold method '${featureName}' not found.`);
613
+ _agiflowai_aicode_utils.messages.error(`❌ Scaffold method '${featureName}' not found.`);
480
614
  process.exit(1);
481
615
  }
482
- __agiflowai_aicode_utils.print.header(`\n🔧 Scaffold Method: ${method.name}\n`);
483
- __agiflowai_aicode_utils.print.debug(`Description: ${method.description}`);
484
- __agiflowai_aicode_utils.print.header("\n📝 Variables Schema:");
485
- __agiflowai_aicode_utils.print.debug(JSON.stringify(method.variables_schema, null, 2));
616
+ _agiflowai_aicode_utils.print.header(`\n🔧 Scaffold Method: ${method.name}\n`);
617
+ _agiflowai_aicode_utils.print.debug(`Description: ${method.description}`);
618
+ _agiflowai_aicode_utils.print.header("\n📝 Variables Schema:");
619
+ _agiflowai_aicode_utils.print.debug(JSON.stringify(method.variables_schema, null, 2));
486
620
  const includes = "includes" in method ? method.includes : [];
487
621
  if (includes && includes.length > 0) {
488
- __agiflowai_aicode_utils.print.header("\n📁 Files to be created:");
622
+ _agiflowai_aicode_utils.print.header("\n📁 Files to be created:");
489
623
  includes.forEach((include) => {
490
624
  const parts = include.split(">>");
491
- if (parts.length === 2) __agiflowai_aicode_utils.print.debug(` - ${parts[1].trim()}`);
492
- else __agiflowai_aicode_utils.print.debug(` - ${include}`);
625
+ if (parts.length === 2) _agiflowai_aicode_utils.print.debug(` - ${parts[1].trim()}`);
626
+ else _agiflowai_aicode_utils.print.debug(` - ${include}`);
493
627
  });
494
628
  }
495
629
  } catch (error) {
496
- __agiflowai_aicode_utils.messages.error(`❌ Error getting scaffold info: ${error.message}`);
630
+ _agiflowai_aicode_utils.messages.error(`❌ Error getting scaffold info: ${error.message}`);
497
631
  process.exit(1);
498
632
  }
499
633
  });
500
-
501
634
  //#endregion
502
635
  //#region src/commands/hook.ts
503
636
  /**
@@ -563,23 +696,23 @@ function resolveFallbackConfig(config) {
563
696
  /**
564
697
  * Hook command for executing scaffold hooks
565
698
  */
566
- const hookCommand = new commander.Command("hook").description("Execute scaffold hooks for AI agent integrations").option("--type <agentAndMethod>", "Hook type: <agent>.<method> (e.g., claude-code.postToolUse, gemini-cli.postToolUse)").option("--marker <tag>", "Scaffold marker tag to scan for in phantom code check").option("--fallback-tool <tool>", `Fallback LLM tool for scaffold operations. Supported: ${__agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`).option("--fallback-tool-config <json>", "JSON config for the fallback tool (e.g., '{\"model\":\"claude-sonnet-4-6\"}')").action(async (options) => {
699
+ const hookCommand = new commander.Command("hook").description("Execute scaffold hooks for AI agent integrations").option("--type <agentAndMethod>", "Hook type: <agent>.<method> (e.g., claude-code.postToolUse, gemini-cli.postToolUse)").option("--marker <tag>", "Scaffold marker tag to scan for in phantom code check").option("--fallback-tool <tool>", `Fallback LLM tool for scaffold operations. Supported: ${_agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`).option("--fallback-tool-config <json>", "JSON config for the fallback tool (e.g., '{\"model\":\"claude-sonnet-4-6\"}')").action(async (options) => {
567
700
  try {
568
701
  if (!options.type) throw new Error("--type option is required. Examples: claude-code.preToolUse, claude-code.postToolUse, gemini-cli.postToolUse");
569
- const { agent, hookMethod } = (0, __agiflowai_hooks_adapter.parseHookType)(options.type);
570
- const methodConfig = ((await __agiflowai_aicode_utils.TemplatesManagerService.readToolkitConfig())?.["scaffold-mcp"]?.hook)?.[agent]?.[hookMethod];
702
+ const { agent, hookMethod } = (0, _agiflowai_hooks_adapter.parseHookType)(options.type);
703
+ const methodConfig = ((await _agiflowai_aicode_utils.TemplatesManagerService.readToolkitConfig())?.["scaffold-mcp"]?.hook)?.[agent]?.[hookMethod];
571
704
  const marker = options.marker ?? "@scaffold-generated";
572
705
  const configuredFallback = resolveFallbackConfig(methodConfig);
573
706
  const fallbackToolStr = options.fallbackTool ?? methodConfig?.["fallback-tool"] ?? methodConfig?.["llm-tool"] ?? configuredFallback.tool;
574
707
  const fallbackToolConfig = options.fallbackToolConfig ? parseJsonConfigOption(options.fallbackToolConfig, "--fallback-tool-config") : methodConfig?.["fallback-tool-config"] ?? methodConfig?.["tool-config"] ?? configuredFallback.config;
575
- if (fallbackToolStr && !(0, __agiflowai_coding_agent_bridge.isValidLlmTool)(fallbackToolStr)) throw new Error(`Invalid --fallback-tool: ${fallbackToolStr}. Supported: ${__agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`);
708
+ if (fallbackToolStr && !(0, _agiflowai_coding_agent_bridge.isValidLlmTool)(fallbackToolStr)) throw new Error(`Invalid --fallback-tool: ${fallbackToolStr}. Supported: ${_agiflowai_coding_agent_bridge.SUPPORTED_LLM_TOOLS.join(", ")}`);
576
709
  const adapterConfig = {};
577
710
  if (fallbackToolConfig) adapterConfig.tool_config = fallbackToolConfig;
578
711
  if (fallbackToolStr) adapterConfig.llm_tool = fallbackToolStr;
579
712
  const resolvedAdapterConfig = Object.keys(adapterConfig).length > 0 ? adapterConfig : void 0;
580
713
  if (!isHookMethod(hookMethod)) process.exit(0);
581
- if (agent === __agiflowai_coding_agent_bridge.CLAUDE_CODE) {
582
- const hookModule = await Promise.resolve().then(() => require("./claudeCode-B6CWgRYJ.cjs"));
714
+ if (agent === _agiflowai_coding_agent_bridge.CLAUDE_CODE) {
715
+ const hookModule = await Promise.resolve().then(() => require("./claudeCode-g1eRidPR.cjs"));
583
716
  const claudeCallbacks = [];
584
717
  if (hookModule.UseScaffoldMethodHook) {
585
718
  const hookInstance = new hookModule.UseScaffoldMethodHook();
@@ -592,9 +725,9 @@ const hookCommand = new commander.Command("hook").description("Execute scaffold
592
725
  if (hookFn) claudeCallbacks.push(hookFn.bind(hookInstance));
593
726
  }
594
727
  if (claudeCallbacks.length === 0) process.exit(0);
595
- await new __agiflowai_hooks_adapter.ClaudeCodeAdapter().executeMultiple(claudeCallbacks, resolvedAdapterConfig);
596
- } else if (agent === __agiflowai_coding_agent_bridge.GEMINI_CLI) {
597
- const hookModule = await Promise.resolve().then(() => require("./geminiCli-COS3X1P7.cjs"));
728
+ await new _agiflowai_hooks_adapter.ClaudeCodeAdapter().executeMultiple(claudeCallbacks, resolvedAdapterConfig);
729
+ } else if (agent === _agiflowai_coding_agent_bridge.GEMINI_CLI) {
730
+ const hookModule = await Promise.resolve().then(() => require("./geminiCli--s1Qy7ZP.cjs"));
598
731
  const geminiCallbacks = [];
599
732
  if (hookModule.UseScaffoldMethodHook) {
600
733
  const hookInstance = new hookModule.UseScaffoldMethodHook();
@@ -602,14 +735,52 @@ const hookCommand = new commander.Command("hook").description("Execute scaffold
602
735
  if (hookFn) geminiCallbacks.push(hookFn.bind(hookInstance));
603
736
  }
604
737
  if (geminiCallbacks.length === 0) process.exit(0);
605
- await new __agiflowai_hooks_adapter.GeminiCliAdapter().executeMultiple(geminiCallbacks, resolvedAdapterConfig);
606
- } else throw new Error(`Unsupported agent: ${agent}. Supported: ${__agiflowai_coding_agent_bridge.CLAUDE_CODE}, ${__agiflowai_coding_agent_bridge.GEMINI_CLI}`);
738
+ await new _agiflowai_hooks_adapter.GeminiCliAdapter().executeMultiple(geminiCallbacks, resolvedAdapterConfig);
739
+ } else throw new Error(`Unsupported agent: ${agent}. Supported: ${_agiflowai_coding_agent_bridge.CLAUDE_CODE}, ${_agiflowai_coding_agent_bridge.GEMINI_CLI}`);
740
+ } catch (error) {
741
+ _agiflowai_aicode_utils.print.error(`Hook error: ${error instanceof Error ? error.message : String(error)}`);
742
+ process.exit(1);
743
+ }
744
+ });
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));
607
778
  } catch (error) {
608
- __agiflowai_aicode_utils.print.error(`Hook error: ${error instanceof Error ? error.message : String(error)}`);
779
+ _agiflowai_aicode_utils.print.error("Error creating template file:", error instanceof Error ? error.message : String(error));
609
780
  process.exit(1);
610
781
  }
611
782
  });
612
-
783
+ templateCommand.addCommand(fileCommand);
613
784
  //#endregion
614
785
  //#region src/cli.ts
615
786
  /**
@@ -621,9 +792,10 @@ async function main() {
621
792
  program.addCommand(mcpServeCommand);
622
793
  program.addCommand(boilerplateCommand);
623
794
  program.addCommand(scaffoldCommand);
795
+ program.addCommand(templateCommand);
796
+ program.addCommand(fileCommand$1);
624
797
  program.addCommand(hookCommand);
625
798
  await program.parseAsync(process.argv);
626
799
  }
627
800
  main();
628
-
629
- //#endregion
801
+ //#endregion