agdi 2.5.1 → 2.6.1

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/index.js CHANGED
@@ -1,14 +1,13 @@
1
1
  #!/usr/bin/env node
2
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
3
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
4
- }) : x)(function(x) {
5
- if (typeof require !== "undefined") return require.apply(this, arguments);
6
- throw Error('Dynamic require of "' + x + '" is not supported');
7
- });
2
+ import {
3
+ __require,
4
+ indexProject,
5
+ searchCodebase
6
+ } from "./chunk-NVMD3WL3.js";
8
7
 
9
8
  // src/index.ts
10
9
  import { Command } from "commander";
11
- import chalk13 from "chalk";
10
+ import chalk14 from "chalk";
12
11
  import ora5 from "ora";
13
12
 
14
13
  // src/core/llm/index.ts
@@ -1426,12 +1425,115 @@ async function selectModel() {
1426
1425
 
1427
1426
  // src/commands/agdi-dev.ts
1428
1427
  import { input as input5, confirm as confirm3 } from "@inquirer/prompts";
1429
- import chalk12 from "chalk";
1430
- 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
+ };
1431
1533
 
1432
1534
  // src/actions/plan-executor.ts
1433
1535
  import { select as select4, confirm } from "@inquirer/prompts";
1434
- import chalk10 from "chalk";
1536
+ import chalk11 from "chalk";
1435
1537
  import { spawn as spawn2 } from "child_process";
1436
1538
  import { resolve as resolve4 } from "path";
1437
1539
 
@@ -1566,7 +1668,7 @@ import { existsSync as existsSync3 } from "fs";
1566
1668
  import { resolve, dirname, relative, isAbsolute } from "path";
1567
1669
 
1568
1670
  // src/security/execution-env.ts
1569
- import chalk8 from "chalk";
1671
+ import chalk9 from "chalk";
1570
1672
  import { platform } from "os";
1571
1673
  import { existsSync, readFileSync } from "fs";
