@agiflowai/scaffold-mcp 1.0.22 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -0
- package/dist/{ListScaffoldingMethodsTool-Dnd3E5X_.cjs → ListScaffoldingMethodsTool-CkIkgP_u.cjs} +78 -78
- package/dist/{ListScaffoldingMethodsTool-DjhhMWjh.mjs → ListScaffoldingMethodsTool-Cx-0gpV3.mjs} +79 -79
- package/dist/{useScaffoldMethod-CmnKY0Vu.cjs → claudeCode-DBoEGOeu.cjs} +144 -3
- package/dist/{useScaffoldMethod-blx199pL.mjs → claudeCode-lHW7zQ5G.mjs} +144 -4
- package/dist/cli.cjs +149 -510
- package/dist/cli.mjs +149 -510
- package/dist/{useScaffoldMethod-CejnYNDD.cjs → geminiCli-BHyWDBcF.cjs} +1 -1
- package/dist/{useScaffoldMethod-BE2tHUMc.mjs → geminiCli-DBdxdDMM.mjs} +1 -1
- package/dist/index.cjs +9 -7
- package/dist/index.d.cts +409 -398
- package/dist/index.d.mts +410 -399
- package/dist/index.mjs +4 -4
- package/dist/src-B4ixzARA.cjs +886 -0
- package/dist/src-COn3FXEz.mjs +850 -0
- package/dist/{tools-S18iKO9I.cjs → tools-CC-lrhQ8.cjs} +3 -3
- package/dist/{tools-DRfJ2LZc.mjs → tools-DtGTxmf-.mjs} +3 -3
- package/package.json +6 -6
- package/dist/phantomCodeCheck-BwQWRJ9Q.mjs +0 -143
- package/dist/phantomCodeCheck-DhzeymO-.cjs +0 -144
- package/dist/stdio-BqcCsHuC.mjs +0 -331
- package/dist/stdio-D8getFsj.cjs +0 -350
package/README.md
CHANGED
|
@@ -149,6 +149,17 @@ npx @agiflowai/scaffold-mcp mcp-serve --type sse --port 3000
|
|
|
149
149
|
|
|
150
150
|
# With admin tools enabled
|
|
151
151
|
npx @agiflowai/scaffold-mcp mcp-serve --admin-enable
|
|
152
|
+
|
|
153
|
+
# With Claude Code skill front matter on prompts
|
|
154
|
+
npx @agiflowai/scaffold-mcp mcp-serve --prompt-as-skill
|
|
155
|
+
|
|
156
|
+
# With a fallback LLM tool for scaffold operations
|
|
157
|
+
npx @agiflowai/scaffold-mcp mcp-serve --fallback-tool claude-code
|
|
158
|
+
|
|
159
|
+
# Fallback tool with a specific model config
|
|
160
|
+
npx @agiflowai/scaffold-mcp mcp-serve \
|
|
161
|
+
--fallback-tool claude-code \
|
|
162
|
+
--fallback-tool-config '{"model":"claude-sonnet-4-6"}'
|
|
152
163
|
```
|
|
153
164
|
|
|
154
165
|
| Option | Description | Default |
|
|
@@ -157,6 +168,9 @@ npx @agiflowai/scaffold-mcp mcp-serve --admin-enable
|
|
|
157
168
|
| `-p, --port` | Port for HTTP/SSE | `3000` |
|
|
158
169
|
| `--host` | Host for HTTP/SSE | `localhost` |
|
|
159
170
|
| `--admin-enable` | Enable template creation tools | `false` |
|
|
171
|
+
| `--prompt-as-skill` | Render MCP prompts with Claude Code skill front matter, exposing them as `/skill` commands | `false` |
|
|
172
|
+
| `--fallback-tool` | LLM tool for scaffold operations (`claude-code`, `gemini-cli`, `codex`) | disabled |
|
|
173
|
+
| `--fallback-tool-config` | JSON config for the fallback tool (e.g., `{"model":"claude-sonnet-4-6"}`) | `{}` |
|
|
160
174
|
|
|
161
175
|
---
|
|
162
176
|
|
package/dist/{ListScaffoldingMethodsTool-Dnd3E5X_.cjs → ListScaffoldingMethodsTool-CkIkgP_u.cjs}
RENAMED
|
@@ -25,16 +25,91 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
}) : target, mod));
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
|
+
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
29
|
+
let zod = require("zod");
|
|
30
|
+
let liquidjs = require("liquidjs");
|
|
28
31
|
let node_path = require("node:path");
|
|
29
32
|
node_path = __toESM(node_path);
|
|
30
|
-
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
31
33
|
let js_yaml = require("js-yaml");
|
|
32
34
|
js_yaml = __toESM(js_yaml);
|
|
33
35
|
let __composio_json_schema_to_zod = require("@composio/json-schema-to-zod");
|
|
34
|
-
let zod = require("zod");
|
|
35
36
|
let node_url = require("node:url");
|
|
36
|
-
let liquidjs = require("liquidjs");
|
|
37
37
|
|
|
38
|
+
//#region src/services/TemplateService.ts
|
|
39
|
+
var TemplateService = class {
|
|
40
|
+
liquid;
|
|
41
|
+
constructor() {
|
|
42
|
+
this.liquid = new liquidjs.Liquid({
|
|
43
|
+
strictFilters: false,
|
|
44
|
+
strictVariables: false
|
|
45
|
+
});
|
|
46
|
+
this.setupCustomFilters();
|
|
47
|
+
__agiflowai_aicode_utils.log.info("TemplateService initialized");
|
|
48
|
+
}
|
|
49
|
+
toPascalCase(str) {
|
|
50
|
+
const camelCase = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
51
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
52
|
+
}
|
|
53
|
+
setupCustomFilters() {
|
|
54
|
+
this.liquid.registerFilter("camelCase", (str) => {
|
|
55
|
+
return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
56
|
+
});
|
|
57
|
+
this.liquid.registerFilter("pascalCase", (str) => {
|
|
58
|
+
return this.toPascalCase(str);
|
|
59
|
+
});
|
|
60
|
+
this.liquid.registerFilter("titleCase", (str) => {
|
|
61
|
+
return this.toPascalCase(str);
|
|
62
|
+
});
|
|
63
|
+
this.liquid.registerFilter("kebabCase", (str) => {
|
|
64
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
65
|
+
});
|
|
66
|
+
this.liquid.registerFilter("snakeCase", (str) => {
|
|
67
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
|
|
68
|
+
});
|
|
69
|
+
this.liquid.registerFilter("upperCase", (str) => {
|
|
70
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
|
|
71
|
+
});
|
|
72
|
+
this.liquid.registerFilter("lower", (str) => str.toLowerCase());
|
|
73
|
+
this.liquid.registerFilter("upper", (str) => str.toUpperCase());
|
|
74
|
+
this.liquid.registerFilter("pluralize", (str) => {
|
|
75
|
+
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
76
|
+
else if (str.endsWith("s") || str.endsWith("sh") || str.endsWith("ch") || str.endsWith("x") || str.endsWith("z")) return `${str}es`;
|
|
77
|
+
else return `${str}s`;
|
|
78
|
+
});
|
|
79
|
+
this.liquid.registerFilter("singularize", (str) => {
|
|
80
|
+
if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
|
|
81
|
+
else if (str.endsWith("es")) return str.slice(0, -2);
|
|
82
|
+
else if (str.endsWith("s") && !str.endsWith("ss")) return str.slice(0, -1);
|
|
83
|
+
else return str;
|
|
84
|
+
});
|
|
85
|
+
this.liquid.registerFilter("strip", (str) => {
|
|
86
|
+
return str.trim();
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
renderString(template, variables) {
|
|
90
|
+
try {
|
|
91
|
+
__agiflowai_aicode_utils.log.debug("Rendering template", {
|
|
92
|
+
variables,
|
|
93
|
+
templatePreview: template.substring(0, 100)
|
|
94
|
+
});
|
|
95
|
+
const result = this.liquid.parseAndRenderSync(template, variables);
|
|
96
|
+
__agiflowai_aicode_utils.log.debug("Rendered template", { resultPreview: result.substring(0, 100) });
|
|
97
|
+
return result;
|
|
98
|
+
} catch (error) {
|
|
99
|
+
__agiflowai_aicode_utils.log.error("LiquidJS rendering error", {
|
|
100
|
+
error: error instanceof Error ? error.message : String(error),
|
|
101
|
+
templatePreview: template.substring(0, 200),
|
|
102
|
+
variables
|
|
103
|
+
});
|
|
104
|
+
return template;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
containsTemplateVariables(content) {
|
|
108
|
+
return [/\{\{.*?\}\}/, /\{%.*?%\}/].some((pattern) => pattern.test(content));
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
//#endregion
|
|
38
113
|
//#region src/utils/pagination.ts
|
|
39
114
|
var PaginationHelper = class PaginationHelper {
|
|
40
115
|
/**
|
|
@@ -622,81 +697,6 @@ var ScaffoldService = class ScaffoldService {
|
|
|
622
697
|
}
|
|
623
698
|
};
|
|
624
699
|
|
|
625
|
-
//#endregion
|
|
626
|
-
//#region src/services/TemplateService.ts
|
|
627
|
-
var TemplateService = class {
|
|
628
|
-
liquid;
|
|
629
|
-
constructor() {
|
|
630
|
-
this.liquid = new liquidjs.Liquid({
|
|
631
|
-
strictFilters: false,
|
|
632
|
-
strictVariables: false
|
|
633
|
-
});
|
|
634
|
-
this.setupCustomFilters();
|
|
635
|
-
__agiflowai_aicode_utils.log.info("TemplateService initialized");
|
|
636
|
-
}
|
|
637
|
-
toPascalCase(str) {
|
|
638
|
-
const camelCase = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
639
|
-
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
640
|
-
}
|
|
641
|
-
setupCustomFilters() {
|
|
642
|
-
this.liquid.registerFilter("camelCase", (str) => {
|
|
643
|
-
return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
644
|
-
});
|
|
645
|
-
this.liquid.registerFilter("pascalCase", (str) => {
|
|
646
|
-
return this.toPascalCase(str);
|
|
647
|
-
});
|
|
648
|
-
this.liquid.registerFilter("titleCase", (str) => {
|
|
649
|
-
return this.toPascalCase(str);
|
|
650
|
-
});
|
|
651
|
-
this.liquid.registerFilter("kebabCase", (str) => {
|
|
652
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
653
|
-
});
|
|
654
|
-
this.liquid.registerFilter("snakeCase", (str) => {
|
|
655
|
-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
|
|
656
|
-
});
|
|
657
|
-
this.liquid.registerFilter("upperCase", (str) => {
|
|
658
|
-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
|
|
659
|
-
});
|
|
660
|
-
this.liquid.registerFilter("lower", (str) => str.toLowerCase());
|
|
661
|
-
this.liquid.registerFilter("upper", (str) => str.toUpperCase());
|
|
662
|
-
this.liquid.registerFilter("pluralize", (str) => {
|
|
663
|
-
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
664
|
-
else if (str.endsWith("s") || str.endsWith("sh") || str.endsWith("ch") || str.endsWith("x") || str.endsWith("z")) return `${str}es`;
|
|
665
|
-
else return `${str}s`;
|
|
666
|
-
});
|
|
667
|
-
this.liquid.registerFilter("singularize", (str) => {
|
|
668
|
-
if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
|
|
669
|
-
else if (str.endsWith("es")) return str.slice(0, -2);
|
|
670
|
-
else if (str.endsWith("s") && !str.endsWith("ss")) return str.slice(0, -1);
|
|
671
|
-
else return str;
|
|
672
|
-
});
|
|
673
|
-
this.liquid.registerFilter("strip", (str) => {
|
|
674
|
-
return str.trim();
|
|
675
|
-
});
|
|
676
|
-
}
|
|
677
|
-
renderString(template, variables) {
|
|
678
|
-
try {
|
|
679
|
-
__agiflowai_aicode_utils.log.debug("Rendering template", {
|
|
680
|
-
variables,
|
|
681
|
-
templatePreview: template.substring(0, 100)
|
|
682
|
-
});
|
|
683
|
-
const result = this.liquid.parseAndRenderSync(template, variables);
|
|
684
|
-
__agiflowai_aicode_utils.log.debug("Rendered template", { resultPreview: result.substring(0, 100) });
|
|
685
|
-
return result;
|
|
686
|
-
} catch (error) {
|
|
687
|
-
__agiflowai_aicode_utils.log.error("LiquidJS rendering error", {
|
|
688
|
-
error: error instanceof Error ? error.message : String(error),
|
|
689
|
-
templatePreview: template.substring(0, 200),
|
|
690
|
-
variables
|
|
691
|
-
});
|
|
692
|
-
return template;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
containsTemplateVariables(content) {
|
|
696
|
-
return [/\{\{.*?\}\}/, /\{%.*?%\}/].some((pattern) => pattern.test(content));
|
|
697
|
-
}
|
|
698
|
-
};
|
|
699
|
-
|
|
700
700
|
//#endregion
|
|
701
701
|
//#region src/services/VariableReplacementService.ts
|
|
702
702
|
var VariableReplacementService = class {
|
package/dist/{ListScaffoldingMethodsTool-DjhhMWjh.mjs → ListScaffoldingMethodsTool-Cx-0gpV3.mjs}
RENAMED
|
@@ -1,11 +1,86 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
1
|
import { ProjectConfigResolver, TemplatesManagerService, copy, ensureDir, log, pathExists, readFile, readJson, readdir, stat, writeFile } from "@agiflowai/aicode-utils";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { Liquid } from "liquidjs";
|
|
4
|
+
import path from "node:path";
|
|
3
5
|
import yaml from "js-yaml";
|
|
4
6
|
import { jsonSchemaToZod } from "@composio/json-schema-to-zod";
|
|
5
|
-
import { z } from "zod";
|
|
6
7
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { Liquid } from "liquidjs";
|
|
8
8
|
|
|
9
|
+
//#region src/services/TemplateService.ts
|
|
10
|
+
var TemplateService = class {
|
|
11
|
+
liquid;
|
|
12
|
+
constructor() {
|
|
13
|
+
this.liquid = new Liquid({
|
|
14
|
+
strictFilters: false,
|
|
15
|
+
strictVariables: false
|
|
16
|
+
});
|
|
17
|
+
this.setupCustomFilters();
|
|
18
|
+
log.info("TemplateService initialized");
|
|
19
|
+
}
|
|
20
|
+
toPascalCase(str) {
|
|
21
|
+
const camelCase = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
22
|
+
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
23
|
+
}
|
|
24
|
+
setupCustomFilters() {
|
|
25
|
+
this.liquid.registerFilter("camelCase", (str) => {
|
|
26
|
+
return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
27
|
+
});
|
|
28
|
+
this.liquid.registerFilter("pascalCase", (str) => {
|
|
29
|
+
return this.toPascalCase(str);
|
|
30
|
+
});
|
|
31
|
+
this.liquid.registerFilter("titleCase", (str) => {
|
|
32
|
+
return this.toPascalCase(str);
|
|
33
|
+
});
|
|
34
|
+
this.liquid.registerFilter("kebabCase", (str) => {
|
|
35
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
36
|
+
});
|
|
37
|
+
this.liquid.registerFilter("snakeCase", (str) => {
|
|
38
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
|
|
39
|
+
});
|
|
40
|
+
this.liquid.registerFilter("upperCase", (str) => {
|
|
41
|
+
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
|
|
42
|
+
});
|
|
43
|
+
this.liquid.registerFilter("lower", (str) => str.toLowerCase());
|
|
44
|
+
this.liquid.registerFilter("upper", (str) => str.toUpperCase());
|
|
45
|
+
this.liquid.registerFilter("pluralize", (str) => {
|
|
46
|
+
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
47
|
+
else if (str.endsWith("s") || str.endsWith("sh") || str.endsWith("ch") || str.endsWith("x") || str.endsWith("z")) return `${str}es`;
|
|
48
|
+
else return `${str}s`;
|
|
49
|
+
});
|
|
50
|
+
this.liquid.registerFilter("singularize", (str) => {
|
|
51
|
+
if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
|
|
52
|
+
else if (str.endsWith("es")) return str.slice(0, -2);
|
|
53
|
+
else if (str.endsWith("s") && !str.endsWith("ss")) return str.slice(0, -1);
|
|
54
|
+
else return str;
|
|
55
|
+
});
|
|
56
|
+
this.liquid.registerFilter("strip", (str) => {
|
|
57
|
+
return str.trim();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
renderString(template, variables) {
|
|
61
|
+
try {
|
|
62
|
+
log.debug("Rendering template", {
|
|
63
|
+
variables,
|
|
64
|
+
templatePreview: template.substring(0, 100)
|
|
65
|
+
});
|
|
66
|
+
const result = this.liquid.parseAndRenderSync(template, variables);
|
|
67
|
+
log.debug("Rendered template", { resultPreview: result.substring(0, 100) });
|
|
68
|
+
return result;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
log.error("LiquidJS rendering error", {
|
|
71
|
+
error: error instanceof Error ? error.message : String(error),
|
|
72
|
+
templatePreview: template.substring(0, 200),
|
|
73
|
+
variables
|
|
74
|
+
});
|
|
75
|
+
return template;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
containsTemplateVariables(content) {
|
|
79
|
+
return [/\{\{.*?\}\}/, /\{%.*?%\}/].some((pattern) => pattern.test(content));
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
//#endregion
|
|
9
84
|
//#region src/utils/pagination.ts
|
|
10
85
|
var PaginationHelper = class PaginationHelper {
|
|
11
86
|
/**
|
|
@@ -593,81 +668,6 @@ var ScaffoldService = class ScaffoldService {
|
|
|
593
668
|
}
|
|
594
669
|
};
|
|
595
670
|
|
|
596
|
-
//#endregion
|
|
597
|
-
//#region src/services/TemplateService.ts
|
|
598
|
-
var TemplateService = class {
|
|
599
|
-
liquid;
|
|
600
|
-
constructor() {
|
|
601
|
-
this.liquid = new Liquid({
|
|
602
|
-
strictFilters: false,
|
|
603
|
-
strictVariables: false
|
|
604
|
-
});
|
|
605
|
-
this.setupCustomFilters();
|
|
606
|
-
log.info("TemplateService initialized");
|
|
607
|
-
}
|
|
608
|
-
toPascalCase(str) {
|
|
609
|
-
const camelCase = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
610
|
-
return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
|
|
611
|
-
}
|
|
612
|
-
setupCustomFilters() {
|
|
613
|
-
this.liquid.registerFilter("camelCase", (str) => {
|
|
614
|
-
return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "");
|
|
615
|
-
});
|
|
616
|
-
this.liquid.registerFilter("pascalCase", (str) => {
|
|
617
|
-
return this.toPascalCase(str);
|
|
618
|
-
});
|
|
619
|
-
this.liquid.registerFilter("titleCase", (str) => {
|
|
620
|
-
return this.toPascalCase(str);
|
|
621
|
-
});
|
|
622
|
-
this.liquid.registerFilter("kebabCase", (str) => {
|
|
623
|
-
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
|
|
624
|
-
});
|
|
625
|
-
this.liquid.registerFilter("snakeCase", (str) => {
|
|
626
|
-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toLowerCase();
|
|
627
|
-
});
|
|
628
|
-
this.liquid.registerFilter("upperCase", (str) => {
|
|
629
|
-
return str.replace(/([a-z])([A-Z])/g, "$1_$2").replace(/[\s-]+/g, "_").toUpperCase();
|
|
630
|
-
});
|
|
631
|
-
this.liquid.registerFilter("lower", (str) => str.toLowerCase());
|
|
632
|
-
this.liquid.registerFilter("upper", (str) => str.toUpperCase());
|
|
633
|
-
this.liquid.registerFilter("pluralize", (str) => {
|
|
634
|
-
if (str.endsWith("y")) return `${str.slice(0, -1)}ies`;
|
|
635
|
-
else if (str.endsWith("s") || str.endsWith("sh") || str.endsWith("ch") || str.endsWith("x") || str.endsWith("z")) return `${str}es`;
|
|
636
|
-
else return `${str}s`;
|
|
637
|
-
});
|
|
638
|
-
this.liquid.registerFilter("singularize", (str) => {
|
|
639
|
-
if (str.endsWith("ies")) return `${str.slice(0, -3)}y`;
|
|
640
|
-
else if (str.endsWith("es")) return str.slice(0, -2);
|
|
641
|
-
else if (str.endsWith("s") && !str.endsWith("ss")) return str.slice(0, -1);
|
|
642
|
-
else return str;
|
|
643
|
-
});
|
|
644
|
-
this.liquid.registerFilter("strip", (str) => {
|
|
645
|
-
return str.trim();
|
|
646
|
-
});
|
|
647
|
-
}
|
|
648
|
-
renderString(template, variables) {
|
|
649
|
-
try {
|
|
650
|
-
log.debug("Rendering template", {
|
|
651
|
-
variables,
|
|
652
|
-
templatePreview: template.substring(0, 100)
|
|
653
|
-
});
|
|
654
|
-
const result = this.liquid.parseAndRenderSync(template, variables);
|
|
655
|
-
log.debug("Rendered template", { resultPreview: result.substring(0, 100) });
|
|
656
|
-
return result;
|
|
657
|
-
} catch (error) {
|
|
658
|
-
log.error("LiquidJS rendering error", {
|
|
659
|
-
error: error instanceof Error ? error.message : String(error),
|
|
660
|
-
templatePreview: template.substring(0, 200),
|
|
661
|
-
variables
|
|
662
|
-
});
|
|
663
|
-
return template;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
containsTemplateVariables(content) {
|
|
667
|
-
return [/\{\{.*?\}\}/, /\{%.*?%\}/].some((pattern) => pattern.test(content));
|
|
668
|
-
}
|
|
669
|
-
};
|
|
670
|
-
|
|
671
671
|
//#endregion
|
|
672
672
|
//#region src/services/VariableReplacementService.ts
|
|
673
673
|
var VariableReplacementService = class {
|
|
@@ -1054,4 +1054,4 @@ var ListScaffoldingMethodsTool = class ListScaffoldingMethodsTool {
|
|
|
1054
1054
|
};
|
|
1055
1055
|
|
|
1056
1056
|
//#endregion
|
|
1057
|
-
export {
|
|
1057
|
+
export { ScaffoldProcessingService as a, PaginationHelper as c, ScaffoldService as i, TemplateService as l, ScaffoldingMethodsService as n, ScaffoldConfigLoader as o, VariableReplacementService as r, FileSystemService as s, ListScaffoldingMethodsTool as t };
|
|
@@ -1,14 +1,154 @@
|
|
|
1
|
-
const require_ListScaffoldingMethodsTool = require('./ListScaffoldingMethodsTool-
|
|
2
|
-
require('./tools-
|
|
1
|
+
const require_ListScaffoldingMethodsTool = require('./ListScaffoldingMethodsTool-CkIkgP_u.cjs');
|
|
2
|
+
require('./tools-CC-lrhQ8.cjs');
|
|
3
|
+
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
3
4
|
let node_path = require("node:path");
|
|
4
5
|
node_path = require_ListScaffoldingMethodsTool.__toESM(node_path);
|
|
5
|
-
let __agiflowai_aicode_utils = require("@agiflowai/aicode-utils");
|
|
6
6
|
let node_fs_promises = require("node:fs/promises");
|
|
7
7
|
node_fs_promises = require_ListScaffoldingMethodsTool.__toESM(node_fs_promises);
|
|
8
8
|
let node_os = require("node:os");
|
|
9
9
|
node_os = require_ListScaffoldingMethodsTool.__toESM(node_os);
|
|
10
10
|
let __agiflowai_hooks_adapter = require("@agiflowai/hooks-adapter");
|
|
11
|
+
let node_child_process = require("node:child_process");
|
|
12
|
+
|
|
13
|
+
//#region src/hooks/claudeCode/phantomCodeCheck.ts
|
|
14
|
+
/**
|
|
15
|
+
* PhantomCodeCheck Hook for Claude Code
|
|
16
|
+
*
|
|
17
|
+
* DESIGN PATTERNS:
|
|
18
|
+
* - Class-based hook pattern: Encapsulates lifecycle hooks in a single class
|
|
19
|
+
* - Fail-open pattern: Errors allow operation to proceed (return DECISION_SKIP)
|
|
20
|
+
* - Marker-based detection: Scans for scaffold marker comments in code files
|
|
21
|
+
*
|
|
22
|
+
* CODING STANDARDS:
|
|
23
|
+
* - Export a class with stop, userPromptSubmit, taskCompleted methods
|
|
24
|
+
* - Handle all errors gracefully with fail-open behavior
|
|
25
|
+
* - Use execFileSync with args array to avoid shell injection
|
|
26
|
+
*
|
|
27
|
+
* AVOID:
|
|
28
|
+
* - Blocking operations on errors
|
|
29
|
+
* - Shell injection via marker parameter
|
|
30
|
+
* - Mutating context object
|
|
31
|
+
*/
|
|
32
|
+
const EXCLUDED_DIRS = [
|
|
33
|
+
"node_modules",
|
|
34
|
+
"dist",
|
|
35
|
+
".git",
|
|
36
|
+
".next",
|
|
37
|
+
"build",
|
|
38
|
+
"coverage",
|
|
39
|
+
".claude"
|
|
40
|
+
];
|
|
41
|
+
/**
|
|
42
|
+
* PhantomCodeCheckHook — scans for unimplemented scaffold files containing marker comments.
|
|
43
|
+
*
|
|
44
|
+
* Checks at session boundaries (Stop, UserPromptSubmit, TaskCompleted) whether
|
|
45
|
+
* any generated files still carry the `// <marker>` comment, indicating they
|
|
46
|
+
* have not yet been implemented by the AI agent.
|
|
47
|
+
*/
|
|
48
|
+
var PhantomCodeCheckHook = class {
|
|
49
|
+
markerComment;
|
|
50
|
+
constructor(marker = "@scaffold-generated") {
|
|
51
|
+
this.markerComment = `// ${marker}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Scans cwd for files containing the scaffold marker comment.
|
|
55
|
+
* Returns relative file paths. Returns empty array on any error (fail-open).
|
|
56
|
+
*/
|
|
57
|
+
scanForPhantomFiles(cwd) {
|
|
58
|
+
try {
|
|
59
|
+
return (0, node_child_process.execFileSync)("grep", [
|
|
60
|
+
"-rl",
|
|
61
|
+
this.markerComment,
|
|
62
|
+
"--include=*.ts",
|
|
63
|
+
"--include=*.tsx",
|
|
64
|
+
"--include=*.js",
|
|
65
|
+
"--include=*.jsx",
|
|
66
|
+
...EXCLUDED_DIRS.map((dir) => `--exclude-dir=${dir}`),
|
|
67
|
+
"."
|
|
68
|
+
], {
|
|
69
|
+
cwd,
|
|
70
|
+
timeout: 1e4,
|
|
71
|
+
encoding: "utf8"
|
|
72
|
+
}).trim().split("\n").filter(Boolean).map((f) => f.replace(/^\.\//, ""));
|
|
73
|
+
} catch (error) {
|
|
74
|
+
if (error instanceof Error && "status" in error && error.status === 1) return [];
|
|
75
|
+
return [];
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Stop hook — blocks session end if phantom files are found.
|
|
80
|
+
* Returns DECISION_DENY to prevent Claude from stopping with unimplemented files.
|
|
81
|
+
*/
|
|
82
|
+
async stop(context) {
|
|
83
|
+
try {
|
|
84
|
+
const phantomFiles = this.scanForPhantomFiles(context.cwd);
|
|
85
|
+
if (phantomFiles.length === 0) return {
|
|
86
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
87
|
+
message: "No phantom scaffold files found"
|
|
88
|
+
};
|
|
89
|
+
const fileList = phantomFiles.map((f) => ` - ${f}`).join("\n");
|
|
90
|
+
return {
|
|
91
|
+
decision: __agiflowai_hooks_adapter.DECISION_DENY,
|
|
92
|
+
message: `⚠️ ${phantomFiles.length} scaffold file(s) still contain \`${this.markerComment}\` and have not been implemented:\n${fileList}\n\nPlease implement these files and remove the marker comment before ending the session.`
|
|
93
|
+
};
|
|
94
|
+
} catch {
|
|
95
|
+
return {
|
|
96
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
97
|
+
message: "PhantomCodeCheckHook.stop error — skipping"
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* UserPromptSubmit hook — warns about phantom files without blocking.
|
|
103
|
+
* Returns DECISION_ALLOW with userMessage written to stderr (visible to user, not LLM).
|
|
104
|
+
*/
|
|
105
|
+
async userPromptSubmit(context) {
|
|
106
|
+
try {
|
|
107
|
+
const phantomFiles = this.scanForPhantomFiles(context.cwd);
|
|
108
|
+
if (phantomFiles.length === 0) return {
|
|
109
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
110
|
+
message: "No phantom scaffold files found"
|
|
111
|
+
};
|
|
112
|
+
const fileList = phantomFiles.map((f) => ` - ${f}`).join("\n");
|
|
113
|
+
return {
|
|
114
|
+
decision: __agiflowai_hooks_adapter.DECISION_ALLOW,
|
|
115
|
+
message: "",
|
|
116
|
+
userMessage: `⚠️ Reminder: ${phantomFiles.length} scaffold file(s) still contain \`${this.markerComment}\`:\n${fileList}\n\nPlease implement these files and remove the marker comment.`
|
|
117
|
+
};
|
|
118
|
+
} catch {
|
|
119
|
+
return {
|
|
120
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
121
|
+
message: "PhantomCodeCheckHook.userPromptSubmit error — skipping"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* TaskCompleted hook — blocks task completion if phantom files are found.
|
|
127
|
+
* Returns DECISION_DENY with exitCode 2 to signal incomplete scaffolding.
|
|
128
|
+
*/
|
|
129
|
+
async taskCompleted(context) {
|
|
130
|
+
try {
|
|
131
|
+
const phantomFiles = this.scanForPhantomFiles(context.cwd);
|
|
132
|
+
if (phantomFiles.length === 0) return {
|
|
133
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
134
|
+
message: "No phantom scaffold files found"
|
|
135
|
+
};
|
|
136
|
+
const fileList = phantomFiles.map((f) => ` - ${f}`).join("\n");
|
|
137
|
+
return {
|
|
138
|
+
decision: __agiflowai_hooks_adapter.DECISION_DENY,
|
|
139
|
+
exitCode: 2,
|
|
140
|
+
message: `⚠️ ${phantomFiles.length} scaffold file(s) still contain \`${this.markerComment}\` and have not been implemented:\n${fileList}\n\nTask cannot complete until all scaffold files are implemented.`
|
|
141
|
+
};
|
|
142
|
+
} catch {
|
|
143
|
+
return {
|
|
144
|
+
decision: __agiflowai_hooks_adapter.DECISION_SKIP,
|
|
145
|
+
message: "PhantomCodeCheckHook.taskCompleted error — skipping"
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
11
150
|
|
|
151
|
+
//#endregion
|
|
12
152
|
//#region src/hooks/claudeCode/useScaffoldMethod.ts
|
|
13
153
|
/**
|
|
14
154
|
* Type guard for ScaffoldMethodsResponse
|
|
@@ -323,4 +463,5 @@ async function processPendingScaffoldLogs(sessionId, scaffoldId) {
|
|
|
323
463
|
}
|
|
324
464
|
|
|
325
465
|
//#endregion
|
|
466
|
+
exports.PhantomCodeCheckHook = PhantomCodeCheckHook;
|
|
326
467
|
exports.UseScaffoldMethodHook = UseScaffoldMethodHook;
|