@agiflowai/scaffold-mcp 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +40 -0
  2. package/dist/ListScaffoldingMethodsTool-BLTCwsd1.mjs +350 -0
  3. package/dist/ListScaffoldingMethodsTool-BuxKRbwi.cjs +376 -0
  4. package/dist/{ScaffoldConfigLoader-B-NLy6VP.cjs → ScaffoldConfigLoader-BB4_YUFL.cjs} +1 -1
  5. package/dist/{ScaffoldConfigLoader-SHk-KEje.mjs → ScaffoldConfigLoader-DKJtnrWT.mjs} +1 -1
  6. package/dist/ScaffoldService-BCjJE9yK.mjs +3 -0
  7. package/dist/ScaffoldService-Bhzxp5-C.cjs +3 -0
  8. package/dist/TemplateService-B1bd6iHw.mjs +3 -0
  9. package/dist/TemplateService-BrJGDvQt.cjs +3 -0
  10. package/dist/VariableReplacementService-BO-UYgcf.mjs +3 -0
  11. package/dist/{VariableReplacementService-DKaF2C9l.cjs → VariableReplacementService-CNimgwaq.cjs} +1 -1
  12. package/dist/cli.cjs +89 -11
  13. package/dist/cli.mjs +84 -6
  14. package/dist/index.cjs +9 -8
  15. package/dist/index.d.cts +7 -0
  16. package/dist/index.d.mts +7 -0
  17. package/dist/index.mjs +6 -5
  18. package/dist/{stdio-BGj_FLky.cjs → stdio-BcTSxlVH.cjs} +47 -367
  19. package/dist/{stdio-wAlpLC6l.mjs → stdio-DovjJsGY.mjs} +42 -347
  20. package/dist/useScaffoldMethod-Btc_9iCj.cjs +237 -0
  21. package/dist/useScaffoldMethod-C1hQdBVD.cjs +267 -0
  22. package/dist/useScaffoldMethod-CHJAsgA2.mjs +236 -0
  23. package/dist/useScaffoldMethod-CsBTssSw.mjs +263 -0
  24. package/package.json +6 -2
  25. package/dist/ScaffoldService-BNOyoqSb.cjs +0 -3
  26. package/dist/ScaffoldService-BNdfC21Z.mjs +0 -3
  27. package/dist/TemplateService-BRfzfaZs.mjs +0 -3
  28. package/dist/TemplateService-DqieT1Tq.cjs +0 -3
  29. package/dist/VariableReplacementService-BWCd-z7X.mjs +0 -3
  30. /package/dist/{ScaffoldConfigLoader-BDMJNI1o.mjs → ScaffoldConfigLoader-8YI7v2GJ.mjs} +0 -0
  31. /package/dist/{ScaffoldConfigLoader-Y_SBLPg7.cjs → ScaffoldConfigLoader-CQlXVksz.cjs} +0 -0
  32. /package/dist/{ScaffoldService-ChzxM0Yc.cjs → ScaffoldService-BPyiY_0B.cjs} +0 -0
  33. /package/dist/{ScaffoldService-BNuN00Fm.mjs → ScaffoldService-CgYunbKN.mjs} +0 -0
  34. /package/dist/{TemplateService-D3ydJR_R.cjs → TemplateService-CAD8jkoO.cjs} +0 -0
  35. /package/dist/{TemplateService-Cg5QV29n.mjs → TemplateService-CVDL2uqt.mjs} +0 -0
  36. /package/dist/{VariableReplacementService-DHIINRnJ.mjs → VariableReplacementService-B9RA8D0a.mjs} +0 -0
  37. /package/dist/{VariableReplacementService-CAjesAYq.cjs → VariableReplacementService-DDG5KZpb.cjs} +0 -0
