@agiflowai/scaffold-mcp 1.0.6 → 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,237 @@
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_ListScaffoldingMethodsTool = require('./ListScaffoldingMethodsTool-BuxKRbwi.cjs');
3
+ require('./TemplateService-CAD8jkoO.cjs');
4
+ let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
5
+ let __agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
6
+
7
+ //#region src/hooks/geminiCli/useScaffoldMethod.ts
8
+ /**
9
+ * UseScaffoldMethod Hook class for Gemini CLI
10
+ *
11
+ * Provides lifecycle hooks for tool execution:
12
+ * - preToolUse: Shows available scaffolding methods before operations
13
+ * - postToolUse: Tracks scaffold completion progress after file edits
14
+ */
15
+ var UseScaffoldMethodHook = class {
16
+ /**
17
+ * PreToolUse hook for Gemini CLI
18
+ * Proactively shows available scaffolding methods and guides AI to use them
19
+ *
20
+ * @param context - Gemini CLI hook input
21
+ * @returns Hook response with scaffolding methods guidance
22
+ */
23
+ async preToolUse(context) {
24
+ try {
25
+ const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
26
+ const sessionKey = `list-scaffold-methods-${context.session_id}`;
27
+ if (await executionLog.hasExecuted({
28
+ filePath: sessionKey,
29
+ decision: __agiflowai_hooks_adapter.DECISION_DENY
30
+ })) {
31
+ await executionLog.logExecution({
32
+ filePath: sessionKey,
33
+ operation: "list-scaffold-methods",
34
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP
35
+ });
36
+ return {
37
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
38
+ message: "Scaffolding methods already provided in this session"
39
+ };
40
+ }
41
+ const result = await new require_ListScaffoldingMethodsTool.ListScaffoldingMethodsTool(await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath(), false).execute(context.tool_input || {});
42
+ if (result.isError) {
43
+ await executionLog.logExecution({
44
+ filePath: sessionKey,
45
+ operation: "list-scaffold-methods",
46
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP
47
+ });
48
+ return {
49
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
50
+ message: `⚠️ Could not load scaffolding methods: ${result.content[0].text}`
51
+ };
52
+ }
53
+ const resultText = result.content[0]?.text;
54
+ if (typeof resultText !== "string") return {
55
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
56
+ message: "⚠️ Invalid response format from scaffolding methods tool"
57
+ };
58
+ const data = JSON.parse(resultText);
59
+ if (!data.methods || data.methods.length === 0) {
60
+ await executionLog.logExecution({
61
+ filePath: sessionKey,
62
+ operation: "list-scaffold-methods",
63
+ decision: __agiflowai_hooks_adapter.DECISION_DENY
64
+ });
65
+ return {
66
+ decision: __agiflowai_hooks_adapter.DECISION_DENY,
67
+ message: "No scaffolding methods are available for this project template. You should write new files directly using the Write tool."
68
+ };
69
+ }
70
+ let message = "🎯 **Scaffolding Methods Available**\n\n";
71
+ message += "Before writing new files, check if any of these scaffolding methods match your needs:\n\n";
72
+ for (const method of data.methods) {
73
+ message += `**${method.name}**\n`;
74
+ message += `${method.instruction || method.description || "No description available"}\n`;
75
+ if (method.variables_schema?.required && method.variables_schema.required.length > 0) message += `Required: ${method.variables_schema.required.join(", ")}\n`;
76
+ message += "\n";
77
+ }
78
+ if (data.nextCursor) message += `\n_Note: More methods available. Use cursor "${data.nextCursor}" to see more._\n\n`;
79
+ message += "\n**Instructions:**\n";
80
+ 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";
81
+ message += "2. If none of these methods are relevant to your task, proceed to write new files directly using the Write tool\n";
82
+ message += "3. Using scaffold methods ensures consistency with project patterns and includes all necessary boilerplate\n";
83
+ await executionLog.logExecution({
84
+ filePath: sessionKey,
85
+ operation: "list-scaffold-methods",
86
+ decision: __agiflowai_hooks_adapter.DECISION_DENY
87
+ });
88
+ return {
89
+ decision: __agiflowai_hooks_adapter.DECISION_DENY,
90
+ message
91
+ };
92
+ } catch (error) {
93
+ return {
94
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
95
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
96
+ };
97
+ }
98
+ }
99
+ /**
100
+ * PostToolUse hook for Gemini CLI
101
+ * Tracks file edits after scaffold generation and reminds AI to complete implementation
102
+ *
103
+ * @param context - Gemini CLI hook input
104
+ * @returns Hook response with scaffold completion tracking
105
+ */
106
+ async postToolUse(context) {
107
+ try {
108
+ const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
109
+ const filePath = context.tool_input?.file_path;
110
+ const actualToolName = context.tool_name === "mcp__one-mcp__use_tool" ? context.tool_input?.toolName : context.tool_name;
111
+ if (actualToolName === "use-scaffold-method") return {
112
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
113
+ message: "Scaffold execution logged for progress tracking"
114
+ };
115
+ const operation = extractOperation(actualToolName);
116
+ if (!filePath || operation !== "edit" && operation !== "write") return {
117
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
118
+ message: "Not a file edit/write operation"
119
+ };
120
+ const lastScaffoldExecution = await getLastScaffoldExecution(executionLog);
121
+ if (!lastScaffoldExecution) return {
122
+ decision: __agiflowai_hooks_adapter.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: __agiflowai_hooks_adapter.DECISION_ALLOW
130
+ })) return {
131
+ decision: __agiflowai_hooks_adapter.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: __agiflowai_hooks_adapter.DECISION_ALLOW
140
+ })) await executionLog.logExecution({
141
+ filePath: editKey,
142
+ operation: "scaffold-file-edit",
143
+ decision: __agiflowai_hooks_adapter.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: __agiflowai_hooks_adapter.DECISION_ALLOW
154
+ });
155
+ return {
156
+ decision: __agiflowai_hooks_adapter.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: __agiflowai_hooks_adapter.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: __agiflowai_hooks_adapter.DECISION_SKIP,
176
+ message: "Edited file not part of last scaffold execution"
177
+ };
178
+ } catch (error) {
179
+ return {
180
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
181
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
182
+ };
183
+ }
184
+ }
185
+ };
186
+ /**
187
+ * Extract operation type from tool name
188
+ */
189
+ function extractOperation(toolName) {
190
+ const lowerToolName = toolName.toLowerCase();
191
+ if (lowerToolName === "edit" || lowerToolName === "update") return "edit";
192
+ if (lowerToolName === "write") return "write";
193
+ if (lowerToolName === "read") return "read";
194
+ return "unknown";
195
+ }
196
+ /**
197
+ * Helper function to get the last scaffold execution for a session
198
+ * Returns null if no scaffold execution found or on error
199
+ */
200
+ async function getLastScaffoldExecution(executionLog) {
201
+ try {
202
+ const entries = await executionLog.loadLog();
203
+ for (let i = entries.length - 1; i >= 0; i--) {
204
+ const entry = entries[i];
205
+ if (entry.operation === "scaffold" && entry.scaffoldId && entry.generatedFiles && entry.generatedFiles.length > 0) return {
206
+ scaffoldId: entry.scaffoldId,
207
+ generatedFiles: entry.generatedFiles,
208
+ featureName: entry.featureName
209
+ };
210
+ }
211
+ return null;
212
+ } catch (error) {
213
+ console.error("Error getting last scaffold execution:", error);
214
+ return null;
215
+ }
216
+ }
217
+ /**
218
+ * Helper function to get list of edited scaffold files
219
+ * Returns empty array if no files found or on error
220
+ */
221
+ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
222
+ try {
223
+ const entries = await executionLog.loadLog();
224
+ const editedFiles = [];
225
+ for (const entry of entries) if (entry.operation === "scaffold-file-edit" && entry.filePath.startsWith(`scaffold-edit-${scaffoldId}-`)) {
226
+ const filePath = entry.filePath.replace(`scaffold-edit-${scaffoldId}-`, "");
227
+ editedFiles.push(filePath);
228
+ }
229
+ return editedFiles;
230
+ } catch (error) {
231
+ console.error(`Error getting edited scaffold files for ${scaffoldId}:`, error);
232
+ return [];
233
+ }
234
+ }
235
+
236
+ //#endregion
237
+ exports.UseScaffoldMethodHook = UseScaffoldMethodHook;
@@ -0,0 +1,267 @@
1
+ const require_chunk = require('./chunk-CUT6urMc.cjs');
2
+ const require_ListScaffoldingMethodsTool = require('./ListScaffoldingMethodsTool-BuxKRbwi.cjs');
3
+ require('./TemplateService-CAD8jkoO.cjs');
4
+ let node_path = require("node:path");
5
+ node_path = require_chunk.__toESM(node_path);
6
+ let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
7
+ let node_fs_promises = require("node:fs/promises");
8
+ node_fs_promises = require_chunk.__toESM(node_fs_promises);
9
+ let node_os = require("node:os");
10
+ node_os = require_chunk.__toESM(node_os);
11
+ let __agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
12
+
13
+ //#region src/hooks/claudeCode/useScaffoldMethod.ts
14
+ /**
15
+ * UseScaffoldMethod Hook class for Claude Code
16
+ *
17
+ * Provides lifecycle hooks for tool execution:
18
+ * - preToolUse: Shows available scaffolding methods before Write operations
19
+ * - postToolUse: Tracks scaffold completion progress after file edits
20
+ */
21
+ var UseScaffoldMethodHook = class {
22
+ /**
23
+ * PreToolUse hook for Claude Code
24
+ * Proactively shows available scaffolding methods and guides AI to use them
25
+ *
26
+ * @param context - Claude Code hook input
27
+ * @returns Hook response with scaffolding methods guidance
28
+ */
29
+ async preToolUse(context) {
30
+ try {
31
+ const filePath = context.tool_input?.file_path;
32
+ if (!filePath || context.tool_name !== "Write") return {
33
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
34
+ message: "Not a file write operation"
35
+ };
36
+ const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
37
+ if (await executionLog.hasExecuted({
38
+ filePath,
39
+ decision: __agiflowai_hooks_adapter.DECISION_DENY
40
+ })) return {
41
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
42
+ message: "Scaffolding methods already provided for this file"
43
+ };
44
+ const tool = new require_ListScaffoldingMethodsTool.ListScaffoldingMethodsTool(await __agiflowai_aicode_utils.TemplatesManagerService.findTemplatesPath(), false);
45
+ const projectFinder = new __agiflowai_aicode_utils.ProjectFinderService(await __agiflowai_aicode_utils.TemplatesManagerService.getWorkspaceRoot(context.cwd));
46
+ const absoluteFilePath = node_path.default.isAbsolute(filePath) ? filePath : node_path.default.join(context.cwd, filePath);
47
+ const projectPath = (await projectFinder.findProjectForFile(absoluteFilePath))?.root || context.cwd;
48
+ const result = await tool.execute({ projectPath });
49
+ if (result.isError) return {
50
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
51
+ message: `⚠️ Could not load scaffolding methods: ${result.content[0].text}`
52
+ };
53
+ const resultText = result.content[0]?.text;
54
+ if (typeof resultText !== "string") return {
55
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
56
+ message: "⚠️ Invalid response format from scaffolding methods tool"
57
+ };
58
+ const data = JSON.parse(resultText);
59
+ if (!data.methods || data.methods.length === 0) {
60
+ await executionLog.logExecution({
61
+ filePath,
62
+ operation: "list-scaffold-methods",
63
+ decision: __agiflowai_hooks_adapter.DECISION_DENY
64
+ });
65
+ return {
66
+ decision: __agiflowai_hooks_adapter.DECISION_DENY,
67
+ message: "No scaffolding methods are available for this project template. You should write new files directly using the Write tool."
68
+ };
69
+ }
70
+ let message = "🎯 **Scaffolding Methods Available**\\n\\n";
71
+ message += "Before writing new files, check if any of these scaffolding methods match your needs:\\n\\n";
72
+ for (const method of data.methods) {
73
+ message += `**${method.name}**\\n`;
74
+ message += `${method.instruction || method.description || "No description available"}\\n`;
75
+ if (method.variables_schema?.required && method.variables_schema.required.length > 0) message += `Required: ${method.variables_schema.required.join(", ")}\\n`;
76
+ message += "\\n";
77
+ }
78
+ if (data.nextCursor) message += `\\n_Note: More methods available. Use cursor "${data.nextCursor}" to see more._\\n\\n`;
79
+ message += "\\n**Instructions:**\\n";
80
+ 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";
81
+ message += "2. If none of these methods are relevant to your task, proceed to write new files directly using the Write tool\\n";
82
+ message += "3. Using scaffold methods ensures consistency with project patterns and includes all necessary boilerplate\\n";
83
+ await executionLog.logExecution({
84
+ filePath,
85
+ operation: "list-scaffold-methods",
86
+ decision: __agiflowai_hooks_adapter.DECISION_DENY
87
+ });
88
+ return {
89
+ decision: __agiflowai_hooks_adapter.DECISION_DENY,
90
+ message
91
+ };
92
+ } catch (error) {
93
+ return {
94
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
95
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
96
+ };
97
+ }
98
+ }
99
+ /**
100
+ * PostToolUse hook for Claude Code
101
+ * Tracks file edits after scaffold generation and reminds AI to complete implementation
102
+ *
103
+ * @param context - Claude Code hook input
104
+ * @returns Hook response with scaffold completion tracking
105
+ */
106
+ async postToolUse(context) {
107
+ try {
108
+ const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(context.session_id);
109
+ const filePath = context.tool_input?.file_path;
110
+ if ((context.tool_name === "mcp__one-mcp__use_tool" ? context.tool_input?.toolName : context.tool_name) === "use-scaffold-method") {
111
+ if (context.hook_event_name === "PostToolUse") {
112
+ const scaffoldId$1 = extractScaffoldId(context.tool_response);
113
+ if (scaffoldId$1) await processPendingScaffoldLogs(context.session_id, scaffoldId$1);
114
+ }
115
+ return {
116
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
117
+ message: "Scaffold execution logged for progress tracking"
118
+ };
119
+ }
120
+ if (!filePath || context.tool_name !== "Edit" && context.tool_name !== "Write" && context.tool_name !== "Update") return {
121
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
122
+ message: "Not a file edit/write operation"
123
+ };
124
+ const lastScaffoldExecution = await getLastScaffoldExecution(executionLog);
125
+ if (!lastScaffoldExecution) return {
126
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
127
+ message: "No scaffold execution found"
128
+ };
129
+ const { scaffoldId, generatedFiles, featureName } = lastScaffoldExecution;
130
+ const fulfilledKey = `scaffold-fulfilled-${scaffoldId}`;
131
+ if (await executionLog.hasExecuted({
132
+ filePath: fulfilledKey,
133
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW
134
+ })) return {
135
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
136
+ message: "Scaffold already fulfilled"
137
+ };
138
+ const isScaffoldedFile = generatedFiles.includes(filePath);
139
+ if (isScaffoldedFile) {
140
+ const editKey = `scaffold-edit-${scaffoldId}-${filePath}`;
141
+ if (!await executionLog.hasExecuted({
142
+ filePath: editKey,
143
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW
144
+ })) await executionLog.logExecution({
145
+ filePath: editKey,
146
+ operation: "scaffold-file-edit",
147
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW
148
+ });
149
+ }
150
+ const editedFiles = await getEditedScaffoldFiles(executionLog, scaffoldId);
151
+ const totalFiles = generatedFiles.length;
152
+ const remainingFiles = generatedFiles.filter((f) => !editedFiles.includes(f));
153
+ if (remainingFiles.length === 0) {
154
+ await executionLog.logExecution({
155
+ filePath: fulfilledKey,
156
+ operation: "scaffold-fulfilled",
157
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW
158
+ });
159
+ return {
160
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
161
+ message: `✅ All scaffold files${featureName ? ` for "${featureName}"` : ""} have been implemented! (${totalFiles}/${totalFiles} files completed)`
162
+ };
163
+ }
164
+ if (isScaffoldedFile) {
165
+ const remainingFilesList = remainingFiles.map((f) => ` - ${f}`).join("\\n");
166
+ return {
167
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
168
+ message: `
169
+ ⚠️ **Scaffold Implementation Progress${featureName ? ` for "${featureName}"` : ""}: ${editedFiles.length}/${totalFiles} files completed**
170
+
171
+ **Remaining files to implement:**
172
+ ${remainingFilesList}
173
+
174
+ Don't forget to complete the implementation for all scaffolded files!
175
+ `.trim()
176
+ };
177
+ }
178
+ return {
179
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
180
+ message: "Edited file not part of last scaffold execution"
181
+ };
182
+ } catch (error) {
183
+ return {
184
+ decision: __agiflowai_hooks_adapter.DECISION_SKIP,
185
+ message: `⚠️ Hook error: ${error instanceof Error ? error.message : String(error)}`
186
+ };
187
+ }
188
+ }
189
+ };
190
+ /**
191
+ * Extract scaffold ID from tool result
192
+ */
193
+ function extractScaffoldId(toolResult) {
194
+ try {
195
+ if (!toolResult || !toolResult.content) return null;
196
+ for (const item of toolResult.content) if (item.type === "text" && typeof item.text === "string") {
197
+ const match = item.text.match(/^SCAFFOLD_ID:([a-z0-9]+)$/);
198
+ if (match) return match[1];
199
+ }
200
+ return null;
201
+ } catch {
202
+ return null;
203
+ }
204
+ }
205
+ /**
206
+ * Helper function to get the last scaffold execution for a session
207
+ */
208
+ async function getLastScaffoldExecution(executionLog) {
209
+ const entries = await executionLog.loadLog();
210
+ for (let i = entries.length - 1; i >= 0; i--) {
211
+ const entry = entries[i];
212
+ if (entry.operation === "scaffold" && entry.scaffoldId && entry.generatedFiles && entry.generatedFiles.length > 0) return {
213
+ scaffoldId: entry.scaffoldId,
214
+ generatedFiles: entry.generatedFiles,
215
+ featureName: entry.featureName
216
+ };
217
+ }
218
+ return null;
219
+ }
220
+ /**
221
+ * Helper function to get list of edited scaffold files
222
+ */
223
+ async function getEditedScaffoldFiles(executionLog, scaffoldId) {
224
+ const entries = await executionLog.loadLog();
225
+ const editedFiles = [];
226
+ for (const entry of entries) if (entry.operation === "scaffold-file-edit" && entry.filePath.startsWith(`scaffold-edit-${scaffoldId}-`)) {
227
+ const filePath = entry.filePath.replace(`scaffold-edit-${scaffoldId}-`, "");
228
+ editedFiles.push(filePath);
229
+ }
230
+ return editedFiles;
231
+ }
232
+ /**
233
+ * Process pending scaffold logs from temp file and copy to ExecutionLogService
234
+ * Called when use-scaffold-method tool is executed
235
+ */
236
+ async function processPendingScaffoldLogs(sessionId, scaffoldId) {
237
+ const tempLogFile = node_path.default.join(node_os.default.tmpdir(), `scaffold-mcp-pending-${scaffoldId}.jsonl`);
238
+ try {
239
+ const lines = (await node_fs_promises.default.readFile(tempLogFile, "utf-8")).trim().split("\\n").filter(Boolean);
240
+ const executionLog = new __agiflowai_hooks_adapter.ExecutionLogService(sessionId);
241
+ try {
242
+ for (const line of lines) try {
243
+ const entry = JSON.parse(line);
244
+ await executionLog.logExecution({
245
+ filePath: `scaffold-${entry.scaffoldId}`,
246
+ operation: "scaffold",
247
+ decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
248
+ generatedFiles: entry.generatedFiles,
249
+ scaffoldId: entry.scaffoldId,
250
+ projectPath: entry.projectPath,
251
+ featureName: entry.featureName
252
+ });
253
+ } catch (parseError) {
254
+ console.error("Failed to parse pending scaffold log entry:", parseError);
255
+ }
256
+ } finally {
257
+ try {
258
+ await node_fs_promises.default.unlink(tempLogFile);
259
+ } catch {}
260
+ }
261
+ } catch (error) {
262
+ if (error instanceof Error && "code" in error && error.code !== "ENOENT") console.error("Error processing pending scaffold logs:", error);
263
+ }
264
+ }
265
+
266
+ //#endregion
267
+ exports.UseScaffoldMethodHook = UseScaffoldMethodHook;