kairn-cli 1.11.0 → 1.13.0
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.js +245 -21
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -256,6 +256,113 @@ var ui = {
|
|
|
256
256
|
`);
|
|
257
257
|
}
|
|
258
258
|
};
|
|
259
|
+
function formatTime(seconds) {
|
|
260
|
+
if (seconds < 60) return `${seconds}s`;
|
|
261
|
+
const min = Math.floor(seconds / 60);
|
|
262
|
+
const sec = seconds % 60;
|
|
263
|
+
return sec > 0 ? `${min}m ${sec}s` : `${min} min`;
|
|
264
|
+
}
|
|
265
|
+
function estimateTime(model, intent) {
|
|
266
|
+
const wordCount = intent.split(/\s+/).length;
|
|
267
|
+
const isComplex = wordCount > 40;
|
|
268
|
+
const perPass = {
|
|
269
|
+
"haiku": 5,
|
|
270
|
+
"sonnet": 20,
|
|
271
|
+
"opus": 60,
|
|
272
|
+
"gpt-4.1-mini": 10,
|
|
273
|
+
"gpt-4.1": 25,
|
|
274
|
+
"gpt-5": 15,
|
|
275
|
+
"o4-mini": 12,
|
|
276
|
+
"gemini-2.5-flash": 8,
|
|
277
|
+
"gemini-3-flash": 8,
|
|
278
|
+
"gemini-2.5-pro": 30,
|
|
279
|
+
"gemini-3.1-pro": 30,
|
|
280
|
+
"grok-4.1-fast": 10,
|
|
281
|
+
"grok-4.20": 25,
|
|
282
|
+
"deepseek": 15,
|
|
283
|
+
"mistral-large": 20,
|
|
284
|
+
"codestral": 15,
|
|
285
|
+
"mistral-small": 10,
|
|
286
|
+
"llama": 10,
|
|
287
|
+
"qwen": 10
|
|
288
|
+
};
|
|
289
|
+
const basePerPass = Object.entries(perPass).find(([k]) => model.toLowerCase().includes(k))?.[1] ?? 20;
|
|
290
|
+
const totalBase = basePerPass * 2;
|
|
291
|
+
if (isComplex) {
|
|
292
|
+
const low = Math.floor(totalBase * 1.5);
|
|
293
|
+
const high = Math.floor(totalBase * 4);
|
|
294
|
+
return `~${formatTime(low)}-${formatTime(high)} (complex workflow)`;
|
|
295
|
+
}
|
|
296
|
+
return `~${formatTime(totalBase)}`;
|
|
297
|
+
}
|
|
298
|
+
function createProgressRenderer() {
|
|
299
|
+
const lines = [];
|
|
300
|
+
let intervalId = null;
|
|
301
|
+
let currentPhase = "";
|
|
302
|
+
let phaseStart = Date.now();
|
|
303
|
+
let lineCount = 0;
|
|
304
|
+
function render() {
|
|
305
|
+
if (lineCount > 0) {
|
|
306
|
+
process.stdout.write(`\x1B[${lineCount}A`);
|
|
307
|
+
}
|
|
308
|
+
for (const line of lines) {
|
|
309
|
+
process.stdout.write("\x1B[2K" + line + "\n");
|
|
310
|
+
}
|
|
311
|
+
lineCount = lines.length;
|
|
312
|
+
}
|
|
313
|
+
function updateElapsed() {
|
|
314
|
+
if (!currentPhase) return;
|
|
315
|
+
const elapsed = Math.floor((Date.now() - phaseStart) / 1e3);
|
|
316
|
+
const lastIdx = lines.length - 1;
|
|
317
|
+
if (lastIdx >= 0) {
|
|
318
|
+
lines[lastIdx] = lines[lastIdx].replace(/\[\d+s\]/, `[${elapsed}s]`);
|
|
319
|
+
render();
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
return {
|
|
323
|
+
update(progress) {
|
|
324
|
+
if (progress.status === "running") {
|
|
325
|
+
currentPhase = progress.phase;
|
|
326
|
+
phaseStart = Date.now();
|
|
327
|
+
lines.push(` ${warmStone("\u25D0")} ${progress.message} ${chalk.dim("[0s]")}`);
|
|
328
|
+
if (!intervalId) {
|
|
329
|
+
intervalId = setInterval(updateElapsed, 1e3);
|
|
330
|
+
}
|
|
331
|
+
} else if (progress.status === "success") {
|
|
332
|
+
const lastIdx = lines.length - 1;
|
|
333
|
+
const elapsed = progress.elapsed != null ? ` ${chalk.dim("\u2014")} ${chalk.dim(Math.floor(progress.elapsed) + "s")}` : "";
|
|
334
|
+
const detail = progress.detail ? ` ${chalk.dim("(" + progress.detail + ")")}` : "";
|
|
335
|
+
if (lastIdx >= 0) {
|
|
336
|
+
lines[lastIdx] = ` ${chalk.green("\u2714")} ${progress.message}${detail}${elapsed}`;
|
|
337
|
+
}
|
|
338
|
+
currentPhase = "";
|
|
339
|
+
} else if (progress.status === "warning") {
|
|
340
|
+
const lastIdx = lines.length - 1;
|
|
341
|
+
if (lastIdx >= 0) {
|
|
342
|
+
lines[lastIdx] = ` ${chalk.yellow("\u26A0")} ${progress.message}`;
|
|
343
|
+
}
|
|
344
|
+
currentPhase = progress.phase;
|
|
345
|
+
phaseStart = Date.now();
|
|
346
|
+
lines.push(` ${warmStone("\u25D0")} Retrying in concise mode... ${chalk.dim("[0s]")}`);
|
|
347
|
+
}
|
|
348
|
+
render();
|
|
349
|
+
},
|
|
350
|
+
finish() {
|
|
351
|
+
if (intervalId) clearInterval(intervalId);
|
|
352
|
+
currentPhase = "";
|
|
353
|
+
render();
|
|
354
|
+
},
|
|
355
|
+
fail(err) {
|
|
356
|
+
if (intervalId) clearInterval(intervalId);
|
|
357
|
+
currentPhase = "";
|
|
358
|
+
const lastIdx = lines.length - 1;
|
|
359
|
+
if (lastIdx >= 0) {
|
|
360
|
+
lines[lastIdx] = ` ${chalk.red("\u2716")} Compilation failed`;
|
|
361
|
+
}
|
|
362
|
+
render();
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
259
366
|
|
|
260
367
|
// src/logo.ts
|
|
261
368
|
import chalk2 from "chalk";
|
|
@@ -450,7 +557,6 @@ var initCommand = new Command("init").description("Set up Kairn with your API ke
|
|
|
450
557
|
import { Command as Command2 } from "commander";
|
|
451
558
|
import { input as input2, confirm, select as select2 } from "@inquirer/prompts";
|
|
452
559
|
import chalk5 from "chalk";
|
|
453
|
-
import ora from "ora";
|
|
454
560
|
|
|
455
561
|
// src/compiler/compile.ts
|
|
456
562
|
import fs4 from "fs/promises";
|
|
@@ -600,6 +706,16 @@ Use subagents for deep investigation to keep main context clean.
|
|
|
600
706
|
- Do not create abstractions for one-time operations
|
|
601
707
|
- Complete the task fully \u2014 don't gold-plate, but don't leave it half-done
|
|
602
708
|
- Prefer editing existing files over creating new ones
|
|
709
|
+
|
|
710
|
+
## First Turn Protocol
|
|
711
|
+
|
|
712
|
+
At the start of every session, before doing ANY work:
|
|
713
|
+
1. Run \`pwd && ls -la && git status --short\` to orient yourself
|
|
714
|
+
2. Check relevant runtimes (e.g. \`node --version\`, \`python3 --version\` \u2014 pick what fits this project)
|
|
715
|
+
3. Read any task-tracking files (docs/SPRINT.md, docs/DECISIONS.md)
|
|
716
|
+
4. Summarize what you see in 2-3 lines, then proceed
|
|
717
|
+
|
|
718
|
+
This saves 2-5 exploratory turns. Never ask "what files are here?" \u2014 look first.
|
|
603
719
|
\`\`\`
|
|
604
720
|
|
|
605
721
|
Do not add generic filler. Every line must be specific to the user's workflow.
|
|
@@ -621,6 +737,7 @@ Do not add generic filler. Every line must be specific to the user's workflow.
|
|
|
621
737
|
13. A "Debugging" section in CLAUDE.md (2 lines: paste raw errors, use subagents)
|
|
622
738
|
14. A "Git Workflow" section in CLAUDE.md (3 rules: small commits, conventional format, <200 lines PR)
|
|
623
739
|
15. "Engineering Standards", "Tool Usage Policy", and "Code Philosophy" sections in CLAUDE.md
|
|
740
|
+
16. A "First Turn Protocol" section in CLAUDE.md (orient before working: pwd, ls, git status, check relevant runtimes, read task files)
|
|
624
741
|
|
|
625
742
|
## Shell-Integrated Commands
|
|
626
743
|
|
|
@@ -896,6 +1013,16 @@ Use subagents for deep investigation to keep main context clean.
|
|
|
896
1013
|
- Do not create abstractions for one-time operations
|
|
897
1014
|
- Complete the task fully \u2014 don't gold-plate, but don't leave it half-done
|
|
898
1015
|
- Prefer editing existing files over creating new ones
|
|
1016
|
+
|
|
1017
|
+
## First Turn Protocol
|
|
1018
|
+
|
|
1019
|
+
At the start of every session, before doing ANY work:
|
|
1020
|
+
1. Run \`pwd && ls -la && git status --short\` to orient yourself
|
|
1021
|
+
2. Check relevant runtimes (e.g. \`node --version\`, \`python3 --version\` \u2014 pick what fits this project)
|
|
1022
|
+
3. Read any task-tracking files (docs/SPRINT.md, docs/DECISIONS.md)
|
|
1023
|
+
4. Summarize what you see in 2-3 lines, then proceed
|
|
1024
|
+
|
|
1025
|
+
This saves 2-5 exploratory turns. Never ask "what files are here?" \u2014 look first.
|
|
899
1026
|
\`\`\`
|
|
900
1027
|
|
|
901
1028
|
Do not add generic filler. Every line must be specific to the user's workflow.
|
|
@@ -917,6 +1044,7 @@ Do not add generic filler. Every line must be specific to the user's workflow.
|
|
|
917
1044
|
13. A "Debugging" section in CLAUDE.md (2 lines: paste raw errors, use subagents)
|
|
918
1045
|
14. A "Git Workflow" section in CLAUDE.md (3 rules: small commits, conventional format, <200 lines PR)
|
|
919
1046
|
15. "Engineering Standards", "Tool Usage Policy", and "Code Philosophy" sections in CLAUDE.md
|
|
1047
|
+
16. A "First Turn Protocol" section in CLAUDE.md (orient before working: pwd, ls, git status, check relevant runtimes, read task files)
|
|
920
1048
|
|
|
921
1049
|
## Tool Selection Rules
|
|
922
1050
|
|
|
@@ -1264,7 +1392,7 @@ function buildMcpConfig(skeleton, registry) {
|
|
|
1264
1392
|
}
|
|
1265
1393
|
return config;
|
|
1266
1394
|
}
|
|
1267
|
-
function validateSpec(spec
|
|
1395
|
+
function validateSpec(spec) {
|
|
1268
1396
|
const warnings = [];
|
|
1269
1397
|
if (spec.tools.length > 8) {
|
|
1270
1398
|
warnings.push(`${spec.tools.length} MCP servers selected (recommended: \u22646)`);
|
|
@@ -1278,25 +1406,33 @@ function validateSpec(spec, onProgress) {
|
|
|
1278
1406
|
if (spec.harness.skills && Object.keys(spec.harness.skills).length > 5) {
|
|
1279
1407
|
warnings.push(`${Object.keys(spec.harness.skills).length} skills (recommended: \u22643)`);
|
|
1280
1408
|
}
|
|
1281
|
-
|
|
1282
|
-
onProgress?.(`\u26A0 ${warning}`);
|
|
1283
|
-
}
|
|
1409
|
+
return warnings;
|
|
1284
1410
|
}
|
|
1285
1411
|
async function compile(intent, onProgress) {
|
|
1412
|
+
const startTime = Date.now();
|
|
1286
1413
|
const config = await loadConfig();
|
|
1287
1414
|
if (!config) {
|
|
1288
1415
|
throw new Error("No config found. Run `kairn init` first.");
|
|
1289
1416
|
}
|
|
1290
|
-
onProgress?.("Loading tool registry...");
|
|
1417
|
+
onProgress?.({ phase: "registry", status: "running", message: "Loading tool registry..." });
|
|
1291
1418
|
const registry = await loadRegistry();
|
|
1292
|
-
onProgress?.("
|
|
1419
|
+
onProgress?.({ phase: "registry", status: "success", message: "Tool registry loaded", detail: `${registry.length} tools` });
|
|
1420
|
+
onProgress?.({ phase: "pass1", status: "running", message: "Pass 1: Analyzing workflow & selecting tools..." });
|
|
1293
1421
|
const skeletonMsg = buildSkeletonMessage(intent, registry);
|
|
1294
1422
|
const skeletonText = await callLLM(config, skeletonMsg, {
|
|
1295
1423
|
maxTokens: 2048,
|
|
1296
1424
|
systemPrompt: SKELETON_PROMPT
|
|
1297
1425
|
});
|
|
1298
1426
|
const skeleton = parseSkeletonResponse(skeletonText);
|
|
1299
|
-
|
|
1427
|
+
const toolNames = skeleton.tools.map((t) => t.tool_id).join(", ");
|
|
1428
|
+
onProgress?.({
|
|
1429
|
+
phase: "pass1",
|
|
1430
|
+
status: "success",
|
|
1431
|
+
message: `Pass 1: Selected ${skeleton.tools.length} tools`,
|
|
1432
|
+
detail: toolNames,
|
|
1433
|
+
elapsed: (Date.now() - startTime) / 1e3
|
|
1434
|
+
});
|
|
1435
|
+
onProgress?.({ phase: "pass2", status: "running", message: "Pass 2: Generating CLAUDE.md, commands, agents..." });
|
|
1300
1436
|
const harnessMsg = buildHarnessMessage(intent, skeleton);
|
|
1301
1437
|
let harness;
|
|
1302
1438
|
try {
|
|
@@ -1306,7 +1442,7 @@ async function compile(intent, onProgress) {
|
|
|
1306
1442
|
});
|
|
1307
1443
|
harness = parseHarnessResponse(harnessText);
|
|
1308
1444
|
} catch {
|
|
1309
|
-
onProgress?.("
|
|
1445
|
+
onProgress?.({ phase: "pass2-retry", status: "warning", message: "Pass 2: Response too large, retrying in concise mode..." });
|
|
1310
1446
|
const retryMsg = buildHarnessMessage(intent, skeleton, true);
|
|
1311
1447
|
const retryText = await callLLM(config, retryMsg, {
|
|
1312
1448
|
maxTokens: 8192,
|
|
@@ -1314,9 +1450,19 @@ async function compile(intent, onProgress) {
|
|
|
1314
1450
|
});
|
|
1315
1451
|
harness = parseHarnessResponse(retryText);
|
|
1316
1452
|
}
|
|
1317
|
-
|
|
1453
|
+
const cmdCount = Object.keys(harness.commands).length;
|
|
1454
|
+
const agentCount = Object.keys(harness.agents ?? {}).length;
|
|
1455
|
+
const ruleCount = Object.keys(harness.rules).length;
|
|
1456
|
+
onProgress?.({
|
|
1457
|
+
phase: "pass2",
|
|
1458
|
+
status: "success",
|
|
1459
|
+
message: `Pass 2: Generated ${cmdCount} commands, ${agentCount} agents, ${ruleCount} rules`,
|
|
1460
|
+
elapsed: (Date.now() - startTime) / 1e3
|
|
1461
|
+
});
|
|
1462
|
+
onProgress?.({ phase: "pass3", status: "running", message: "Pass 3: Configuring MCP servers & settings..." });
|
|
1318
1463
|
const settings = buildSettings(skeleton, registry);
|
|
1319
1464
|
const mcpConfig = buildMcpConfig(skeleton, registry);
|
|
1465
|
+
onProgress?.({ phase: "pass3", status: "success", message: "Pass 3: Configured MCP servers & settings" });
|
|
1320
1466
|
const spec = {
|
|
1321
1467
|
id: `env_${crypto.randomUUID()}`,
|
|
1322
1468
|
intent,
|
|
@@ -1336,7 +1482,12 @@ async function compile(intent, onProgress) {
|
|
|
1336
1482
|
docs: harness.docs
|
|
1337
1483
|
}
|
|
1338
1484
|
};
|
|
1339
|
-
validateSpec(spec
|
|
1485
|
+
const warnings = validateSpec(spec);
|
|
1486
|
+
for (const w of warnings) {
|
|
1487
|
+
onProgress?.({ phase: "done", status: "warning", message: `\u26A0 ${w}` });
|
|
1488
|
+
}
|
|
1489
|
+
const totalElapsed = ((Date.now() - startTime) / 1e3).toFixed(0);
|
|
1490
|
+
onProgress?.({ phase: "done", status: "success", message: `Environment compiled in ${totalElapsed}s`, elapsed: (Date.now() - startTime) / 1e3 });
|
|
1340
1491
|
await ensureDirs();
|
|
1341
1492
|
const envPath = path4.join(getEnvsDir(), `${spec.id}.json`);
|
|
1342
1493
|
await fs4.writeFile(envPath, JSON.stringify(spec, null, 2), "utf-8");
|
|
@@ -1448,6 +1599,61 @@ ${agentList}
|
|
|
1448
1599
|
Type \`/project:help\` in Claude Code for a quick reference.
|
|
1449
1600
|
`;
|
|
1450
1601
|
}
|
|
1602
|
+
var BOOTSTRAP_COMMAND = `# Environment Snapshot
|
|
1603
|
+
|
|
1604
|
+
Run this command at the start of any session to gather runtime context.
|
|
1605
|
+
This saves 2-5 exploratory turns.
|
|
1606
|
+
|
|
1607
|
+
1. Run the following compound command and read the output:
|
|
1608
|
+
\`\`\`bash
|
|
1609
|
+
echo '=== WORKING DIRECTORY ===' && pwd && \\
|
|
1610
|
+
echo '=== PROJECT FILES ===' && ls -la && \\
|
|
1611
|
+
echo '=== GIT STATUS ===' && (git status --short 2>/dev/null || echo 'not a git repo') && \\
|
|
1612
|
+
echo '=== LANGUAGES ===' && \\
|
|
1613
|
+
(node --version 2>&1 || true) && \\
|
|
1614
|
+
(python3 --version 2>&1 || true) && \\
|
|
1615
|
+
(go version 2>&1 || true) && \\
|
|
1616
|
+
(rustc --version 2>&1 || true) && \\
|
|
1617
|
+
echo '=== PACKAGE MANAGERS ===' && \\
|
|
1618
|
+
(npm --version 2>&1 && echo "npm $(npm --version 2>&1)" || true) && \\
|
|
1619
|
+
(pip3 --version 2>&1 || true) && \\
|
|
1620
|
+
(cargo --version 2>&1 || true) && \\
|
|
1621
|
+
echo '=== ENVIRONMENT ===' && \\
|
|
1622
|
+
(cat .env 2>/dev/null | sed 's/=.*/=***/' || echo 'no .env file')
|
|
1623
|
+
\`\`\`
|
|
1624
|
+
|
|
1625
|
+
2. Summarize the environment in 3-4 lines:
|
|
1626
|
+
- Runtime: [languages + versions found]
|
|
1627
|
+
- Project: [framework, key deps, file count]
|
|
1628
|
+
- State: [git branch, clean/dirty, .env present]
|
|
1629
|
+
|
|
1630
|
+
3. Keep this summary in context for the rest of the session.`;
|
|
1631
|
+
function buildBootstrapHookCommand(spec) {
|
|
1632
|
+
const checks = [
|
|
1633
|
+
"echo '--- Environment Snapshot ---'",
|
|
1634
|
+
"pwd",
|
|
1635
|
+
"ls -la --color=never | head -20",
|
|
1636
|
+
"echo '---'",
|
|
1637
|
+
"git status --short 2>/dev/null || true",
|
|
1638
|
+
"echo '---'"
|
|
1639
|
+
];
|
|
1640
|
+
const md = (spec.harness.claude_md ?? "").toLowerCase();
|
|
1641
|
+
if (md.includes("node") || md.includes("typescript") || md.includes("javascript") || md.includes("react") || md.includes("next")) {
|
|
1642
|
+
checks.push("node --version 2>&1 || true");
|
|
1643
|
+
checks.push("cat package.json 2>/dev/null | head -5 || true");
|
|
1644
|
+
}
|
|
1645
|
+
if (md.includes("python") || md.includes("django") || md.includes("flask") || md.includes("fastapi")) {
|
|
1646
|
+
checks.push("python3 --version 2>&1 || true");
|
|
1647
|
+
}
|
|
1648
|
+
if (md.includes("rust") || md.includes("cargo")) {
|
|
1649
|
+
checks.push("rustc --version 2>&1 || true");
|
|
1650
|
+
}
|
|
1651
|
+
if (md.includes("go ") || md.includes("golang")) {
|
|
1652
|
+
checks.push("go version 2>&1 || true");
|
|
1653
|
+
}
|
|
1654
|
+
checks.push("cat .env 2>/dev/null | sed 's/=.*/=***/' || true");
|
|
1655
|
+
return checks.join(" && ");
|
|
1656
|
+
}
|
|
1451
1657
|
var LOOP_COMMAND_CODE = `# Development Loop
|
|
1452
1658
|
|
|
1453
1659
|
Run an assisted development cycle for the next feature.
|
|
@@ -1621,6 +1827,9 @@ function applyAutonomyLevel(spec) {
|
|
|
1621
1827
|
settings.hooks = hooks;
|
|
1622
1828
|
}
|
|
1623
1829
|
if (level >= 2) {
|
|
1830
|
+
if (!("bootstrap" in commands)) {
|
|
1831
|
+
commands.bootstrap = BOOTSTRAP_COMMAND;
|
|
1832
|
+
}
|
|
1624
1833
|
if (!("loop" in commands)) {
|
|
1625
1834
|
commands.loop = isResearchProject(spec) ? LOOP_COMMAND_RESEARCH : LOOP_COMMAND_CODE;
|
|
1626
1835
|
}
|
|
@@ -1632,6 +1841,18 @@ function applyAutonomyLevel(spec) {
|
|
|
1632
1841
|
if (!("auto" in commands)) {
|
|
1633
1842
|
commands.auto = AUTO_COMMAND;
|
|
1634
1843
|
}
|
|
1844
|
+
const hooks = settings.hooks ?? {};
|
|
1845
|
+
const sessionStart = hooks.SessionStart ?? [];
|
|
1846
|
+
const bootstrapHook = {
|
|
1847
|
+
matcher: "",
|
|
1848
|
+
hooks: [{
|
|
1849
|
+
type: "command",
|
|
1850
|
+
command: buildBootstrapHookCommand(spec)
|
|
1851
|
+
}]
|
|
1852
|
+
};
|
|
1853
|
+
sessionStart.push(bootstrapHook);
|
|
1854
|
+
hooks.SessionStart = sessionStart;
|
|
1855
|
+
settings.hooks = hooks;
|
|
1635
1856
|
}
|
|
1636
1857
|
if (level >= 4) {
|
|
1637
1858
|
if (!("autopilot" in commands)) {
|
|
@@ -2112,16 +2333,19 @@ ${clarificationLines}`;
|
|
|
2112
2333
|
Autonomy level: ${autonomyLevel} (${autonomyLabel(autonomyLevel)})`;
|
|
2113
2334
|
}
|
|
2114
2335
|
console.log(ui.section("Compilation"));
|
|
2115
|
-
const
|
|
2336
|
+
const estimate = estimateTime(config.model, finalIntent);
|
|
2337
|
+
console.log(chalk5.dim(` Estimated time: ${estimate} (${config.model})`));
|
|
2338
|
+
console.log("");
|
|
2339
|
+
const renderer = createProgressRenderer();
|
|
2116
2340
|
let spec;
|
|
2117
2341
|
try {
|
|
2118
|
-
spec = await compile(finalIntent, (
|
|
2119
|
-
|
|
2342
|
+
spec = await compile(finalIntent, (progress) => {
|
|
2343
|
+
renderer.update(progress);
|
|
2120
2344
|
});
|
|
2121
2345
|
spec.autonomy_level = autonomyLevel;
|
|
2122
|
-
|
|
2346
|
+
renderer.finish();
|
|
2123
2347
|
} catch (err) {
|
|
2124
|
-
|
|
2348
|
+
renderer.fail(err);
|
|
2125
2349
|
const msg = err instanceof Error ? err.message : String(err);
|
|
2126
2350
|
console.log(chalk5.red(`
|
|
2127
2351
|
${msg}
|
|
@@ -2366,7 +2590,7 @@ var updateRegistryCommand = new Command5("update-registry").description("Fetch t
|
|
|
2366
2590
|
import { Command as Command6 } from "commander";
|
|
2367
2591
|
import { confirm as confirm2 } from "@inquirer/prompts";
|
|
2368
2592
|
import chalk9 from "chalk";
|
|
2369
|
-
import
|
|
2593
|
+
import ora from "ora";
|
|
2370
2594
|
import fs12 from "fs/promises";
|
|
2371
2595
|
import path12 from "path";
|
|
2372
2596
|
|
|
@@ -2691,7 +2915,7 @@ var optimizeCommand = new Command6("optimize").description("Scan an existing pro
|
|
|
2691
2915
|
}
|
|
2692
2916
|
const targetDir = process.cwd();
|
|
2693
2917
|
console.log(ui.section("Project Scan"));
|
|
2694
|
-
const scanSpinner =
|
|
2918
|
+
const scanSpinner = ora({ text: "Scanning project...", indent: 2 }).start();
|
|
2695
2919
|
const profile = await scanProject(targetDir);
|
|
2696
2920
|
scanSpinner.stop();
|
|
2697
2921
|
if (profile.language) console.log(ui.kv("Language:", profile.language));
|
|
@@ -2760,10 +2984,10 @@ var optimizeCommand = new Command6("optimize").description("Scan an existing pro
|
|
|
2760
2984
|
}
|
|
2761
2985
|
const intent = buildOptimizeIntent(profile);
|
|
2762
2986
|
let spec;
|
|
2763
|
-
const spinner =
|
|
2987
|
+
const spinner = ora({ text: "Compiling optimized environment...", indent: 2 }).start();
|
|
2764
2988
|
try {
|
|
2765
|
-
spec = await compile(intent, (
|
|
2766
|
-
spinner.text =
|
|
2989
|
+
spec = await compile(intent, (progress) => {
|
|
2990
|
+
spinner.text = progress.message;
|
|
2767
2991
|
});
|
|
2768
2992
|
spinner.succeed("Environment compiled");
|
|
2769
2993
|
} catch (err) {
|