@el-j/magic-agent-helix 4.0.0-beta.7 โ 4.0.0-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +222 -210
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as p from "node:fs";
|
|
3
3
|
import { realpathSync as te, readFileSync as oe } from "node:fs";
|
|
4
|
-
import * as
|
|
4
|
+
import * as f from "node:path";
|
|
5
5
|
import { resolve as ne, dirname as se, join as ie } from "node:path";
|
|
6
6
|
import { fileURLToPath as U } from "node:url";
|
|
7
7
|
import { Command as re } from "commander";
|
|
8
8
|
import t from "picocolors";
|
|
9
|
-
import { loadUserConfig as O, mergeConfigs as
|
|
9
|
+
import { loadUserConfig as O, mergeConfigs as M, PluginRegistry as C, getFormatter as K, validateInstructions as ae } from "@el-j/magic-helix-core";
|
|
10
10
|
import W from "inquirer";
|
|
11
11
|
import j from "ora";
|
|
12
12
|
import q from "gradient-string";
|
|
@@ -14,13 +14,13 @@ import { glob as ce } from "glob";
|
|
|
14
14
|
async function le() {
|
|
15
15
|
console.log(t.cyan(`๐งน Cleaning generated instruction files...
|
|
16
16
|
`));
|
|
17
|
-
const e = j("Loading configuration...").start(), n = O(), s =
|
|
17
|
+
const e = j("Loading configuration...").start(), n = O(), s = M(n);
|
|
18
18
|
e.succeed("Configuration loaded.");
|
|
19
|
-
const
|
|
19
|
+
const a = f.resolve(
|
|
20
20
|
process.cwd(),
|
|
21
21
|
s.outputDirectory
|
|
22
22
|
);
|
|
23
|
-
if (!p.existsSync(
|
|
23
|
+
if (!p.existsSync(a)) {
|
|
24
24
|
console.log(
|
|
25
25
|
t.yellow(
|
|
26
26
|
`โ ๏ธ Output directory ${s.outputDirectory} does not exist. Nothing to clean.`
|
|
@@ -28,16 +28,16 @@ async function le() {
|
|
|
28
28
|
);
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
-
const
|
|
32
|
-
if (
|
|
31
|
+
const i = p.readdirSync(a).filter((g) => g.endsWith(".md"));
|
|
32
|
+
if (i.length === 0) {
|
|
33
33
|
console.log(t.gray("No instruction files found. Nothing to clean."));
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
36
36
|
console.log(
|
|
37
|
-
t.yellow(`Found ${
|
|
37
|
+
t.yellow(`Found ${i.length} instruction file(s) to delete:
|
|
38
38
|
`)
|
|
39
39
|
);
|
|
40
|
-
for (const g of
|
|
40
|
+
for (const g of i)
|
|
41
41
|
console.log(t.gray(` - ${g}`));
|
|
42
42
|
console.log();
|
|
43
43
|
const { confirm: o } = await W.prompt([
|
|
@@ -45,7 +45,7 @@ async function le() {
|
|
|
45
45
|
type: "confirm",
|
|
46
46
|
name: "confirm",
|
|
47
47
|
message: t.red(
|
|
48
|
-
`Are you sure you want to delete all ${
|
|
48
|
+
`Are you sure you want to delete all ${i.length} file(s)?`
|
|
49
49
|
),
|
|
50
50
|
default: !1
|
|
51
51
|
}
|
|
@@ -54,21 +54,21 @@ async function le() {
|
|
|
54
54
|
console.log(t.yellow("Clean cancelled."));
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
57
|
-
const
|
|
58
|
-
let
|
|
59
|
-
for (const g of
|
|
57
|
+
const r = j("Deleting files...").start();
|
|
58
|
+
let c = 0, l = 0;
|
|
59
|
+
for (const g of i)
|
|
60
60
|
try {
|
|
61
|
-
p.unlinkSync(
|
|
61
|
+
p.unlinkSync(f.join(a, g)), c++;
|
|
62
62
|
} catch (u) {
|
|
63
63
|
console.error(
|
|
64
64
|
t.red(` โ Error deleting ${g}: ${u.message}`)
|
|
65
65
|
), l++;
|
|
66
66
|
}
|
|
67
|
-
l === 0 ?
|
|
68
|
-
t.green(`โ
Successfully deleted ${
|
|
69
|
-
) :
|
|
67
|
+
l === 0 ? r.succeed(
|
|
68
|
+
t.green(`โ
Successfully deleted ${c} file(s).`)
|
|
69
|
+
) : r.warn(
|
|
70
70
|
t.yellow(
|
|
71
|
-
`โ ๏ธ Deleted ${
|
|
71
|
+
`โ ๏ธ Deleted ${c} file(s), ${l} error(s) occurred.`
|
|
72
72
|
)
|
|
73
73
|
);
|
|
74
74
|
}
|
|
@@ -94,10 +94,10 @@ const _ = "magic-helix.config.json", I = "ai_templates", ge = {
|
|
|
94
94
|
async function ue() {
|
|
95
95
|
const e = j(
|
|
96
96
|
t.bold("Initializing Magic Helix for custom rules...")
|
|
97
|
-
).start(), n =
|
|
97
|
+
).start(), n = f.resolve(process.cwd(), _), s = f.resolve(process.cwd(), I);
|
|
98
98
|
if (p.existsSync(n)) {
|
|
99
99
|
e.stop();
|
|
100
|
-
const { overwrite:
|
|
100
|
+
const { overwrite: i } = await W.prompt([
|
|
101
101
|
{
|
|
102
102
|
type: "confirm",
|
|
103
103
|
name: "overwrite",
|
|
@@ -105,7 +105,7 @@ async function ue() {
|
|
|
105
105
|
default: !1
|
|
106
106
|
}
|
|
107
107
|
]);
|
|
108
|
-
if (!
|
|
108
|
+
if (!i) {
|
|
109
109
|
e.warn(t.yellow("Operation cancelled."));
|
|
110
110
|
return;
|
|
111
111
|
}
|
|
@@ -119,18 +119,18 @@ async function ue() {
|
|
|
119
119
|
), e.succeed(
|
|
120
120
|
t.green(`Created minimal config file: ${t.bold(_)}`)
|
|
121
121
|
);
|
|
122
|
-
} catch (
|
|
123
|
-
e.fail(t.red(`Error writing config file: ${
|
|
122
|
+
} catch (i) {
|
|
123
|
+
e.fail(t.red(`Error writing config file: ${i.message}`));
|
|
124
124
|
return;
|
|
125
125
|
}
|
|
126
126
|
e.start("Creating templates directory..."), p.existsSync(s) || p.mkdirSync(s, { recursive: !0 });
|
|
127
|
-
const
|
|
128
|
-
p.existsSync(
|
|
127
|
+
const a = f.resolve(s, "my-custom-rule.md");
|
|
128
|
+
p.existsSync(a) ? e.succeed(
|
|
129
129
|
t.green(
|
|
130
130
|
`Templates directory ${t.bold(I)} already exists.`
|
|
131
131
|
)
|
|
132
132
|
) : (p.writeFileSync(
|
|
133
|
-
|
|
133
|
+
a,
|
|
134
134
|
`# My Team's Custom Rule
|
|
135
135
|
- This rule is specific to our "domain-my-rules" tag.
|
|
136
136
|
- ALWAYS follow this important pattern.
|
|
@@ -157,20 +157,20 @@ Next steps:`)), console.log(
|
|
|
157
157
|
async function de() {
|
|
158
158
|
console.log(t.cyan(`๐ Listing project information...
|
|
159
159
|
`));
|
|
160
|
-
const e = j("Loading configuration...").start(), n = O(), s =
|
|
160
|
+
const e = j("Loading configuration...").start(), n = O(), s = M(n);
|
|
161
161
|
e.succeed("Configuration loaded.");
|
|
162
|
-
const { dependencyTagMap:
|
|
162
|
+
const { dependencyTagMap: a, configFileTagMap: i, fileGlobTagMap: o, tagTemplateMap: r } = s, c = j("Scanning for projects...").start(), l = await fe();
|
|
163
163
|
if (l.length === 0) {
|
|
164
|
-
|
|
164
|
+
c.warn(t.yellow("No projects found."));
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
|
-
|
|
167
|
+
c.succeed(`Found ${l.length} projects.`);
|
|
168
168
|
const g = j("Analyzing projects...").start();
|
|
169
169
|
for (const u of l)
|
|
170
170
|
await pe(
|
|
171
171
|
u,
|
|
172
|
-
r,
|
|
173
172
|
a,
|
|
173
|
+
i,
|
|
174
174
|
o
|
|
175
175
|
);
|
|
176
176
|
g.succeed(`Analysis complete.
|
|
@@ -183,7 +183,7 @@ async function de() {
|
|
|
183
183
|
console.log(t.green(` Tags: ${[...u.tags].join(", ")}`));
|
|
184
184
|
const h = [];
|
|
185
185
|
for (const w of u.tags) {
|
|
186
|
-
const m =
|
|
186
|
+
const m = r[w];
|
|
187
187
|
if (m)
|
|
188
188
|
for (const v of m)
|
|
189
189
|
h.push(`${u.name}.${v.suffix}`);
|
|
@@ -198,25 +198,25 @@ async function de() {
|
|
|
198
198
|
async function fe() {
|
|
199
199
|
const e = [], n = process.cwd(), s = C.getInstance();
|
|
200
200
|
await s.initialize();
|
|
201
|
-
const
|
|
202
|
-
if (
|
|
201
|
+
const i = (await s.detectAllProjects(n)).map((o) => o.metadata);
|
|
202
|
+
if (i.length === 0)
|
|
203
203
|
return [];
|
|
204
|
-
for (const o of
|
|
205
|
-
const
|
|
204
|
+
for (const o of i) {
|
|
205
|
+
const r = f.relative(n, o.projectPath);
|
|
206
206
|
e.push({
|
|
207
|
-
name: o.name ||
|
|
208
|
-
path:
|
|
207
|
+
name: o.name || f.basename(o.projectPath),
|
|
208
|
+
path: r || ".",
|
|
209
209
|
tags: /* @__PURE__ */ new Set()
|
|
210
210
|
});
|
|
211
211
|
}
|
|
212
212
|
return e;
|
|
213
213
|
}
|
|
214
|
-
async function pe(e, n, s,
|
|
215
|
-
const
|
|
214
|
+
async function pe(e, n, s, a) {
|
|
215
|
+
const i = f.resolve(process.cwd(), e.path);
|
|
216
216
|
try {
|
|
217
|
-
const
|
|
218
|
-
if (
|
|
219
|
-
const l =
|
|
217
|
+
const c = (await C.getInstance().detectAllProjects(i)).map((l) => l.metadata);
|
|
218
|
+
if (c.length > 0) {
|
|
219
|
+
const l = c[0];
|
|
220
220
|
if (l.tags?.length)
|
|
221
221
|
for (const g of l.tags)
|
|
222
222
|
e.tags.add(g);
|
|
@@ -230,20 +230,20 @@ async function pe(e, n, s, r) {
|
|
|
230
230
|
}
|
|
231
231
|
try {
|
|
232
232
|
for (const o in s) {
|
|
233
|
-
const
|
|
234
|
-
p.existsSync(
|
|
233
|
+
const r = s[o], c = f.join(i, o);
|
|
234
|
+
p.existsSync(c) && e.tags.add(r);
|
|
235
235
|
}
|
|
236
236
|
} catch {
|
|
237
237
|
}
|
|
238
238
|
try {
|
|
239
239
|
const { glob: o } = await import("glob");
|
|
240
|
-
for (const
|
|
241
|
-
const
|
|
242
|
-
(await o(
|
|
243
|
-
cwd:
|
|
240
|
+
for (const r in a) {
|
|
241
|
+
const c = a[r];
|
|
242
|
+
(await o(r, {
|
|
243
|
+
cwd: i,
|
|
244
244
|
nodir: !0,
|
|
245
245
|
dot: !0
|
|
246
|
-
})).length > 0 && e.tags.add(
|
|
246
|
+
})).length > 0 && e.tags.add(c);
|
|
247
247
|
}
|
|
248
248
|
} catch {
|
|
249
249
|
}
|
|
@@ -253,22 +253,22 @@ async function me(e = {}) {
|
|
|
253
253
|
try {
|
|
254
254
|
const n = C.getInstance();
|
|
255
255
|
await n.initialize({ verbose: e.verbose });
|
|
256
|
-
const s = await n.getAllPlugins(),
|
|
256
|
+
const s = await n.getAllPlugins(), a = n.getStatistics();
|
|
257
257
|
if (s.length === 0) {
|
|
258
258
|
console.log(t.yellow("โ ๏ธ No plugins loaded"));
|
|
259
259
|
return;
|
|
260
260
|
}
|
|
261
261
|
console.log(t.green(`โ
${s.length} plugin(s) loaded successfully`)), console.log();
|
|
262
|
-
const
|
|
262
|
+
const i = s.sort((o, r) => r.priority - o.priority);
|
|
263
263
|
console.log(t.bold("Available Language Plugins:")), console.log("โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
|
|
264
|
-
for (const o of
|
|
265
|
-
const
|
|
264
|
+
for (const o of i) {
|
|
265
|
+
const r = o.priority >= 90 ? "green" : o.priority >= 70 ? "yellow" : "cyan";
|
|
266
266
|
if (console.log(
|
|
267
|
-
`${t.bold(o.displayName)} (${t[
|
|
267
|
+
`${t.bold(o.displayName)} (${t[r](`priority: ${o.priority}`)}) v${o.version}`
|
|
268
268
|
), e.verbose) {
|
|
269
|
-
const
|
|
270
|
-
|
|
271
|
-
` ๐ Templates: ${
|
|
269
|
+
const c = o.getTemplates();
|
|
270
|
+
c.length > 0 && console.log(
|
|
271
|
+
` ๐ Templates: ${c.map((g) => g.name).join(", ")}`
|
|
272
272
|
);
|
|
273
273
|
const l = o.getDependencyTagMap?.();
|
|
274
274
|
l && Object.keys(l).length > 0 && console.log(
|
|
@@ -276,11 +276,11 @@ async function me(e = {}) {
|
|
|
276
276
|
), console.log();
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
-
if (e.verbose || (console.log(), console.log(t.dim("๐ก Use --verbose for detailed plugin information"))), console.log(), console.log(t.bold("System Statistics:")), console.log("โโโโโโโโโโโโโโโโโโ"), console.log(`๐ Total plugins: ${
|
|
279
|
+
if (e.verbose || (console.log(), console.log(t.dim("๐ก Use --verbose for detailed plugin information"))), console.log(), console.log(t.bold("System Statistics:")), console.log("โโโโโโโโโโโโโโโโโโ"), console.log(`๐ Total plugins: ${a.totalLoaded}`), console.log(`โก Average load time: ${a.averageLoadTime.toFixed(1)}ms`), console.log(`โ Load errors: ${a.totalErrors}`), a.totalErrors > 0 && e.verbose) {
|
|
280
280
|
const o = n.getLoadErrors();
|
|
281
281
|
console.log(), console.log(t.red("Load Errors:")), console.log("โโโโโโโโโโโโ");
|
|
282
|
-
for (const
|
|
283
|
-
console.log(`โ ${
|
|
282
|
+
for (const r of o)
|
|
283
|
+
console.log(`โ ${r.source.identifier}: ${r.error.message}`);
|
|
284
284
|
}
|
|
285
285
|
} catch (n) {
|
|
286
286
|
console.error(
|
|
@@ -432,21 +432,21 @@ const ye = {
|
|
|
432
432
|
function he(e) {
|
|
433
433
|
return ye[e]?.extensions || [];
|
|
434
434
|
}
|
|
435
|
-
function
|
|
436
|
-
const
|
|
437
|
-
for (const
|
|
438
|
-
const
|
|
439
|
-
for (const l of
|
|
440
|
-
|
|
435
|
+
function Y(e, n, s) {
|
|
436
|
+
const a = /* @__PURE__ */ new Set();
|
|
437
|
+
for (const r of n) {
|
|
438
|
+
const c = he(r);
|
|
439
|
+
for (const l of c)
|
|
440
|
+
a.add(l);
|
|
441
441
|
}
|
|
442
|
-
if (
|
|
442
|
+
if (a.size === 0)
|
|
443
443
|
return `${e}/src/**/*.{ts,js,vue,tsx,jsx}`;
|
|
444
|
-
const
|
|
445
|
-
let o = `${e}/src/**/*.{${
|
|
444
|
+
const i = Array.from(a).join(",");
|
|
445
|
+
let o = `${e}/src/**/*.{${i}}`;
|
|
446
446
|
if (s) {
|
|
447
|
-
const
|
|
448
|
-
for (const
|
|
449
|
-
|
|
447
|
+
const r = s.split(",").map((c) => c.trim());
|
|
448
|
+
for (const c of r)
|
|
449
|
+
c.endsWith("/**") ? o += ` !(${e}/src/${c})` : c.includes("*") ? o += ` !(${e}/src/${c})` : o += ` !(${e}/src/${c})`;
|
|
450
450
|
}
|
|
451
451
|
return o;
|
|
452
452
|
}
|
|
@@ -458,19 +458,19 @@ function $(e, n) {
|
|
|
458
458
|
}
|
|
459
459
|
async function we(e = {}) {
|
|
460
460
|
Q(e);
|
|
461
|
-
const n = j("Loading configurations...").start(), s = O(e.config),
|
|
462
|
-
e.target && (
|
|
463
|
-
const { dependencyTagMap:
|
|
461
|
+
const n = j("Loading configurations...").start(), s = O(e.config), a = M(s);
|
|
462
|
+
e.target && (a.target = e.target), n.succeed("Configuration loaded.");
|
|
463
|
+
const { dependencyTagMap: i, configFileTagMap: o, fileGlobTagMap: r, tagTemplateMap: c } = a, l = f.resolve(
|
|
464
464
|
process.cwd(),
|
|
465
|
-
|
|
466
|
-
), g =
|
|
465
|
+
a.templateDirectory
|
|
466
|
+
), g = f.resolve(
|
|
467
467
|
process.cwd(),
|
|
468
|
-
|
|
469
|
-
), u =
|
|
468
|
+
a.outputDirectory
|
|
469
|
+
), u = K(a.target);
|
|
470
470
|
if (!p.existsSync(g)) {
|
|
471
471
|
console.log(
|
|
472
472
|
t.yellow(
|
|
473
|
-
`โ ๏ธ Output directory ${
|
|
473
|
+
`โ ๏ธ Output directory ${a.outputDirectory} does not exist.`
|
|
474
474
|
)
|
|
475
475
|
), console.log(
|
|
476
476
|
t.gray(" Run 'magic-helix run' first to generate instruction files.")
|
|
@@ -492,13 +492,13 @@ async function we(e = {}) {
|
|
|
492
492
|
for (const y of w)
|
|
493
493
|
await je(
|
|
494
494
|
y,
|
|
495
|
-
|
|
495
|
+
i,
|
|
496
496
|
o,
|
|
497
|
-
|
|
497
|
+
r
|
|
498
498
|
), v += y.tags.size;
|
|
499
499
|
m.succeed(`Project analysis complete. Found ${v} tags.`), console.log(
|
|
500
500
|
t.cyan(`
|
|
501
|
-
Refreshing instruction files in ${
|
|
501
|
+
Refreshing instruction files in ${a.outputDirectory}...`)
|
|
502
502
|
);
|
|
503
503
|
let D = 0, N = 0;
|
|
504
504
|
for (const y of w) {
|
|
@@ -507,25 +507,25 @@ Refreshing instruction files in ${r.outputDirectory}...`)
|
|
|
507
507
|
continue;
|
|
508
508
|
}
|
|
509
509
|
console.log(t.bold(` Processing: ${y.name}`)), console.log(t.gray(` Tags: ${[...y.tags].join(", ")}`));
|
|
510
|
-
const z =
|
|
510
|
+
const z = Y(y.path, y.tags);
|
|
511
511
|
for (const S of y.tags) {
|
|
512
|
-
const
|
|
513
|
-
if (
|
|
514
|
-
for (const P of
|
|
515
|
-
const T = `${y.name}.${P.suffix}`, F =
|
|
512
|
+
const L = c[S];
|
|
513
|
+
if (L)
|
|
514
|
+
for (const P of L) {
|
|
515
|
+
const T = `${y.name}.${P.suffix}`, F = f.join(g, T);
|
|
516
516
|
if (!p.existsSync(F)) {
|
|
517
517
|
console.log(
|
|
518
518
|
t.yellow(` โ ๏ธ File not found, skipping: ${T}`)
|
|
519
519
|
);
|
|
520
520
|
continue;
|
|
521
521
|
}
|
|
522
|
-
const
|
|
523
|
-
if (!
|
|
522
|
+
const d = xe(l, P.template), x = "Custom";
|
|
523
|
+
if (!d) {
|
|
524
524
|
console.warn(t.yellow(` โ ๏ธ Template not found: ${P.template}`));
|
|
525
525
|
continue;
|
|
526
526
|
}
|
|
527
527
|
const R = u.getFrontmatter(z, y.name), k = u.format(
|
|
528
|
-
|
|
528
|
+
d,
|
|
529
529
|
z,
|
|
530
530
|
y.name
|
|
531
531
|
), b = `${R}
|
|
@@ -544,25 +544,25 @@ ${k}`;
|
|
|
544
544
|
async function $e() {
|
|
545
545
|
const e = [], n = process.cwd(), s = C.getInstance();
|
|
546
546
|
await s.initialize();
|
|
547
|
-
const
|
|
548
|
-
if (
|
|
547
|
+
const i = (await s.detectAllProjects(n)).map((o) => o.metadata);
|
|
548
|
+
if (i.length === 0)
|
|
549
549
|
return [];
|
|
550
|
-
for (const o of
|
|
551
|
-
const
|
|
550
|
+
for (const o of i) {
|
|
551
|
+
const r = f.relative(n, o.projectPath);
|
|
552
552
|
e.push({
|
|
553
|
-
name: o.name ||
|
|
554
|
-
path:
|
|
553
|
+
name: o.name || f.basename(o.projectPath),
|
|
554
|
+
path: r || ".",
|
|
555
555
|
tags: /* @__PURE__ */ new Set()
|
|
556
556
|
});
|
|
557
557
|
}
|
|
558
558
|
return e;
|
|
559
559
|
}
|
|
560
|
-
async function je(e, n, s,
|
|
561
|
-
const
|
|
560
|
+
async function je(e, n, s, a) {
|
|
561
|
+
const i = f.resolve(process.cwd(), e.path);
|
|
562
562
|
try {
|
|
563
|
-
const
|
|
564
|
-
if (
|
|
565
|
-
const l =
|
|
563
|
+
const c = (await C.getInstance().detectAllProjects(i)).map((l) => l.metadata);
|
|
564
|
+
if (c.length > 0) {
|
|
565
|
+
const l = c[0];
|
|
566
566
|
if (l.tags?.length)
|
|
567
567
|
for (const g of l.tags)
|
|
568
568
|
e.tags.add(g);
|
|
@@ -581,8 +581,8 @@ async function je(e, n, s, r) {
|
|
|
581
581
|
}
|
|
582
582
|
try {
|
|
583
583
|
for (const o in s) {
|
|
584
|
-
const
|
|
585
|
-
p.existsSync(
|
|
584
|
+
const r = s[o], c = f.join(i, o);
|
|
585
|
+
p.existsSync(c) && e.tags.add(r);
|
|
586
586
|
}
|
|
587
587
|
} catch (o) {
|
|
588
588
|
console.warn(
|
|
@@ -593,13 +593,13 @@ async function je(e, n, s, r) {
|
|
|
593
593
|
}
|
|
594
594
|
try {
|
|
595
595
|
const { glob: o } = await import("glob");
|
|
596
|
-
for (const
|
|
597
|
-
const
|
|
598
|
-
(await o(
|
|
599
|
-
cwd:
|
|
596
|
+
for (const r in a) {
|
|
597
|
+
const c = a[r];
|
|
598
|
+
(await o(r, {
|
|
599
|
+
cwd: i,
|
|
600
600
|
nodir: !0,
|
|
601
601
|
dot: !0
|
|
602
|
-
})).length > 0 && e.tags.add(
|
|
602
|
+
})).length > 0 && e.tags.add(c);
|
|
603
603
|
}
|
|
604
604
|
} catch (o) {
|
|
605
605
|
console.warn(
|
|
@@ -610,7 +610,7 @@ async function je(e, n, s, r) {
|
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
612
|
function xe(e, n) {
|
|
613
|
-
const s =
|
|
613
|
+
const s = f.join(e, n);
|
|
614
614
|
try {
|
|
615
615
|
return p.readFileSync(s, "utf-8");
|
|
616
616
|
} catch {
|
|
@@ -682,15 +682,15 @@ async function J(e = {}) {
|
|
|
682
682
|
q.pastel.multiline("๐ค Running AI Convention Aligner...")
|
|
683
683
|
), n.dryRun && $("normal", s) && console.log(t.yellow(`๐ DRY RUN MODE - No files will be written
|
|
684
684
|
`));
|
|
685
|
-
const
|
|
686
|
-
n.outputDir && (o.outputDirectory = n.outputDir), n.target && (o.target = n.target),
|
|
687
|
-
const { dependencyTagMap:
|
|
685
|
+
const a = j("Loading configurations...").start(), i = O(n.config), o = M(i);
|
|
686
|
+
n.outputDir && (o.outputDirectory = n.outputDir), n.target && (o.target = n.target), a.succeed("Configuration loaded.");
|
|
687
|
+
const { dependencyTagMap: r, configFileTagMap: c, fileGlobTagMap: l, tagTemplateMap: g } = o, u = f.resolve(
|
|
688
688
|
process.cwd(),
|
|
689
689
|
o.templateDirectory
|
|
690
|
-
), h =
|
|
690
|
+
), h = f.resolve(
|
|
691
691
|
process.cwd(),
|
|
692
692
|
o.outputDirectory
|
|
693
|
-
), w =
|
|
693
|
+
), w = K(o.target), m = j("Scanning for projects...").start(), v = await Pe();
|
|
694
694
|
if (v.length === 0) {
|
|
695
695
|
m.warn(
|
|
696
696
|
t.yellow(
|
|
@@ -715,25 +715,25 @@ Supported project types: Node.js, Python, Go, Rust, Java, Ruby, PHP, C#, Swift,
|
|
|
715
715
|
m.succeed(`Found ${v.length} projects.`);
|
|
716
716
|
const D = j("Analyzing project tags...").start();
|
|
717
717
|
let N = 0;
|
|
718
|
-
for (const
|
|
719
|
-
if (n.project &&
|
|
720
|
-
$("verbose", s) && console.log(t.gray(`Skipping ${
|
|
718
|
+
for (const d of v) {
|
|
719
|
+
if (n.project && d.name !== n.project) {
|
|
720
|
+
$("verbose", s) && console.log(t.gray(`Skipping ${d.name} (not target project)`));
|
|
721
721
|
continue;
|
|
722
722
|
}
|
|
723
723
|
await Te(
|
|
724
|
-
|
|
724
|
+
d,
|
|
725
|
+
r,
|
|
725
726
|
c,
|
|
726
|
-
i,
|
|
727
727
|
l
|
|
728
|
-
), N +=
|
|
728
|
+
), N += d.tags.size;
|
|
729
729
|
}
|
|
730
730
|
D.succeed(`Project analysis complete. Found ${N} tags.`), n.dryRun ? $("verbose", s) && console.log(t.gray(`Would ensure directory: ${h}`)) : be(h);
|
|
731
731
|
let y = g;
|
|
732
732
|
if (n.template) {
|
|
733
|
-
const
|
|
733
|
+
const d = n.template.split(",").map((x) => x.trim());
|
|
734
734
|
y = {};
|
|
735
735
|
for (const [x, R] of Object.entries(g)) {
|
|
736
|
-
const k = R.filter((b) =>
|
|
736
|
+
const k = R.filter((b) => d.some((A) => {
|
|
737
737
|
if (A.includes("*")) {
|
|
738
738
|
const E = new RegExp(A.replace(/\*/g, ".*"));
|
|
739
739
|
return E.test(b.template) || E.test(x);
|
|
@@ -747,13 +747,13 @@ Supported project types: Node.js, Python, Go, Rust, Java, Ruby, PHP, C#, Swift,
|
|
|
747
747
|
);
|
|
748
748
|
}
|
|
749
749
|
const z = await Se(), S = {};
|
|
750
|
-
for (const [
|
|
751
|
-
S[
|
|
750
|
+
for (const [d, x] of Object.entries(y))
|
|
751
|
+
S[d] = x.map((R) => ({
|
|
752
752
|
template: R.template,
|
|
753
753
|
suffix: R.suffix
|
|
754
754
|
}));
|
|
755
|
-
for (const [
|
|
756
|
-
S[
|
|
755
|
+
for (const [d, x] of Object.entries(z))
|
|
756
|
+
S[d] || (S[d] = []), S[d].push(...x);
|
|
757
757
|
$("verbose", s) && (console.log(t.gray(`
|
|
758
758
|
--- Template Map Debug ---`)), console.log(
|
|
759
759
|
t.gray(
|
|
@@ -777,22 +777,22 @@ Supported project types: Node.js, Python, Go, Rust, Java, Ruby, PHP, C#, Swift,
|
|
|
777
777
|
t.cyan(`
|
|
778
778
|
Generating instruction files in ${o.outputDirectory}...`)
|
|
779
779
|
);
|
|
780
|
-
const
|
|
780
|
+
const L = j("Generating instruction files...").start(), P = [];
|
|
781
781
|
let T = 0, F = 0;
|
|
782
|
-
for (const
|
|
783
|
-
if (n.project &&
|
|
782
|
+
for (const d of v) {
|
|
783
|
+
if (n.project && d.name !== n.project)
|
|
784
784
|
continue;
|
|
785
|
-
if (
|
|
786
|
-
$("normal", s) && console.log(t.gray(` Skipping: ${
|
|
785
|
+
if (d.tags.size === 0) {
|
|
786
|
+
$("normal", s) && console.log(t.gray(` Skipping: ${d.name} (No matching tags)`));
|
|
787
787
|
continue;
|
|
788
788
|
}
|
|
789
|
-
T++, $("normal", s) && console.log(t.bold(` Processing: ${
|
|
790
|
-
const x =
|
|
791
|
-
|
|
792
|
-
|
|
789
|
+
T++, $("normal", s) && console.log(t.bold(` Processing: ${d.name}`)), $("verbose", s) && console.log(t.gray(` Tags: ${[...d.tags].join(", ")}`));
|
|
790
|
+
const x = Y(
|
|
791
|
+
d.path,
|
|
792
|
+
d.tags,
|
|
793
793
|
n.exclude
|
|
794
794
|
);
|
|
795
|
-
for (const R of
|
|
795
|
+
for (const R of d.tags) {
|
|
796
796
|
const k = S[R];
|
|
797
797
|
if (k)
|
|
798
798
|
for (const b of k) {
|
|
@@ -802,12 +802,12 @@ Generating instruction files in ${o.outputDirectory}...`)
|
|
|
802
802
|
console.warn(t.yellow(` โ ๏ธ Template not found: ${b.template}`));
|
|
803
803
|
continue;
|
|
804
804
|
}
|
|
805
|
-
const B = w.getFrontmatter(x,
|
|
805
|
+
const B = w.getFrontmatter(x, d.name), X = w.format(
|
|
806
806
|
A,
|
|
807
807
|
x,
|
|
808
|
-
|
|
808
|
+
d.name
|
|
809
809
|
), Z = `${B}
|
|
810
|
-
${X}`, G = b.suffix
|
|
810
|
+
${X}`, G = `${v.length > 1 ? `${d.name.replace(/[@/]/g, "-")}.` : ""}${b.suffix}`, ee = f.join(h, G);
|
|
811
811
|
P.push(G), n.dryRun ? $("normal", s) && console.log(
|
|
812
812
|
t.cyan(
|
|
813
813
|
` ๐ Would generate: ${t.bold(G)} (from ${E})`
|
|
@@ -820,7 +820,7 @@ ${X}`, G = b.suffix, ee = d.join(h, G);
|
|
|
820
820
|
}
|
|
821
821
|
}
|
|
822
822
|
}
|
|
823
|
-
|
|
823
|
+
L.succeed(
|
|
824
824
|
`Generated ${P.length} files from ${F} templates across ${T} projects`
|
|
825
825
|
), !n.dryRun && !n.skipPruning ? await Fe(h, P, n.force) : n.dryRun && $("verbose", s) && console.log(t.gray(`
|
|
826
826
|
Would check for old files to prune...`)), $("normal", s) && (console.log(`
|
|
@@ -877,9 +877,9 @@ async function Se() {
|
|
|
877
877
|
let n = [];
|
|
878
878
|
try {
|
|
879
879
|
n = await e.getAllPlugins();
|
|
880
|
-
} catch (
|
|
880
|
+
} catch (a) {
|
|
881
881
|
console.warn(
|
|
882
|
-
t.yellow(`โ ๏ธ Failed to get plugins: ${
|
|
882
|
+
t.yellow(`โ ๏ธ Failed to get plugins: ${a.message}`)
|
|
883
883
|
), console.warn(
|
|
884
884
|
t.yellow(
|
|
885
885
|
`โ ๏ธ Registry type: ${typeof e}, has getAllPlugins: ${typeof e?.getAllPlugins}`
|
|
@@ -888,35 +888,35 @@ async function Se() {
|
|
|
888
888
|
}
|
|
889
889
|
n.length === 0 && console.warn(t.yellow("โ ๏ธ No plugins loaded from registry!"));
|
|
890
890
|
const s = {};
|
|
891
|
-
for (const
|
|
892
|
-
let
|
|
891
|
+
for (const a of n) {
|
|
892
|
+
let i = [];
|
|
893
893
|
try {
|
|
894
|
-
const o = await
|
|
895
|
-
|
|
894
|
+
const o = await a.getTemplates();
|
|
895
|
+
i = Array.isArray(o) ? o : [];
|
|
896
896
|
} catch (o) {
|
|
897
897
|
console.warn(
|
|
898
898
|
t.yellow(
|
|
899
|
-
`โ ๏ธ Plugin ${
|
|
899
|
+
`โ ๏ธ Plugin ${a.name} getTemplates failed: ${o.message}`
|
|
900
900
|
)
|
|
901
901
|
);
|
|
902
902
|
continue;
|
|
903
903
|
}
|
|
904
|
-
for (const o of
|
|
905
|
-
const
|
|
904
|
+
for (const o of i) {
|
|
905
|
+
const c = `${o.name.replace(/^lang-/, "").replace(/-core$/, "")}.instructions.md`;
|
|
906
906
|
let l = null;
|
|
907
907
|
try {
|
|
908
908
|
l = typeof o.content == "function" ? await o.content() : o.content;
|
|
909
909
|
} catch (g) {
|
|
910
910
|
console.warn(
|
|
911
911
|
t.yellow(
|
|
912
|
-
`โ ๏ธ Plugin ${
|
|
912
|
+
`โ ๏ธ Plugin ${a.name} template ${o.name} failed to load: ${g.message}`
|
|
913
913
|
)
|
|
914
914
|
);
|
|
915
915
|
}
|
|
916
916
|
for (const g of o.tags)
|
|
917
917
|
s[g] || (s[g] = []), s[g].push({
|
|
918
|
-
template: `plugin:${
|
|
919
|
-
suffix:
|
|
918
|
+
template: `plugin:${a.name}/${o.name}`,
|
|
919
|
+
suffix: c,
|
|
920
920
|
inlineContent: l ?? void 0
|
|
921
921
|
});
|
|
922
922
|
}
|
|
@@ -925,39 +925,51 @@ async function Se() {
|
|
|
925
925
|
}
|
|
926
926
|
async function Pe() {
|
|
927
927
|
await H();
|
|
928
|
-
const e =
|
|
929
|
-
if (
|
|
928
|
+
const e = process.cwd(), s = await C.getInstance().detectAllProjects(e);
|
|
929
|
+
if (s.length === 0)
|
|
930
930
|
return [];
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
e.
|
|
931
|
+
const a = /* @__PURE__ */ new Map();
|
|
932
|
+
for (const i of s) {
|
|
933
|
+
const r = f.relative(e, i.metadata.projectPath) || ".";
|
|
934
|
+
a.has(r) || a.set(r, {
|
|
934
935
|
name: Ce(
|
|
935
|
-
|
|
936
|
+
i.metadata.name || f.basename(i.metadata.projectPath)
|
|
936
937
|
),
|
|
937
|
-
path:
|
|
938
|
-
tags: /* @__PURE__ */ new Set()
|
|
938
|
+
path: r,
|
|
939
|
+
tags: /* @__PURE__ */ new Set(),
|
|
940
|
+
allMetadata: []
|
|
939
941
|
});
|
|
942
|
+
const c = a.get(r);
|
|
943
|
+
if (c.allMetadata.push(i.metadata), i.metadata.tags?.length)
|
|
944
|
+
for (const l of i.metadata.tags)
|
|
945
|
+
c.tags.add(l);
|
|
940
946
|
}
|
|
941
|
-
return
|
|
947
|
+
return Array.from(a.values()).map(
|
|
948
|
+
({ name: i, path: o, tags: r }) => ({
|
|
949
|
+
name: i,
|
|
950
|
+
path: o,
|
|
951
|
+
tags: r
|
|
952
|
+
})
|
|
953
|
+
);
|
|
942
954
|
}
|
|
943
955
|
function Ce(e) {
|
|
944
956
|
let s = e.trim().replace(/^@/, "").replace(/[\\/\s]+/g, "-");
|
|
945
957
|
return s = s.replace(/-+/g, "-"), s;
|
|
946
958
|
}
|
|
947
|
-
async function Te(e, n, s,
|
|
959
|
+
async function Te(e, n, s, a) {
|
|
948
960
|
await H();
|
|
949
|
-
const
|
|
961
|
+
const i = f.resolve(process.cwd(), e.path);
|
|
950
962
|
try {
|
|
951
|
-
const
|
|
952
|
-
|
|
953
|
-
const
|
|
954
|
-
if (
|
|
955
|
-
for (const
|
|
956
|
-
e.tags.add(
|
|
957
|
-
for (const
|
|
958
|
-
n[
|
|
959
|
-
const
|
|
960
|
-
|
|
963
|
+
const r = await C.getInstance().detectAllProjects(i);
|
|
964
|
+
for (const c of r) {
|
|
965
|
+
const l = c.metadata;
|
|
966
|
+
if (l.tags?.length)
|
|
967
|
+
for (const g of l.tags)
|
|
968
|
+
e.tags.add(g);
|
|
969
|
+
for (const g in l.dependencies) {
|
|
970
|
+
n[g] && e.tags.add(n[g]);
|
|
971
|
+
const u = g.split(/[@/:]/g).pop();
|
|
972
|
+
u && n[u] && e.tags.add(n[u]);
|
|
961
973
|
}
|
|
962
974
|
}
|
|
963
975
|
} catch (o) {
|
|
@@ -969,8 +981,8 @@ async function Te(e, n, s, r) {
|
|
|
969
981
|
}
|
|
970
982
|
try {
|
|
971
983
|
for (const o in s) {
|
|
972
|
-
const
|
|
973
|
-
p.existsSync(
|
|
984
|
+
const r = s[o], c = f.join(i, o);
|
|
985
|
+
p.existsSync(c) && e.tags.add(r);
|
|
974
986
|
}
|
|
975
987
|
} catch (o) {
|
|
976
988
|
console.warn(
|
|
@@ -980,14 +992,14 @@ async function Te(e, n, s, r) {
|
|
|
980
992
|
);
|
|
981
993
|
}
|
|
982
994
|
try {
|
|
983
|
-
for (const o in
|
|
984
|
-
const
|
|
995
|
+
for (const o in a) {
|
|
996
|
+
const r = a[o];
|
|
985
997
|
(await ce(o, {
|
|
986
|
-
cwd:
|
|
998
|
+
cwd: i,
|
|
987
999
|
nodir: !0,
|
|
988
1000
|
dot: !0
|
|
989
1001
|
// Include dotfiles if needed, though 'src' patterns usually don't
|
|
990
|
-
})).length > 0 && e.tags.add(
|
|
1002
|
+
})).length > 0 && e.tags.add(r);
|
|
991
1003
|
}
|
|
992
1004
|
} catch (o) {
|
|
993
1005
|
console.warn(
|
|
@@ -998,7 +1010,7 @@ async function Te(e, n, s, r) {
|
|
|
998
1010
|
}
|
|
999
1011
|
}
|
|
1000
1012
|
function Re(e, n) {
|
|
1001
|
-
const s =
|
|
1013
|
+
const s = f.join(e, n);
|
|
1002
1014
|
try {
|
|
1003
1015
|
return p.readFileSync(s, "utf-8");
|
|
1004
1016
|
} catch {
|
|
@@ -1006,35 +1018,35 @@ function Re(e, n) {
|
|
|
1006
1018
|
}
|
|
1007
1019
|
}
|
|
1008
1020
|
async function Fe(e, n, s = !1) {
|
|
1009
|
-
const
|
|
1010
|
-
if (
|
|
1021
|
+
const i = p.readdirSync(e).filter((o) => o.endsWith(".md")).filter((o) => !n.includes(o));
|
|
1022
|
+
if (i.length > 0) {
|
|
1011
1023
|
console.warn(
|
|
1012
1024
|
t.yellow(
|
|
1013
1025
|
`
|
|
1014
|
-
โ ๏ธ Found ${
|
|
1026
|
+
โ ๏ธ Found ${i.length} instruction files that are no longer generated:`
|
|
1015
1027
|
)
|
|
1016
1028
|
);
|
|
1017
|
-
for (const
|
|
1018
|
-
console.warn(t.yellow(` - ${
|
|
1029
|
+
for (const r of i)
|
|
1030
|
+
console.warn(t.yellow(` - ${r}`));
|
|
1019
1031
|
let o = s;
|
|
1020
1032
|
if (s || (o = (await W.prompt([
|
|
1021
1033
|
{
|
|
1022
1034
|
type: "confirm",
|
|
1023
1035
|
name: "prune",
|
|
1024
|
-
message: `Do you want to delete these ${
|
|
1036
|
+
message: `Do you want to delete these ${i.length} old files?`,
|
|
1025
1037
|
default: !1
|
|
1026
1038
|
}
|
|
1027
1039
|
])).prune), o) {
|
|
1028
|
-
let
|
|
1029
|
-
for (const
|
|
1040
|
+
let r = 0;
|
|
1041
|
+
for (const c of i)
|
|
1030
1042
|
try {
|
|
1031
|
-
p.unlinkSync(
|
|
1043
|
+
p.unlinkSync(f.join(e, c)), r++;
|
|
1032
1044
|
} catch (l) {
|
|
1033
1045
|
console.error(
|
|
1034
|
-
t.red(` โ Error deleting ${
|
|
1046
|
+
t.red(` โ Error deleting ${c}: ${l.message}`)
|
|
1035
1047
|
);
|
|
1036
1048
|
}
|
|
1037
|
-
console.log(`โ
Pruned ${
|
|
1049
|
+
console.log(`โ
Pruned ${r} old files.`);
|
|
1038
1050
|
}
|
|
1039
1051
|
}
|
|
1040
1052
|
}
|
|
@@ -1043,13 +1055,13 @@ async function ke() {
|
|
|
1043
1055
|
t.cyan(`๐ Validating instruction files with quality scoring...
|
|
1044
1056
|
`)
|
|
1045
1057
|
);
|
|
1046
|
-
const e = j("Loading configuration...").start(), n = O(), s =
|
|
1058
|
+
const e = j("Loading configuration...").start(), n = O(), s = M(n);
|
|
1047
1059
|
e.succeed("Configuration loaded.");
|
|
1048
|
-
const
|
|
1060
|
+
const a = f.resolve(
|
|
1049
1061
|
process.cwd(),
|
|
1050
1062
|
s.outputDirectory
|
|
1051
1063
|
);
|
|
1052
|
-
if (!p.existsSync(
|
|
1064
|
+
if (!p.existsSync(a)) {
|
|
1053
1065
|
e.fail(
|
|
1054
1066
|
t.red(
|
|
1055
1067
|
`โ Output directory ${s.outputDirectory} does not exist. Run 'magic-helix run' first.`
|
|
@@ -1057,14 +1069,14 @@ async function ke() {
|
|
|
1057
1069
|
);
|
|
1058
1070
|
return;
|
|
1059
1071
|
}
|
|
1060
|
-
const
|
|
1061
|
-
if (
|
|
1072
|
+
const i = p.readdirSync(a).filter((u) => u.endsWith(".md"));
|
|
1073
|
+
if (i.length === 0) {
|
|
1062
1074
|
console.log(
|
|
1063
1075
|
t.yellow("No instruction files found. Run 'magic-helix run' first.")
|
|
1064
1076
|
);
|
|
1065
1077
|
return;
|
|
1066
1078
|
}
|
|
1067
|
-
console.log(t.gray(`Checking ${
|
|
1079
|
+
console.log(t.gray(`Checking ${i.length} instruction file(s)...
|
|
1068
1080
|
`));
|
|
1069
1081
|
let o = { track: () => {
|
|
1070
1082
|
} };
|
|
@@ -1076,13 +1088,13 @@ async function ke() {
|
|
|
1076
1088
|
}
|
|
1077
1089
|
} catch {
|
|
1078
1090
|
}
|
|
1079
|
-
let
|
|
1091
|
+
let r = 0, c = 0;
|
|
1080
1092
|
const l = [];
|
|
1081
|
-
for (const u of
|
|
1082
|
-
const h =
|
|
1093
|
+
for (const u of i) {
|
|
1094
|
+
const h = f.join(a, u);
|
|
1083
1095
|
try {
|
|
1084
1096
|
const w = p.readFileSync(h, "utf-8"), m = ae(w), v = Ae(m.overallScore);
|
|
1085
|
-
l.push({ file: u, score: m.overallScore, grade: v }), m.overallScore >= 70 ?
|
|
1097
|
+
l.push({ file: u, score: m.overallScore, grade: v }), m.overallScore >= 70 ? r++ : c++;
|
|
1086
1098
|
const D = m.overallScore >= 90 ? t.green : m.overallScore >= 70 ? t.blue : t.yellow;
|
|
1087
1099
|
console.log(
|
|
1088
1100
|
D(`${v} ${m.overallScore}/100`) + t.gray(` - ${u}`)
|
|
@@ -1098,24 +1110,24 @@ async function ke() {
|
|
|
1098
1110
|
missingCount: m.missingElements.length
|
|
1099
1111
|
});
|
|
1100
1112
|
} catch (w) {
|
|
1101
|
-
|
|
1113
|
+
c++, console.log(t.red(`ERROR - ${u}: ${w.message}`));
|
|
1102
1114
|
}
|
|
1103
1115
|
}
|
|
1104
1116
|
console.log(t.bold(`
|
|
1105
1117
|
=== Validation Summary ===
|
|
1106
|
-
`)), console.log(t.green(`โ
Passed (โฅ70): ${
|
|
1118
|
+
`)), console.log(t.green(`โ
Passed (โฅ70): ${r}`)), console.log(t.red(`โ Failed (<70): ${c}`));
|
|
1107
1119
|
const g = l.reduce((u, h) => u + h.score, 0) / l.length;
|
|
1108
1120
|
console.log(t.cyan(`๐ Average Score: ${Math.round(g)}/100`)), o.track({
|
|
1109
1121
|
type: "summary",
|
|
1110
1122
|
files: l.length,
|
|
1111
|
-
pass:
|
|
1112
|
-
fail:
|
|
1123
|
+
pass: r,
|
|
1124
|
+
fail: c,
|
|
1113
1125
|
averageScore: Math.round(g)
|
|
1114
|
-
}),
|
|
1115
|
-
โจ All instruction files meet quality standards!`)) :
|
|
1126
|
+
}), c === 0 && g >= 80 ? console.log(t.green(`
|
|
1127
|
+
โจ All instruction files meet quality standards!`)) : c > 0 && console.log(
|
|
1116
1128
|
t.yellow(
|
|
1117
1129
|
`
|
|
1118
|
-
โ ๏ธ ${
|
|
1130
|
+
โ ๏ธ ${c} file(s) need improvement. Run with --verbose for details.`
|
|
1119
1131
|
)
|
|
1120
1132
|
);
|
|
1121
1133
|
}
|