1572
1674
  function detectWSL() {
@@ -1675,11 +1777,11 @@ function formatNetwork(policy, domains) {
1675
1777
  function formatTrust(trust) {
1676
1778
  switch (trust) {
1677
1779
  case "untrusted":
1678
- return chalk8.red("untrusted (read-only mode)");
1780
+ return chalk9.red("untrusted (read-only mode)");
1679
1781
  case "session":
1680
- return chalk8.yellow("session trusted");
1782
+ return chalk9.yellow("session trusted");
1681
1783
  case "persistent":
1682
- return chalk8.green("trusted");
1784
+ return chalk9.green("trusted");
1683
1785
  }
1684
1786
  }
1685
1787
  function displaySessionHeader(env) {
@@ -1693,12 +1795,12 @@ function displaySessionHeader(env) {
1693
1795
  `Network: ${formatNetwork(env.networkPolicy, env.allowedDomains)}`,
1694
1796
  `Trust: ${formatTrust(env.trustLevel)}`
1695
1797
  ];
1696
- console.log(chalk8.cyan(topBorder));
1798
+ console.log(chalk9.cyan(topBorder));
1697
1799
  for (const line of lines) {
1698
1800
  const padding = " ".repeat(Math.max(0, boxWidth - stripAnsi(line).length - 2));
1699
- console.log(chalk8.cyan("\u2502 ") + line + padding + chalk8.cyan(" \u2502"));
1801
+ console.log(chalk9.cyan("\u2502 ") + line + padding + chalk9.cyan(" \u2502"));
1700
1802
  }
1701
- console.log(chalk8.cyan(bottomBorder));
1803
+ console.log(chalk9.cyan(bottomBorder));
1702
1804
  console.log("");
1703
1805
  }
1704
1806
  function truncatePath(path4, maxLen) {
@@ -2697,7 +2799,7 @@ function getRiskDescription(tier, argv) {
2697
2799
 
2698
2800
  // src/security/workspace-trust.ts
2699
2801
  import { select as select3 } from "@inquirer/prompts";
2700
- import chalk9 from "chalk";
2802
+ import chalk10 from "chalk";
2701
2803
  import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
2702
2804
  import { join as join3, resolve as resolve3 } from "path";
2703
2805
  import { homedir as homedir4 } from "os";
@@ -2746,14 +2848,14 @@ function trustWorkspace(workspacePath) {
2746
2848
  }
2747
2849
  async function promptWorkspaceTrust(workspacePath) {
2748
2850
  if (isWorkspaceTrusted(workspacePath)) {
2749
- console.log(chalk9.green("\u2713 Workspace is trusted\n"));
2851
+ console.log(chalk10.green("\u2713 Workspace is trusted\n"));
2750
2852
  return "persistent";
2751
2853
  }
2752
- console.log(chalk9.yellow("\n\u26A0\uFE0F Untrusted Workspace"));
2753
- console.log(chalk9.gray(` ${workspacePath}
2854
+ console.log(chalk10.yellow("\n\u26A0\uFE0F Untrusted Workspace"));
2855
+ console.log(chalk10.gray(` ${workspacePath}
2754
2856
  `));
2755
- console.log(chalk9.gray("Agdi can run commands in this workspace."));
2756
- 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"));
2757
2859
  const choice = await select3({
2758
2860
  message: "Trust this workspace?",
2759
2861
  choices: [
@@ -2781,15 +2883,15 @@ async function handleTrustFlow(workspacePath) {
2781
2883
  switch (choice) {
2782
2884
  case "session":
2783
2885
  updateEnvironment({ trustLevel: "session" });
2784
- console.log(chalk9.green("\u2713 Trusted for this session\n"));
2886
+ console.log(chalk10.green("\u2713 Trusted for this session\n"));
2785
2887
  return "session";
2786
2888
  case "persistent":
2787
2889
  trustWorkspace(workspacePath);
2788
2890
  updateEnvironment({ trustLevel: "persistent" });
2789
- console.log(chalk9.green("\u2713 Workspace trusted and remembered\n"));
2891
+ console.log(chalk10.green("\u2713 Workspace trusted and remembered\n"));
2790
2892
  return "persistent";
2791
2893
  case "exit":
2792
- 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"));
2793
2895
  return null;
2794
2896
  }
2795
2897
  }
@@ -2857,53 +2959,33 @@ async function downloadImageAsBase64(url) {
2857
2959
  // src/actions/plan-executor.ts
2858
2960
  function displayPlanSummary(plan) {
2859
2961
  const summary = summarizePlan(plan);
2860
- const boxWidth = 56;
2861
- console.log("");
2862
- console.log(chalk10.cyan("\u256D\u2500 Action Plan \u2500" + "\u2500".repeat(boxWidth - 15) + "\u256E"));
2863
- console.log(chalk10.cyan("\u2502 ") + chalk10.white(`Project: ${plan.projectName}`.padEnd(boxWidth - 2)) + chalk10.cyan(" \u2502"));
2864
- console.log(chalk10.cyan("\u2502 ") + "\u2500".repeat(boxWidth - 2) + chalk10.cyan(" \u2502"));
2865
2962
  const lines = [];
2866
- if (summary.dirsCreated > 0) {
2867
- lines.push(`\u{1F4C1} Create ${summary.dirsCreated} directories`);
2868
- }
2869
- if (summary.filesCreated > 0) {
2870
- lines.push(`\u{1F4C4} Create ${summary.filesCreated} files`);
2871
- }
2872
- if (summary.filesDeleted > 0) {
2873
- lines.push(`\u{1F5D1}\uFE0F Delete ${summary.filesDeleted} files`);
2874
- }
2875
- if (summary.commandsToRun > 0) {
2876
- lines.push(`\u26A1 Run ${summary.commandsToRun} commands`);
2877
- }
2878
- if (summary.domains.length > 0) {
2879
- lines.push(`\u{1F310} Network: ${summary.domains.join(", ")}`);
2880
- }
2881
- if (summary.ports.length > 0) {
2882
- lines.push(`\u{1F50C} Ports: ${summary.ports.join(", ")}`);
2883
- }
2884
- for (const line of lines) {
2885
- console.log(chalk10.cyan("\u2502 ") + chalk10.gray(line.padEnd(boxWidth - 2)) + chalk10.cyan(" \u2502"));
2886
- }
2887
- console.log(chalk10.cyan("\u2570" + "\u2500".repeat(boxWidth) + "\u256F"));
2888
- 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");
2889
2971
  }
2890
2972
  function displayActionProgress(action, index, total) {
2891
2973
  const num = `[${index + 1}/${total}]`;
2892
2974
  switch (action.type) {
2893
2975
  case "mkdir":
2894
- console.log(chalk10.gray(`${num} Creating directory: ${action.path}`));
2976
+ console.log(chalk11.gray(`${num} Creating directory: ${action.path}`));
2895
2977
  break;
2896
2978
  case "writeFile":
2897
- console.log(chalk10.gray(`${num} Writing file: ${action.path}`));
2979
+ console.log(chalk11.gray(`${num} Writing file: ${action.path}`));
2898
2980
  break;
2899
2981
  case "deleteFile":
2900
- console.log(chalk10.gray(`${num} Deleting file: ${action.path}`));
2982
+ console.log(chalk11.gray(`${num} Deleting file: ${action.path}`));
2901
2983
  break;
2902
2984
  case "exec":
2903
- console.log(chalk10.blue(`${num} Running: ${action.argv.join(" ")}`));
2985
+ console.log(chalk11.blue(`${num} Running: ${action.argv.join(" ")}`));
2904
2986
  break;
2905
2987
  case "generateImage":
2906
- console.log(chalk10.magenta(`${num} \u{1F3A8} Generating image: ${action.savePath}`));
2988
+ console.log(chalk11.magenta(`${num} \u{1F3A8} Generating image: ${action.savePath}`));
2907
2989
  break;
2908
2990
  }
2909
2991
  }
@@ -3014,16 +3096,16 @@ async function executeAction(action) {
3014
3096
  };
3015
3097
  }
3016
3098
  try {
3017
- console.log(chalk10.gray(` Prompt: "${action.prompt.slice(0, 50)}..."`));
3099
+ console.log(chalk11.gray(` Prompt: "${action.prompt.slice(0, 50)}..."`));
3018
3100
  const result = await generateImage(action.prompt, apiKey, { style: action.style });
3019
3101
  if (result.url) {
3020
3102
  const base64Data = await downloadImageAsBase64(result.url);
3021
3103
  const imageBuffer = Buffer.from(base64Data, "base64");
3022
3104
  await writeFileTool(action.savePath, imageBuffer.toString("base64"));
3023
- console.log(chalk10.green(` \u2713 Saved to ${action.savePath}`));
3105
+ console.log(chalk11.green(` \u2713 Saved to ${action.savePath}`));
3024
3106
  } else if (result.base64) {
3025
3107
  await writeFileTool(action.savePath, result.base64);
3026
- console.log(chalk10.green(` \u2713 Saved to ${action.savePath}`));
3108
+ console.log(chalk11.green(` \u2713 Saved to ${action.savePath}`));
3027
3109
  }
3028
3110
  return {
3029
3111
  action,
@@ -3049,18 +3131,19 @@ async function executePlan(plan) {
3049
3131
  displayPlanSummary(plan);
3050
3132
  const dryRun = await dryRunActions(plan);
3051
3133
  if (!dryRun.canProceed) {
3052
- console.log(chalk10.red("\n\u26D4 Plan contains actions that cannot be approved:"));
3053
- for (const result of dryRun.gateResults) {
3054
- if (result.decision === "deny") {
3055
- console.log(chalk10.red(` - ${result.command}: ${result.reason}`));
3056
- errors.push(result.reason);
3057
- }
3058
- }
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));
3059
3137
  return { success: false, results, filesCreated, commandsRun, errors };
3060
3138
  }
3061
3139
  if (dryRun.requiresTrust) {
3062
- console.log(chalk10.yellow("\u26A0\uFE0F This workspace is not trusted."));
3063
- 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
+ );
3064
3147
  const trustChoice = await select4({
3065
3148
  message: "Trust this workspace?",
3066
3149
  choices: [
@@ -3070,16 +3153,16 @@ async function executePlan(plan) {
3070
3153
  ]
3071
3154
  });
3072
3155
  if (trustChoice === "cancel") {
3073
- console.log(chalk10.yellow("\n\u{1F44B} Plan cancelled.\n"));
3156
+ console.log(chalk11.yellow("\n\u{1F44B} Plan cancelled.\n"));
3074
3157
  return { success: false, results, filesCreated, commandsRun, errors: ["User cancelled"] };
3075
3158
  }
3076
3159
  if (trustChoice === "persistent") {
3077
3160
  trustWorkspace(env.workspaceRoot);
3078
3161
  updateEnvironment({ trustLevel: "persistent" });
3079
- console.log(chalk10.green("\u2713 Workspace trusted and remembered\n"));
3162
+ console.log(chalk11.green("\u2713 Workspace trusted and remembered\n"));
3080
3163
  } else {
3081
3164
  updateEnvironment({ trustLevel: "session" });
3082
- console.log(chalk10.green("\u2713 Trusted for this session\n"));
3165
+ console.log(chalk11.green("\u2713 Trusted for this session\n"));
3083
3166
  }
3084
3167
  }
3085
3168
  const approved = await confirm({
@@ -3087,7 +3170,7 @@ async function executePlan(plan) {
3087
3170
  default: true
3088
3171
  });
3089
3172
  if (!approved) {
3090
- console.log(chalk10.yellow("\n\u{1F44B} Plan cancelled.\n"));
3173
+ console.log(chalk11.yellow("\n\u{1F44B} Plan cancelled.\n"));
3091
3174
  return { success: false, results, filesCreated, commandsRun, errors: ["User cancelled"] };
3092
3175
  }
3093
3176
  logEvent({
@@ -3098,7 +3181,7 @@ async function executePlan(plan) {
3098
3181
  summary: summarizePlan(plan)
3099
3182
  }
3100
3183
  });
3101
- console.log(chalk10.cyan("\n\u25B6 Executing plan...\n"));
3184
+ console.log(chalk11.cyan("\n\u25B6 Executing plan...\n"));
3102
3185
  for (let i = 0; i < plan.actions.length; i++) {
3103
3186
  const action = plan.actions[i];
3104
3187
  displayActionProgress(action, i, plan.actions.length);
@@ -3113,24 +3196,24 @@ async function executePlan(plan) {
3113
3196
  }
3114
3197
  } else {
3115
3198
  errors.push(result.error || "Unknown error");
3116
- console.log(chalk10.red(` \u2717 Failed: ${result.error}`));
3199
+ console.log(chalk11.red(` \u2717 Failed: ${result.error}`));
3117
3200
  }
3118
3201
  }
3119
3202
  const success = errors.length === 0;
3120
3203
  if (success) {
3121
- console.log(chalk10.green(`
3204
+ console.log(chalk11.green(`
3122
3205
  \u2713 Plan executed successfully!`));
3123
- console.log(chalk10.gray(` Created ${filesCreated.length} files`));
3124
- 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
3125
3208
  `));
3126
3209
  } else {
3127
- console.log(chalk10.red(`
3210
+ console.log(chalk11.red(`
3128
3211
  \u2717 Plan completed with ${errors.length} errors
3129
3212
  `));
3130
3213
  }
3131
3214
  if (plan.nextSteps) {
3132
- console.log(chalk10.cyan("Next steps:"));
3133
- console.log(chalk10.gray(` ${plan.nextSteps}
3215
+ console.log(chalk11.cyan("Next steps:"));
3216
+ console.log(chalk11.gray(` ${plan.nextSteps}
3134
3217
  `));
3135
3218
  }
3136
3219
  logEvent({
@@ -3150,7 +3233,7 @@ async function executePlan(plan) {
3150
3233
  async function parseAndExecutePlan(response) {
3151
3234
  const plan = parseActionPlan(response);
3152
3235
  if (!plan) {
3153
- 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"));
3154
3237
  return null;
3155
3238
  }
3156
3239
  return executePlan(plan);
@@ -3720,8 +3803,8 @@ function clearConversation() {
3720
3803
  // src/core/file-editor.ts
3721
3804
  import { readFile as readFile2 } from "fs/promises";
3722
3805
  import { existsSync as existsSync9 } from "fs";
3723
- import chalk11 from "chalk";
3724
- import ora3 from "ora";
3806
+ import chalk12 from "chalk";
3807
+ import ora4 from "ora";
3725
3808
  import { input as input4, confirm as confirm2 } from "@inquirer/prompts";
3726
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.
3727
3810
 
@@ -3788,19 +3871,19 @@ function extractDiff(response) {
3788
3871
  return null;
3789
3872
  }
3790
3873
  function previewDiff(diff) {
3791
- console.log(chalk11.cyan.bold("\n\u{1F4DD} Proposed Changes:\n"));
3874
+ console.log(chalk12.cyan.bold("\n\u{1F4DD} Proposed Changes:\n"));
3792
3875
  const lines = diff.split("\n");
3793
3876
  for (const line of lines) {
3794
3877
  if (line.startsWith("+++") || line.startsWith("---")) {
3795
- console.log(chalk11.gray(line));
3878
+ console.log(chalk12.gray(line));
3796
3879
  } else if (line.startsWith("@@")) {
3797
- console.log(chalk11.cyan(line));
3880
+ console.log(chalk12.cyan(line));
3798
3881
  } else if (line.startsWith("+")) {
3799
- console.log(chalk11.green(line));
3882
+ console.log(chalk12.green(line));
3800
3883
  } else if (line.startsWith("-")) {
3801
- console.log(chalk11.red(line));
3884
+ console.log(chalk12.red(line));
3802
3885
  } else {
3803
- console.log(chalk11.gray(line));
3886
+ console.log(chalk12.gray(line));
3804
3887
  }
3805
3888
  }
3806
3889
  console.log("");
@@ -3821,35 +3904,35 @@ function countChanges(diff) {
3821
3904
  async function handleFileEdit(filePath, llm) {
3822
3905
  const env = getEnvironment();
3823
3906
  if (!fileExists(filePath)) {
3824
- console.log(chalk11.red(`
3907
+ console.log(chalk12.red(`
3825
3908
  \u2717 File not found: ${filePath}
3826
3909
  `));
3827
3910
  return { success: false, error: "File not found" };
3828
3911
  }
3829
3912
  const fileData = await readFileForEdit(filePath);
3830
3913
  if (!fileData) {
3831
- console.log(chalk11.red(`
3914
+ console.log(chalk12.red(`
3832
3915
  \u2717 Could not read file: ${filePath}
3833
3916
  `));
3834
3917
  return { success: false, error: "Could not read file" };
3835
3918
  }
3836
3919
  const previewLines = fileData.numbered.split("\n").slice(0, 20);
3837
- console.log(chalk11.cyan.bold(`
3920
+ console.log(chalk12.cyan.bold(`
3838
3921
  \u{1F4C4} ${filePath}
3839
3922
  `));
3840
- console.log(chalk11.gray(previewLines.join("\n")));
3923
+ console.log(chalk12.gray(previewLines.join("\n")));
3841
3924
  if (fileData.content.split("\n").length > 20) {
3842
- 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)`));
3843
3926
  }
3844
3927
  console.log("");
3845
3928
  const instruction = await input4({
3846
- message: chalk11.yellow("Describe the edit:")
3929
+ message: chalk12.yellow("Describe the edit:")
3847
3930
  });
3848
3931
  if (!instruction.trim()) {
3849
- console.log(chalk11.gray("\n(no instruction provided)\n"));
3932
+ console.log(chalk12.gray("\n(no instruction provided)\n"));
3850
3933
  return { success: false, error: "No instruction" };
3851
3934
  }
3852
- const spinner = ora3("Generating edit...").start();
3935
+ const spinner = ora4("Generating edit...").start();
3853
3936
  try {
3854
3937
  const prompt = `File: ${filePath}
3855
3938
 
@@ -3865,27 +3948,27 @@ Generate the unified diff to make this change.`;
3865
3948
  spinner.stop();
3866
3949
  const diff = extractDiff(response.text);
3867
3950
  if (!diff) {
3868
- console.log(chalk11.yellow("\n\u26A0\uFE0F Could not generate a valid diff.\n"));
3869
- 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)));
3870
3953
  return { success: false, error: "Invalid diff generated" };
3871
3954
  }
3872
3955
  previewDiff(diff);
3873
3956
  const changes = countChanges(diff);
3874
- 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
3875
3958
  `));
3876
3959
  const shouldApply = await confirm2({
3877
3960
  message: "Apply these changes?",
3878
3961
  default: true
3879
3962
  });
3880
3963
  if (!shouldApply) {
3881
- console.log(chalk11.gray("\n\u{1F44B} Edit cancelled.\n"));
3964
+ console.log(chalk12.gray("\n\u{1F44B} Edit cancelled.\n"));
3882
3965
  return { success: false, error: "Cancelled by user" };
3883
3966
  }
3884
- const applySpinner = ora3("Applying changes...").start();
3967
+ const applySpinner = ora4("Applying changes...").start();
3885
3968
  const result = await applyPatchTool(filePath, diff);
3886
3969
  applySpinner.stop();
3887
3970
  if (result.success) {
3888
- console.log(chalk11.green(`
3971
+ console.log(chalk12.green(`
3889
3972
  \u2713 Successfully edited ${filePath}
3890
3973
  `));
3891
3974
  logEvent({
@@ -3900,7 +3983,7 @@ Generate the unified diff to make this change.`;
3900
3983
  });
3901
3984
  return { success: true, linesChanged: changes.added + changes.removed };
3902
3985
  } else {
3903
- console.log(chalk11.red(`
3986
+ console.log(chalk12.red(`
3904
3987
  \u2717 Failed to apply changes: ${result.error}
3905
3988
  `));
3906
3989
  return { success: false, error: result.error };
@@ -3908,14 +3991,181 @@ Generate the unified diff to make this change.`;
3908
3991
  } catch (error) {
3909
3992
  spinner.stop();
3910
3993
  const msg = error instanceof Error ? error.message : String(error);
3911
- console.log(chalk11.red(`
3994
+ console.log(chalk12.red(`
3912
3995
  \u2717 Error: ${msg}
3913
3996
  `));
3914
3997
  return { success: false, error: msg };
3915
3998
  }
3916
3999
  }
3917
4000
 
4001
+ // src/core/mcp/tools.ts
4002
+ var tools = /* @__PURE__ */ new Map();
4003
+ function registerTool(tool) {
4004
+ tools.set(tool.name, tool);
4005
+ }
4006
+ function listTools() {
4007
+ return Array.from(tools.values());
4008
+ }
4009
+ registerTool({
4010
+ name: "read_file",
4011
+ description: "Read the contents of a file",
4012
+ category: "filesystem",
4013
+ parameters: [
4014
+ { name: "path", type: "string", description: "File path to read", required: true }
4015
+ ],
4016
+ execute: async (params) => {
4017
+ const { readFileSync: readFileSync8 } = await import("fs");
4018
+ const { resolve: resolve5 } = await import("path");
4019
+ try {
4020
+ const filePath = resolve5(process.cwd(), params.path);
4021
+ const content = readFileSync8(filePath, "utf-8");
4022
+ return {
4023
+ success: true,
4024
+ data: content,
4025
+ display: `Read ${content.split("\n").length} lines from ${params.path}`
4026
+ };
4027
+ } catch (error) {
4028
+ return {
4029
+ success: false,
4030
+ error: `Failed to read file: ${error}`
4031
+ };
4032
+ }
4033
+ }
4034
+ });
4035
+ registerTool({
4036
+ name: "list_dir",
4037
+ description: "List files in a directory",
4038
+ category: "filesystem",
4039
+ parameters: [
4040
+ { name: "path", type: "string", description: "Directory path", required: false, default: "." }
4041
+ ],
4042
+ execute: async (params) => {
4043
+ const { readdirSync: readdirSync2, statSync: statSync2 } = await import("fs");
4044
+ const { resolve: resolve5, join: join8 } = await import("path");
4045
+ try {
4046
+ const dirPath = resolve5(process.cwd(), params.path || ".");
4047
+ const entries = readdirSync2(dirPath);
4048
+ const files = [];
4049
+ const dirs = [];
4050
+ for (const entry of entries) {
4051
+ try {
4052
+ const stat = statSync2(join8(dirPath, entry));
4053
+ if (stat.isDirectory()) {
4054
+ dirs.push(entry + "/");
4055
+ } else {
4056
+ files.push(entry);
4057
+ }
4058
+ } catch {
4059
+ files.push(entry);
4060
+ }
4061
+ }
4062
+ return {
4063
+ success: true,
4064
+ data: { dirs, files },
4065
+ display: `${dirs.length} directories, ${files.length} files`
4066
+ };
4067
+ } catch (error) {
4068
+ return {
4069
+ success: false,
4070
+ error: `Failed to list directory: ${error}`
4071
+ };
4072
+ }
4073
+ }
4074
+ });
4075
+ registerTool({
4076
+ name: "search_code",
4077
+ description: "Search for code in the current project",
4078
+ category: "code",
4079
+ parameters: [
4080
+ { name: "query", type: "string", description: "Search query", required: true },
4081
+ { name: "limit", type: "number", description: "Max results", required: false, default: 5 }
4082
+ ],
4083
+ execute: async (params) => {
4084
+ const { searchCodebase: searchCodebase2 } = await import("./rag-6HO4ZLBN.js");
4085
+ const results = searchCodebase2(
4086
+ process.cwd(),
4087
+ params.query,
4088
+ { limit: params.limit || 5 }
4089
+ );
4090
+ if (results.length === 0) {
4091
+ return {
4092
+ success: true,
4093
+ data: [],
4094
+ display: "No results found"
4095
+ };
4096
+ }
4097
+ const display = results.map(
4098
+ (r) => `${r.chunk.relativePath}:${r.chunk.startLine} (score: ${r.score.toFixed(2)})`
4099
+ ).join("\n");
4100
+ return {
4101
+ success: true,
4102
+ data: results.map((r) => ({
4103
+ file: r.chunk.relativePath,
4104
+ line: r.chunk.startLine,
4105
+ content: r.chunk.content.slice(0, 200)
4106
+ })),
4107
+ display
4108
+ };
4109
+ }
4110
+ });
4111
+ registerTool({
4112
+ name: "run_command",
4113
+ description: "Run a shell command (requires user approval)",
4114
+ category: "system",
4115
+ parameters: [
4116
+ { name: "command", type: "string", description: "Command to run", required: true }
4117
+ ],
4118
+ execute: async (params) => {
4119
+ return {
4120
+ success: false,
4121
+ error: "Shell commands require explicit user approval. Use /build or /exec instead."
4122
+ };
4123
+ }
4124
+ });
4125
+
4126
+ // src/core/memory-store.ts
4127
+ import { existsSync as existsSync10, readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
4128
+ import { join as join7 } from "path";
4129
+ import { homedir as homedir6 } from "os";
4130
+ var MEMORY_DIR = join7(homedir6(), ".agdi", "memory");
4131
+ var MEMORY_FILE = join7(MEMORY_DIR, "store.json");
4132
+ function ensureMemoryDir() {
4133
+ if (!existsSync10(MEMORY_DIR)) {
4134
+ mkdirSync5(MEMORY_DIR, { recursive: true });
4135
+ }
4136
+ }
4137
+ function loadMemoryStore() {
4138
+ ensureMemoryDir();
4139
+ if (existsSync10(MEMORY_FILE)) {
4140
+ try {
4141
+ const data = readFileSync7(MEMORY_FILE, "utf-8");
4142
+ return JSON.parse(data);
4143
+ } catch {
4144
+ }
4145
+ }
4146
+ return {
4147
+ version: 1,
4148
+ entries: [],
4149
+ userPreferences: {},
4150
+ projectContexts: {}
4151
+ };
4152
+ }
4153
+ function getMemoryStats() {
4154
+ const store = loadMemoryStore();
4155
+ const byType = {};
4156
+ for (const entry of store.entries) {
4157
+ byType[entry.type] = (byType[entry.type] || 0) + 1;
4158
+ }
4159
+ return {
4160
+ totalEntries: store.entries.length,
4161
+ byType,
4162
+ projectCount: Object.keys(store.projectContexts).length,
4163
+ preferenceCount: Object.keys(store.userPreferences).length
4164
+ };
4165
+ }
4166
+
3918
4167
  // src/commands/agdi-dev.ts
4168
+ var multiAgentMode = false;
3919
4169
  var BASE_CHAT_PROMPT = `You are Agdi dev, an elite AI coding assistant. You help developers write code, debug issues, and build applications.
3920
4170
 
3921
4171
  ## Your Capabilities
@@ -3993,7 +4243,7 @@ For landing pages, portfolios, or apps that need visuals, use generateImage acti
3993
4243
  async function startCodingMode() {
3994
4244
  const activeConfig = getActiveProvider();
3995
4245
  if (!activeConfig) {
3996
- console.log(chalk12.red("\u274C No API key configured. Run: agdi"));
4246
+ console.log(chalk13.red("\u274C No API key configured. Run: agdi"));
3997
4247
  return;
3998
4248
  }
3999
4249
  const { provider, apiKey, model } = activeConfig;
@@ -4005,11 +4255,15 @@ async function startCodingMode() {
4005
4255
  process.exit(0);
4006
4256
  }
4007
4257
  logSessionStart(env.workspaceRoot, env.trustLevel);
4008
- console.log(chalk12.cyan.bold("\u26A1 Agdi dev\n"));
4009
- console.log(chalk12.gray(`Model: ${chalk12.cyan(model)}`));
4010
- console.log(chalk12.gray(`Workspace: ${chalk12.cyan(env.workspaceRoot)}`));
4011
- console.log(chalk12.gray("Commands: /status, /diff, /commit, /build, /clear, /history, /model, /help, /exit\n"));
4012
- 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();
4013
4267
  const pm = new ProjectManager();
4014
4268
  let llm = createLLMProvider(provider, { apiKey, model });
4015
4269
  const conversation = getConversation();
@@ -4017,12 +4271,12 @@ async function startCodingMode() {
4017
4271
  while (true) {
4018
4272
  try {
4019
4273
  const userInput = await input5({
4020
- message: chalk12.green("\u2192")
4274
+ message: chalk13.cyan.bold("\u{1F464} YOU \u203A")
4021
4275
  });
4022
4276
  const trimmed = userInput.trim().toLowerCase();
4023
4277
  if (trimmed === "/exit" || trimmed === "exit" || trimmed === "quit") {
4024
4278
  logSessionEnd();
4025
- console.log(chalk12.gray("\n\u{1F44B} Goodbye!\n"));
4279
+ console.log(chalk13.gray("\n\u{1F44B} Goodbye!\n"));
4026
4280
  break;
4027
4281
  }
4028
4282
  if (trimmed === "/help") {
@@ -4037,34 +4291,34 @@ async function startCodingMode() {
4037
4291
  apiKey: newConfig.apiKey,
4038
4292
  model: newConfig.model
4039
4293
  });
4040
- console.log(chalk12.gray(`Now using: ${chalk12.cyan(newConfig.model)}
4294
+ console.log(chalk13.gray(`Now using: ${chalk13.cyan(newConfig.model)}
4041
4295
  `));
4042
4296
  }
4043
4297
  continue;
4044
4298
  }
4045
4299
  if (trimmed === "/chat") {
4046
- 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"));
4047
4301
  await chatMode(llm);
4048
4302
  continue;
4049
4303
  }
4050
4304
  if (trimmed === "/clear") {
4051
4305
  clearConversation();
4052
4306
  conversation.setSystemPrompt(buildContextAwarePrompt());
4053
- console.log(chalk12.green("\n\u2713 Conversation cleared.\n"));
4307
+ console.log(chalk13.green("\n\u2713 Conversation cleared.\n"));
4054
4308
  continue;
4055
4309
  }
4056
4310
  if (trimmed === "/history") {
4057
4311
  const messages = conversation.getMessages();
4058
4312
  if (messages.length === 0) {
4059
- console.log(chalk12.gray("\n(no conversation history)\n"));
4313
+ console.log(chalk13.gray("\n(no conversation history)\n"));
4060
4314
  } else {
4061
- console.log(chalk12.cyan.bold("\n\u{1F4DC} Conversation History\n"));
4062
- 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()));
4063
4317
  console.log("");
4064
4318
  for (const msg of messages.slice(-6)) {
4065
- const role = msg.role === "user" ? chalk12.green("You") : chalk12.cyan("AI");
4319
+ const role = msg.role === "user" ? chalk13.green("You") : chalk13.cyan("AI");
4066
4320
  const preview = msg.content.slice(0, 80) + (msg.content.length > 80 ? "..." : "");
4067
- console.log(` ${role}: ${chalk12.gray(preview)}`);
4321
+ console.log(` ${role}: ${chalk13.gray(preview)}`);
4068
4322
  }
4069
4323
  console.log("");
4070
4324
  }
@@ -4087,16 +4341,79 @@ async function startCodingMode() {
4087
4341
  if (filePath) {
4088
4342
  await handleFileEdit(filePath, llm);
4089
4343
  } else {
4090
- console.log(chalk12.yellow("\nUsage: /edit <file>\n"));
4344
+ console.log(chalk13.yellow("\nUsage: /edit <file>\n"));
4345
+ }
4346
+ continue;
4347
+ }
4348
+ if (trimmed === "/index") {
4349
+ const spinner2 = ui.createSpinner("Indexing project...").start();
4350
+ try {
4351
+ const index = indexProject(process.cwd());
4352
+ spinner2.succeed(`Indexed ${index.fileCount} files, ${index.chunkCount} chunks`);
4353
+ } catch (error) {
4354
+ spinner2.fail("Indexing failed: " + (error instanceof Error ? error.message : String(error)));
4355
+ }
4356
+ continue;
4357
+ }
4358
+ if (trimmed.startsWith("/search ")) {
4359
+ const query = userInput.slice(8).trim();
4360
+ if (!query) {
4361
+ console.log(chalk13.yellow("\nUsage: /search <query>\n"));
4362
+ continue;
4363
+ }
4364
+ const results = searchCodebase(process.cwd(), query, { limit: 8 });
4365
+ if (results.length === 0) {
4366
+ console.log(chalk13.gray("\nNo results found. Try /index first.\n"));
4367
+ } else {
4368
+ console.log(chalk13.cyan.bold("\n\u{1F50D} Search Results\n"));
4369
+ for (const r of results) {
4370
+ console.log(chalk13.green(` ${r.chunk.relativePath}:${r.chunk.startLine}`) + chalk13.gray(` (${r.score.toFixed(2)})`));
4371
+ if (r.highlights.length > 0) {
4372
+ console.log(chalk13.gray(` ${r.highlights[0].slice(0, 60)}...`));
4373
+ }
4374
+ }
4375
+ console.log("");
4091
4376
  }
4092
4377
  continue;
4093
4378
  }
4379
+ if (trimmed === "/tools") {
4380
+ const tools2 = listTools();
4381
+ console.log(chalk13.cyan.bold("\n\u{1F527} Available Tools\n"));
4382
+ for (const tool of tools2) {
4383
+ console.log(chalk13.green(` ${tool.name}`) + chalk13.gray(` [${tool.category}]`));
4384
+ console.log(chalk13.gray(` ${tool.description}`));
4385
+ }
4386
+ console.log("");
4387
+ continue;
4388
+ }
4389
+ if (trimmed === "/agent") {
4390
+ multiAgentMode = !multiAgentMode;
4391
+ console.log(chalk13.cyan(`
4392
+ \u{1F916} Multi-agent mode: ${multiAgentMode ? chalk13.green("ON") : chalk13.gray("OFF")}
4393
+ `));
4394
+ if (multiAgentMode) {
4395
+ console.log(chalk13.gray(" Planner \u2192 Coder \u2192 Reviewer pipeline enabled\n"));
4396
+ }
4397
+ continue;
4398
+ }
4399
+ if (trimmed === "/memory") {
4400
+ const stats = getMemoryStats();
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}`));
4405
+ for (const [type, count] of Object.entries(stats.byType)) {
4406
+ console.log(chalk13.gray(` ${type}: ${count}`));
4407
+ }
4408
+ console.log("");
4409
+ continue;
4410
+ }
4094
4411
  if (trimmed.startsWith("/build ") || trimmed.startsWith("build ")) {
4095
4412
  const prompt = userInput.replace(/^\/?build\s+/i, "").trim();
4096
4413
  if (prompt) {
4097
4414
  await buildAppWithPlan(prompt, llm);
4098
4415
  } else {
4099
- console.log(chalk12.yellow("\nUsage: /build <description>\n"));
4416
+ console.log(chalk13.yellow("\nUsage: /build <description>\n"));
4100
4417
  }
4101
4418
  continue;
4102
4419
  }
@@ -4108,7 +4425,7 @@ async function startCodingMode() {
4108
4425
  await buildAppWithPlan(userInput, llm);
4109
4426
  continue;
4110
4427
  }
4111
- const spinner = ora4("Thinking...").start();
4428
+ const spinner = ui.createSpinner("Thinking...").start();
4112
4429
  try {
4113
4430
  conversation.addUserMessage(userInput);
4114
4431
  let response;
@@ -4120,7 +4437,7 @@ async function startCodingMode() {
4120
4437
  }
4121
4438
  conversation.addAssistantMessage(response.text);
4122
4439
  spinner.stop();
4123
- console.log("\n" + formatResponse(response.text) + "\n");
4440
+ ui.printAIMessage(formatResponse(response.text));
4124
4441
  } catch (error) {
4125
4442
  spinner.fail("Error");
4126
4443
  handleError(error);
@@ -4128,7 +4445,7 @@ async function startCodingMode() {
4128
4445
  } catch (error) {
4129
4446
  if (error.name === "ExitPromptError") {
4130
4447
  logSessionEnd();
4131
- console.log(chalk12.gray("\n\n\u{1F44B} Goodbye!\n"));
4448
+ console.log(chalk13.gray("\n\n\u{1F44B} Goodbye!\n"));
4132
4449
  process.exit(0);
4133
4450
  }
4134
4451
  throw error;
@@ -4136,13 +4453,13 @@ async function startCodingMode() {
4136
4453
  }
4137
4454
  }
4138
4455
  async function buildAppWithPlan(prompt, llm) {
4139
- const spinner = ora4("Generating action plan...").start();
4456
+ const spinner = ui.createSpinner("Generating action plan...").start();
4140
4457
  try {
4141
4458
  const response = await llm.generate(prompt, BUILD_SYSTEM_PROMPT);
4142
4459
  spinner.stop();
4143
4460
  const result = await parseAndExecutePlan(response.text);
4144
4461
  if (!result) {
4145
- 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"));
4146
4463
  console.log(formatResponse(response.text) + "\n");
4147
4464
  }
4148
4465
  } catch (error) {
@@ -4154,17 +4471,17 @@ async function chatMode(llm) {
4154
4471
  while (true) {
4155
4472
  try {
4156
4473
  const userInput = await input5({
4157
- message: chalk12.blue("\u{1F4AC}")
4474
+ message: chalk13.blue("\u{1F4AC}")
4158
4475
  });
4159
4476
  if (userInput.toLowerCase() === "/code" || userInput.toLowerCase() === "/exit") {
4160
- console.log(chalk12.gray("\nBack to Agdi dev mode.\n"));
4477
+ console.log(chalk13.gray("\nBack to Agdi dev mode.\n"));
4161
4478
  return;
4162
4479
  }
4163
4480
  if (!userInput.trim()) continue;
4164
- const spinner = ora4("...").start();
4481
+ const spinner = ui.createSpinner("Thinking...").start();
4165
4482
  const response = await llm.generate(userInput, "You are a helpful assistant. Be friendly and concise.");
4166
4483
  spinner.stop();
4167
- console.log("\n" + response.text + "\n");
4484
+ ui.printAIMessage(response.text);
4168
4485
  } catch (error) {
4169
4486
  if (error.name === "ExitPromptError") {
4170
4487
  return;
@@ -4175,10 +4492,10 @@ async function chatMode(llm) {
4175
4492
  }
4176
4493
  async function handleGitStatus(llm) {
4177
4494
  if (!isGitRepo()) {
4178
- 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"));
4179
4496
  return;
4180
4497
  }
4181
- const spinner = ora4("Analyzing git status...").start();
4498
+ const spinner = ui.createSpinner("Analyzing git status...").start();
4182
4499
  try {
4183
4500
  const status = getStatus();
4184
4501
  const statusText = formatStatusForPrompt(status);
@@ -4187,10 +4504,10 @@ async function handleGitStatus(llm) {
4187
4504
  ${statusText}`;
4188
4505
  const response = await llm.generate(prompt, BASE_CHAT_PROMPT);
4189
4506
  spinner.stop();
4190
- console.log(chalk12.cyan.bold("\n\u{1F4CA} Git Status Analysis\n"));
4191
- console.log(chalk12.gray(statusText));
4192
- console.log(chalk12.cyan("\n\u2500\u2500\u2500 AI Analysis \u2500\u2500\u2500\n"));
4193
- 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));
4194
4511
  } catch (error) {
4195
4512
  spinner.fail("Error analyzing status");
4196
4513
  handleError(error);
@@ -4198,16 +4515,16 @@ ${statusText}`;
4198
4515
  }
4199
4516
  async function handleGitDiff(llm) {
4200
4517
  if (!isGitRepo()) {
4201
- 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"));
4202
4519
  return;
4203
4520
  }
4204
- const spinner = ora4("Analyzing changes...").start();
4521
+ const spinner = ui.createSpinner("Analyzing changes...").start();
4205
4522
  try {
4206
4523
  const stagedDiff = getDiff(true);
4207
4524
  const unstagedDiff = getDiff(false);
4208
4525
  if (stagedDiff.files.length === 0 && unstagedDiff.files.length === 0) {
4209
4526
  spinner.stop();
4210
- console.log(chalk12.gray("\n(no changes to analyze)\n"));
4527
+ console.log(chalk13.gray("\n(no changes to analyze)\n"));
4211
4528
  return;
4212
4529
  }
4213
4530
  let diffContext = "";
@@ -4222,8 +4539,8 @@ async function handleGitDiff(llm) {
4222
4539
  ${diffContext}`;
4223
4540
  const response = await llm.generate(prompt, BASE_CHAT_PROMPT);
4224
4541
  spinner.stop();
4225
- console.log(chalk12.cyan.bold("\n\u{1F50D} Diff Analysis\n"));
4226
- console.log(formatResponse(response.text) + "\n");
4542
+ console.log(chalk13.cyan.bold("\n\u{1F50D} Diff Analysis\n"));
4543
+ ui.printAIMessage(formatResponse(response.text));
4227
4544
  } catch (error) {
4228
4545
  spinner.fail("Error analyzing diff");
4229
4546
  handleError(error);
@@ -4231,15 +4548,15 @@ ${diffContext}`;
4231
4548
  }
4232
4549
  async function handleGitCommit(llm) {
4233
4550
  if (!isGitRepo()) {
4234
- 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"));
4235
4552
  return;
4236
4553
  }
4237
4554
  const status = getStatus();
4238
4555
  if (status.staged.length === 0) {
4239
- 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"));
4240
4557
  return;
4241
4558
  }
4242
- const spinner = ora4("Generating commit message...").start();
4559
+ const spinner = ui.createSpinner("Generating commit message...").start();
4243
4560
  try {
4244
4561
  const stagedDiff = getDiff(true);
4245
4562
  const diffText = formatDiffForPrompt(stagedDiff);
@@ -4254,8 +4571,8 @@ ${diffText}`;
4254
4571
  const response = await llm.generate(prompt, "You are a git commit message generator. Output ONLY the commit message, no explanation.");
4255
4572
  spinner.stop();
4256
4573
  const commitMessage = response.text.trim().split("\n")[0];
4257
- console.log(chalk12.cyan.bold("\n\u{1F4AC} Generated Commit Message\n"));
4258
- console.log(chalk12.white(` ${commitMessage}
4574
+ console.log(chalk13.cyan.bold("\n\u{1F4AC} Generated Commit Message\n"));
4575
+ console.log(chalk13.white(` ${commitMessage}
4259
4576
  `));
4260
4577
  const shouldCommit = await confirm3({
4261
4578
  message: "Commit with this message?",
@@ -4269,12 +4586,12 @@ ${diffText}`;
4269
4586
  cwd: env.workspaceRoot,
4270
4587
  stdio: "inherit"
4271
4588
  });
4272
- console.log(chalk12.green("\n\u2713 Committed successfully!\n"));
4589
+ console.log(chalk13.green("\n\u2713 Committed successfully!\n"));
4273
4590
  } catch (gitError) {
4274
- 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"));
4275
4592
  }
4276
4593
  } else {
4277
- console.log(chalk12.gray("\n\u{1F44B} Commit cancelled.\n"));
4594
+ console.log(chalk13.gray("\n\u{1F44B} Commit cancelled.\n"));
4278
4595
  }
4279
4596
  } catch (error) {
4280
4597
  spinner.fail("Error generating commit");
@@ -4283,73 +4600,82 @@ ${diffText}`;
4283
4600
  }
4284
4601
  function formatResponse(text) {
4285
4602
  return text.replace(/```(\w+)?\n([\s\S]*?)```/g, (_, lang, code) => {
4286
- 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");
4287
4604
  return `
4288
4605
  ${header}
4289
- ${chalk12.white(code.trim())}
4290
- ${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")}
4291
4608
  `;
4292
4609
  });
4293
4610
  }
4294
4611
  function showHelp() {
4295
- console.log(chalk12.cyan.bold("\n\u{1F4D6} Commands\n"));
4296
- console.log(chalk12.cyan(" Git Commands:"));
4297
- console.log(chalk12.gray(" /status ") + "AI analysis of git status");
4298
- console.log(chalk12.gray(" /diff ") + "AI explanation of current changes");
4299
- 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");
4617
+ console.log("");
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");
4621
+ console.log("");
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");
4300
4625
  console.log("");
4301
- console.log(chalk12.cyan(" Build Commands:"));
4302
- console.log(chalk12.gray(" /build ") + "Generate and execute an application");
4303
- console.log(chalk12.gray(" /edit ") + "AI-powered surgical file editing");
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");
4304
4630
  console.log("");
4305
- console.log(chalk12.cyan(" Conversation:"));
4306
- console.log(chalk12.gray(" /clear ") + "Clear conversation history");
4307
- 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");
4308
4634
  console.log("");
4309
- console.log(chalk12.cyan(" General:"));
4310
- console.log(chalk12.gray(" /model ") + "Change AI model");
4311
- console.log(chalk12.gray(" /chat ") + "Switch to chat mode");
4312
- console.log(chalk12.gray(" /help ") + "Show this help");
4313
- console.log(chalk12.gray(" /exit ") + "Exit Agdi");
4314
- console.log(chalk12.gray("\n Or just type your coding question!\n"));
4315
- console.log(chalk12.gray('Tip: "Create a todo app" will generate & write files.\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"));
4316
4641
  }
4317
4642
  function handleError(error) {
4318
4643
  const msg = error instanceof Error ? error.message : String(error);
4319
4644
  if (msg.includes("429") || msg.includes("quota")) {
4320
- 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"));
4321
4646
  } else if (msg.includes("401") || msg.includes("403")) {
4322
- 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"));
4323
4648
  } else {
4324
- console.log(chalk12.red("\n" + msg + "\n"));
4649
+ console.log(chalk13.red("\n" + msg + "\n"));
4325
4650
  }
4326
4651
  }
4327
4652
 
4328
4653
  // src/index.ts
4329
4654
  var BANNER = `
4330
- ${chalk13.cyan(` ___ __ _ `)}
4331
- ${chalk13.cyan(` / | ____ _____/ /(_) `)}
4332
- ${chalk13.cyan(` / /| | / __ \`/ __ // / `)}
4333
- ${chalk13.cyan(` / ___ |/ /_/ / /_/ // / `)}
4334
- ${chalk13.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4335
- ${chalk13.cyan(` /____/ `)}
4655
+ ${chalk14.cyan(` ___ __ _ `)}
4656
+ ${chalk14.cyan(` / | ____ _____/ /(_) `)}
4657
+ ${chalk14.cyan(` / /| | / __ \`/ __ // / `)}
4658
+ ${chalk14.cyan(` / ___ |/ /_/ / /_/ // / `)}
4659
+ ${chalk14.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4660
+ ${chalk14.cyan(` /____/ `)}
4336
4661
  `;
4337
4662
  var program = new Command();
4338
- 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({
4339
4664
  // Show banner only when help is requested
4340
4665
  formatHelp: (cmd, helper) => {
4341
- 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);
4342
4667
  }
4343
4668
  });
4344
4669
  program.action(async () => {
4345
4670
  try {
4671
+ await ui.renderBanner();
4346
4672
  if (needsOnboarding()) {
4347
4673
  await runOnboarding();
4348
4674
  }
4349
4675
  await startCodingMode();
4350
4676
  } catch (error) {
4351
4677
  if (error.name === "ExitPromptError") {
4352
- console.log(chalk13.gray("\n\n\u{1F44B} Goodbye!\n"));
4678
+ console.log(chalk14.gray("\n\n\u{1F44B} Goodbye!\n"));
4353
4679
  process.exit(0);
4354
4680
  }
4355
4681
  throw error;
@@ -4364,7 +4690,7 @@ program.command("auth").description("Configure API keys").option("--status", "Sh
4364
4690
  }
4365
4691
  } catch (error) {
4366
4692
  if (error.name === "ExitPromptError") {
4367
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4693
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4368
4694
  process.exit(0);
4369
4695
  }
4370
4696
  throw error;
@@ -4375,7 +4701,7 @@ program.command("model").alias("models").description("Change AI model").action(a
4375
4701
  await selectModel();
4376
4702
  } catch (error) {
4377
4703
  if (error.name === "ExitPromptError") {
4378
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4704
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4379
4705
  process.exit(0);
4380
4706
  }
4381
4707
  throw error;
@@ -4389,7 +4715,7 @@ program.command("chat").description("Start a chat session").action(async () => {
4389
4715
  await startChat();
4390
4716
  } catch (error) {
4391
4717
  if (error.name === "ExitPromptError") {
4392
- console.log(chalk13.gray("\n\n\u{1F44B} Goodbye!\n"));
4718
+ console.log(chalk14.gray("\n\n\u{1F44B} Goodbye!\n"));
4393
4719
  process.exit(0);
4394
4720
  }
4395
4721
  throw error;
@@ -4400,7 +4726,7 @@ program.command("run [directory]").description("Run a generated project").action
4400
4726
  await runProject(directory);
4401
4727
  } catch (error) {
4402
4728
  if (error.name === "ExitPromptError") {
4403
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4729
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4404
4730
  process.exit(0);
4405
4731
  }
4406
4732
  throw error;
@@ -4413,7 +4739,7 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4413
4739
  }
4414
4740
  const activeConfig = getActiveProvider();
4415
4741
  if (!activeConfig) {
4416
- 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"));
4417
4743
  return;
4418
4744
  }
4419
4745
  const spinner = ora5("Generating application...").start();
@@ -4425,30 +4751,30 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4425
4751
  const pm = new ProjectManager();
4426
4752
  pm.create(options.output.replace("./", ""), prompt);
4427
4753
  const { plan, files } = await generateApp(prompt, llm, (step, file) => {
4428
- spinner.text = file ? `${step} ${chalk13.gray(file)}` : step;
4754
+ spinner.text = file ? `${step} ${chalk14.gray(file)}` : step;
4429
4755
  });
4430
4756
  pm.updateFiles(files);
4431
4757
  pm.updateDependencies(plan.dependencies);
4432
4758
  await writeProject(pm.get(), options.output);
4433
- spinner.succeed(chalk13.green("App generated!"));
4434
- console.log(chalk13.gray(`
4435
- \u{1F4C1} Created ${files.length} files in ${chalk13.cyan(options.output)}`));
4436
- 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"));
4437
4763
  } catch (error) {
4438
4764
  spinner.fail("Generation failed");
4439
4765
  const msg = error instanceof Error ? error.message : String(error);
4440
4766
  if (msg.includes("429") || msg.includes("quota")) {
4441
- 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"));
4442
4768
  } else if (msg.includes("401") || msg.includes("403")) {
4443
- 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"));
4444
4770
  } else {
4445
- console.error(chalk13.red("\n" + msg + "\n"));
4771
+ console.error(chalk14.red("\n" + msg + "\n"));
4446
4772
  }
4447
4773
  process.exit(1);
4448
4774
  }
4449
4775
  } catch (error) {
4450
4776
  if (error.name === "ExitPromptError") {
4451
- console.log(chalk13.gray("\n\n\u{1F44B} Cancelled.\n"));
4777
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4452
4778
  process.exit(0);
4453
4779
  }
4454
4780
  throw error;
@@ -4457,11 +4783,11 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4457
4783
  program.command("config").description("Show configuration").action(async () => {
4458
4784
  const config = loadConfig();
4459
4785
  const active = getActiveProvider();
4460
- console.log(chalk13.cyan.bold("\n\u2699\uFE0F Configuration\n"));
4461
- console.log(chalk13.gray(" Provider: ") + chalk13.cyan(config.defaultProvider || "not set"));
4462
- console.log(chalk13.gray(" Model: ") + chalk13.cyan(config.defaultModel || "not set"));
4463
- console.log(chalk13.gray(" Config: ") + chalk13.gray("~/.agdi/config.json"));
4464
- 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"));
4465
4791
  const keys = [
4466
4792
  ["Gemini", config.geminiApiKey],
4467
4793
  ["OpenRouter", config.openrouterApiKey],
@@ -4470,7 +4796,7 @@ program.command("config").description("Show configuration").action(async () => {
4470
4796
  ["DeepSeek", config.deepseekApiKey]
4471
4797
  ];
4472
4798
  for (const [name, key] of keys) {
4473
- const status = key ? chalk13.green("\u2713") : chalk13.gray("\u2717");
4799
+ const status = key ? chalk14.green("\u2713") : chalk14.gray("\u2717");
4474
4800
  console.log(` ${status} ${name}`);
4475
4801
  }
4476
4802
  console.log("");