agdi 2.6.0 → 2.6.2

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.
Files changed (3) hide show
  1. package/README.md +156 -406
  2. package/dist/index.js +313 -224
  3. package/package.json +8 -3
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
 
8
8
  // src/index.ts
9
9
  import { Command } from "commander";
10
- import chalk13 from "chalk";
10
+ import chalk14 from "chalk";
11
11
  import ora5 from "ora";
12
12
 
13
13
  // src/core/llm/index.ts
@@ -1425,12 +1425,115 @@ async function selectModel() {
1425
1425
 
1426
1426
  // src/commands/agdi-dev.ts
1427
1427
  import { input as input5, confirm as confirm3 } from "@inquirer/prompts";
1428
- import chalk12 from "chalk";
1429
- import ora4 from "ora";
1428
+ import chalk13 from "chalk";
1429
+
1430
+ // src/utils/ui.ts
1431
+ import chalk8 from "chalk";
1432
+ import gradient from "gradient-string";
1433
+ import boxen from "boxen";
1434
+ import figlet from "figlet";
1435
+ import ora3 from "ora";
1436
+ var THEME = {
1437
+ cyan: "#06b6d4",
1438
+ // Cyan-500
1439
+ purple: "#8b5cf6",
1440
+ // Violet-500
1441
+ red: "#ef4444",
1442
+ // Red-500
1443
+ yellow: "#eab308",
1444
+ // Yellow-500
1445
+ gray: "#71717a",
1446
+ // Zinc-500
1447
+ dim: "#52525b"
1448
+ // Zinc-600
1449
+ };
1450
+ var brandGradient = gradient([THEME.cyan, THEME.purple]);
1451
+ var errorGradient = gradient([THEME.red, "#b91c1c"]);
1452
+ var goldGradient = gradient([THEME.yellow, "#fbbf24"]);
1453
+ async function renderBanner(version = "v2.6.0") {
1454
+ console.clear();
1455
+ const text = await new Promise((resolve5) => {
1456
+ figlet("AGDI", { font: "Slant" }, (err, data) => {
1457
+ resolve5(data || "AGDI");
1458
+ });
1459
+ });
1460
+ console.log(brandGradient.multiline(text));
1461
+ console.log(chalk8.hex(THEME.dim)(` ${version} [ARCHITECT ONLINE]
1462
+ `));
1463
+ }
1464
+ function renderBox(title, content, style = "info") {
1465
+ let borderColor = THEME.cyan;
1466
+ let titleColor = chalk8.cyan;
1467
+ if (style === "success") {
1468
+ borderColor = THEME.cyan;
1469
+ } else if (style === "warning") {
1470
+ borderColor = THEME.yellow;
1471
+ titleColor = chalk8.yellow;
1472
+ } else if (style === "error") {
1473
+ borderColor = THEME.red;
1474
+ titleColor = chalk8.red;
1475
+ }
1476
+ const box = boxen(content, {
1477
+ title: titleColor.bold(title),
1478
+ padding: 1,
1479
+ margin: 1,
1480
+ borderStyle: "round",
1481
+ borderColor,
1482
+ dimBorder: false,
1483
+ float: "left"
1484
+ });
1485
+ console.log(box);
1486
+ }
1487
+ function renderAlert(title, message) {
1488
+ console.log("");
1489
+ const box = boxen(chalk8.white(message), {
1490
+ title: chalk8.red.bold(`\u{1F6E1}\uFE0F ${title.toUpperCase()} `),
1491
+ padding: 1,
1492
+ borderStyle: "double",
1493
+ borderColor: "red",
1494
+ textAlignment: "center"
1495
+ });
1496
+ console.log(box);
1497
+ console.log("");
1498
+ }
1499
+ function printUserMessage(message) {
1500
+ console.log("");
1501
+ console.log(chalk8.cyan.bold("\u{1F464} YOU \u203A ") + chalk8.white(message));
1502
+ console.log("");
1503
+ }
1504
+ function printAIMessage(message) {
1505
+ console.log("");
1506
+ console.log(brandGradient.multiline("\u26A1 AGDI \u203A "));
1507
+ console.log(message.trim());
1508
+ console.log("");
1509
+ }
1510
+ function createSpinner(text) {
1511
+ return ora3({
1512
+ text: chalk8.hex(THEME.gray)(text),
1513
+ color: "cyan",
1514
+ spinner: "dots",
1515
+ discardStdin: false
1516
+ // Important for allowing interruption if needed
1517
+ });
1518
+ }
1519
+ function printIter() {
1520
+ console.log(chalk8.hex(THEME.dim)("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1521
+ }
1522
+ var ui = {
1523
+ renderBanner,
1524
+ renderBox,
1525
+ renderAlert,
1526
+ printUserMessage,
1527
+ printAIMessage,
1528
+ createSpinner,
1529
+ printIter,
1530
+ brandGradient,
1531
+ THEME
1532
+ };
1430
1533
 
1431
1534
  // src/actions/plan-executor.ts
1432
1535
  import { select as select4, confirm } from "@inquirer/prompts";
1433
- import chalk10 from "chalk";
1536
+ import chalk11 from "chalk";
1434
1537
  import { spawn as spawn2 } from "child_process";
1435
1538
  import { resolve as resolve4 } from "path";
1436
1539
 
@@ -1565,7 +1668,7 @@ import { existsSync as existsSync3 } from "fs";
1565
1668
  import { resolve, dirname, relative, isAbsolute } from "path";
1566
1669
 
1567
1670
  // src/security/execution-env.ts
1568
- import chalk8 from "chalk";
1671
+ import chalk9 from "chalk";
1569
1672
  import { platform } from "os";
1570
1673
  import { existsSync, readFileSync } from "fs";
1571
1674
  function detectWSL() {
@@ -1674,11 +1777,11 @@ function formatNetwork(policy, domains) {
1674
1777
  function formatTrust(trust) {
1675
1778
  switch (trust) {
1676
1779
  case "untrusted":
1677
- return chalk8.red("untrusted (read-only mode)");
1780
+ return chalk9.red("untrusted (read-only mode)");
1678
1781
  case "session":
1679
- return chalk8.yellow("session trusted");
1782
+ return chalk9.yellow("session trusted");
1680
1783
  case "persistent":
1681
- return chalk8.green("trusted");
1784
+ return chalk9.green("trusted");
1682
1785
  }
1683
1786
  }
1684
1787
  function displaySessionHeader(env) {
@@ -1692,12 +1795,12 @@ function displaySessionHeader(env) {
1692
1795
  `Network: ${formatNetwork(env.networkPolicy, env.allowedDomains)}`,
1693
1796
  `Trust: ${formatTrust(env.trustLevel)}`
1694
1797
  ];
1695
- console.log(chalk8.cyan(topBorder));
1798
+ console.log(chalk9.cyan(topBorder));
1696
1799
  for (const line of lines) {
1697
1800
  const padding = " ".repeat(Math.max(0, boxWidth - stripAnsi(line).length - 2));
1698
- console.log(chalk8.cyan("\u2502 ") + line + padding + chalk8.cyan(" \u2502"));
1801
+ console.log(chalk9.cyan("\u2502 ") + line + padding + chalk9.cyan(" \u2502"));
1699
1802
  }
1700
- console.log(chalk8.cyan(bottomBorder));
1803
+ console.log(chalk9.cyan(bottomBorder));
1701
1804
  console.log("");
1702
1805
  }
1703
1806
  function truncatePath(path4, maxLen) {
@@ -2696,7 +2799,7 @@ function getRiskDescription(tier, argv) {
2696
2799
 
2697
2800
  // src/security/workspace-trust.ts
2698
2801
  import { select as select3 } from "@inquirer/prompts";
2699
- import chalk9 from "chalk";
2802
+ import chalk10 from "chalk";
2700
2803
  import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
2701
2804
  import { join as join3, resolve as resolve3 } from "path";
2702
2805
  import { homedir as homedir4 } from "os";
@@ -2745,14 +2848,14 @@ function trustWorkspace(workspacePath) {
2745
2848
  }
2746
2849
  async function promptWorkspaceTrust(workspacePath) {
2747
2850
  if (isWorkspaceTrusted(workspacePath)) {
2748
- console.log(chalk9.green("\u2713 Workspace is trusted\n"));
2851
+ console.log(chalk10.green("\u2713 Workspace is trusted\n"));
2749
2852
  return "persistent";
2750
2853
  }
2751
- console.log(chalk9.yellow("\n\u26A0\uFE0F Untrusted Workspace"));
2752
- console.log(chalk9.gray(` ${workspacePath}
2854
+ console.log(chalk10.yellow("\n\u26A0\uFE0F Untrusted Workspace"));
2855
+ console.log(chalk10.gray(` ${workspacePath}
2753
2856
  `));
2754
- console.log(chalk9.gray("Agdi can run commands in this workspace."));
2755
- console.log(chalk9.gray("Do you trust the contents of this folder?\n"));
2857
+ console.log(chalk10.gray("Agdi can run commands in this workspace."));
2858
+ console.log(chalk10.gray("Do you trust the contents of this folder?\n"));
2756
2859
  const choice = await select3({
2757
2860
  message: "Trust this workspace?",
2758
2861
  choices: [
@@ -2780,15 +2883,15 @@ async function handleTrustFlow(workspacePath) {
2780
2883
  switch (choice) {
2781
2884
  case "session":
2782
2885
  updateEnvironment({ trustLevel: "session" });
2783
- console.log(chalk9.green("\u2713 Trusted for this session\n"));
2886
+ console.log(chalk10.green("\u2713 Trusted for this session\n"));
2784
2887
  return "session";
2785
2888
  case "persistent":
2786
2889
  trustWorkspace(workspacePath);
2787
2890
  updateEnvironment({ trustLevel: "persistent" });
2788
- console.log(chalk9.green("\u2713 Workspace trusted and remembered\n"));
2891
+ console.log(chalk10.green("\u2713 Workspace trusted and remembered\n"));
2789
2892
  return "persistent";
2790
2893
  case "exit":
2791
- console.log(chalk9.yellow("\n\u{1F44B} Exiting. Workspace not trusted.\n"));
2894
+ console.log(chalk10.yellow("\n\u{1F44B} Exiting. Workspace not trusted.\n"));
2792
2895
  return null;
2793
2896
  }
2794
2897
  }
@@ -2856,53 +2959,33 @@ async function downloadImageAsBase64(url) {
2856
2959
  // src/actions/plan-executor.ts
2857
2960
  function displayPlanSummary(plan) {
2858
2961
  const summary = summarizePlan(plan);
2859
- const boxWidth = 56;
2860
- console.log("");
2861
- console.log(chalk10.cyan("\u256D\u2500 Action Plan \u2500" + "\u2500".repeat(boxWidth - 15) + "\u256E"));
2862
- console.log(chalk10.cyan("\u2502 ") + chalk10.white(`Project: ${plan.projectName}`.padEnd(boxWidth - 2)) + chalk10.cyan(" \u2502"));
2863
- console.log(chalk10.cyan("\u2502 ") + "\u2500".repeat(boxWidth - 2) + chalk10.cyan(" \u2502"));
2864
2962
  const lines = [];
2865
- if (summary.dirsCreated > 0) {
2866
- lines.push(`\u{1F4C1} Create ${summary.dirsCreated} directories`);
2867
- }
2868
- if (summary.filesCreated > 0) {
2869
- lines.push(`\u{1F4C4} Create ${summary.filesCreated} files`);
2870
- }
2871
- if (summary.filesDeleted > 0) {
2872
- lines.push(`\u{1F5D1}\uFE0F Delete ${summary.filesDeleted} files`);
2873
- }
2874
- if (summary.commandsToRun > 0) {
2875
- lines.push(`\u26A1 Run ${summary.commandsToRun} commands`);
2876
- }
2877
- if (summary.domains.length > 0) {
2878
- lines.push(`\u{1F310} Network: ${summary.domains.join(", ")}`);
2879
- }
2880
- if (summary.ports.length > 0) {
2881
- lines.push(`\u{1F50C} Ports: ${summary.ports.join(", ")}`);
2882
- }
2883
- for (const line of lines) {
2884
- console.log(chalk10.cyan("\u2502 ") + chalk10.gray(line.padEnd(boxWidth - 2)) + chalk10.cyan(" \u2502"));
2885
- }
2886
- console.log(chalk10.cyan("\u2570" + "\u2500".repeat(boxWidth) + "\u256F"));
2887
- console.log("");
2963
+ if (summary.dirsCreated > 0) lines.push(`\u{1F4C1} Create ${summary.dirsCreated} directories`);
2964
+ if (summary.filesCreated > 0) lines.push(`\u{1F4C4} Create ${summary.filesCreated} files`);
2965
+ if (summary.filesDeleted > 0) lines.push(`\u{1F5D1}\uFE0F Delete ${summary.filesDeleted} files`);
2966
+ if (summary.commandsToRun > 0) lines.push(`\u26A1 Run ${summary.commandsToRun} commands`);
2967
+ if (summary.domains.length > 0) lines.push(`\u{1F310} Network: ${summary.domains.join(", ")}`);
2968
+ if (summary.ports.length > 0) lines.push(`\u{1F50C} Ports: ${summary.ports.join(", ")}`);
2969
+ const content = lines.join("\n");
2970
+ ui.renderBox(`PLAN: ${plan.projectName}`, content, "info");
2888
2971
  }
2889
2972
  function displayActionProgress(action, index, total) {
2890
2973
  const num = `[${index + 1}/${total}]`;
2891
2974
  switch (action.type) {
2892
2975
  case "mkdir":
2893
- console.log(chalk10.gray(`${num} Creating directory: ${action.path}`));
2976
+ console.log(chalk11.gray(`${num} Creating directory: ${action.path}`));
2894
2977
  break;
2895
2978
  case "writeFile":
2896
- console.log(chalk10.gray(`${num} Writing file: ${action.path}`));
2979
+ console.log(chalk11.gray(`${num} Writing file: ${action.path}`));
2897
2980
  break;
2898
2981
  case "deleteFile":
2899
- console.log(chalk10.gray(`${num} Deleting file: ${action.path}`));
2982
+ console.log(chalk11.gray(`${num} Deleting file: ${action.path}`));
2900
2983
  break;
2901
2984
  case "exec":
2902
- console.log(chalk10.blue(`${num} Running: ${action.argv.join(" ")}`));
2985
+ console.log(chalk11.blue(`${num} Running: ${action.argv.join(" ")}`));
2903
2986
  break;
2904
2987
  case "generateImage":
2905
- console.log(chalk10.magenta(`${num} \u{1F3A8} Generating image: ${action.savePath}`));
2988
+ console.log(chalk11.magenta(`${num} \u{1F3A8} Generating image: ${action.savePath}`));
2906
2989
  break;
2907
2990
  }
2908
2991
  }
@@ -3013,16 +3096,16 @@ async function executeAction(action) {
3013
3096
  };
3014
3097
  }
3015
3098
  try {
3016
- console.log(chalk10.gray(` Prompt: "${action.prompt.slice(0, 50)}..."`));
3099
+ console.log(chalk11.gray(` Prompt: "${action.prompt.slice(0, 50)}..."`));
3017
3100
  const result = await generateImage(action.prompt, apiKey, { style: action.style });
3018
3101
  if (result.url) {
3019
3102
  const base64Data = await downloadImageAsBase64(result.url);
3020
3103
  const imageBuffer = Buffer.from(base64Data, "base64");
3021
3104
  await writeFileTool(action.savePath, imageBuffer.toString("base64"));
3022
- console.log(chalk10.green(` \u2713 Saved to ${action.savePath}`));
3105
+ console.log(chalk11.green(` \u2713 Saved to ${action.savePath}`));
3023
3106
  } else if (result.base64) {
3024
3107
  await writeFileTool(action.savePath, result.base64);
3025
- console.log(chalk10.green(` \u2713 Saved to ${action.savePath}`));
3108
+ console.log(chalk11.green(` \u2713 Saved to ${action.savePath}`));
3026
3109
  }
3027
3110
  return {
3028
3111
  action,
@@ -3048,18 +3131,19 @@ async function executePlan(plan) {
3048
3131
  displayPlanSummary(plan);
3049
3132
  const dryRun = await dryRunActions(plan);
3050
3133
  if (!dryRun.canProceed) {
3051
- console.log(chalk10.red("\n\u26D4 Plan contains actions that cannot be approved:"));
3052
- for (const result of dryRun.gateResults) {
3053
- if (result.decision === "deny") {
3054
- console.log(chalk10.red(` - ${result.command}: ${result.reason}`));
3055
- errors.push(result.reason);
3056
- }
3057
- }
3134
+ const errorLines = dryRun.gateResults.filter((r) => r.decision === "deny").map((r) => `\u2022 ${r.command}: ${r.reason}`);
3135
+ ui.renderBox("BLOCKED ACTIONS", errorLines.join("\n"), "error");
3136
+ dryRun.gateResults.filter((r) => r.decision === "deny").forEach((r) => errors.push(r.reason));
3058
3137
  return { success: false, results, filesCreated, commandsRun, errors };
3059
3138
  }
3060
3139
  if (dryRun.requiresTrust) {
3061
- console.log(chalk10.yellow("\u26A0\uFE0F This workspace is not trusted."));
3062
- console.log(chalk10.gray(" The plan requires file writes and command execution.\n"));
3140
+ ui.renderAlert(
3141
+ "UNTRUSTED WORKSPACE",
3142
+ `The agent wants to execute ${plan.actions.length} actions in this folder.
3143
+ This includes writing files and/or running commands.
3144
+
3145
+ Target: ${env.workspaceRoot}`
3146
+ );
3063
3147
  const trustChoice = await select4({
3064
3148
  message: "Trust this workspace?",
3065
3149
  choices: [
@@ -3069,16 +3153,16 @@ async function executePlan(plan) {
3069
3153
  ]
3070
3154
  });
3071
3155
  if (trustChoice === "cancel") {
3072
- console.log(chalk10.yellow("\n\u{1F44B} Plan cancelled.\n"));
3156
+ console.log(chalk11.yellow("\n\u{1F44B} Plan cancelled.\n"));
3073
3157
  return { success: false, results, filesCreated, commandsRun, errors: ["User cancelled"] };
3074
3158
  }
3075
3159
  if (trustChoice === "persistent") {
3076
3160
  trustWorkspace(env.workspaceRoot);
3077
3161
  updateEnvironment({ trustLevel: "persistent" });
3078
- console.log(chalk10.green("\u2713 Workspace trusted and remembered\n"));
3162
+ console.log(chalk11.green("\u2713 Workspace trusted and remembered\n"));
3079
3163
  } else {
3080
3164
  updateEnvironment({ trustLevel: "session" });
3081
- console.log(chalk10.green("\u2713 Trusted for this session\n"));
3165
+ console.log(chalk11.green("\u2713 Trusted for this session\n"));
3082
3166
  }
3083
3167
  }
3084
3168
  const approved = await confirm({
@@ -3086,7 +3170,7 @@ async function executePlan(plan) {
3086
3170
  default: true
3087
3171
  });
3088
3172
  if (!approved) {
3089
- console.log(chalk10.yellow("\n\u{1F44B} Plan cancelled.\n"));
3173
+ console.log(chalk11.yellow("\n\u{1F44B} Plan cancelled.\n"));
3090
3174
  return { success: false, results, filesCreated, commandsRun, errors: ["User cancelled"] };
3091
3175
  }
3092
3176
  logEvent({
@@ -3097,7 +3181,7 @@ async function executePlan(plan) {
3097
3181
  summary: summarizePlan(plan)
3098
3182
  }
3099
3183
  });
3100
- console.log(chalk10.cyan("\n\u25B6 Executing plan...\n"));
3184
+ console.log(chalk11.cyan("\n\u25B6 Executing plan...\n"));
3101
3185
  for (let i = 0; i < plan.actions.length; i++) {
3102
3186
  const action = plan.actions[i];
3103
3187
  displayActionProgress(action, i, plan.actions.length);
@@ -3112,24 +3196,24 @@ async function executePlan(plan) {
3112
3196
  }
3113
3197
  } else {
3114
3198
  errors.push(result.error || "Unknown error");
3115
- console.log(chalk10.red(` \u2717 Failed: ${result.error}`));
3199
+ console.log(chalk11.red(` \u2717 Failed: ${result.error}`));
3116
3200
  }
3117
3201
  }
3118
3202
  const success = errors.length === 0;
3119
3203
  if (success) {
3120
- console.log(chalk10.green(`
3204
+ console.log(chalk11.green(`
3121
3205
  \u2713 Plan executed successfully!`));
3122
- console.log(chalk10.gray(` Created ${filesCreated.length} files`));
3123
- console.log(chalk10.gray(` Ran ${commandsRun.length} commands
3206
+ console.log(chalk11.gray(` Created ${filesCreated.length} files`));
3207
+ console.log(chalk11.gray(` Ran ${commandsRun.length} commands
3124
3208
  `));
3125
3209
  } else {
3126
- console.log(chalk10.red(`
3210
+ console.log(chalk11.red(`
3127
3211
  \u2717 Plan completed with ${errors.length} errors
3128
3212
  `));
3129
3213
  }
3130
3214
  if (plan.nextSteps) {
3131
- console.log(chalk10.cyan("Next steps:"));
3132
- console.log(chalk10.gray(` ${plan.nextSteps}
3215
+ console.log(chalk11.cyan("Next steps:"));
3216
+ console.log(chalk11.gray(` ${plan.nextSteps}
3133
3217
  `));
3134
3218
  }
3135
3219
  logEvent({
@@ -3149,7 +3233,7 @@ async function executePlan(plan) {
3149
3233
  async function parseAndExecutePlan(response) {
3150
3234
  const plan = parseActionPlan(response);
3151
3235
  if (!plan) {
3152
- console.log(chalk10.yellow("\n\u26A0\uFE0F Could not parse action plan from response.\n"));
3236
+ console.log(chalk11.yellow("\n\u26A0\uFE0F Could not parse action plan from response.\n"));
3153
3237
  return null;
3154
3238
  }
3155
3239
  return executePlan(plan);
@@ -3719,8 +3803,8 @@ function clearConversation() {
3719
3803
  // src/core/file-editor.ts
3720
3804
  import { readFile as readFile2 } from "fs/promises";
3721
3805
  import { existsSync as existsSync9 } from "fs";
3722
- import chalk11 from "chalk";
3723
- import ora3 from "ora";
3806
+ import chalk12 from "chalk";
3807
+ import ora4 from "ora";
3724
3808
  import { input as input4, confirm as confirm2 } from "@inquirer/prompts";
3725
3809
  var EDIT_SYSTEM_PROMPT = `You are a surgical code editor. Given a file's content and an edit instruction, output ONLY a unified diff patch.
3726
3810
 
@@ -3787,19 +3871,19 @@ function extractDiff(response) {
3787
3871
  return null;
3788
3872
  }
3789
3873
  function previewDiff(diff) {
3790
- console.log(chalk11.cyan.bold("\n\u{1F4DD} Proposed Changes:\n"));
3874
+ console.log(chalk12.cyan.bold("\n\u{1F4DD} Proposed Changes:\n"));
3791
3875
  const lines = diff.split("\n");
3792
3876
  for (const line of lines) {
3793
3877
  if (line.startsWith("+++") || line.startsWith("---")) {
3794
- console.log(chalk11.gray(line));
3878
+ console.log(chalk12.gray(line));
3795
3879
  } else if (line.startsWith("@@")) {
3796
- console.log(chalk11.cyan(line));
3880
+ console.log(chalk12.cyan(line));
3797
3881
  } else if (line.startsWith("+")) {
3798
- console.log(chalk11.green(line));
3882
+ console.log(chalk12.green(line));
3799
3883
  } else if (line.startsWith("-")) {
3800
- console.log(chalk11.red(line));
3884
+ console.log(chalk12.red(line));
3801
3885
  } else {
3802
- console.log(chalk11.gray(line));
3886
+ console.log(chalk12.gray(line));
3803
3887
  }
3804
3888
  }
3805
3889
  console.log("");
@@ -3820,35 +3904,35 @@ function countChanges(diff) {
3820
3904
  async function handleFileEdit(filePath, llm) {
3821
3905
  const env = getEnvironment();
3822
3906
  if (!fileExists(filePath)) {
3823
- console.log(chalk11.red(`
3907
+ console.log(chalk12.red(`
3824
3908
  \u2717 File not found: ${filePath}
3825
3909
  `));
3826
3910
  return { success: false, error: "File not found" };
3827
3911
  }
3828
3912
  const fileData = await readFileForEdit(filePath);
3829
3913
  if (!fileData) {
3830
- console.log(chalk11.red(`
3914
+ console.log(chalk12.red(`
3831
3915
  \u2717 Could not read file: ${filePath}
3832
3916
  `));
3833
3917
  return { success: false, error: "Could not read file" };
3834
3918
  }
3835
3919
  const previewLines = fileData.numbered.split("\n").slice(0, 20);
3836
- console.log(chalk11.cyan.bold(`
3920
+ console.log(chalk12.cyan.bold(`
3837
3921
  \u{1F4C4} ${filePath}
3838
3922
  `));
3839
- console.log(chalk11.gray(previewLines.join("\n")));
3923
+ console.log(chalk12.gray(previewLines.join("\n")));
3840
3924
  if (fileData.content.split("\n").length > 20) {
3841
- console.log(chalk11.gray(` ... (${fileData.content.split("\n").length - 20} more lines)`));
3925
+ console.log(chalk12.gray(` ... (${fileData.content.split("\n").length - 20} more lines)`));
3842
3926
  }
3843
3927
  console.log("");
3844
3928
  const instruction = await input4({
3845
- message: chalk11.yellow("Describe the edit:")
3929
+ message: chalk12.yellow("Describe the edit:")
3846
3930
  });
3847
3931
  if (!instruction.trim()) {
3848
- console.log(chalk11.gray("\n(no instruction provided)\n"));
3932
+ console.log(chalk12.gray("\n(no instruction provided)\n"));
3849
3933
  return { success: false, error: "No instruction" };
3850
3934
  }
3851
- const spinner = ora3("Generating edit...").start();
3935
+ const spinner = ora4("Generating edit...").start();
3852
3936
  try {
3853
3937
  const prompt = `File: ${filePath}
3854
3938
 
@@ -3864,27 +3948,27 @@ Generate the unified diff to make this change.`;
3864
3948
  spinner.stop();
3865
3949
  const diff = extractDiff(response.text);
3866
3950
  if (!diff) {
3867
- console.log(chalk11.yellow("\n\u26A0\uFE0F Could not generate a valid diff.\n"));
3868
- console.log(chalk11.gray("AI response:\n" + response.text.slice(0, 500)));
3951
+ console.log(chalk12.yellow("\n\u26A0\uFE0F Could not generate a valid diff.\n"));
3952
+ console.log(chalk12.gray("AI response:\n" + response.text.slice(0, 500)));
3869
3953
  return { success: false, error: "Invalid diff generated" };
3870
3954
  }
3871
3955
  previewDiff(diff);
3872
3956
  const changes = countChanges(diff);
3873
- console.log(chalk11.gray(` ${chalk11.green(`+${changes.added}`)} additions, ${chalk11.red(`-${changes.removed}`)} deletions
3957
+ console.log(chalk12.gray(` ${chalk12.green(`+${changes.added}`)} additions, ${chalk12.red(`-${changes.removed}`)} deletions
3874
3958
  `));
3875
3959
  const shouldApply = await confirm2({
3876
3960
  message: "Apply these changes?",
3877
3961
  default: true
3878
3962
  });
3879
3963
  if (!shouldApply) {
3880
- console.log(chalk11.gray("\n\u{1F44B} Edit cancelled.\n"));
3964
+ console.log(chalk12.gray("\n\u{1F44B} Edit cancelled.\n"));
3881
3965
  return { success: false, error: "Cancelled by user" };
3882
3966
  }
3883
- const applySpinner = ora3("Applying changes...").start();
3967
+ const applySpinner = ora4("Applying changes...").start();
3884
3968
  const result = await applyPatchTool(filePath, diff);
3885
3969
  applySpinner.stop();
3886
3970
  if (result.success) {
3887
- console.log(chalk11.green(`
3971
+ console.log(chalk12.green(`
3888
3972
  \u2713 Successfully edited ${filePath}
3889
3973
  `));
3890
3974
  logEvent({
@@ -3899,7 +3983,7 @@ Generate the unified diff to make this change.`;
3899
3983
  });
3900
3984
  return { success: true, linesChanged: changes.added + changes.removed };
3901
3985
  } else {
3902
- console.log(chalk11.red(`
3986
+ console.log(chalk12.red(`
3903
3987
  \u2717 Failed to apply changes: ${result.error}
3904
3988
  `));
3905
3989
  return { success: false, error: result.error };
@@ -3907,7 +3991,7 @@ Generate the unified diff to make this change.`;
3907
3991
  } catch (error) {
3908
3992
  spinner.stop();
3909
3993
  const msg = error instanceof Error ? error.message : String(error);
3910
- console.log(chalk11.red(`
3994
+ console.log(chalk12.red(`
3911
3995
  \u2717 Error: ${msg}
3912
3996
  `));
3913
3997
  return { success: false, error: msg };
@@ -4159,7 +4243,7 @@ For landing pages, portfolios, or apps that need visuals, use generateImage acti
4159
4243
  async function startCodingMode() {
4160
4244
  const activeConfig = getActiveProvider();
4161
4245
  if (!activeConfig) {
4162
- console.log(chalk12.red("\u274C No API key configured. Run: agdi"));
4246
+ console.log(chalk13.red("\u274C No API key configured. Run: agdi"));
4163
4247
  return;
4164
4248
  }
4165
4249
  const { provider, apiKey, model } = activeConfig;
@@ -4171,11 +4255,15 @@ async function startCodingMode() {
4171
4255
  process.exit(0);
4172
4256
  }
4173
4257
  logSessionStart(env.workspaceRoot, env.trustLevel);
4174
- console.log(chalk12.cyan.bold("\u26A1 Agdi dev\n"));
4175
- console.log(chalk12.gray(`Model: ${chalk12.cyan(model)}`));
4176
- console.log(chalk12.gray(`Workspace: ${chalk12.cyan(env.workspaceRoot)}`));
4177
- console.log(chalk12.gray("Commands: /status, /diff, /commit, /build, /clear, /history, /model, /help, /exit\n"));
4178
- console.log(chalk12.gray("\u2500".repeat(50) + "\n"));
4258
+ ui.renderBox(
4259
+ "SESSION INFO",
4260
+ `Model: ${chalk13.cyan(model)}
4261
+ Workspace: ${chalk13.cyan(env.workspaceRoot)}
4262
+ Context: ${isGitRepo() ? chalk13.green("Git Repository") : chalk13.gray("Local Folder")}`,
4263
+ "info"
4264
+ );
4265
+ console.log(chalk13.gray("Commands: /status, /diff, /commit, /build, /help..."));
4266
+ ui.printIter();
4179
4267
  const pm = new ProjectManager();
4180
4268
  let llm = createLLMProvider(provider, { apiKey, model });
4181
4269
  const conversation = getConversation();
@@ -4183,12 +4271,12 @@ async function startCodingMode() {
4183
4271
  while (true) {
4184
4272
  try {
4185
4273
  const userInput = await input5({
4186
- message: chalk12.green("\u2192")
4274
+ message: chalk13.cyan.bold("\u{1F464} YOU \u203A")
4187
4275
  });
4188
4276
  const trimmed = userInput.trim().toLowerCase();
4189
4277
  if (trimmed === "/exit" || trimmed === "exit" || trimmed === "quit") {
4190
4278
  logSessionEnd();
4191
- console.log(chalk12.gray("\n\u{1F44B} Goodbye!\n"));
4279
+ console.log(chalk13.gray("\n\u{1F44B} Goodbye!\n"));
4192
4280
  break;
4193
4281
  }
4194
4282
  if (trimmed === "/help") {
@@ -4203,34 +4291,34 @@ async function startCodingMode() {
4203
4291
  apiKey: newConfig.apiKey,
4204
4292
  model: newConfig.model
4205
4293
  });
4206
- console.log(chalk12.gray(`Now using: ${chalk12.cyan(newConfig.model)}
4294
+ console.log(chalk13.gray(`Now using: ${chalk13.cyan(newConfig.model)}
4207
4295
  `));
4208
4296
  }
4209
4297
  continue;
4210
4298
  }
4211
4299
  if (trimmed === "/chat") {
4212
- console.log(chalk12.gray("\nSwitching to chat mode. Type /code to return.\n"));
4300
+ console.log(chalk13.gray("\nSwitching to chat mode. Type /code to return.\n"));
4213
4301
  await chatMode(llm);
4214
4302
  continue;
4215
4303
  }
4216
4304
  if (trimmed === "/clear") {
4217
4305
  clearConversation();
4218
4306
  conversation.setSystemPrompt(buildContextAwarePrompt());
4219
- console.log(chalk12.green("\n\u2713 Conversation cleared.\n"));
4307
+ console.log(chalk13.green("\n\u2713 Conversation cleared.\n"));
4220
4308
  continue;
4221
4309
  }
4222
4310
  if (trimmed === "/history") {
4223
4311
  const messages = conversation.getMessages();
4224
4312
  if (messages.length === 0) {
4225
- console.log(chalk12.gray("\n(no conversation history)\n"));
4313
+ console.log(chalk13.gray("\n(no conversation history)\n"));
4226
4314
  } else {
4227
- console.log(chalk12.cyan.bold("\n\u{1F4DC} Conversation History\n"));
4228
- console.log(chalk12.gray(conversation.getSummary()));
4315
+ console.log(chalk13.cyan.bold("\n\u{1F4DC} Conversation History\n"));
4316
+ console.log(chalk13.gray(conversation.getSummary()));
4229
4317
  console.log("");
4230
4318
  for (const msg of messages.slice(-6)) {
4231
- const role = msg.role === "user" ? chalk12.green("You") : chalk12.cyan("AI");
4319
+ const role = msg.role === "user" ? chalk13.green("You") : chalk13.cyan("AI");
4232
4320
  const preview = msg.content.slice(0, 80) + (msg.content.length > 80 ? "..." : "");
4233
- console.log(` ${role}: ${chalk12.gray(preview)}`);
4321
+ console.log(` ${role}: ${chalk13.gray(preview)}`);
4234
4322
  }
4235
4323
  console.log("");
4236
4324
  }
@@ -4253,12 +4341,12 @@ async function startCodingMode() {
4253
4341
  if (filePath) {
4254
4342
  await handleFileEdit(filePath, llm);
4255
4343
  } else {
4256
- console.log(chalk12.yellow("\nUsage: /edit <file>\n"));
4344
+ console.log(chalk13.yellow("\nUsage: /edit <file>\n"));
4257
4345
  }
4258
4346
  continue;
4259
4347
  }
4260
4348
  if (trimmed === "/index") {
4261
- const spinner2 = ora4("Indexing project...").start();
4349
+ const spinner2 = ui.createSpinner("Indexing project...").start();
4262
4350
  try {
4263
4351
  const index = indexProject(process.cwd());
4264
4352
  spinner2.succeed(`Indexed ${index.fileCount} files, ${index.chunkCount} chunks`);
@@ -4270,18 +4358,18 @@ async function startCodingMode() {
4270
4358
  if (trimmed.startsWith("/search ")) {
4271
4359
  const query = userInput.slice(8).trim();
4272
4360
  if (!query) {
4273
- console.log(chalk12.yellow("\nUsage: /search <query>\n"));
4361
+ console.log(chalk13.yellow("\nUsage: /search <query>\n"));
4274
4362
  continue;
4275
4363
  }
4276
4364
  const results = searchCodebase(process.cwd(), query, { limit: 8 });
4277
4365
  if (results.length === 0) {
4278
- console.log(chalk12.gray("\nNo results found. Try /index first.\n"));
4366
+ console.log(chalk13.gray("\nNo results found. Try /index first.\n"));
4279
4367
  } else {
4280
- console.log(chalk12.cyan.bold("\n\u{1F50D} Search Results\n"));
4368
+ console.log(chalk13.cyan.bold("\n\u{1F50D} Search Results\n"));
4281
4369
  for (const r of results) {
4282
- console.log(chalk12.green(` ${r.chunk.relativePath}:${r.chunk.startLine}`) + chalk12.gray(` (${r.score.toFixed(2)})`));
4370
+ console.log(chalk13.green(` ${r.chunk.relativePath}:${r.chunk.startLine}`) + chalk13.gray(` (${r.score.toFixed(2)})`));
4283
4371
  if (r.highlights.length > 0) {
4284
- console.log(chalk12.gray(` ${r.highlights[0].slice(0, 60)}...`));
4372
+ console.log(chalk13.gray(` ${r.highlights[0].slice(0, 60)}...`));
4285
4373
  }
4286
4374
  }
4287
4375
  console.log("");
@@ -4290,32 +4378,32 @@ async function startCodingMode() {
4290
4378
  }
4291
4379
  if (trimmed === "/tools") {
4292
4380
  const tools2 = listTools();
4293
- console.log(chalk12.cyan.bold("\n\u{1F527} Available Tools\n"));
4381
+ console.log(chalk13.cyan.bold("\n\u{1F527} Available Tools\n"));
4294
4382
  for (const tool of tools2) {
4295
- console.log(chalk12.green(` ${tool.name}`) + chalk12.gray(` [${tool.category}]`));
4296
- console.log(chalk12.gray(` ${tool.description}`));
4383
+ console.log(chalk13.green(` ${tool.name}`) + chalk13.gray(` [${tool.category}]`));
4384
+ console.log(chalk13.gray(` ${tool.description}`));
4297
4385
  }
4298
4386
  console.log("");
4299
4387
  continue;
4300
4388
  }
4301
4389
  if (trimmed === "/agent") {
4302
4390
  multiAgentMode = !multiAgentMode;
4303
- console.log(chalk12.cyan(`
4304
- \u{1F916} Multi-agent mode: ${multiAgentMode ? chalk12.green("ON") : chalk12.gray("OFF")}
4391
+ console.log(chalk13.cyan(`
4392
+ \u{1F916} Multi-agent mode: ${multiAgentMode ? chalk13.green("ON") : chalk13.gray("OFF")}
4305
4393
  `));
4306
4394
  if (multiAgentMode) {
4307
- console.log(chalk12.gray(" Planner \u2192 Coder \u2192 Reviewer pipeline enabled\n"));
4395
+ console.log(chalk13.gray(" Planner \u2192 Coder \u2192 Reviewer pipeline enabled\n"));
4308
4396
  }
4309
4397
  continue;
4310
4398
  }
4311
4399
  if (trimmed === "/memory") {
4312
4400
  const stats = getMemoryStats();
4313
- console.log(chalk12.cyan.bold("\n\u{1F9E0} Memory Stats\n"));
4314
- console.log(chalk12.gray(` Total entries: ${stats.totalEntries}`));
4315
- console.log(chalk12.gray(` Projects: ${stats.projectCount}`));
4316
- console.log(chalk12.gray(` Preferences: ${stats.preferenceCount}`));
4401
+ console.log(chalk13.cyan.bold("\n\u{1F9E0} Memory Stats\n"));
4402
+ console.log(chalk13.gray(` Total entries: ${stats.totalEntries}`));
4403
+ console.log(chalk13.gray(` Projects: ${stats.projectCount}`));
4404
+ console.log(chalk13.gray(` Preferences: ${stats.preferenceCount}`));
4317
4405
  for (const [type, count] of Object.entries(stats.byType)) {
4318
- console.log(chalk12.gray(` ${type}: ${count}`));
4406
+ console.log(chalk13.gray(` ${type}: ${count}`));
4319
4407
  }
4320
4408
  console.log("");
4321
4409
  continue;
@@ -4325,7 +4413,7 @@ async function startCodingMode() {
4325
4413
  if (prompt) {
4326
4414
  await buildAppWithPlan(prompt, llm);
4327
4415
  } else {
4328
- console.log(chalk12.yellow("\nUsage: /build <description>\n"));
4416
+ console.log(chalk13.yellow("\nUsage: /build <description>\n"));
4329
4417
  }
4330
4418
  continue;
4331
4419
  }
@@ -4337,7 +4425,7 @@ async function startCodingMode() {
4337
4425
  await buildAppWithPlan(userInput, llm);
4338
4426
  continue;
4339
4427
  }
4340
- const spinner = ora4("Thinking...").start();
4428
+ const spinner = ui.createSpinner("Thinking...").start();
4341
4429
  try {
4342
4430
  conversation.addUserMessage(userInput);
4343
4431
  let response;
@@ -4349,7 +4437,7 @@ async function startCodingMode() {
4349
4437
  }
4350
4438
  conversation.addAssistantMessage(response.text);
4351
4439
  spinner.stop();
4352
- console.log("\n" + formatResponse(response.text) + "\n");
4440
+ ui.printAIMessage(formatResponse(response.text));
4353
4441
  } catch (error) {
4354
4442
  spinner.fail("Error");
4355
4443
  handleError(error);
@@ -4357,7 +4445,7 @@ async function startCodingMode() {
4357
4445
  } catch (error) {
4358
4446
  if (error.name === "ExitPromptError") {
4359
4447
  logSessionEnd();
4360
- console.log(chalk12.gray("\n\n\u{1F44B} Goodbye!\n"));
4448
+ console.log(chalk13.gray("\n\n\u{1F44B} Goodbye!\n"));
4361
4449
  process.exit(0);
4362
4450
  }
4363
4451
  throw error;
@@ -4365,13 +4453,13 @@ async function startCodingMode() {
4365
4453
  }
4366
4454
  }
4367
4455
  async function buildAppWithPlan(prompt, llm) {
4368
- const spinner = ora4("Generating action plan...").start();
4456
+ const spinner = ui.createSpinner("Generating action plan...").start();
4369
4457
  try {
4370
4458
  const response = await llm.generate(prompt, BUILD_SYSTEM_PROMPT);
4371
4459
  spinner.stop();
4372
4460
  const result = await parseAndExecutePlan(response.text);
4373
4461
  if (!result) {
4374
- console.log(chalk12.yellow("\n\u26A0\uFE0F Model did not return an action plan. Showing response:\n"));
4462
+ console.log(chalk13.yellow("\n\u26A0\uFE0F Model did not return an action plan. Showing response:\n"));
4375
4463
  console.log(formatResponse(response.text) + "\n");
4376
4464
  }
4377
4465
  } catch (error) {
@@ -4383,17 +4471,17 @@ async function chatMode(llm) {
4383
4471
  while (true) {
4384
4472
  try {
4385
4473
  const userInput = await input5({
4386
- message: chalk12.blue("\u{1F4AC}")
4474
+ message: chalk13.blue("\u{1F4AC}")
4387
4475
  });
4388
4476
  if (userInput.toLowerCase() === "/code" || userInput.toLowerCase() === "/exit") {
4389
- console.log(chalk12.gray("\nBack to Agdi dev mode.\n"));
4477
+ console.log(chalk13.gray("\nBack to Agdi dev mode.\n"));
4390
4478
  return;
4391
4479
  }
4392
4480
  if (!userInput.trim()) continue;
4393
- const spinner = ora4("...").start();
4481
+ const spinner = ui.createSpinner("Thinking...").start();
4394
4482
  const response = await llm.generate(userInput, "You are a helpful assistant. Be friendly and concise.");
4395
4483
  spinner.stop();
4396
- console.log("\n" + response.text + "\n");
4484
+ ui.printAIMessage(response.text);
4397
4485
  } catch (error) {
4398
4486
  if (error.name === "ExitPromptError") {
4399
4487
  return;
@@ -4404,10 +4492,10 @@ async function chatMode(llm) {
4404
4492
  }
4405
4493
  async function handleGitStatus(llm) {
4406
4494
  if (!isGitRepo()) {
4407
- console.log(chalk12.yellow("\n\u26A0\uFE0F Not a git repository\n"));
4495
+ console.log(chalk13.yellow("\n\u26A0\uFE0F Not a git repository\n"));
4408
4496
  return;
4409
4497
  }
4410
- const spinner = ora4("Analyzing git status...").start();
4498
+ const spinner = ui.createSpinner("Analyzing git status...").start();
4411
4499
  try {
4412
4500
  const status = getStatus();
4413
4501
  const statusText = formatStatusForPrompt(status);
@@ -4416,10 +4504,10 @@ async function handleGitStatus(llm) {
4416
4504
  ${statusText}`;
4417
4505
  const response = await llm.generate(prompt, BASE_CHAT_PROMPT);
4418
4506
  spinner.stop();
4419
- console.log(chalk12.cyan.bold("\n\u{1F4CA} Git Status Analysis\n"));
4420
- console.log(chalk12.gray(statusText));
4421
- console.log(chalk12.cyan("\n\u2500\u2500\u2500 AI Analysis \u2500\u2500\u2500\n"));
4422
- console.log(formatResponse(response.text) + "\n");
4507
+ console.log(chalk13.cyan.bold("\n\u{1F4CA} Git Status Analysis\n"));
4508
+ console.log(chalk13.gray(statusText));
4509
+ console.log(chalk13.cyan("\n\u2500\u2500\u2500 AI Analysis \u2500\u2500\u2500\n"));
4510
+ ui.printAIMessage(formatResponse(response.text));
4423
4511
  } catch (error) {
4424
4512
  spinner.fail("Error analyzing status");
4425
4513
  handleError(error);
@@ -4427,16 +4515,16 @@ ${statusText}`;
4427
4515
  }
4428
4516
  async function handleGitDiff(llm) {
4429
4517
  if (!isGitRepo()) {
4430
- console.log(chalk12.yellow("\n\u26A0\uFE0F Not a git repository\n"));
4518
+ console.log(chalk13.yellow("\n\u26A0\uFE0F Not a git repository\n"));
4431
4519
  return;
4432
4520
  }
4433
- const spinner = ora4("Analyzing changes...").start();
4521
+ const spinner = ui.createSpinner("Analyzing changes...").start();
4434
4522
  try {
4435
4523
  const stagedDiff = getDiff(true);
4436
4524
  const unstagedDiff = getDiff(false);
4437
4525
  if (stagedDiff.files.length === 0 && unstagedDiff.files.length === 0) {
4438
4526
  spinner.stop();
4439
- console.log(chalk12.gray("\n(no changes to analyze)\n"));
4527
+ console.log(chalk13.gray("\n(no changes to analyze)\n"));
4440
4528
  return;
4441
4529
  }
4442
4530
  let diffContext = "";
@@ -4451,8 +4539,8 @@ async function handleGitDiff(llm) {
4451
4539
  ${diffContext}`;
4452
4540
  const response = await llm.generate(prompt, BASE_CHAT_PROMPT);
4453
4541
  spinner.stop();
4454
- console.log(chalk12.cyan.bold("\n\u{1F50D} Diff Analysis\n"));
4455
- console.log(formatResponse(response.text) + "\n");
4542
+ console.log(chalk13.cyan.bold("\n\u{1F50D} Diff Analysis\n"));
4543
+ ui.printAIMessage(formatResponse(response.text));
4456
4544
  } catch (error) {
4457
4545
  spinner.fail("Error analyzing diff");
4458
4546
  handleError(error);
@@ -4460,15 +4548,15 @@ ${diffContext}`;
4460
4548
  }
4461
4549
  async function handleGitCommit(llm) {
4462
4550
  if (!isGitRepo()) {
4463
- console.log(chalk12.yellow("\n\u26A0\uFE0F Not a git repository\n"));
4551
+ console.log(chalk13.yellow("\n\u26A0\uFE0F Not a git repository\n"));
4464
4552
  return;
4465
4553
  }
4466
4554
  const status = getStatus();
4467
4555
  if (status.staged.length === 0) {
4468
- console.log(chalk12.yellow("\n\u26A0\uFE0F No staged changes. Stage some changes first with `git add`.\n"));
4556
+ console.log(chalk13.yellow("\n\u26A0\uFE0F No staged changes. Stage some changes first with `git add`.\n"));
4469
4557
  return;
4470
4558
  }
4471
- const spinner = ora4("Generating commit message...").start();
4559
+ const spinner = ui.createSpinner("Generating commit message...").start();
4472
4560
  try {
4473
4561
  const stagedDiff = getDiff(true);
4474
4562
  const diffText = formatDiffForPrompt(stagedDiff);
@@ -4483,8 +4571,8 @@ ${diffText}`;
4483
4571
  const response = await llm.generate(prompt, "You are a git commit message generator. Output ONLY the commit message, no explanation.");
4484
4572
  spinner.stop();
4485
4573
  const commitMessage = response.text.trim().split("\n")[0];
4486
- console.log(chalk12.cyan.bold("\n\u{1F4AC} Generated Commit Message\n"));
4487
- console.log(chalk12.white(` ${commitMessage}
4574
+ console.log(chalk13.cyan.bold("\n\u{1F4AC} Generated Commit Message\n"));
4575
+ console.log(chalk13.white(` ${commitMessage}
4488
4576
  `));
4489
4577
  const shouldCommit = await confirm3({
4490
4578
  message: "Commit with this message?",
@@ -4498,12 +4586,12 @@ ${diffText}`;
4498
4586
  cwd: env.workspaceRoot,
4499
4587
  stdio: "inherit"
4500
4588
  });
4501
- console.log(chalk12.green("\n\u2713 Committed successfully!\n"));
4589
+ console.log(chalk13.green("\n\u2713 Committed successfully!\n"));
4502
4590
  } catch (gitError) {
4503
- console.log(chalk12.red("\n\u2717 Commit failed. Check git output above.\n"));
4591
+ console.log(chalk13.red("\n\u2717 Commit failed. Check git output above.\n"));
4504
4592
  }
4505
4593
  } else {
4506
- console.log(chalk12.gray("\n\u{1F44B} Commit cancelled.\n"));
4594
+ console.log(chalk13.gray("\n\u{1F44B} Commit cancelled.\n"));
4507
4595
  }
4508
4596
  } catch (error) {
4509
4597
  spinner.fail("Error generating commit");
@@ -4512,81 +4600,82 @@ ${diffText}`;
4512
4600
  }
4513
4601
  function formatResponse(text) {
4514
4602
  return text.replace(/```(\w+)?\n([\s\S]*?)```/g, (_, lang, code) => {
4515
- const header = lang ? chalk12.gray(`\u2500\u2500 ${lang} \u2500\u2500`) : chalk12.gray("\u2500\u2500 code \u2500\u2500");
4603
+ const header = lang ? chalk13.gray(`\u2500\u2500 ${lang} \u2500\u2500`) : chalk13.gray("\u2500\u2500 code \u2500\u2500");
4516
4604
  return `
4517
4605
  ${header}
4518
- ${chalk12.white(code.trim())}
4519
- ${chalk12.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
4606
+ ${chalk13.white(code.trim())}
4607
+ ${chalk13.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}
4520
4608
  `;
4521
4609
  });
4522
4610
  }
4523
4611
  function showHelp() {
4524
- console.log(chalk12.cyan.bold("\n\u{1F4D6} Commands\n"));
4525
- console.log(chalk12.cyan(" Git Commands:"));
4526
- console.log(chalk12.gray(" /status ") + "AI analysis of git status");
4527
- console.log(chalk12.gray(" /diff ") + "AI explanation of current changes");
4528
- console.log(chalk12.gray(" /commit ") + "Generate and run git commit");
4612
+ console.log(chalk13.cyan.bold("\n\u{1F4D6} Commands\n"));
4613
+ console.log(chalk13.cyan(" Git Commands:"));
4614
+ console.log(chalk13.gray(" /status ") + "AI analysis of git status");
4615
+ console.log(chalk13.gray(" /diff ") + "AI explanation of current changes");
4616
+ console.log(chalk13.gray(" /commit ") + "Generate and run git commit");
4529
4617
  console.log("");
4530
- console.log(chalk12.cyan(" Build Commands:"));
4531
- console.log(chalk12.gray(" /build ") + "Generate and execute an application");
4532
- console.log(chalk12.gray(" /edit ") + "AI-powered surgical file editing");
4618
+ console.log(chalk13.cyan(" Build Commands:"));
4619
+ console.log(chalk13.gray(" /build ") + "Generate and execute an application");
4620
+ console.log(chalk13.gray(" /edit ") + "AI-powered surgical file editing");
4533
4621
  console.log("");
4534
- console.log(chalk12.cyan(" RAG Commands:"));
4535
- console.log(chalk12.gray(" /index ") + "Index current project for search");
4536
- console.log(chalk12.gray(" /search ") + "Semantic code search");
4622
+ console.log(chalk13.cyan(" RAG Commands:"));
4623
+ console.log(chalk13.gray(" /index ") + "Index current project for search");
4624
+ console.log(chalk13.gray(" /search ") + "Semantic code search");
4537
4625
  console.log("");
4538
- console.log(chalk12.cyan(" Advanced:"));
4539
- console.log(chalk12.gray(" /tools ") + "List available MCP tools");
4540
- console.log(chalk12.gray(" /agent ") + "Toggle multi-agent mode");
4541
- console.log(chalk12.gray(" /memory ") + "Show memory stats");
4626
+ console.log(chalk13.cyan(" Advanced:"));
4627
+ console.log(chalk13.gray(" /tools ") + "List available MCP tools");
4628
+ console.log(chalk13.gray(" /agent ") + "Toggle multi-agent mode");
4629
+ console.log(chalk13.gray(" /memory ") + "Show memory stats");
4542
4630
  console.log("");
4543
- console.log(chalk12.cyan(" Conversation:"));
4544
- console.log(chalk12.gray(" /clear ") + "Clear conversation history");
4545
- console.log(chalk12.gray(" /history ") + "Show recent conversation");
4631
+ console.log(chalk13.cyan(" Conversation:"));
4632
+ console.log(chalk13.gray(" /clear ") + "Clear conversation history");
4633
+ console.log(chalk13.gray(" /history ") + "Show recent conversation");
4546
4634
  console.log("");
4547
- console.log(chalk12.cyan(" General:"));
4548
- console.log(chalk12.gray(" /model ") + "Change AI model");
4549
- console.log(chalk12.gray(" /chat ") + "Switch to chat mode");
4550
- console.log(chalk12.gray(" /help ") + "Show this help");
4551
- console.log(chalk12.gray(" /exit ") + "Exit Agdi");
4552
- console.log(chalk12.gray("\n Or just type your coding question!\n"));
4635
+ console.log(chalk13.cyan(" General:"));
4636
+ console.log(chalk13.gray(" /model ") + "Change AI model");
4637
+ console.log(chalk13.gray(" /chat ") + "Switch to chat mode");
4638
+ console.log(chalk13.gray(" /help ") + "Show this help");
4639
+ console.log(chalk13.gray(" /exit ") + "Exit Agdi");
4640
+ console.log(chalk13.gray("\n Or just type your coding question!\n"));
4553
4641
  }
4554
4642
  function handleError(error) {
4555
4643
  const msg = error instanceof Error ? error.message : String(error);
4556
4644
  if (msg.includes("429") || msg.includes("quota")) {
4557
- console.log(chalk12.yellow("\n\u26A0\uFE0F Quota exceeded. Run /model to switch.\n"));
4645
+ console.log(chalk13.yellow("\n\u26A0\uFE0F Quota exceeded. Run /model to switch.\n"));
4558
4646
  } else if (msg.includes("401") || msg.includes("403")) {
4559
- console.log(chalk12.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
4647
+ console.log(chalk13.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
4560
4648
  } else {
4561
- console.log(chalk12.red("\n" + msg + "\n"));
4649
+ console.log(chalk13.red("\n" + msg + "\n"));
4562
4650
  }
4563
4651
  }
4564
4652
 
4565
4653
  // src/index.ts
4566
4654
  var BANNER = `
4567
- ${chalk13.cyan(` ___ __ _ `)}
4568
- ${chalk13.cyan(` / | ____ _____/ /(_) `)}
4569
- ${chalk13.cyan(` / /| | / __ \`/ __ // / `)}
4570
- ${chalk13.cyan(` / ___ |/ /_/ / /_/ // / `)}
4571
- ${chalk13.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4572
- ${chalk13.cyan(` /____/ `)}
4655
+ ${chalk14.cyan(` ___ __ _ `)}
4656
+ ${chalk14.cyan(` / | ____ _____/ /(_) `)}
4657
+ ${chalk14.cyan(` / /| | / __ \`/ __ // / `)}
4658
+ ${chalk14.cyan(` / ___ |/ /_/ / /_/ // / `)}
4659
+ ${chalk14.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4660
+ ${chalk14.cyan(` /____/ `)}
4573
4661
  `;
4574
4662
  var program = new Command();
4575
- program.name("agdi").description(chalk13.cyan("\u{1F680} AI-powered coding assistant")).version("2.2.2").configureHelp({
4663
+ program.name("agdi").description(chalk14.cyan("\u{1F680} AI-powered coding assistant")).version("2.6.0").configureHelp({
4576
4664
  // Show banner only when help is requested
4577
4665
  formatHelp: (cmd, helper) => {
4578
- return BANNER + "\n" + chalk13.gray(" The Open Source AI Architect") + "\n" + chalk13.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n") + "\n" + helper.formatHelp(cmd, helper);
4666
+ return BANNER + "\n" + chalk14.gray(" The Open Source AI Architect") + "\n" + chalk14.gray(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n") + "\n" + helper.formatHelp(cmd, helper);
4579
4667
  }
4580
4668
  });
4581
4669
  program.action(async () => {
4582
4670
  try {
4671
+ await ui.renderBanner();
4583
4672
  if (needsOnboarding()) {
4584
4673
  await runOnboarding();
4585
4674
  }
4586
4675
  await startCodingMode();
4587
4676
  } catch (error) {
4588
4677
  if (error.name === "ExitPromptError") {
4589
- console.log(chalk13.gray("\n\n\u{1F44B} Goodbye!\n"));
4678
+ console.log(chalk14.gray("\n\n\u{1F44B} Goodbye!\n"));
4590
4679
  process.exit(0);
4591
4680
  }
4592
4681
  throw error;
@@ -4601,7 +4690,7 @@ program.command("auth").description("Configure API keys").option("--status", "Sh
4601
4690
  }
4602
4691
  } catch (error) {
4603
4692
  if (error.name === "ExitPromptError") {
4604
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4693
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4605
4694
  process.exit(0);
4606
4695
  }
4607
4696
  throw error;
@@ -4612,7 +4701,7 @@ program.command("model").alias("models").description("Change AI model").action(a
4612
4701
  await selectModel();
4613
4702
  } catch (error) {
4614
4703
  if (error.name === "ExitPromptError") {
4615
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4704
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4616
4705
  process.exit(0);
4617
4706
  }
4618
4707
  throw error;
@@ -4626,7 +4715,7 @@ program.command("chat").description("Start a chat session").action(async () => {
4626
4715
  await startChat();
4627
4716
  } catch (error) {
4628
4717
  if (error.name === "ExitPromptError") {
4629
- console.log(chalk13.gray("\n\n\u{1F44B} Goodbye!\n"));
4718
+ console.log(chalk14.gray("\n\n\u{1F44B} Goodbye!\n"));
4630
4719
  process.exit(0);
4631
4720
  }
4632
4721
  throw error;
@@ -4637,7 +4726,7 @@ program.command("run [directory]").description("Run a generated project").action
4637
4726
  await runProject(directory);
4638
4727
  } catch (error) {
4639
4728
  if (error.name === "ExitPromptError") {
4640
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4729
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4641
4730
  process.exit(0);
4642
4731
  }
4643
4732
  throw error;
@@ -4650,7 +4739,7 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4650
4739
  }
4651
4740
  const activeConfig = getActiveProvider();
4652
4741
  if (!activeConfig) {
4653
- console.log(chalk13.red("\u274C No API key configured. Run: agdi auth"));
4742
+ console.log(chalk14.red("\u274C No API key configured. Run: agdi auth"));
4654
4743
  return;
4655
4744
  }
4656
4745
  const spinner = ora5("Generating application...").start();
@@ -4662,30 +4751,30 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4662
4751
  const pm = new ProjectManager();
4663
4752
  pm.create(options.output.replace("./", ""), prompt);
4664
4753
  const { plan, files } = await generateApp(prompt, llm, (step, file) => {
4665
- spinner.text = file ? `${step} ${chalk13.gray(file)}` : step;
4754
+ spinner.text = file ? `${step} ${chalk14.gray(file)}` : step;
4666
4755
  });
4667
4756
  pm.updateFiles(files);
4668
4757
  pm.updateDependencies(plan.dependencies);
4669
4758
  await writeProject(pm.get(), options.output);
4670
- spinner.succeed(chalk13.green("App generated!"));
4671
- console.log(chalk13.gray(`
4672
- \u{1F4C1} Created ${files.length} files in ${chalk13.cyan(options.output)}`));
4673
- console.log(chalk13.gray("\nNext: cd " + options.output + " && npm install && npm run dev\n"));
4759
+ spinner.succeed(chalk14.green("App generated!"));
4760
+ console.log(chalk14.gray(`
4761
+ \u{1F4C1} Created ${files.length} files in ${chalk14.cyan(options.output)}`));
4762
+ console.log(chalk14.gray("\nNext: cd " + options.output + " && npm install && npm run dev\n"));
4674
4763
  } catch (error) {
4675
4764
  spinner.fail("Generation failed");
4676
4765
  const msg = error instanceof Error ? error.message : String(error);
4677
4766
  if (msg.includes("429") || msg.includes("quota")) {
4678
- console.log(chalk13.yellow("\n\u26A0\uFE0F Quota exceeded. Run: agdi model\n"));
4767
+ console.log(chalk14.yellow("\n\u26A0\uFE0F Quota exceeded. Run: agdi model\n"));
4679
4768
  } else if (msg.includes("401") || msg.includes("403")) {
4680
- console.log(chalk13.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
4769
+ console.log(chalk14.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
4681
4770
  } else {
4682
- console.error(chalk13.red("\n" + msg + "\n"));
4771
+ console.error(chalk14.red("\n" + msg + "\n"));
4683
4772
  }
4684
4773
  process.exit(1);
4685
4774
  }
4686
4775
  } catch (error) {
4687
4776
  if (error.name === "ExitPromptError") {
4688
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4777
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4689
4778
  process.exit(0);
4690
4779
  }
4691
4780
  throw error;
@@ -4694,11 +4783,11 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4694
4783
  program.command("config").description("Show configuration").action(async () => {
4695
4784
  const config = loadConfig();
4696
4785
  const active = getActiveProvider();
4697
- console.log(chalk13.cyan.bold("\n\u2699\uFE0F Configuration\n"));
4698
- console.log(chalk13.gray(" Provider: ") + chalk13.cyan(config.defaultProvider || "not set"));
4699
- console.log(chalk13.gray(" Model: ") + chalk13.cyan(config.defaultModel || "not set"));
4700
- console.log(chalk13.gray(" Config: ") + chalk13.gray("~/.agdi/config.json"));
4701
- console.log(chalk13.cyan.bold("\n\u{1F510} API Keys\n"));
4786
+ console.log(chalk14.cyan.bold("\n\u2699\uFE0F Configuration\n"));
4787
+ console.log(chalk14.gray(" Provider: ") + chalk14.cyan(config.defaultProvider || "not set"));
4788
+ console.log(chalk14.gray(" Model: ") + chalk14.cyan(config.defaultModel || "not set"));
4789
+ console.log(chalk14.gray(" Config: ") + chalk14.gray("~/.agdi/config.json"));
4790
+ console.log(chalk14.cyan.bold("\n\u{1F510} API Keys\n"));
4702
4791
  const keys = [
4703
4792
  ["Gemini", config.geminiApiKey],
4704
4793
  ["OpenRouter", config.openrouterApiKey],
@@ -4707,7 +4796,7 @@ program.command("config").description("Show configuration").action(async () => {
4707
4796
  ["DeepSeek", config.deepseekApiKey]
4708
4797
  ];
4709
4798
  for (const [name, key] of keys) {
4710
- const status = key ? chalk13.green("\u2713") : chalk13.gray("\u2717");
4799
+ const status = key ? chalk14.green("\u2713") : chalk14.gray("\u2717");
4711
4800
  console.log(` ${status} ${name}`);
4712
4801
  }
4713
4802
  console.log("");