@@ -0,0 +1,236 @@
1
+ import { t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-BLTCwsd1.mjs";
2
+ import "./TemplateService-CVDL2uqt.mjs";
3
+ import { TemplatesManagerService } from "@agiflowai/aicode-utils";
4
+ import { DECISION_ALLOW, DECISION_DENY, DECISION_SKIP, ExecutionLogService } from "@agiflowai/hooks-adapter";
5
+
6
+ //#region src/hooks/geminiCli/useScaffoldMethod.ts
7
+ /**
8
+ * UseScaffoldMethod Hook class for Gemini CLI
9
+ *
10
+ * Provides lifecycle hooks for tool execution:
11
+ * - preToolUse: Shows available scaffolding methods before operations
12
+ * - postToolUse: Tracks scaffold completion progress after file edits
13
+ */
14
+ var UseScaffoldMethodHook = class {
15
+ /**
16
+ * PreToolUse hook for Gemini CLI
17
+ * Proactively shows available scaffolding methods and guides AI to use them
18
+ *
19
+ * @param context - Gemini CLI hook input
20
+ * @returns Hook response with scaffolding methods guidance
21
+ */
22
+ async preToolUse(context) {
23
+ try {
24
+ const executionLog = new ExecutionLogService(context.session_id);
25
+ const sessionKey = `list-scaffold-methods-${context.session_id}`;
26
+ if (await executionLog.hasExecuted({
27
+ filePath: sessionKey,
28
+ decision: DECISION_DENY
29
+ })) {
30
+ await executionLog.logExecution({
31
+ filePath: sessionKey,
32
+ operation: "list-scaffold-methods",
33
+ decision: DECISION_SKIP
34
+ });
35
+ return {
36
+ decision: DECISION_SKIP,
37
+ message: "Scaffolding methods already provided in this session"
38
+ };
39
+ }
40
+ const result = await new ListScaffoldingMethodsTool(await TemplatesManagerService.findTemplatesPath(), false).execute(context.tool_input || {});
41
+ if (result.isError) {
42
+ await executionLog.logExecution({
43
+ filePath: sessionKey,
44
+ operation: "list-scaffold-methods",
45
+ decision: DECISION_SKIP
46
+ });
47
+ return {
48
+ decision: DECISION_SKIP,
49
+ message: `⚠️ Could not load scaffolding methods: ${result.content[0].text}`
50
+ };
51
+ }
52
+ const resultText = result.content[0]?.text;
53
+ if (typeof resultText !== "string") return {
54
+ decision: DECISION_SKIP,
55
+ message: "⚠️ Invalid response format from scaffolding methods tool"
56
+ };
57
+ const data = JSON.parse(resultText);
58
+ if (!data.methods || data.methods.length === 0) {
59
+ await executionLog.logExecution({
60
+ filePath: sessionKey,
61
+ operation: "list-scaffold-methods",
62
+ decision: DECISION_DENY
63
+ });
64
+ return {
65
+ decision: DECISION_DENY,
66
+ message: "No scaffolding methods are available for this project template. You should write new files directly using the Write tool."
67
+ };
68
+ }
69
+ let message = "🎯 **Scaffolding Methods Available**\n\n";
70
+ message += "Before writing new files, check if any of these scaffolding methods match your needs:\n\n";
71
+ for (const method of data.methods) {
72
+ message += `**${method.name}**\n`;
73
+ message += `${method.instruction || method.description || "No description available"}\n`;
74
+ if (method.variables_schema?.required && method.variables_schema.required.length > 0) message += `Required: ${method.variables_schema.required.join(", ")}\n`;
75
+ message += "\n";
76
+ }
77
+ if (data.nextCursor) message += `\n_Note: More methods available. Use cursor "${data.nextCursor}" to see more._\n\n`;
78
+ message += "\n**Instructions:**\n";
79
+ message += "1. If one of these scaffold methods matches what you need to create, use the `use-scaffold-method` MCP tool instead of writing files manually\n";
80
+ message += "2. If none of these methods are relevant to your task, proceed to write new files directly using the Write tool\n";
81
+ message += "3. Using scaffold methods ensures consistency with project patterns and includes all necessary boilerplate\n";
82
+ await executionLog.logExecution({
83
+ filePath: sessionKey,
84
+ operation: "list-scaffold-methods",
85
+ decision: DECISION_DENY
86
+ });
87
+ return {
88
+ decision: DECISION_DENY,
89
+ message
90
+ };
91
+ } catch (error) {
92
+ return {
93
+ decision: DECISION_SKIP,
94
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
95
+ };
96
+ }
97
+ }
98
+ /**
99
+ * PostToolUse hook for Gemini CLI
100
+ * Tracks file edits after scaffold generation and reminds AI to complete implementation
101
+ *
102
+ * @param context - Gemini CLI hook input
103
+ * @returns Hook response with scaffold completion tracking
104
+ */
105
+ async postToolUse(context) {
106
+ try {
107
+ const executionLog = new ExecutionLogService(context.session_id);
108
+ const filePath = context.tool_input?.file_path;
109
+ const actualToolName = context.tool_name === "mcp__one-mcp__use_tool" ? context.tool_input?.toolName : context.tool_name;
110
+ if (actualToolName === "use-scaffold-method") return {
111
+ decision: DECISION_ALLOW,
112
+ message: "Scaffold execution logged for progress tracking"
113
+ };
114
+ const operation = extractOperation(actualToolName);
115
+ if (!filePath || operation !== "edit" && operation !== "write") return {
116
+ decision: DECISION_SKIP,
117
+ message: "Not a file edit/write operation"
118
+ };
119
+ const lastScaffoldExecution = await getLastScaffoldExecution(executionLog);
120
+ if (!lastScaffoldExecution) return {
121
+ decision: DECISION_SKIP,
122
+ message: "No scaffold execution found"
123
+ };
124
+ const { scaffoldId, generatedFiles, featureName } = lastScaffoldExecution;
125
+ const fulfilledKey = `scaffold-fulfilled-${scaffoldId}`;
126
+ if (await executionLog.hasExecuted({
127
+ filePath: fulfilledKey,
128
+ decision: DECISION_ALLOW
129
+ })) return {
130
+ decision: DECISION_SKIP,
131
+ message: "Scaffold already fulfilled"
132
+ };
133
+ const isScaffoldedFile = generatedFiles.includes(filePath);
134
+ if (isScaffoldedFile) {
135
+ const editKey = `scaffold-edit-${scaffoldId}-${filePath}`;
136
+ if (!await executionLog.hasExecuted({
137
+ filePath: editKey,
138
+ decision: DECISION_ALLOW
139
+ })) await executionLog.logExecution({
140
+ filePath: editKey,
141
+ operation: "scaffold-file-edit",
142
+ decision: DECISION_ALLOW
143
+ });
144
+ }
145
+ const editedFiles = await getEditedScaffoldFiles(executionLog, scaffoldId);
146
+ const totalFiles = generatedFiles.length;
147
+ const remainingFiles = generatedFiles.filter((f) => !editedFiles.includes(f));
148
+ if (remainingFiles.length === 0) {
149
+ await executionLog.logExecution({
150
+ filePath: fulfilledKey,
151
+ operation: "scaffold-fulfilled",
152
+ decision: DECISION_ALLOW
153
+ });
154
+ return {
155
+ decision: DECISION_ALLOW,
156
+ message: `✅ All scaffold files${featureName ? ` for "${featureName}"` : ""} have been implemented! (${totalFiles}/${totalFiles} files completed)`
157
+ };
158
+ }
159
+ if (isScaffoldedFile) {
160
+ const remainingFilesList = remainingFiles.map((f) => ` - ${f}`).join("\n");
161
+ return {
162
+ decision: DECISION_ALLOW,
163
+ message: `
164
+ ⚠️ **Scaffold Implementation Progress${featureName ? ` for "${featureName}"` : ""}: ${editedFiles.length}/${totalFiles} files completed**
165
+
166
+ **Remaining files to implement:**
167
+ ${remainingFilesList}
168
+
169
+ Don't forget to complete the implementation for all scaffolded files!
170
+ `.trim()
171
+ };
172
+ }
173
+ return {
174
+ decision: DECISION_SKIP,
175
+ message: "Edited file not part of last scaffold execution"
176
+ };
177
+ } catch (error) {
178
+ return {
179
+ decision: DECISION_SKIP,
180
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
181
+ };
182
+ }
183
+ }
184
+ };
185
+ /**
186
+ * Extract operation type from tool name
187
+ */
188
+ function extractOperation(toolName) {
189
+ const lowerToolName = toolName.toLowerCase();
190
+ if (lowerToolName === "edit" || lowerToolName === "update") return "edit";
191
+ if (lowerToolName === "write") return "write";
192
+ if (lowerToolName === "read") return "read";
193
+ return "unknown";
194
+ }
195
+ /**
196
+ * Helper function to get the last scaffold execution for a session
197
+ * Returns null if no scaffold execution found or on error
198
+ */
199
+ async function getLastScaffoldExecution(executionLog) {
200
+ try {
201
+ const entries = await executionLog.loadLog();
202
+ for (let i = entries.length - 1; i >= 0; i--) {
203
+ const entry = entries[i];
204
+ if (entry.operation === "scaffold" && entry.scaffoldId && entry.generatedFiles && entry.generatedFiles.length > 0) return {
205
+ scaffoldId: entry.scaffoldId,
206
+ generatedFiles: entry.generatedFiles,
207
+ featureName: entry.featureName
208
+ };
209
+ }
210
+ return null;
211
+ } catch (error) {
212
+ console.error("Error getting last scaffold execution:", error);
213
+ return null;
214
+ }
215
+ }
216
+ /**
217
+ * Helper function to get list of edited scaffold files
218
+ * Returns empty array if no files found or on error
219
+ */
220
+ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
221
+ try {
222
+ const entries = await executionLog.loadLog();
223
+ const editedFiles = [];
224
+ for (const entry of entries) if (entry.operation === "scaffold-file-edit" && entry.filePath.startsWith(`scaffold-edit-${scaffoldId}-`)) {
225
+ const filePath = entry.filePath.replace(`scaffold-edit-${scaffoldId}-`, "");
226
+ editedFiles.push(filePath);
227
+ }
228
+ return editedFiles;
229
+ } catch (error) {
230
+ console.error(`Error getting edited scaffold files for ${scaffoldId}:`, error);
231
+ return [];
232
+ }
233
+ }
234
+
235
+ //#endregion
236
+ export { UseScaffoldMethodHook };
@@ -0,0 +1,263 @@
1
+ import { t as ListScaffoldingMethodsTool } from "./ListScaffoldingMethodsTool-BLTCwsd1.mjs";
2
+ import "./TemplateService-CVDL2uqt.mjs";
3
+ import path from "node:path";
4
+ import { ProjectFinderService, TemplatesManagerService } from "@agiflowai/aicode-utils";
5
+ import fs from "node:fs/promises";
6
+ import os from "node:os";
7
+ import { DECISION_ALLOW, DECISION_DENY, DECISION_SKIP, ExecutionLogService } from "@agiflowai/hooks-adapter";
8
+
9
+ //#region src/hooks/claudeCode/useScaffoldMethod.ts
10
+ /**
11
+ * UseScaffoldMethod Hook class for Claude Code
12
+ *
13
+ * Provides lifecycle hooks for tool execution:
14
+ * - preToolUse: Shows available scaffolding methods before Write operations
15
+ * - postToolUse: Tracks scaffold completion progress after file edits
16
+ */
17
+ var UseScaffoldMethodHook = class {
18
+ /**
19
+ * PreToolUse hook for Claude Code
20
+ * Proactively shows available scaffolding methods and guides AI to use them
21
+ *
22
+ * @param context - Claude Code hook input
23
+ * @returns Hook response with scaffolding methods guidance
24
+ */
25
+ async preToolUse(context) {
26
+ try {
27
+ const filePath = context.tool_input?.file_path;
28
+ if (!filePath || context.tool_name !== "Write") return {
29
+ decision: DECISION_SKIP,
30
+ message: "Not a file write operation"
31
+ };
32
+ const executionLog = new ExecutionLogService(context.session_id);
33
+ if (await executionLog.hasExecuted({
34
+ filePath,
35
+ decision: DECISION_DENY
36
+ })) return {
37
+ decision: DECISION_SKIP,
38
+ message: "Scaffolding methods already provided for this file"
39
+ };
40
+ const tool = new ListScaffoldingMethodsTool(await TemplatesManagerService.findTemplatesPath(), false);
41
+ const projectFinder = new ProjectFinderService(await TemplatesManagerService.getWorkspaceRoot(context.cwd));
42
+ const absoluteFilePath = path.isAbsolute(filePath) ? filePath : path.join(context.cwd, filePath);
43
+ const projectPath = (await projectFinder.findProjectForFile(absoluteFilePath))?.root || context.cwd;
44
+ const result = await tool.execute({ projectPath });
45
+ if (result.isError) return {
46
+ decision: DECISION_SKIP,
47
+ message: `⚠️ Could not load scaffolding methods: ${result.content[0].text}`
48
+ };
49
+ const resultText = result.content[0]?.text;
50
+ if (typeof resultText !== "string") return {
51
+ decision: DECISION_SKIP,
52
+ message: "⚠️ Invalid response format from scaffolding methods tool"
53
+ };
54
+ const data = JSON.parse(resultText);
55
+ if (!data.methods || data.methods.length === 0) {
56
+ await executionLog.logExecution({
57
+ filePath,
58
+ operation: "list-scaffold-methods",
59
+ decision: DECISION_DENY
60
+ });
61
+ return {
62
+ decision: DECISION_DENY,
63
+ message: "No scaffolding methods are available for this project template. You should write new files directly using the Write tool."
64
+ };
65
+ }
66
+ let message = "🎯 **Scaffolding Methods Available**\\n\\n";
67
+ message += "Before writing new files, check if any of these scaffolding methods match your needs:\\n\\n";
68
+ for (const method of data.methods) {
69
+ message += `**${method.name}**\\n`;
70
+ message += `${method.instruction || method.description || "No description available"}\\n`;
71
+ if (method.variables_schema?.required && method.variables_schema.required.length > 0) message += `Required: ${method.variables_schema.required.join(", ")}\\n`;
72
+ message += "\\n";
73
+ }
74
+ if (data.nextCursor) message += `\\n_Note: More methods available. Use cursor "${data.nextCursor}" to see more._\\n\\n`;
75
+ message += "\\n**Instructions:**\\n";
76
+ message += "1. If one of these scaffold methods matches what you need to create, use the `use-scaffold-method` MCP tool instead of writing files manually\\n";
77
+ message += "2. If none of these methods are relevant to your task, proceed to write new files directly using the Write tool\\n";
78
+ message += "3. Using scaffold methods ensures consistency with project patterns and includes all necessary boilerplate\\n";
79
+ await executionLog.logExecution({
80
+ filePath,
81
+ operation: "list-scaffold-methods",
82
+ decision: DECISION_DENY
83
+ });
84
+ return {
85
+ decision: DECISION_DENY,
86
+ message
87
+ };
88
+ } catch (error) {
89
+ return {
90
+ decision: DECISION_SKIP,
91
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
92
+ };
93
+ }
94
+ }
95
+ /**
96
+ * PostToolUse hook for Claude Code
97
+ * Tracks file edits after scaffold generation and reminds AI to complete implementation
98
+ *
99
+ * @param context - Claude Code hook input
100
+ * @returns Hook response with scaffold completion tracking
101
+ */
102
+ async postToolUse(context) {
103
+ try {
104
+ const executionLog = new ExecutionLogService(context.session_id);
105
+ const filePath = context.tool_input?.file_path;
106
+ if ((context.tool_name === "mcp__one-mcp__use_tool" ? context.tool_input?.toolName : context.tool_name) === "use-scaffold-method") {
107
+ if (context.hook_event_name === "PostToolUse") {
108
+ const scaffoldId$1 = extractScaffoldId(context.tool_response);
109
+ if (scaffoldId$1) await processPendingScaffoldLogs(context.session_id, scaffoldId$1);
110
+ }
111
+ return {
112
+ decision: DECISION_ALLOW,
113
+ message: "Scaffold execution logged for progress tracking"
114
+ };
115
+ }
116
+ if (!filePath || context.tool_name !== "Edit" && context.tool_name !== "Write" && context.tool_name !== "Update") return {
117
+ decision: DECISION_SKIP,
118
+ message: "Not a file edit/write operation"
119
+ };
120
+ const lastScaffoldExecution = await getLastScaffoldExecution(executionLog);
121
+ if (!lastScaffoldExecution) return {
122
+ decision: DECISION_SKIP,
123
+ message: "No scaffold execution found"
124
+ };
125
+ const { scaffoldId, generatedFiles, featureName } = lastScaffoldExecution;
126
+ const fulfilledKey = `scaffold-fulfilled-${scaffoldId}`;
127
+ if (await executionLog.hasExecuted({
128
+ filePath: fulfilledKey,
129
+ decision: DECISION_ALLOW
130
+ })) return {
131
+ decision: DECISION_SKIP,
132
+ message: "Scaffold already fulfilled"
133
+ };
134
+ const isScaffoldedFile = generatedFiles.includes(filePath);
135
+ if (isScaffoldedFile) {
136
+ const editKey = `scaffold-edit-${scaffoldId}-${filePath}`;
137
+ if (!await executionLog.hasExecuted({
138
+ filePath: editKey,
139
+ decision: DECISION_ALLOW
140
+ })) await executionLog.logExecution({
141
+ filePath: editKey,
142
+ operation: "scaffold-file-edit",
143
+ decision: DECISION_ALLOW
144
+ });
145
+ }
146
+ const editedFiles = await getEditedScaffoldFiles(executionLog, scaffoldId);
147
+ const totalFiles = generatedFiles.length;
148
+ const remainingFiles = generatedFiles.filter((f) => !editedFiles.includes(f));
149
+ if (remainingFiles.length === 0) {
150
+ await executionLog.logExecution({
151
+ filePath: fulfilledKey,
152
+ operation: "scaffold-fulfilled",
153
+ decision: DECISION_ALLOW
154
+ });
155
+ return {
156
+ decision: DECISION_ALLOW,
157
+ message: `✅ All scaffold files${featureName ? ` for "${featureName}"` : ""} have been implemented! (${totalFiles}/${totalFiles} files completed)`
158
+ };
159
+ }
160
+ if (isScaffoldedFile) {
161
+ const remainingFilesList = remainingFiles.map((f) => ` - ${f}`).join("\\n");
162
+ return {
163
+ decision: DECISION_ALLOW,
164
+ message: `
165
+ ⚠️ **Scaffold Implementation Progress${featureName ? ` for "${featureName}"` : ""}: ${editedFiles.length}/${totalFiles} files completed**
166
+
167
+ **Remaining files to implement:**
168
+ ${remainingFilesList}
169
+
170
+ Don't forget to complete the implementation for all scaffolded files!
171
+ `.trim()
172
+ };
173
+ }
174
+ return {
175
+ decision: DECISION_SKIP,
176
+ message: "Edited file not part of last scaffold execution"
177
+ };
178
+ } catch (error) {
179
+ return {
180
+ decision: DECISION_SKIP,
181
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
182
+ };
183
+ }
184
+ }
185
+ };
186
+ /**
187
+ * Extract scaffold ID from tool result
188
+ */
189
+ function extractScaffoldId(toolResult) {
190
+ try {
191
+ if (!toolResult || !toolResult.content) return null;
192
+ for (const item of toolResult.content) if (item.type === "text" && typeof item.text === "string") {
193
+ const match = item.text.match(/^SCAFFOLD_ID:([a-z0-9]+)$/);
194
+ if (match) return match[1];
195
+ }
196
+ return null;
197
+ } catch {
198
+ return null;
199
+ }
200
+ }
201
+ /**
202
+ * Helper function to get the last scaffold execution for a session
203
+ */
204
+ async function getLastScaffoldExecution(executionLog) {
205
+ const entries = await executionLog.loadLog();
206
+ for (let i = entries.length - 1; i >= 0; i--) {
207
+ const entry = entries[i];
208
+ if (entry.operation === "scaffold" && entry.scaffoldId && entry.generatedFiles && entry.generatedFiles.length > 0) return {
209
+ scaffoldId: entry.scaffoldId,
210
+ generatedFiles: entry.generatedFiles,
211
+ featureName: entry.featureName
212
+ };
213
+ }
214
+ return null;
215
+ }
216
+ /**
217
+ * Helper function to get list of edited scaffold files
218
+ */
219
+ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
220
+ const entries = await executionLog.loadLog();
221
+ const editedFiles = [];
222
+ for (const entry of entries) if (entry.operation === "scaffold-file-edit" && entry.filePath.startsWith(`scaffold-edit-${scaffoldId}-`)) {
223
+ const filePath = entry.filePath.replace(`scaffold-edit-${scaffoldId}-`, "");
224
+ editedFiles.push(filePath);
225
+ }
226
+ return editedFiles;
227
+ }
228
+ /**
229
+ * Process pending scaffold logs from temp file and copy to ExecutionLogService
230
+ * Called when use-scaffold-method tool is executed
231
+ */
232
+ async function processPendingScaffoldLogs(sessionId, scaffoldId) {
233
+ const tempLogFile = path.join(os.tmpdir(), `scaffold-mcp-pending-${scaffoldId}.jsonl`);
234
+ try {
235
+ const lines = (await fs.readFile(tempLogFile, "utf-8")).trim().split("\\n").filter(Boolean);
236
+ const executionLog = new ExecutionLogService(sessionId);
237
+ try {
238
+ for (const line of lines) try {
239
+ const entry = JSON.parse(line);
240
+ await executionLog.logExecution({
241
+ filePath: `scaffold-${entry.scaffoldId}`,
242
+ operation: "scaffold",
243
+ decision: DECISION_ALLOW,
244
+ generatedFiles: entry.generatedFiles,
245
+ scaffoldId: entry.scaffoldId,
246
+ projectPath: entry.projectPath,
247
+ featureName: entry.featureName
248
+ });
249
+ } catch (parseError) {
250
+ console.error("Failed to parse pending scaffold log entry:", parseError);
251
+ }
252
+ } finally {
253
+ try {
254
+ await fs.unlink(tempLogFile);
255
+ } catch {}
256
+ }
257
+ } catch (error) {
258
+ if (error instanceof Error && "code" in error && error.code !== "ENOENT") console.error("Error processing pending scaffold logs:", error);
259
+ }
260
+ }
261
+
262
+ //#endregion
263
+ export { UseScaffoldMethodHook };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@agiflowai/scaffold-mcp",
3
3
  "description": "MCP server for scaffolding applications with boilerplate templates",
