@synchronized-studio/cmsassets-agent 0.3.4 → 0.3.6
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/aiReview-JWBCUMGP.js +9 -0
- package/dist/chunk-KYRW5D2O.js +1121 -0
- package/dist/chunk-N3DHLGCN.js +1734 -0
- package/dist/chunk-UOLEBOWJ.js +475 -0
- package/dist/cli.js +296 -222
- package/dist/index.d.ts +16 -16
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
saveReport,
|
|
10
10
|
scan,
|
|
11
11
|
verify
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-N3DHLGCN.js";
|
|
13
|
+
import "./chunk-KYRW5D2O.js";
|
|
14
14
|
import "./chunk-E74TGIFQ.js";
|
|
15
15
|
import "./chunk-QGM4M3NI.js";
|
|
16
16
|
|
|
17
17
|
// src/cli.ts
|
|
18
|
-
import { existsSync as
|
|
18
|
+
import { existsSync as existsSync5 } from "fs";
|
|
19
19
|
import { dirname as pathDirname, resolve as resolve6 } from "path";
|
|
20
20
|
import { fileURLToPath } from "url";
|
|
21
21
|
import { defineCommand as defineCommand8, runMain } from "citty";
|
|
@@ -25,7 +25,7 @@ import { config as dotenvConfig } from "dotenv";
|
|
|
25
25
|
import { createInterface } from "readline";
|
|
26
26
|
import { resolve } from "path";
|
|
27
27
|
import { defineCommand } from "citty";
|
|
28
|
-
import
|
|
28
|
+
import consola3 from "consola";
|
|
29
29
|
import pc from "picocolors";
|
|
30
30
|
|
|
31
31
|
// src/patcher/injectScript.ts
|
|
@@ -58,6 +58,74 @@ function injectNpmScript(projectRoot) {
|
|
|
58
58
|
return { added: true };
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
// src/patcher/injectNuxtRuntimeConfig.ts
|
|
62
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
63
|
+
import { join as join2 } from "path";
|
|
64
|
+
import consola2 from "consola";
|
|
65
|
+
function injectNuxtRuntimeConfig(projectRoot) {
|
|
66
|
+
const candidates = ["nuxt.config.ts", "nuxt.config.js", "nuxt.config.mjs"];
|
|
67
|
+
const configFile = candidates.find((f) => existsSync2(join2(projectRoot, f)));
|
|
68
|
+
if (!configFile) {
|
|
69
|
+
return { added: false, reason: "No nuxt.config found" };
|
|
70
|
+
}
|
|
71
|
+
const absPath = join2(projectRoot, configFile);
|
|
72
|
+
let content = readFileSync2(absPath, "utf-8");
|
|
73
|
+
if (content.includes("cmsAssetsUrl")) {
|
|
74
|
+
return { added: false, reason: "cmsAssetsUrl already present in nuxt.config" };
|
|
75
|
+
}
|
|
76
|
+
const indentMatch = content.match(/^( +)\S/m);
|
|
77
|
+
const indent = indentMatch?.[1] ?? " ";
|
|
78
|
+
const i2 = indent.repeat(2);
|
|
79
|
+
const i3 = indent.repeat(3);
|
|
80
|
+
const entry = `cmsAssetsUrl: process.env.CMS_ASSETS_URL || ''`;
|
|
81
|
+
const publicBlockRe = /(runtimeConfig\s*:\s*\{[^}]*?public\s*:\s*\{)(\s*)/;
|
|
82
|
+
if (publicBlockRe.test(content)) {
|
|
83
|
+
content = content.replace(publicBlockRe, `$1$2${i3}${entry},
|
|
84
|
+
`);
|
|
85
|
+
writeFileSync2(absPath, content, "utf-8");
|
|
86
|
+
consola2.success(`Added cmsAssetsUrl to runtimeConfig.public in ${configFile}`);
|
|
87
|
+
return { added: true };
|
|
88
|
+
}
|
|
89
|
+
const runtimeConfigRe = /(runtimeConfig\s*:\s*\{)(\s*)/;
|
|
90
|
+
if (runtimeConfigRe.test(content)) {
|
|
91
|
+
const publicBlock = `$1$2${i2}public: {
|
|
92
|
+
${i3}${entry},
|
|
93
|
+
${i2}},
|
|
94
|
+
`;
|
|
95
|
+
content = content.replace(runtimeConfigRe, publicBlock);
|
|
96
|
+
writeFileSync2(absPath, content, "utf-8");
|
|
97
|
+
consola2.success(`Added runtimeConfig.public.cmsAssetsUrl in ${configFile}`);
|
|
98
|
+
return { added: true };
|
|
99
|
+
}
|
|
100
|
+
const defineConfigRe = /(defineNuxtConfig\s*\(\s*\{)(\s*)/;
|
|
101
|
+
if (defineConfigRe.test(content)) {
|
|
102
|
+
const block = `$1$2${indent}runtimeConfig: {
|
|
103
|
+
${i2}public: {
|
|
104
|
+
${i3}${entry},
|
|
105
|
+
${i2}},
|
|
106
|
+
${indent}},
|
|
107
|
+
`;
|
|
108
|
+
content = content.replace(defineConfigRe, block);
|
|
109
|
+
writeFileSync2(absPath, content, "utf-8");
|
|
110
|
+
consola2.success(`Added runtimeConfig.public.cmsAssetsUrl in ${configFile}`);
|
|
111
|
+
return { added: true };
|
|
112
|
+
}
|
|
113
|
+
const exportRe = /(export\s+default\s*\{)(\s*)/;
|
|
114
|
+
if (exportRe.test(content)) {
|
|
115
|
+
const block = `$1$2${indent}runtimeConfig: {
|
|
116
|
+
${i2}public: {
|
|
117
|
+
${i3}${entry},
|
|
118
|
+
${i2}},
|
|
119
|
+
${indent}},
|
|
120
|
+
`;
|
|
121
|
+
content = content.replace(exportRe, block);
|
|
122
|
+
writeFileSync2(absPath, content, "utf-8");
|
|
123
|
+
consola2.success(`Added runtimeConfig.public.cmsAssetsUrl in ${configFile}`);
|
|
124
|
+
return { added: true };
|
|
125
|
+
}
|
|
126
|
+
return { added: false, reason: "Could not find insertion point in nuxt.config" };
|
|
127
|
+
}
|
|
128
|
+
|
|
61
129
|
// src/commands/init.ts
|
|
62
130
|
function confirm(question) {
|
|
63
131
|
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -165,47 +233,47 @@ var initCommand = defineCommand({
|
|
|
165
233
|
},
|
|
166
234
|
async run({ args }) {
|
|
167
235
|
const root = resolve(args.dir);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
236
|
+
consola3.log("");
|
|
237
|
+
consola3.log(pc.bold(" CMS Assets Agent \u2014 Init"));
|
|
238
|
+
consola3.log(pc.dim(" \u2500".repeat(25)));
|
|
239
|
+
consola3.log("");
|
|
172
240
|
const scanResult = scan(root);
|
|
173
241
|
if (args.cms) scanResult.cms.type = args.cms;
|
|
174
242
|
if (args.repository) scanResult.cms.params.repository = args.repository;
|
|
175
243
|
if (args.spaceId) scanResult.cms.params.spaceId = args.spaceId;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
244
|
+
consola3.log(` ${pc.cyan("Framework:")} ${scanResult.framework.name} ${pc.dim(scanResult.framework.version)}`);
|
|
245
|
+
consola3.log(` ${pc.cyan("CMS:")} ${scanResult.cms.type}`);
|
|
246
|
+
consola3.log(` ${pc.cyan("Package mgr:")} ${scanResult.packageManager}`);
|
|
247
|
+
consola3.log("");
|
|
180
248
|
if (scanResult.injectionPoints.length === 0) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
249
|
+
consola3.warn(" No injection points found. Nothing to do.");
|
|
250
|
+
consola3.log("");
|
|
251
|
+
consola3.log(
|
|
184
252
|
` ${pc.dim("Tip:")} Run from your project root. The agent looks for fetch/useFetch/loaders that return CMS data.`
|
|
185
253
|
);
|
|
186
|
-
|
|
254
|
+
consola3.log(
|
|
187
255
|
` ${pc.dim("If you already ran init here, all detected points may already be patched.")}`
|
|
188
256
|
);
|
|
189
|
-
|
|
190
|
-
|
|
257
|
+
consola3.log(` ${pc.dim("Run")} ${pc.cyan("npx @synchronized-studio/cmsassets-agent scan")} ${pc.dim("to see framework/CMS detection.")}`);
|
|
258
|
+
consola3.log("");
|
|
191
259
|
return;
|
|
192
260
|
}
|
|
193
|
-
|
|
194
|
-
|
|
261
|
+
consola3.log(` ${pc.bold("Injection points:")} ${scanResult.injectionPoints.length} found`);
|
|
262
|
+
consola3.log("");
|
|
195
263
|
for (const point of scanResult.injectionPoints) {
|
|
196
264
|
const color = point.confidence === "high" ? pc.green : point.confidence === "medium" ? pc.yellow : pc.red;
|
|
197
|
-
|
|
265
|
+
consola3.log(
|
|
198
266
|
` ${color("\u25CF")} ${point.filePath} ${pc.dim(`[${point.confidence}]`)}`
|
|
199
267
|
);
|
|
200
268
|
}
|
|
201
|
-
|
|
269
|
+
consola3.log("");
|
|
202
270
|
if (!args.yes && !args["dry-run"]) {
|
|
203
271
|
const ok = await confirm(` Proceed with integration? ${pc.dim("(y/N)")} `);
|
|
204
272
|
if (!ok) {
|
|
205
|
-
|
|
273
|
+
consola3.log(" Aborted.");
|
|
206
274
|
return;
|
|
207
275
|
}
|
|
208
|
-
|
|
276
|
+
consola3.log("");
|
|
209
277
|
}
|
|
210
278
|
const plan = createPlan(scanResult);
|
|
211
279
|
if (args.slug) plan.env.placeholder = `https://${args.slug}.cmsassets.com`;
|
|
@@ -213,62 +281,62 @@ var initCommand = defineCommand({
|
|
|
213
281
|
if (args["llm-all"]) plan.policies.llmFallbackForAll = true;
|
|
214
282
|
if (args["llm-only"]) plan.policies.llmOnly = true;
|
|
215
283
|
if (args["dry-run"]) {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
284
|
+
consola3.log(pc.bold(" Dry Run \u2014 planned changes:"));
|
|
285
|
+
consola3.log("");
|
|
286
|
+
consola3.log(` ${pc.cyan("Install:")} ${plan.install.command}`);
|
|
287
|
+
consola3.log(` ${pc.cyan("Env:")} ${plan.env.key}=${plan.env.placeholder}`);
|
|
288
|
+
consola3.log("");
|
|
221
289
|
for (const patch of plan.patches) {
|
|
222
290
|
const color = patch.confidence === "high" ? pc.green : patch.confidence === "medium" ? pc.yellow : pc.red;
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
291
|
+
consola3.log(` ${color("\u25CF")} ${patch.filePath} ${pc.dim(`[${patch.confidence}]`)}`);
|
|
292
|
+
consola3.log(` ${pc.dim(patch.wrapTarget.originalCode)}`);
|
|
293
|
+
consola3.log(` ${pc.green("\u2192 " + patch.wrapTarget.transformedCode)}`);
|
|
226
294
|
}
|
|
227
|
-
|
|
228
|
-
|
|
295
|
+
consola3.log("");
|
|
296
|
+
consola3.log(` ${pc.dim("Run without --dry-run to apply.")}`);
|
|
229
297
|
return;
|
|
230
298
|
}
|
|
231
299
|
let installed = false;
|
|
232
300
|
if (!args["no-install"]) {
|
|
233
|
-
|
|
301
|
+
consola3.info(`Installing: ${plan.install.command}`);
|
|
234
302
|
try {
|
|
235
303
|
const { execSync } = await import("child_process");
|
|
236
304
|
execSync(plan.install.command, { cwd: root, stdio: "inherit" });
|
|
237
305
|
installed = true;
|
|
238
306
|
} catch {
|
|
239
|
-
|
|
307
|
+
consola3.warn("Package install failed. You can install it manually later.");
|
|
240
308
|
}
|
|
241
309
|
}
|
|
242
310
|
const hasAiKey = !!process.env.OPENAI_API_KEY;
|
|
243
311
|
let aiMode = args["ai-verify"] && hasAiKey;
|
|
244
312
|
if (args["ai-verify"] && !hasAiKey) {
|
|
245
|
-
|
|
246
|
-
|
|
313
|
+
consola3.log(` ${pc.yellow("No OPENAI_API_KEY")} \u2014 using mixed fallback (AST for high/medium, report-only for low)`);
|
|
314
|
+
consola3.log("");
|
|
247
315
|
} else if (aiMode) {
|
|
248
316
|
const { checkAiVerifyReady } = await import("./openaiClient-YGAFYB3X.js");
|
|
249
317
|
let ready = await checkAiVerifyReady(root);
|
|
250
318
|
if (!ready.ok && ready.canInstallInProject) {
|
|
251
319
|
const openaiInstallCmd = getOpenAiInstallCommand(scanResult.packageManager);
|
|
252
|
-
|
|
320
|
+
consola3.info(`Installing openai in project: ${openaiInstallCmd}`);
|
|
253
321
|
try {
|
|
254
322
|
const { execSync } = await import("child_process");
|
|
255
323
|
execSync(openaiInstallCmd, { cwd: root, stdio: "inherit" });
|
|
256
324
|
ready = await checkAiVerifyReady(root);
|
|
257
325
|
} catch {
|
|
258
|
-
|
|
326
|
+
consola3.warn("Installing openai failed.");
|
|
259
327
|
ready = { ok: false };
|
|
260
328
|
}
|
|
261
329
|
}
|
|
262
330
|
if (!ready.ok) {
|
|
263
|
-
|
|
264
|
-
|
|
331
|
+
consola3.log(` ${pc.yellow("AI mode unavailable")} \u2014 falling back to AST-only patching`);
|
|
332
|
+
consola3.log("");
|
|
265
333
|
aiMode = false;
|
|
266
334
|
} else {
|
|
267
|
-
|
|
268
|
-
|
|
335
|
+
consola3.log(` ${pc.cyan("AI mode")} \u2014 AI will patch and verify each file`);
|
|
336
|
+
consola3.log("");
|
|
269
337
|
}
|
|
270
338
|
}
|
|
271
|
-
|
|
339
|
+
consola3.info("Applying patches...");
|
|
272
340
|
const applyReport = await applyPlan(plan, {
|
|
273
341
|
dryRun: false,
|
|
274
342
|
includeTests: args["include-tests"],
|
|
@@ -284,41 +352,46 @@ var initCommand = defineCommand({
|
|
|
284
352
|
let ready = await checkAiVerifyReady(root);
|
|
285
353
|
if (!ready.ok && ready.canInstallInProject) {
|
|
286
354
|
const openaiInstallCmd = getOpenAiInstallCommand(scanResult.packageManager);
|
|
287
|
-
|
|
355
|
+
consola3.info(`Installing openai in project: ${openaiInstallCmd}`);
|
|
288
356
|
try {
|
|
289
357
|
const { execSync } = await import("child_process");
|
|
290
358
|
execSync(openaiInstallCmd, { cwd: root, stdio: "inherit" });
|
|
291
359
|
ready = await checkAiVerifyReady(root);
|
|
292
360
|
} catch {
|
|
293
|
-
|
|
361
|
+
consola3.warn("Installing openai failed. AI verification skipped.");
|
|
294
362
|
ready = { ok: false };
|
|
295
363
|
}
|
|
296
364
|
}
|
|
297
365
|
if (!ready.ok) {
|
|
298
|
-
|
|
366
|
+
consola3.warn(` ${pc.yellow("AI Verification skipped:")} ${ready.reason}`);
|
|
299
367
|
} else {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
const { aiReviewAll } = await import("./aiReview-
|
|
368
|
+
consola3.log("");
|
|
369
|
+
consola3.log(pc.bold(" CMS Assets Agent \u2014 AI Verification"));
|
|
370
|
+
consola3.log(pc.dim(" \u2500".repeat(25)));
|
|
371
|
+
consola3.log("");
|
|
372
|
+
const { aiReviewAll } = await import("./aiReview-JWBCUMGP.js");
|
|
305
373
|
aiReviewReport = await aiReviewAll(root, appliedPaths, plan, {
|
|
306
374
|
model: args["ai-model"] ?? "gpt-4o",
|
|
307
375
|
maxIterations: parseInt(args["ai-max-iterations"] ?? "3", 10)
|
|
308
376
|
});
|
|
309
|
-
|
|
310
|
-
|
|
377
|
+
consola3.log("");
|
|
378
|
+
consola3.log(` ${pc.green("Passed:")} ${aiReviewReport.filesPassed} files`);
|
|
311
379
|
if (aiReviewReport.filesFixed > 0) {
|
|
312
|
-
|
|
380
|
+
consola3.log(` ${pc.blue("Fixed:")} ${aiReviewReport.filesFixed} files`);
|
|
313
381
|
}
|
|
314
382
|
if (aiReviewReport.filesFailed > 0) {
|
|
315
|
-
|
|
383
|
+
consola3.log(` ${pc.red("Failed:")} ${aiReviewReport.filesFailed} files`);
|
|
316
384
|
}
|
|
317
|
-
|
|
318
|
-
|
|
385
|
+
consola3.log(` ${pc.dim(`Tokens used: ${aiReviewReport.tokensUsed}`)}`);
|
|
386
|
+
consola3.log("");
|
|
319
387
|
}
|
|
320
388
|
}
|
|
321
389
|
}
|
|
390
|
+
let runtimeConfigAdded = false;
|
|
391
|
+
if (scanResult.framework.name === "nuxt") {
|
|
392
|
+
const rcResult = injectNuxtRuntimeConfig(root);
|
|
393
|
+
runtimeConfigAdded = rcResult.added;
|
|
394
|
+
}
|
|
322
395
|
let scriptAdded = false;
|
|
323
396
|
if (!args["no-script"]) {
|
|
324
397
|
const result = injectNpmScript(root);
|
|
@@ -330,52 +403,53 @@ var initCommand = defineCommand({
|
|
|
330
403
|
const manualReview = applyReport.files.filter((f) => f.method === "manual-review");
|
|
331
404
|
const skipped = applyReport.files.filter((f) => !f.applied && f.method === "skipped");
|
|
332
405
|
const s = applyReport.summary;
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
406
|
+
consola3.log("");
|
|
407
|
+
consola3.log(pc.bold(" CMS Assets Agent \u2014 Init Complete"));
|
|
408
|
+
consola3.log(pc.dim(" \u2500".repeat(25)));
|
|
409
|
+
consola3.log("");
|
|
337
410
|
if (s) {
|
|
338
|
-
|
|
339
|
-
if (s.patchedByAi > 0)
|
|
340
|
-
if (s.patchedByAst > 0)
|
|
341
|
-
if (s.manualReviewRequired > 0)
|
|
342
|
-
if (s.skipped > 0)
|
|
411
|
+
consola3.log(` ${pc.dim("Candidates:")} ${s.candidatesFound}`);
|
|
412
|
+
if (s.patchedByAi > 0) consola3.log(` ${pc.green("Patched (AI):")} ${s.patchedByAi}`);
|
|
413
|
+
if (s.patchedByAst > 0) consola3.log(` ${pc.green("Patched (AST):")} ${s.patchedByAst}`);
|
|
414
|
+
if (s.manualReviewRequired > 0) consola3.log(` ${pc.yellow("Manual review:")} ${s.manualReviewRequired}`);
|
|
415
|
+
if (s.skipped > 0) consola3.log(` ${pc.dim("Skipped:")} ${s.skipped}`);
|
|
343
416
|
} else {
|
|
344
|
-
|
|
345
|
-
|
|
417
|
+
consola3.log(` ${pc.green("Applied:")} ${applied.length} files`);
|
|
418
|
+
consola3.log(` ${pc.yellow("Skipped:")} ${skipped.length + manualReview.length} files`);
|
|
346
419
|
}
|
|
347
|
-
if (installed)
|
|
348
|
-
if (
|
|
349
|
-
|
|
420
|
+
if (installed) consola3.log(` ${pc.green("Installed:")} @synchronized-studio/response-transformer`);
|
|
421
|
+
if (runtimeConfigAdded) consola3.log(` ${pc.green("Config:")} Added runtimeConfig.public.cmsAssetsUrl to nuxt.config`);
|
|
422
|
+
if (scriptAdded) consola3.log(` ${pc.green("Script:")} Added "cmsassets:transform" to package.json`);
|
|
423
|
+
consola3.log("");
|
|
350
424
|
for (const file of applied) {
|
|
351
|
-
|
|
425
|
+
consola3.log(` ${pc.green("+")} ${file.filePath} ${pc.dim(`(${file.method}, ${file.durationMs}ms)`)}`);
|
|
352
426
|
}
|
|
353
427
|
for (const file of manualReview) {
|
|
354
|
-
|
|
428
|
+
consola3.log(` ${pc.yellow("?")} ${file.filePath} ${pc.dim(`\u2014 ${file.reason}`)}`);
|
|
355
429
|
}
|
|
356
430
|
for (const file of skipped) {
|
|
357
|
-
|
|
431
|
+
consola3.log(` ${pc.dim("-")} ${file.filePath} ${pc.dim(`\u2014 ${file.reason}`)}`);
|
|
358
432
|
}
|
|
359
|
-
|
|
433
|
+
consola3.log("");
|
|
360
434
|
if (!installed) {
|
|
361
|
-
|
|
435
|
+
consola3.log(` ${pc.dim("Don't forget to install:")} ${pc.cyan(plan.install.command)}`);
|
|
362
436
|
}
|
|
363
437
|
if (!applyReport.envUpdated) {
|
|
364
|
-
|
|
438
|
+
consola3.log(` ${pc.dim("Set your env var:")} ${pc.cyan(`${plan.env.key}=${plan.env.placeholder}`)}`);
|
|
365
439
|
}
|
|
366
440
|
if (scriptAdded) {
|
|
367
|
-
|
|
441
|
+
consola3.log(` ${pc.dim("Re-run later with:")} ${pc.cyan("npm run cmsassets:transform")}`);
|
|
368
442
|
}
|
|
369
443
|
if (!args["ai-verify"] && applied.length > 0) {
|
|
370
|
-
|
|
444
|
+
consola3.log(` ${pc.dim("Optional:")} Add ${pc.cyan("--ai-verify")} to have AI review patched files (requires OPENAI_API_KEY).`);
|
|
371
445
|
}
|
|
372
|
-
|
|
446
|
+
consola3.log("");
|
|
373
447
|
}
|
|
374
448
|
});
|
|
375
449
|
|
|
376
450
|
// src/commands/scan.ts
|
|
377
451
|
import { defineCommand as defineCommand2 } from "citty";
|
|
378
|
-
import
|
|
452
|
+
import consola4 from "consola";
|
|
379
453
|
import pc2 from "picocolors";
|
|
380
454
|
var scanCommand = defineCommand2({
|
|
381
455
|
meta: {
|
|
@@ -400,49 +474,49 @@ var scanCommand = defineCommand2({
|
|
|
400
474
|
console.log(JSON.stringify(result, null, 2));
|
|
401
475
|
return;
|
|
402
476
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
477
|
+
consola4.log("");
|
|
478
|
+
consola4.log(pc2.bold(" CMS Assets Agent \u2014 Scan Results"));
|
|
479
|
+
consola4.log(pc2.dim(" \u2500".repeat(25)));
|
|
480
|
+
consola4.log("");
|
|
481
|
+
consola4.log(` ${pc2.cyan("Framework:")} ${result.framework.name} ${pc2.dim(result.framework.version)}`);
|
|
408
482
|
if (result.framework.configFile) {
|
|
409
|
-
|
|
483
|
+
consola4.log(` ${pc2.dim("Config:")} ${result.framework.configFile}`);
|
|
410
484
|
}
|
|
411
|
-
|
|
485
|
+
consola4.log(` ${pc2.cyan("CMS:")} ${result.cms.type}`);
|
|
412
486
|
if (Object.keys(result.cms.params).length > 0) {
|
|
413
487
|
for (const [key, val] of Object.entries(result.cms.params)) {
|
|
414
|
-
|
|
488
|
+
consola4.log(` ${pc2.dim(key + ":")} ${val}`);
|
|
415
489
|
}
|
|
416
490
|
}
|
|
417
491
|
if (result.cms.detectedFrom.length > 0) {
|
|
418
|
-
|
|
492
|
+
consola4.log(` ${pc2.dim("Detected from:")} ${result.cms.detectedFrom.slice(0, 3).join(", ")}`);
|
|
419
493
|
}
|
|
420
|
-
|
|
421
|
-
|
|
494
|
+
consola4.log(` ${pc2.cyan("Package mgr:")} ${result.packageManager}`);
|
|
495
|
+
consola4.log("");
|
|
422
496
|
if (result.injectionPoints.length === 0) {
|
|
423
|
-
|
|
497
|
+
consola4.warn(" No injection points found.");
|
|
424
498
|
return;
|
|
425
499
|
}
|
|
426
|
-
|
|
427
|
-
|
|
500
|
+
consola4.log(` ${pc2.bold("Injection points:")} ${result.injectionPoints.length} found`);
|
|
501
|
+
consola4.log("");
|
|
428
502
|
for (let i = 0; i < result.injectionPoints.length; i++) {
|
|
429
503
|
const point = result.injectionPoints[i];
|
|
430
504
|
const confidenceColor = point.confidence === "high" ? pc2.green : point.confidence === "medium" ? pc2.yellow : pc2.red;
|
|
431
|
-
|
|
505
|
+
consola4.log(
|
|
432
506
|
` ${pc2.bold(String(i + 1) + ".")} ${point.filePath} ${confidenceColor(`[${point.confidence.toUpperCase()}]`)} ${pc2.dim(`score: ${point.score}`)}`
|
|
433
507
|
);
|
|
434
|
-
|
|
508
|
+
consola4.log(` ${pc2.dim(`Line ${point.line}:`)} ${point.type}`);
|
|
435
509
|
for (const reason of point.reasons) {
|
|
436
|
-
|
|
510
|
+
consola4.log(` ${pc2.dim("\u2022")} ${reason}`);
|
|
437
511
|
}
|
|
438
|
-
|
|
512
|
+
consola4.log("");
|
|
439
513
|
}
|
|
440
514
|
}
|
|
441
515
|
});
|
|
442
516
|
|
|
443
517
|
// src/commands/plan.ts
|
|
444
518
|
import { defineCommand as defineCommand3 } from "citty";
|
|
445
|
-
import
|
|
519
|
+
import consola5 from "consola";
|
|
446
520
|
import pc3 from "picocolors";
|
|
447
521
|
var planCommand = defineCommand3({
|
|
448
522
|
meta: {
|
|
@@ -497,34 +571,34 @@ var planCommand = defineCommand3({
|
|
|
497
571
|
return;
|
|
498
572
|
}
|
|
499
573
|
const filePath = savePlanFile(scanResult.projectRoot, plan);
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
574
|
+
consola5.log("");
|
|
575
|
+
consola5.log(pc3.bold(" CMS Assets Agent \u2014 Plan Generated"));
|
|
576
|
+
consola5.log(pc3.dim(" \u2500".repeat(25)));
|
|
577
|
+
consola5.log("");
|
|
578
|
+
consola5.log(` ${pc3.cyan("Plan file:")} ${filePath}`);
|
|
579
|
+
consola5.log(` ${pc3.cyan("Install:")} ${plan.install.command}`);
|
|
580
|
+
consola5.log(` ${pc3.cyan("Env var:")} ${plan.env.key}=${plan.env.placeholder}`);
|
|
581
|
+
consola5.log(` ${pc3.cyan("Patches:")} ${plan.patches.length} files`);
|
|
582
|
+
consola5.log("");
|
|
509
583
|
for (let i = 0; i < plan.patches.length; i++) {
|
|
510
584
|
const patch = plan.patches[i];
|
|
511
585
|
const confidenceColor = patch.confidence === "high" ? pc3.green : patch.confidence === "medium" ? pc3.yellow : pc3.red;
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
586
|
+
consola5.log(` ${pc3.bold(String(i + 1) + ".")} ${patch.filePath} ${confidenceColor(`[${patch.confidence.toUpperCase()}]`)}`);
|
|
587
|
+
consola5.log(` ${patch.description}`);
|
|
588
|
+
consola5.log(` ${pc3.dim("Line " + patch.wrapTarget.line + ":")} ${pc3.red(patch.wrapTarget.originalCode)}`);
|
|
589
|
+
consola5.log(` ${pc3.dim(" \u2192")} ${pc3.green(patch.wrapTarget.transformedCode)}`);
|
|
590
|
+
consola5.log("");
|
|
517
591
|
}
|
|
518
|
-
|
|
519
|
-
|
|
592
|
+
consola5.log(` ${pc3.dim("Review the plan, then run:")} ${pc3.cyan("cmsassets-agent apply")}`);
|
|
593
|
+
consola5.log("");
|
|
520
594
|
}
|
|
521
595
|
});
|
|
522
596
|
|
|
523
597
|
// src/commands/apply.ts
|
|
524
|
-
import { existsSync as
|
|
525
|
-
import { join as
|
|
598
|
+
import { existsSync as existsSync3 } from "fs";
|
|
599
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
526
600
|
import { defineCommand as defineCommand4 } from "citty";
|
|
527
|
-
import
|
|
601
|
+
import consola6 from "consola";
|
|
528
602
|
import pc4 from "picocolors";
|
|
529
603
|
var applyCommand = defineCommand4({
|
|
530
604
|
meta: {
|
|
@@ -634,7 +708,7 @@ var applyCommand = defineCommand4({
|
|
|
634
708
|
async run({ args }) {
|
|
635
709
|
const root = resolve2(args.dir);
|
|
636
710
|
if (gitOps.isGitRepo(root) && !args["allow-dirty"] && !gitOps.isClean(root)) {
|
|
637
|
-
|
|
711
|
+
consola6.error(
|
|
638
712
|
"Git worktree is dirty. Commit or stash changes first, or use --allow-dirty."
|
|
639
713
|
);
|
|
640
714
|
process.exit(1);
|
|
@@ -644,19 +718,19 @@ var applyCommand = defineCommand4({
|
|
|
644
718
|
const planPath = resolve2(args.plan);
|
|
645
719
|
const loaded = loadPlanFile(planPath);
|
|
646
720
|
if (!loaded) {
|
|
647
|
-
|
|
721
|
+
consola6.error(`Invalid plan file: ${planPath}`);
|
|
648
722
|
process.exit(1);
|
|
649
723
|
}
|
|
650
724
|
plan = loaded;
|
|
651
725
|
} else {
|
|
652
|
-
const defaultPlanPath =
|
|
653
|
-
if (
|
|
654
|
-
|
|
726
|
+
const defaultPlanPath = join3(root, "cmsassets-agent.plan.json");
|
|
727
|
+
if (existsSync3(defaultPlanPath)) {
|
|
728
|
+
consola6.info(`Found existing plan file: ${defaultPlanPath}`);
|
|
655
729
|
const loaded = loadPlanFile(defaultPlanPath);
|
|
656
730
|
if (loaded) {
|
|
657
731
|
plan = loaded;
|
|
658
732
|
} else {
|
|
659
|
-
|
|
733
|
+
consola6.warn("Plan file invalid, regenerating...");
|
|
660
734
|
plan = generatePlan(root, args);
|
|
661
735
|
}
|
|
662
736
|
} else {
|
|
@@ -669,21 +743,21 @@ var applyCommand = defineCommand4({
|
|
|
669
743
|
if (args["max-files"]) plan.policies.maxFilesAutoApply = parseInt(args["max-files"], 10);
|
|
670
744
|
if (args.force) plan.policies.maxFilesAutoApply = Number.MAX_SAFE_INTEGER;
|
|
671
745
|
if (args["dry-run"]) {
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
746
|
+
consola6.log("");
|
|
747
|
+
consola6.log(pc4.bold(" CMS Assets Agent \u2014 Dry Run"));
|
|
748
|
+
consola6.log(pc4.dim(" \u2500".repeat(25)));
|
|
749
|
+
consola6.log("");
|
|
750
|
+
consola6.log(` ${pc4.cyan("Install:")} ${plan.install.command}`);
|
|
751
|
+
consola6.log(` ${pc4.cyan("Env:")} ${plan.env.key}=${plan.env.placeholder}`);
|
|
752
|
+
consola6.log("");
|
|
679
753
|
for (const patch of plan.patches) {
|
|
680
754
|
const color = patch.confidence === "high" ? pc4.green : patch.confidence === "medium" ? pc4.yellow : pc4.red;
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
755
|
+
consola6.log(` ${color("\u25CF")} ${patch.filePath} ${pc4.dim(`[${patch.confidence}]`)}`);
|
|
756
|
+
consola6.log(` ${pc4.dim(patch.wrapTarget.originalCode)}`);
|
|
757
|
+
consola6.log(` ${pc4.green("\u2192 " + patch.wrapTarget.transformedCode)}`);
|
|
684
758
|
}
|
|
685
|
-
|
|
686
|
-
|
|
759
|
+
consola6.log("");
|
|
760
|
+
consola6.log(` ${pc4.dim("Run without --dry-run to apply these changes.")}`);
|
|
687
761
|
return;
|
|
688
762
|
}
|
|
689
763
|
let branchCreated = false;
|
|
@@ -695,16 +769,16 @@ var applyCommand = defineCommand4({
|
|
|
695
769
|
}
|
|
696
770
|
let installed = false;
|
|
697
771
|
if (args.install) {
|
|
698
|
-
|
|
772
|
+
consola6.info(`Installing: ${plan.install.command}`);
|
|
699
773
|
try {
|
|
700
774
|
const { execSync } = await import("child_process");
|
|
701
775
|
execSync(plan.install.command, { cwd: root, stdio: "inherit" });
|
|
702
776
|
installed = true;
|
|
703
777
|
} catch {
|
|
704
|
-
|
|
778
|
+
consola6.warn("Package install failed. You can install it manually later.");
|
|
705
779
|
}
|
|
706
780
|
}
|
|
707
|
-
|
|
781
|
+
consola6.info("Applying patches...");
|
|
708
782
|
const applyReport = await applyPlan(plan, {
|
|
709
783
|
dryRun: false,
|
|
710
784
|
includeTests: args["include-tests"],
|
|
@@ -730,27 +804,27 @@ var applyCommand = defineCommand4({
|
|
|
730
804
|
const { checkAiVerifyReady } = await import("./openaiClient-YGAFYB3X.js");
|
|
731
805
|
const ready = await checkAiVerifyReady(root);
|
|
732
806
|
if (!ready.ok) {
|
|
733
|
-
|
|
807
|
+
consola6.warn(` ${pc4.yellow("AI Verification skipped:")} ${ready.reason}`);
|
|
734
808
|
} else {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
const { aiReviewAll } = await import("./aiReview-
|
|
809
|
+
consola6.log("");
|
|
810
|
+
consola6.log(pc4.bold(" CMS Assets Agent \u2014 AI Verification"));
|
|
811
|
+
consola6.log(pc4.dim(" \u2500".repeat(25)));
|
|
812
|
+
consola6.log("");
|
|
813
|
+
const { aiReviewAll } = await import("./aiReview-JWBCUMGP.js");
|
|
740
814
|
aiReviewReport = await aiReviewAll(root, appliedPaths, plan, {
|
|
741
815
|
model: args["ai-model"] ?? "gpt-4o",
|
|
742
816
|
maxIterations: parseInt(args["ai-max-iterations"] ?? "3", 10)
|
|
743
817
|
});
|
|
744
|
-
|
|
745
|
-
|
|
818
|
+
consola6.log("");
|
|
819
|
+
consola6.log(` ${pc4.green("Passed:")} ${aiReviewReport.filesPassed} files`);
|
|
746
820
|
if (aiReviewReport.filesFixed > 0) {
|
|
747
|
-
|
|
821
|
+
consola6.log(` ${pc4.blue("Fixed:")} ${aiReviewReport.filesFixed} files`);
|
|
748
822
|
}
|
|
749
823
|
if (aiReviewReport.filesFailed > 0) {
|
|
750
|
-
|
|
824
|
+
consola6.log(` ${pc4.red("Failed:")} ${aiReviewReport.filesFailed} files`);
|
|
751
825
|
}
|
|
752
|
-
|
|
753
|
-
|
|
826
|
+
consola6.log(` ${pc4.dim(`Tokens used: ${aiReviewReport.tokensUsed}`)}`);
|
|
827
|
+
consola6.log("");
|
|
754
828
|
if (aiReviewReport.filesFixed > 0 && gitOps.isGitRepo(root) && branchCreated) {
|
|
755
829
|
gitOps.stageAll(root);
|
|
756
830
|
gitOps.commit(root, "chore(cmsassets-agent): AI-verified fixes for missed transforms");
|
|
@@ -767,47 +841,47 @@ var applyCommand = defineCommand4({
|
|
|
767
841
|
saveReport(root, report);
|
|
768
842
|
const applied = applyReport.files.filter((f) => f.applied);
|
|
769
843
|
const skipped = applyReport.files.filter((f) => !f.applied);
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
844
|
+
consola6.log("");
|
|
845
|
+
consola6.log(pc4.bold(" CMS Assets Agent \u2014 Apply Complete"));
|
|
846
|
+
consola6.log(pc4.dim(" \u2500".repeat(25)));
|
|
847
|
+
consola6.log("");
|
|
848
|
+
consola6.log(` ${pc4.green("Applied:")} ${applied.length} files`);
|
|
849
|
+
consola6.log(` ${pc4.yellow("Skipped:")} ${skipped.length} files`);
|
|
850
|
+
consola6.log(` ${pc4.cyan("Duration:")} ${applyReport.totalDurationMs}ms`);
|
|
777
851
|
if (applyReport.gitBranch) {
|
|
778
|
-
|
|
852
|
+
consola6.log(` ${pc4.cyan("Branch:")} ${applyReport.gitBranch}`);
|
|
779
853
|
}
|
|
780
854
|
if (applyReport.gitCommit) {
|
|
781
|
-
|
|
855
|
+
consola6.log(` ${pc4.cyan("Commit:")} ${applyReport.gitCommit}`);
|
|
782
856
|
}
|
|
783
|
-
|
|
857
|
+
consola6.log("");
|
|
784
858
|
for (const file of applied) {
|
|
785
|
-
|
|
859
|
+
consola6.log(` ${pc4.green("\u2713")} ${file.filePath} ${pc4.dim(`(${file.method}, ${file.durationMs}ms)`)}`);
|
|
786
860
|
}
|
|
787
861
|
for (const file of skipped) {
|
|
788
|
-
|
|
862
|
+
consola6.log(` ${pc4.yellow("\u25CB")} ${file.filePath} ${pc4.dim(`\u2014 ${file.reason}`)}`);
|
|
789
863
|
}
|
|
790
|
-
|
|
864
|
+
consola6.log("");
|
|
791
865
|
if (scriptAdded) {
|
|
792
|
-
|
|
866
|
+
consola6.log(` ${pc4.green("Script:")} Added "cmsassets:transform" to package.json`);
|
|
793
867
|
}
|
|
794
868
|
if (!installed) {
|
|
795
|
-
|
|
869
|
+
consola6.log(` ${pc4.dim("Don't forget to install:")} ${pc4.cyan(plan.install.command)}`);
|
|
796
870
|
}
|
|
797
871
|
if (!applyReport.envUpdated) {
|
|
798
|
-
|
|
872
|
+
consola6.log(` ${pc4.dim("Set your env var:")} ${pc4.cyan(`${plan.env.key}=${plan.env.placeholder}`)}`);
|
|
799
873
|
}
|
|
800
874
|
if (scriptAdded) {
|
|
801
|
-
|
|
875
|
+
consola6.log(` ${pc4.dim("Re-run later with:")} ${pc4.cyan("npm run cmsassets:transform")}`);
|
|
802
876
|
}
|
|
803
|
-
|
|
877
|
+
consola6.log("");
|
|
804
878
|
if (args["create-pr"] && gitOps.isGitRepo(root)) {
|
|
805
879
|
const token = args["github-token"] ?? process.env.GITHUB_TOKEN;
|
|
806
880
|
if (!token) {
|
|
807
|
-
|
|
881
|
+
consola6.warn("No GitHub token provided. Use --github-token or set GITHUB_TOKEN.");
|
|
808
882
|
return;
|
|
809
883
|
}
|
|
810
|
-
|
|
884
|
+
consola6.info("Pushing branch and creating PR...");
|
|
811
885
|
const pushed = gitOps.push(root);
|
|
812
886
|
if (pushed) {
|
|
813
887
|
try {
|
|
@@ -823,7 +897,7 @@ var applyCommand = defineCommand4({
|
|
|
823
897
|
{ cwd: root, stdio: "inherit", env: { ...process.env, GITHUB_TOKEN: token } }
|
|
824
898
|
);
|
|
825
899
|
} catch {
|
|
826
|
-
|
|
900
|
+
consola6.warn("PR creation failed. Push was successful, create PR manually.");
|
|
827
901
|
}
|
|
828
902
|
}
|
|
829
903
|
}
|
|
@@ -842,7 +916,7 @@ function generatePlan(root, args) {
|
|
|
842
916
|
// src/commands/verify.ts
|
|
843
917
|
import { resolve as resolve3 } from "path";
|
|
844
918
|
import { defineCommand as defineCommand5 } from "citty";
|
|
845
|
-
import
|
|
919
|
+
import consola7 from "consola";
|
|
846
920
|
import pc5 from "picocolors";
|
|
847
921
|
var verifyCommand = defineCommand5({
|
|
848
922
|
meta: {
|
|
@@ -864,38 +938,38 @@ var verifyCommand = defineCommand5({
|
|
|
864
938
|
async run({ args }) {
|
|
865
939
|
const root = resolve3(args.dir);
|
|
866
940
|
const scanResult = scan(root);
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
941
|
+
consola7.log("");
|
|
942
|
+
consola7.log(pc5.bold(` CMS Assets Agent \u2014 Verify (${args.profile})`));
|
|
943
|
+
consola7.log(pc5.dim(" \u2500".repeat(25)));
|
|
944
|
+
consola7.log("");
|
|
871
945
|
const report = verify(root, {
|
|
872
946
|
profile: args.profile,
|
|
873
947
|
framework: scanResult.framework.name
|
|
874
948
|
});
|
|
875
|
-
|
|
949
|
+
consola7.log("");
|
|
876
950
|
const pass = pc5.green("PASS");
|
|
877
951
|
const fail = pc5.red("FAIL");
|
|
878
952
|
const skip = pc5.dim("SKIP");
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
953
|
+
consola7.log(` Lint: ${report.lintPassed === null ? skip : report.lintPassed ? pass : fail}`);
|
|
954
|
+
consola7.log(` Build: ${report.buildPassed === null ? skip : report.buildPassed ? pass : fail}`);
|
|
955
|
+
consola7.log(` Tests: ${report.testsPassed === null ? skip : report.testsPassed ? pass : fail}`);
|
|
956
|
+
consola7.log(` ${pc5.dim(`Duration: ${report.durationMs}ms`)}`);
|
|
883
957
|
if (report.warnings.length > 0) {
|
|
884
|
-
|
|
885
|
-
|
|
958
|
+
consola7.log("");
|
|
959
|
+
consola7.log(pc5.yellow(" Warnings:"));
|
|
886
960
|
for (const w of report.warnings) {
|
|
887
|
-
|
|
961
|
+
consola7.log(` ${pc5.dim("\u2022")} ${w.substring(0, 120)}`);
|
|
888
962
|
}
|
|
889
963
|
}
|
|
890
|
-
|
|
964
|
+
consola7.log("");
|
|
891
965
|
}
|
|
892
966
|
});
|
|
893
967
|
|
|
894
968
|
// src/commands/doctor.ts
|
|
895
|
-
import { existsSync as
|
|
896
|
-
import { resolve as resolve4, join as
|
|
969
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
|
|
970
|
+
import { resolve as resolve4, join as join4 } from "path";
|
|
897
971
|
import { defineCommand as defineCommand6 } from "citty";
|
|
898
|
-
import
|
|
972
|
+
import consola8 from "consola";
|
|
899
973
|
import pc6 from "picocolors";
|
|
900
974
|
var doctorCommand = defineCommand6({
|
|
901
975
|
meta: {
|
|
@@ -914,8 +988,8 @@ var doctorCommand = defineCommand6({
|
|
|
914
988
|
const checks = [];
|
|
915
989
|
checks.push({
|
|
916
990
|
label: "package.json",
|
|
917
|
-
ok:
|
|
918
|
-
detail:
|
|
991
|
+
ok: existsSync4(join4(root, "package.json")),
|
|
992
|
+
detail: existsSync4(join4(root, "package.json")) ? "Found" : "Missing \u2014 this may not be a JS/TS project"
|
|
919
993
|
});
|
|
920
994
|
const isGit = gitOps.isGitRepo(root);
|
|
921
995
|
checks.push({
|
|
@@ -955,7 +1029,7 @@ var doctorCommand = defineCommand6({
|
|
|
955
1029
|
});
|
|
956
1030
|
let pkgJson = {};
|
|
957
1031
|
try {
|
|
958
|
-
pkgJson = JSON.parse(
|
|
1032
|
+
pkgJson = JSON.parse(readFileSync4(join4(root, "package.json"), "utf-8"));
|
|
959
1033
|
} catch {
|
|
960
1034
|
}
|
|
961
1035
|
const allDeps = { ...pkgJson.dependencies ?? {}, ...pkgJson.devDependencies ?? {} };
|
|
@@ -968,9 +1042,9 @@ var doctorCommand = defineCommand6({
|
|
|
968
1042
|
const envFiles = [".env", ".env.local", ".env.development"];
|
|
969
1043
|
let hasEnvVar = false;
|
|
970
1044
|
for (const f of envFiles) {
|
|
971
|
-
const p =
|
|
972
|
-
if (
|
|
973
|
-
const content =
|
|
1045
|
+
const p = join4(root, f);
|
|
1046
|
+
if (existsSync4(p)) {
|
|
1047
|
+
const content = readFileSync4(p, "utf-8");
|
|
974
1048
|
if (content.includes("CMS_ASSETS_URL")) {
|
|
975
1049
|
hasEnvVar = true;
|
|
976
1050
|
break;
|
|
@@ -982,30 +1056,30 @@ var doctorCommand = defineCommand6({
|
|
|
982
1056
|
ok: true,
|
|
983
1057
|
detail: hasEnvVar ? "Set in .env file" : "Not set \u2014 you will need to add CMS_ASSETS_URL=https://YOUR-SLUG.cmsassets.com"
|
|
984
1058
|
});
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1059
|
+
consola8.log("");
|
|
1060
|
+
consola8.log(pc6.bold(" CMS Assets Agent \u2014 Doctor"));
|
|
1061
|
+
consola8.log(pc6.dim(" \u2500".repeat(25)));
|
|
1062
|
+
consola8.log("");
|
|
989
1063
|
for (const check of checks) {
|
|
990
1064
|
const icon = check.ok ? pc6.green("\u2713") : pc6.yellow("!");
|
|
991
|
-
|
|
992
|
-
|
|
1065
|
+
consola8.log(` ${icon} ${pc6.bold(check.label)}`);
|
|
1066
|
+
consola8.log(` ${pc6.dim(check.detail)}`);
|
|
993
1067
|
}
|
|
994
|
-
|
|
1068
|
+
consola8.log("");
|
|
995
1069
|
const issues = checks.filter((c) => !c.ok);
|
|
996
1070
|
if (issues.length === 0) {
|
|
997
|
-
|
|
1071
|
+
consola8.log(pc6.green(" All checks passed. Ready to run: cmsassets-agent plan"));
|
|
998
1072
|
} else {
|
|
999
|
-
|
|
1073
|
+
consola8.log(pc6.yellow(` ${issues.length} issue(s) found. Fix them before running apply.`));
|
|
1000
1074
|
}
|
|
1001
|
-
|
|
1075
|
+
consola8.log("");
|
|
1002
1076
|
}
|
|
1003
1077
|
});
|
|
1004
1078
|
|
|
1005
1079
|
// src/commands/rollback.ts
|
|
1006
1080
|
import { resolve as resolve5 } from "path";
|
|
1007
1081
|
import { defineCommand as defineCommand7 } from "citty";
|
|
1008
|
-
import
|
|
1082
|
+
import consola9 from "consola";
|
|
1009
1083
|
import pc7 from "picocolors";
|
|
1010
1084
|
var rollbackCommand = defineCommand7({
|
|
1011
1085
|
meta: {
|
|
@@ -1026,37 +1100,37 @@ var rollbackCommand = defineCommand7({
|
|
|
1026
1100
|
async run({ args }) {
|
|
1027
1101
|
const root = resolve5(args.dir);
|
|
1028
1102
|
if (!gitOps.isGitRepo(root)) {
|
|
1029
|
-
|
|
1103
|
+
consola9.error("Not a git repository. Cannot rollback.");
|
|
1030
1104
|
process.exit(1);
|
|
1031
1105
|
}
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1106
|
+
consola9.log("");
|
|
1107
|
+
consola9.log(pc7.bold(" CMS Assets Agent \u2014 Rollback"));
|
|
1108
|
+
consola9.log(pc7.dim(" \u2500".repeat(25)));
|
|
1109
|
+
consola9.log("");
|
|
1036
1110
|
let targetCommit = null;
|
|
1037
1111
|
if (args.commit) {
|
|
1038
1112
|
targetCommit = args.commit;
|
|
1039
1113
|
} else {
|
|
1040
1114
|
const agentCommit = gitOps.getLastCommitByAgent(root);
|
|
1041
1115
|
if (!agentCommit) {
|
|
1042
|
-
|
|
1116
|
+
consola9.error("No agent commit found in git history.");
|
|
1043
1117
|
process.exit(1);
|
|
1044
1118
|
}
|
|
1045
1119
|
targetCommit = gitOps.getCommitBefore(root, agentCommit);
|
|
1046
1120
|
if (!targetCommit) {
|
|
1047
|
-
|
|
1121
|
+
consola9.error("Cannot find parent commit for rollback.");
|
|
1048
1122
|
process.exit(1);
|
|
1049
1123
|
}
|
|
1050
1124
|
}
|
|
1051
|
-
|
|
1125
|
+
consola9.info(`Rolling back to commit: ${targetCommit}`);
|
|
1052
1126
|
const success = gitOps.rollbackToCommit(root, targetCommit);
|
|
1053
1127
|
if (success) {
|
|
1054
|
-
|
|
1128
|
+
consola9.success(`Rollback complete. HEAD is now at ${targetCommit}`);
|
|
1055
1129
|
} else {
|
|
1056
|
-
|
|
1130
|
+
consola9.error("Rollback failed. Check your git state manually.");
|
|
1057
1131
|
process.exit(1);
|
|
1058
1132
|
}
|
|
1059
|
-
|
|
1133
|
+
consola9.log("");
|
|
1060
1134
|
}
|
|
1061
1135
|
});
|
|
1062
1136
|
|
|
@@ -1083,7 +1157,7 @@ function findProjectRootEnv(startDir) {
|
|
|
1083
1157
|
let dir = resolve6(startDir);
|
|
1084
1158
|
for (let i = 0; i < 6; i++) {
|
|
1085
1159
|
const envPath = resolve6(dir, ".env");
|
|
1086
|
-
if (
|
|
1160
|
+
if (existsSync5(envPath)) return envPath;
|
|
1087
1161
|
const parent = pathDirname(dir);
|
|
1088
1162
|
if (parent === dir) break;
|
|
1089
1163
|
dir = parent;
|
|
@@ -1097,7 +1171,7 @@ envPaths.push(resolve6(cwd, ".env"));
|
|
|
1097
1171
|
var projectRootEnv = findProjectRootEnv(cliDir);
|
|
1098
1172
|
if (projectRootEnv && !envPaths.includes(projectRootEnv)) envPaths.push(projectRootEnv);
|
|
1099
1173
|
for (const p of envPaths) {
|
|
1100
|
-
if (
|
|
1174
|
+
if (existsSync5(p)) {
|
|
1101
1175
|
dotenvConfig({ path: p });
|
|
1102
1176
|
if (process.env.OPENAI_API_KEY) break;
|
|
1103
1177
|
}
|