@ulpi/cli 0.1.5 → 0.1.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.
- package/README.md +143 -214
- package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
- package/dist/{auth-BFFBUJUC.js → auth-HDK7ECJL.js} +2 -1
- package/dist/{chunk-RJIRWQJD.js → chunk-3BCW6ABU.js} +402 -142
- package/dist/{chunk-L3PWNHSA.js → chunk-3WB5CXH4.js} +180 -5
- package/dist/{chunk-K4OVPFY2.js → chunk-4UCJIAOU.js} +2 -2
- package/dist/chunk-4XTHZVDS.js +109 -0
- package/dist/chunk-4ZPOZULQ.js +6522 -0
- package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
- package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
- package/dist/{chunk-AV5RB3N2.js → chunk-76D3BYJD.js} +48 -0
- package/dist/{chunk-DOIKS6C5.js → chunk-AWOSRA5F.js} +1 -1
- package/dist/{chunk-UCMT5OKP.js → chunk-BFEKZZHM.js} +274 -57
- package/dist/chunk-C7CLUQI6.js +1286 -0
- package/dist/{chunk-ELTGWMDE.js → chunk-E3B5NROU.js} +7 -7
- package/dist/chunk-EJ7TW77N.js +1418 -0
- package/dist/{chunk-P2RESJRN.js → chunk-EWLYVXQ4.js} +2 -2
- package/dist/{chunk-6OURRFP7.js → chunk-IV6MWETF.js} +383 -168
- package/dist/chunk-IZPJHSPX.js +1478 -0
- package/dist/chunk-JLHNLM3C.js +228 -0
- package/dist/chunk-PO4NUZUU.js +147 -0
- package/dist/chunk-S6ANCSYO.js +1271 -0
- package/dist/chunk-SEU7WWNQ.js +1251 -0
- package/dist/chunk-SNQ7NAIS.js +453 -0
- package/dist/{ulpi-RMMCUAGP-EWYUE7RU.js → chunk-TSLDGT5O.js} +73 -35
- package/dist/{chunk-EIWYSP3A.js → chunk-UXHCHOWQ.js} +83 -62
- package/dist/chunk-WED4LM5N.js +322 -0
- package/dist/chunk-WVOZE25N.js +6757 -0
- package/dist/{chunk-5SCG7UYM.js → chunk-XKF4DPUM.js} +7 -7
- package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
- package/dist/chunk-Z53CAR7G.js +298 -0
- package/dist/{ci-JQ56YIKC.js → ci-COZRTPGQ.js} +124 -26
- package/dist/cloud-2F3NLVHN.js +274 -0
- package/dist/{codemap-HMYBXJL2.js → codemap-XNGMAF3F.js} +37 -37
- package/dist/codex-MB5YTMRT.js +132 -0
- package/dist/{config-YYWEN7U2.js → config-OOELBYTH.js} +1 -1
- package/dist/dist-2BJYR5EI.js +59 -0
- package/dist/dist-3EIQTZHT.js +1380 -0
- package/dist/{dist-WAMAQVPK.js → dist-4U5L2X2C.js} +2 -2
- package/dist/{dist-4XTJ6HLM.js → dist-54KAMNLO.js} +16 -15
- package/dist/dist-6M4MZWZW.js +58 -0
- package/dist/dist-6X576SU2.js +27 -0
- package/dist/dist-7QOEYLFX.js +103 -0
- package/dist/dist-AYBGHEDY.js +2541 -0
- package/dist/dist-EK45QNEM.js +45 -0
- package/dist/{dist-U7ZIJMZD.js → dist-FKFEJRPX.js} +16 -15
- package/dist/dist-GTEJUBBT.js +66 -0
- package/dist/dist-HA74OKJZ.js +40 -0
- package/dist/{dist-XG2GG5SD.js → dist-HU5RZAON.js} +14 -2
- package/dist/dist-IYE3OBRB.js +374 -0
- package/dist/{dist-7WLLPWWB.js → dist-JLU26AB6.js} +12 -9
- package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
- package/dist/dist-NUEMFZFL.js +33 -0
- package/dist/{dist-GWGTAHNM.js → dist-NUXMDXZ3.js} +31 -3
- package/dist/{dist-5R4RYNQO.js → dist-YCNWHSLN.js} +15 -5
- package/dist/{dist-6MFVWIFF.js → dist-YFFG2ZD6.js} +9 -16
- package/dist/dist-ZG4OKCSR.js +15 -0
- package/dist/doctor-FKYSIHER.js +345 -0
- package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
- package/dist/{history-RNUWO4JZ.js → history-UMGQNQQ7.js} +7 -7
- package/dist/{hooks-installer-K2JXEBNN.js → hooks-installer-YEYTYA6Q.js} +2 -2
- package/dist/index.js +398 -622
- package/dist/{init-NQWFZPKO.js → init-TJYW5ROZ.js} +78 -12
- package/dist/job-HIDMAFW2.js +376 -0
- package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
- package/dist/kiro-VMUHDFGK.js +153 -0
- package/dist/{launchd-OYXUAVW6.js → launchd-U3MSWBRH.js} +9 -17
- package/dist/mcp-PDUD7SGP.js +249 -0
- package/dist/mcp-installer-PQU3XOGO.js +259 -0
- package/dist/mcp-setup-OA7IB3H3.js +263 -0
- package/dist/{memory-D6ZFFCI2.js → memory-ZNAEAK3B.js} +17 -17
- package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
- package/dist/{openai-E7G2YAHU-IG33BFYF.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
- package/dist/portal-JYWVHXDU.js +210 -0
- package/dist/prd-Q4J5NVAR.js +408 -0
- package/dist/repos-WWZXNN3P.js +271 -0
- package/dist/review-integration-RQE4KMAV.js +14 -0
- package/dist/{rules-3OFGWHP4.js → rules-Y4VSOY5Y.js} +3 -3
- package/dist/run-VPNXEIBY.js +687 -0
- package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
- package/dist/server-U7PQ6FTS-MG4MJPTS.js +20 -0
- package/dist/{skills-GY2CTPWN.js → skills-QEYU2N27.js} +4 -2
- package/dist/start-IJKY5RVT.js +303 -0
- package/dist/{status-SE43TIFJ.js → status-BHQYYGAL.js} +2 -2
- package/dist/{templates-O2XDKB5R.js → templates-CBRUJ66V.js} +6 -5
- package/dist/tui-DP7736EX.js +61 -0
- package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
- package/dist/{uninstall-KWGSGZTI.js → uninstall-BX6FOV77.js} +3 -3
- package/dist/{update-QYZA4D23.js → update-AQKTHFVQ.js} +3 -3
- package/dist/{version-checker-MVB74DEX.js → version-checker-5L5PUOEX.js} +2 -2
- package/package.json +13 -4
- package/dist/chunk-26LLDX2T.js +0 -553
- package/dist/chunk-DDRLI6JU.js +0 -331
- package/dist/chunk-IFATANHR.js +0 -453
- package/dist/chunk-JWUUVXIV.js +0 -13694
- package/dist/chunk-LD52XG3X.js +0 -4273
- package/dist/chunk-MIAQVCFW.js +0 -39
- package/dist/chunk-YYZOFYS6.js +0 -415
- package/dist/dist-XD4YI27T.js +0 -26
- package/dist/mcp-installer-TOYDP77X.js +0 -124
- package/dist/projects-COUJP4ZC.js +0 -271
- package/dist/review-KMGP2S25.js +0 -152
- package/dist/server-USLHY6GH-F4JSXCWA.js +0 -18
- package/dist/server-X5P6WH2M-ULZF5WHZ.js +0 -11
- package/dist/ui-4SM2SUI6.js +0 -167
- package/dist/ui.html +0 -698
- /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/SKILL.md +0 -0
- /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/references/framework-rules.md +0 -0
- /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/references/language-rules.md +0 -0
package/dist/chunk-IFATANHR.js
DELETED
|
@@ -1,453 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
USER_SKILLS_DIR,
|
|
3
|
-
USER_TEMPLATES_DIR
|
|
4
|
-
} from "./chunk-DDRLI6JU.js";
|
|
5
|
-
|
|
6
|
-
// ../../packages/templates-engine/dist/index.js
|
|
7
|
-
import * as fs from "fs";
|
|
8
|
-
import * as path from "path";
|
|
9
|
-
import { parse as parseYaml } from "yaml";
|
|
10
|
-
import * as fs2 from "fs";
|
|
11
|
-
import * as path2 from "path";
|
|
12
|
-
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
13
|
-
import * as fs3 from "fs";
|
|
14
|
-
import * as path3 from "path";
|
|
15
|
-
function findTemplatesDir() {
|
|
16
|
-
let dir = path.dirname(new URL(import.meta.url).pathname);
|
|
17
|
-
for (let i = 0; i < 5; i++) {
|
|
18
|
-
const candidate = path.join(dir, "templates");
|
|
19
|
-
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
|
20
|
-
return candidate;
|
|
21
|
-
}
|
|
22
|
-
dir = path.dirname(dir);
|
|
23
|
-
}
|
|
24
|
-
return path.resolve(dir, "templates");
|
|
25
|
-
}
|
|
26
|
-
var MAX_TEMPLATE_SIZE = 1e6;
|
|
27
|
-
function loadTemplateFile(filePath) {
|
|
28
|
-
try {
|
|
29
|
-
const stat = fs.statSync(filePath);
|
|
30
|
-
if (stat.size > MAX_TEMPLATE_SIZE) {
|
|
31
|
-
console.error(`[ulpi] Warning: skipping oversized template file: ${filePath} (${stat.size} bytes)`);
|
|
32
|
-
return null;
|
|
33
|
-
}
|
|
34
|
-
const raw = fs.readFileSync(filePath, "utf-8");
|
|
35
|
-
const parsed = parseYaml(raw);
|
|
36
|
-
if (!parsed || typeof parsed !== "object" || !parsed.id) {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
return {
|
|
40
|
-
id: parsed.id,
|
|
41
|
-
name: parsed.name ?? parsed.id,
|
|
42
|
-
category: parsed.category ?? "universal",
|
|
43
|
-
variables: parsed.variables ?? void 0,
|
|
44
|
-
rules: {
|
|
45
|
-
preconditions: parsed.rules?.preconditions,
|
|
46
|
-
postconditions: parsed.rules?.postconditions,
|
|
47
|
-
permissions: parsed.rules?.permissions,
|
|
48
|
-
pipelines: parsed.rules?.pipelines
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
} catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function loadBundledTemplates() {
|
|
56
|
-
const dir = findTemplatesDir();
|
|
57
|
-
return loadTemplatesFromDir(dir);
|
|
58
|
-
}
|
|
59
|
-
function loadTemplates(dir) {
|
|
60
|
-
return loadTemplatesFromDir(dir);
|
|
61
|
-
}
|
|
62
|
-
function loadTemplatesFromDir(dir) {
|
|
63
|
-
if (!fs.existsSync(dir)) {
|
|
64
|
-
return [];
|
|
65
|
-
}
|
|
66
|
-
const files = fs.readdirSync(dir).filter((f) => /\.ya?ml$/i.test(f));
|
|
67
|
-
const layers = [];
|
|
68
|
-
for (const file of files.sort()) {
|
|
69
|
-
const layer = loadTemplateFile(path.join(dir, file));
|
|
70
|
-
if (layer) {
|
|
71
|
-
layers.push(layer);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
return layers;
|
|
75
|
-
}
|
|
76
|
-
function getBundledTemplate(id) {
|
|
77
|
-
const all = loadBundledTemplates();
|
|
78
|
-
return all.find((t) => t.id === id) ?? null;
|
|
79
|
-
}
|
|
80
|
-
function deepClone(value) {
|
|
81
|
-
if (typeof structuredClone === "function") {
|
|
82
|
-
return structuredClone(value);
|
|
83
|
-
}
|
|
84
|
-
return JSON.parse(JSON.stringify(value));
|
|
85
|
-
}
|
|
86
|
-
function composeTemplates(layers) {
|
|
87
|
-
const result = {
|
|
88
|
-
variables: {},
|
|
89
|
-
preconditions: {},
|
|
90
|
-
postconditions: {},
|
|
91
|
-
permissions: {},
|
|
92
|
-
pipelines: {}
|
|
93
|
-
};
|
|
94
|
-
for (const layer of layers) {
|
|
95
|
-
const cloned = deepClone(layer);
|
|
96
|
-
if (cloned.variables) {
|
|
97
|
-
Object.assign(result.variables, cloned.variables);
|
|
98
|
-
}
|
|
99
|
-
if (cloned.rules.preconditions) {
|
|
100
|
-
for (const [key, rule] of Object.entries(cloned.rules.preconditions)) {
|
|
101
|
-
result.preconditions[key] = {
|
|
102
|
-
...result.preconditions[key],
|
|
103
|
-
...rule,
|
|
104
|
-
id: key,
|
|
105
|
-
type: "precondition",
|
|
106
|
-
source: "template"
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
if (cloned.rules.postconditions) {
|
|
111
|
-
for (const [key, rule] of Object.entries(cloned.rules.postconditions)) {
|
|
112
|
-
result.postconditions[key] = {
|
|
113
|
-
...result.postconditions[key],
|
|
114
|
-
...rule,
|
|
115
|
-
id: key,
|
|
116
|
-
type: "postcondition",
|
|
117
|
-
source: "template"
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
if (cloned.rules.permissions) {
|
|
122
|
-
for (const [key, rule] of Object.entries(cloned.rules.permissions)) {
|
|
123
|
-
result.permissions[key] = {
|
|
124
|
-
...result.permissions[key],
|
|
125
|
-
...rule,
|
|
126
|
-
id: key,
|
|
127
|
-
type: "permission",
|
|
128
|
-
source: "template"
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
if (cloned.rules.pipelines) {
|
|
133
|
-
for (const [key, rule] of Object.entries(cloned.rules.pipelines)) {
|
|
134
|
-
result.pipelines[key] = {
|
|
135
|
-
...result.pipelines[key],
|
|
136
|
-
...rule,
|
|
137
|
-
id: key,
|
|
138
|
-
type: "pipeline",
|
|
139
|
-
source: "template"
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return result;
|
|
145
|
-
}
|
|
146
|
-
function buildVariableMap(templateVars, config) {
|
|
147
|
-
const pm = config.package_manager ?? templateVars.package_manager ?? "npm";
|
|
148
|
-
const vars = { ...templateVars };
|
|
149
|
-
vars.package_manager = pm;
|
|
150
|
-
vars.project_name = config.name ?? vars.project_name ?? "";
|
|
151
|
-
vars.test_command = vars.test_command ?? `${pm} test`;
|
|
152
|
-
vars.lint_command = vars.lint_command ?? `${pm} lint`;
|
|
153
|
-
vars.build_command = vars.build_command ?? `${pm} build`;
|
|
154
|
-
if (config.test_command) vars.test_command = config.test_command;
|
|
155
|
-
if (config.lint_command) vars.lint_command = config.lint_command;
|
|
156
|
-
if (config.build_command) vars.build_command = config.build_command;
|
|
157
|
-
if (config.format_command) vars.format_command = config.format_command;
|
|
158
|
-
return vars;
|
|
159
|
-
}
|
|
160
|
-
var MAX_RESOLVE_ITERATIONS = 10;
|
|
161
|
-
function resolveValue(value, vars) {
|
|
162
|
-
if (typeof value === "string") {
|
|
163
|
-
let result = value;
|
|
164
|
-
for (let pass = 0; pass < MAX_RESOLVE_ITERATIONS; pass++) {
|
|
165
|
-
const next = result.replace(
|
|
166
|
-
/\{(\w+)\}/g,
|
|
167
|
-
(_match, key) => vars[key] ?? `{${key}}`
|
|
168
|
-
);
|
|
169
|
-
if (next === result) break;
|
|
170
|
-
result = next;
|
|
171
|
-
}
|
|
172
|
-
return result;
|
|
173
|
-
}
|
|
174
|
-
if (Array.isArray(value)) {
|
|
175
|
-
return value.map((item) => resolveValue(item, vars));
|
|
176
|
-
}
|
|
177
|
-
if (value !== null && typeof value === "object") {
|
|
178
|
-
const resolved = {};
|
|
179
|
-
for (const [k, v] of Object.entries(value)) {
|
|
180
|
-
resolved[k] = resolveValue(v, vars);
|
|
181
|
-
}
|
|
182
|
-
return resolved;
|
|
183
|
-
}
|
|
184
|
-
return value;
|
|
185
|
-
}
|
|
186
|
-
function findUnresolvedPlaceholders(value) {
|
|
187
|
-
const found = [];
|
|
188
|
-
if (typeof value === "string") {
|
|
189
|
-
const matches = value.match(/\{(\w+)\}/g);
|
|
190
|
-
if (matches) found.push(...matches);
|
|
191
|
-
} else if (Array.isArray(value)) {
|
|
192
|
-
for (const item of value) found.push(...findUnresolvedPlaceholders(item));
|
|
193
|
-
} else if (value !== null && typeof value === "object") {
|
|
194
|
-
for (const v of Object.values(value)) {
|
|
195
|
-
found.push(...findUnresolvedPlaceholders(v));
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
return found;
|
|
199
|
-
}
|
|
200
|
-
function resolveTemplate(composed, config) {
|
|
201
|
-
const vars = buildVariableMap(composed.variables, config);
|
|
202
|
-
const resolved = {
|
|
203
|
-
variables: vars,
|
|
204
|
-
preconditions: resolveValue(composed.preconditions, vars),
|
|
205
|
-
postconditions: resolveValue(composed.postconditions, vars),
|
|
206
|
-
permissions: resolveValue(composed.permissions, vars),
|
|
207
|
-
pipelines: resolveValue(composed.pipelines, vars)
|
|
208
|
-
};
|
|
209
|
-
const RUNTIME_PLACEHOLDERS = /* @__PURE__ */ new Set(["{file_path}", "{command}"]);
|
|
210
|
-
const unresolved = [
|
|
211
|
-
...findUnresolvedPlaceholders(resolved.preconditions),
|
|
212
|
-
...findUnresolvedPlaceholders(resolved.postconditions),
|
|
213
|
-
...findUnresolvedPlaceholders(resolved.permissions),
|
|
214
|
-
...findUnresolvedPlaceholders(resolved.pipelines)
|
|
215
|
-
].filter((p) => !RUNTIME_PLACEHOLDERS.has(p));
|
|
216
|
-
if (unresolved.length > 0) {
|
|
217
|
-
const unique = [...new Set(unresolved)];
|
|
218
|
-
console.error(`[ulpi] Warning: unresolved template variables after resolution: ${unique.join(", ")}`);
|
|
219
|
-
}
|
|
220
|
-
return resolved;
|
|
221
|
-
}
|
|
222
|
-
var DEFAULT_BASE_DIR = USER_TEMPLATES_DIR;
|
|
223
|
-
function ensureDir(dir) {
|
|
224
|
-
if (!fs2.existsSync(dir)) {
|
|
225
|
-
fs2.mkdirSync(dir, { recursive: true });
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
function validateTemplateName(name) {
|
|
229
|
-
if (!name) {
|
|
230
|
-
throw new Error("Invalid template name: name is required");
|
|
231
|
-
}
|
|
232
|
-
if (name.includes("..") || name.includes("/") || name.includes("\\")) {
|
|
233
|
-
throw new Error("Invalid template name: contains path traversal characters");
|
|
234
|
-
}
|
|
235
|
-
if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
|
|
236
|
-
throw new Error("Template name must be alphanumeric with hyphens/underscores only");
|
|
237
|
-
}
|
|
238
|
-
if (name.length > 100) {
|
|
239
|
-
throw new Error("Template name too long (max 100 characters)");
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
function templatePath(name, baseDir) {
|
|
243
|
-
validateTemplateName(name);
|
|
244
|
-
return path2.join(baseDir, `${name}.yml`);
|
|
245
|
-
}
|
|
246
|
-
function saveUserTemplate(template, baseDir = DEFAULT_BASE_DIR) {
|
|
247
|
-
ensureDir(baseDir);
|
|
248
|
-
const filePath = templatePath(template.name, baseDir);
|
|
249
|
-
const yaml = stringifyYaml(template, { indent: 2, lineWidth: 0 });
|
|
250
|
-
fs2.writeFileSync(filePath, yaml, "utf-8");
|
|
251
|
-
}
|
|
252
|
-
function loadUserTemplate(name, baseDir = DEFAULT_BASE_DIR) {
|
|
253
|
-
const filePath = templatePath(name, baseDir);
|
|
254
|
-
if (!fs2.existsSync(filePath)) {
|
|
255
|
-
return null;
|
|
256
|
-
}
|
|
257
|
-
try {
|
|
258
|
-
const raw = fs2.readFileSync(filePath, "utf-8");
|
|
259
|
-
const parsed = parseYaml2(raw);
|
|
260
|
-
if (!parsed || typeof parsed !== "object" || !parsed.name) {
|
|
261
|
-
return null;
|
|
262
|
-
}
|
|
263
|
-
return parsed;
|
|
264
|
-
} catch {
|
|
265
|
-
return null;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
function listUserTemplates(baseDir = DEFAULT_BASE_DIR) {
|
|
269
|
-
if (!fs2.existsSync(baseDir)) {
|
|
270
|
-
return [];
|
|
271
|
-
}
|
|
272
|
-
const files = fs2.readdirSync(baseDir).filter((f) => /\.ya?ml$/i.test(f));
|
|
273
|
-
const templates = [];
|
|
274
|
-
for (const file of files.sort()) {
|
|
275
|
-
try {
|
|
276
|
-
const raw = fs2.readFileSync(path2.join(baseDir, file), "utf-8");
|
|
277
|
-
const parsed = parseYaml2(raw);
|
|
278
|
-
if (parsed && typeof parsed === "object" && parsed.name) {
|
|
279
|
-
templates.push(parsed);
|
|
280
|
-
}
|
|
281
|
-
} catch {
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
return templates;
|
|
285
|
-
}
|
|
286
|
-
function deleteUserTemplate(name, baseDir = DEFAULT_BASE_DIR) {
|
|
287
|
-
const filePath = templatePath(name, baseDir);
|
|
288
|
-
if (!fs2.existsSync(filePath)) {
|
|
289
|
-
return false;
|
|
290
|
-
}
|
|
291
|
-
fs2.unlinkSync(filePath);
|
|
292
|
-
return true;
|
|
293
|
-
}
|
|
294
|
-
function exportUserTemplate(name, baseDir = DEFAULT_BASE_DIR) {
|
|
295
|
-
const filePath = templatePath(name, baseDir);
|
|
296
|
-
if (!fs2.existsSync(filePath)) {
|
|
297
|
-
return null;
|
|
298
|
-
}
|
|
299
|
-
return fs2.readFileSync(filePath, "utf-8");
|
|
300
|
-
}
|
|
301
|
-
function importUserTemplate(yamlContent, baseDir = DEFAULT_BASE_DIR) {
|
|
302
|
-
const parsed = parseYaml2(yamlContent);
|
|
303
|
-
if (!parsed || typeof parsed !== "object") {
|
|
304
|
-
throw new Error("Invalid YAML: expected an object");
|
|
305
|
-
}
|
|
306
|
-
if (!parsed.name || typeof parsed.name !== "string") {
|
|
307
|
-
throw new Error("Invalid template: missing 'name' field");
|
|
308
|
-
}
|
|
309
|
-
validateTemplateName(parsed.name);
|
|
310
|
-
if (!parsed.stack || typeof parsed.stack !== "object") {
|
|
311
|
-
throw new Error("Invalid template: missing 'stack' field");
|
|
312
|
-
}
|
|
313
|
-
if (!parsed.stack.runtime || typeof parsed.stack.runtime !== "string" || parsed.stack.runtime.trim() === "") {
|
|
314
|
-
throw new Error("Invalid template: stack.runtime must be a non-empty string");
|
|
315
|
-
}
|
|
316
|
-
if (parsed.layers !== void 0 && !Array.isArray(parsed.layers)) {
|
|
317
|
-
throw new Error("Invalid template: 'layers' must be an array if present");
|
|
318
|
-
}
|
|
319
|
-
if (!parsed.layers) {
|
|
320
|
-
parsed.layers = [];
|
|
321
|
-
}
|
|
322
|
-
if (!parsed.createdAt) {
|
|
323
|
-
parsed.createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
324
|
-
}
|
|
325
|
-
if (parsed.rules !== void 0 && (typeof parsed.rules !== "object" || parsed.rules === null)) {
|
|
326
|
-
throw new Error("Invalid template: 'rules' must be an object if present");
|
|
327
|
-
}
|
|
328
|
-
if (!parsed.rules) {
|
|
329
|
-
parsed.rules = {
|
|
330
|
-
preconditions: {},
|
|
331
|
-
postconditions: {},
|
|
332
|
-
permissions: {},
|
|
333
|
-
pipelines: {}
|
|
334
|
-
};
|
|
335
|
-
} else {
|
|
336
|
-
const rulesSections = ["preconditions", "postconditions", "permissions", "pipelines"];
|
|
337
|
-
for (const section of rulesSections) {
|
|
338
|
-
const value = parsed.rules[section];
|
|
339
|
-
if (value !== void 0 && (typeof value !== "object" || value === null || Array.isArray(value))) {
|
|
340
|
-
throw new Error(`Invalid template: rules.${section} must be an object if present`);
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
if (!parsed.rules.preconditions) parsed.rules.preconditions = {};
|
|
344
|
-
if (!parsed.rules.postconditions) parsed.rules.postconditions = {};
|
|
345
|
-
if (!parsed.rules.permissions) parsed.rules.permissions = {};
|
|
346
|
-
if (!parsed.rules.pipelines) parsed.rules.pipelines = {};
|
|
347
|
-
}
|
|
348
|
-
if (parsed.skills !== void 0 && !Array.isArray(parsed.skills)) {
|
|
349
|
-
throw new Error("Invalid template: 'skills' must be an array if present");
|
|
350
|
-
}
|
|
351
|
-
if (!parsed.skills) {
|
|
352
|
-
parsed.skills = [];
|
|
353
|
-
}
|
|
354
|
-
saveUserTemplate(parsed, baseDir);
|
|
355
|
-
return parsed;
|
|
356
|
-
}
|
|
357
|
-
function isWithinBase(resolved, base) {
|
|
358
|
-
const normalizedResolved = path3.resolve(resolved);
|
|
359
|
-
const normalizedBase = path3.resolve(base);
|
|
360
|
-
return normalizedResolved.startsWith(normalizedBase + path3.sep) || normalizedResolved === normalizedBase;
|
|
361
|
-
}
|
|
362
|
-
function loadSkillSync(skillPath, projectDir) {
|
|
363
|
-
const projectResolved = path3.resolve(projectDir, skillPath);
|
|
364
|
-
if (isWithinBase(projectResolved, projectDir)) {
|
|
365
|
-
try {
|
|
366
|
-
return fs3.readFileSync(projectResolved, "utf-8");
|
|
367
|
-
} catch {
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
const userResolved = path3.join(USER_SKILLS_DIR, path3.basename(skillPath));
|
|
371
|
-
if (isWithinBase(userResolved, USER_SKILLS_DIR)) {
|
|
372
|
-
try {
|
|
373
|
-
return fs3.readFileSync(userResolved, "utf-8");
|
|
374
|
-
} catch {
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return null;
|
|
378
|
-
}
|
|
379
|
-
function injectSkill(message, skillPath, projectDir) {
|
|
380
|
-
if (!skillPath) return message;
|
|
381
|
-
const skillContent = loadSkillSync(skillPath, projectDir);
|
|
382
|
-
if (!skillContent) return message;
|
|
383
|
-
return `${message}
|
|
384
|
-
|
|
385
|
-
---
|
|
386
|
-
|
|
387
|
-
${skillContent}`;
|
|
388
|
-
}
|
|
389
|
-
var BUNDLED_SKILLS = [
|
|
390
|
-
{
|
|
391
|
-
id: "conventional-commits",
|
|
392
|
-
name: "Conventional Commits",
|
|
393
|
-
description: "Guide for writing conventional commit messages",
|
|
394
|
-
filename: "conventional-commits.md",
|
|
395
|
-
category: "workflow"
|
|
396
|
-
},
|
|
397
|
-
{
|
|
398
|
-
id: "safe-migrations",
|
|
399
|
-
name: "Safe Database Migrations",
|
|
400
|
-
description: "Best practices for writing safe database migrations",
|
|
401
|
-
filename: "safe-migrations.md",
|
|
402
|
-
category: "operations"
|
|
403
|
-
},
|
|
404
|
-
{
|
|
405
|
-
id: "env-management",
|
|
406
|
-
name: "Environment Variable Management",
|
|
407
|
-
description: "Rules for managing environment variables and secrets",
|
|
408
|
-
filename: "env-management.md",
|
|
409
|
-
category: "security"
|
|
410
|
-
},
|
|
411
|
-
{
|
|
412
|
-
id: "error-handling",
|
|
413
|
-
name: "Error Handling",
|
|
414
|
-
description: "Error handling patterns and best practices",
|
|
415
|
-
filename: "error-handling.md",
|
|
416
|
-
category: "quality"
|
|
417
|
-
},
|
|
418
|
-
{
|
|
419
|
-
id: "test-writing",
|
|
420
|
-
name: "Test Writing Guide",
|
|
421
|
-
description: "Guide for writing effective tests",
|
|
422
|
-
filename: "test-writing.md",
|
|
423
|
-
category: "quality"
|
|
424
|
-
},
|
|
425
|
-
{
|
|
426
|
-
id: "code-review-checklist",
|
|
427
|
-
name: "Code Review Checklist",
|
|
428
|
-
description: "Pre-review checklist for code quality",
|
|
429
|
-
filename: "code-review-checklist.md",
|
|
430
|
-
category: "quality"
|
|
431
|
-
}
|
|
432
|
-
];
|
|
433
|
-
function getBundledSkillInfo(id) {
|
|
434
|
-
return BUNDLED_SKILLS.find((s) => s.id === id);
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
export {
|
|
438
|
-
loadBundledTemplates,
|
|
439
|
-
loadTemplates,
|
|
440
|
-
getBundledTemplate,
|
|
441
|
-
composeTemplates,
|
|
442
|
-
resolveTemplate,
|
|
443
|
-
saveUserTemplate,
|
|
444
|
-
loadUserTemplate,
|
|
445
|
-
listUserTemplates,
|
|
446
|
-
deleteUserTemplate,
|
|
447
|
-
exportUserTemplate,
|
|
448
|
-
importUserTemplate,
|
|
449
|
-
loadSkillSync,
|
|
450
|
-
injectSkill,
|
|
451
|
-
BUNDLED_SKILLS,
|
|
452
|
-
getBundledSkillInfo
|
|
453
|
-
};
|