4
- "version": "1.0.5",
4
+ "version": "1.0.7",
5
5
  "license": "AGPL-3.0",
6
6
  "author": "AgiflowIO",
7
7
  "repository": {
@@ -44,10 +44,14 @@
44
44
  "express": "^4.21.2",
45
45
  "js-yaml": "4.1.0",
46
46
  "liquidjs": "10.21.1",
47
+ "minimatch": "^10.0.1",
47
48
  "pino": "^10.0.0",
48
49
  "pino-pretty": "^13.1.1",
49
50
  "zod": "3.25.76",
50
- "@agiflowai/aicode-utils": "1.0.4"
51
+ "@agiflowai/aicode-utils": "1.0.6",
52
+ "@agiflowai/architect-mcp": "1.0.7",
53
+ "@agiflowai/hooks-adapter": "0.0.2",
54
+ "@agiflowai/coding-agent-bridge": "1.0.6"
51
55
  },
52
56
  "devDependencies": {
53
57
  "@types/express": "^5.0.0",
@@ -1,3 +0,0 @@
1
- const require_ScaffoldService = require('./ScaffoldService-ChzxM0Yc.cjs');
2
-
3
- exports.ScaffoldService = require_ScaffoldService.ScaffoldService;
@@ -1,3 +0,0 @@
1
- import { t as ScaffoldService } from "./ScaffoldService-BNuN00Fm.mjs";
2
-
3
- export { ScaffoldService };
@@ -1,3 +0,0 @@
1
- import { t as TemplateService } from "./TemplateService-Cg5QV29n.mjs";
2
-
3
- export { TemplateService };
@@ -1,3 +0,0 @@
1
- const require_TemplateService = require('./TemplateService-D3ydJR_R.cjs');
2
-
3
- exports.TemplateService = require_TemplateService.TemplateService;
@@ -1,3 +0,0 @@
1
- import { t as VariableReplacementService } from "./VariableReplacementService-DHIINRnJ.mjs";
2
-
3
- export { VariableReplacementService };