agdi 3.2.0 → 3.3.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.
package/README.md CHANGED
@@ -5,6 +5,7 @@
5
5
 
6
6
  # 🦸 AGDI
7
7
  ### The Autonomous AI Software Squad in Your Terminal
8
+ #### v3.3.0: New Mission Control TUI
8
9
 
9
10
  [![npm version](https://img.shields.io/npm/v/agdi.svg?style=for-the-badge&logo=npm&color=cyan)](https://www.npmjs.com/package/agdi)
10
11
  [![License](https://img.shields.io/npm/l/agdi.svg?style=for-the-badge&color=blue)](https://github.com/anassagd432/Agdi-dev)
@@ -0,0 +1,14 @@
1
+ // src/core/event-bus.ts
2
+ import { EventEmitter } from "events";
3
+ var agentEventBus = new EventEmitter();
4
+ function emitAgentEvent(event) {
5
+ agentEventBus.emit("agent_event", {
6
+ ...event,
7
+ timestamp: Date.now()
8
+ });
9
+ }
10
+
11
+ export {
12
+ agentEventBus,
13
+ emitAgentEvent
14
+ };
@@ -0,0 +1,8 @@
1
+ import {
2
+ agentEventBus,
3
+ emitAgentEvent
4
+ } from "./chunk-AEWEBMJY.js";
5
+ export {
6
+ agentEventBus,
7
+ emitAgentEvent
8
+ };
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ agentEventBus,
4
+ emitAgentEvent
5
+ } from "./chunk-AEWEBMJY.js";
2
6
  import {
3
7
  loadConfig,
4
8
  saveConfig
@@ -6,7 +10,7 @@ import {
6
10
 
7
11
  // src/index.ts
8
12
  import { Command } from "commander";
9
- import chalk15 from "chalk";
13
+ import chalk14 from "chalk";
10
14
  import ora6 from "ora";
11
15
 
12
16
  // src/core/llm/index.ts
@@ -449,8 +453,8 @@ async function smartConfirm(message, defaultValue = false) {
449
453
  console.warn(chalk.yellow("\u26A0\uFE0F Non-interactive session detected. Use --yes to approve actions."));
450
454
  return false;
451
455
  }
452
- const { confirm: confirm2 } = await import("@inquirer/prompts");
453
- return confirm2({ message, default: defaultValue });
456
+ const { confirm } = await import("@inquirer/prompts");
457
+ return confirm({ message, default: defaultValue });
454
458
  }
455
459
  async function smartSelect(message, choices, defaultValue) {
456
460
  if (!process.stdout.isTTY || flags.headless) {
@@ -460,8 +464,8 @@ async function smartSelect(message, choices, defaultValue) {
460
464
  }
461
465
  return result || null;
462
466
  }
463
- const { select: select4 } = await import("@inquirer/prompts");
464
- return select4({ message, choices });
467
+ const { select: select3 } = await import("@inquirer/prompts");
468
+ return select3({ message, choices });
465
469
  }
466
470
  var ui = {
467
471
  renderBanner,
@@ -1782,8 +1786,8 @@ async function runOnboarding() {
1782
1786
  console.log(chalk7.gray("We collect anonymous error logs (like a ") + chalk7.yellow("'Check Engine'") + chalk7.gray(" light)"));
1783
1787
  console.log(chalk7.gray("to fix bugs faster. We ") + chalk7.green.bold("never") + chalk7.gray(" see your code or keys.\n"));
1784
1788
  console.log(chalk7.dim("Verify anytime: agdi config telemetry --dry-run\n"));
1785
- const { confirm: confirm2 } = await import("@inquirer/prompts");
1786
- const enableTelemetry = await confirm2({
1789
+ const { confirm } = await import("@inquirer/prompts");
1790
+ const enableTelemetry = await confirm({
1787
1791
  message: "Enable crash reporting? (helps us fix bugs)",
1788
1792
  default: false
1789
1793
  });
@@ -2072,6 +2076,13 @@ var BaseAgent = class {
2072
2076
  * Log a message (if verbose)
2073
2077
  */
2074
2078
  log(message, type = "info") {
2079
+ emitAgentEvent({
2080
+ type: "log",
2081
+ agentName: this.name,
2082
+ role: this.role,
2083
+ message,
2084
+ metadata: { type }
2085
+ });
2075
2086
  if (!this.verbose) return;
2076
2087
  const prefix = `[${this.name}]`;
2077
2088
  switch (type) {
@@ -2093,7 +2104,20 @@ var BaseAgent = class {
2093
2104
  */
2094
2105
  async think(prompt) {
2095
2106
  this.log("Thinking...", "info");
2107
+ emitAgentEvent({
2108
+ type: "thought",
2109
+ agentName: this.name,
2110
+ role: this.role,
2111
+ message: `Analyzing task...`
2112
+ });
2096
2113
  const response = await this.llm.generate(prompt, this.getSystemPrompt());
2114
+ const summary = response.text.split("\n")[0].substring(0, 80) + "...";
2115
+ emitAgentEvent({
2116
+ type: "thought",
2117
+ agentName: this.name,
2118
+ role: this.role,
2119
+ message: `Generated response: ${summary}`
2120
+ });
2097
2121
  this.collectSourcesFromText(response.text);
2098
2122
  return response.text;
2099
2123
  }
@@ -3568,6 +3592,14 @@ ${qaResult.errors?.join("\n")}`,
3568
3592
  */
3569
3593
  async executeTask(task) {
3570
3594
  this.log(`[${task.assignee}] ${task.title}`, "task");
3595
+ const { emitAgentEvent: emitAgentEvent2 } = await import("./event-bus-EDC4P3T5.js");
3596
+ emitAgentEvent2({
3597
+ type: "handoff",
3598
+ agentName: task.assignee,
3599
+ // e.g. "frontend"
3600
+ role: task.assignee,
3601
+ message: `Taking control for task: ${task.title}`
3602
+ });
3571
3603
  await this.appendTrace("task_start", {
3572
3604
  id: task.id,
3573
3605
  title: task.title,
@@ -4075,225 +4107,19 @@ ${msg}
4075
4107
  }
4076
4108
  }
4077
4109
 
4078
- // src/commands/wizard.ts
4079
- import { input as input5, select as select3, confirm, password as password3 } from "@inquirer/prompts";
4080
- import chalk13 from "chalk";
4081
- import path6 from "path";
4082
- import os from "os";
4083
- import fs6 from "fs";
4084
- async function runWizard() {
4085
- await checkSafety();
4086
- if (needsOnboarding()) {
4087
- await runOnboarding();
4088
- }
4089
- await setupOptionalTools();
4090
- const wantsSaas = await confirm({
4091
- message: "Enable SaaS Blueprint mode? (Next.js + Prisma + Postgres + Stripe)",
4092
- default: true
4093
- });
4094
- if (wantsSaas) {
4095
- ui.setFlags({ saas: true });
4096
- }
4097
- console.log(chalk13.cyan.bold("\n\u{1F3AF} Mission Control"));
4098
- console.log(chalk13.gray("Describe your app in detail. The Agdi Squad will handle the rest."));
4099
- let prompt = await input5({
4100
- message: "What are we building today?",
4101
- validate: (value) => value.length > 5 ? true : "Please provide more detail (min 5 chars)"
4102
- });
4103
- if (wantsSaas) {
4104
- prompt = `${prompt}
4105
-
4106
- Constraints: Build a production SaaS using Next.js App Router, Prisma, Postgres, and Stripe. Include auth, billing, multi-tenant orgs, and a dashboard.`;
4107
- }
4108
- const activeConfig = getActiveProvider();
4109
- if (!activeConfig) {
4110
- console.log(chalk13.red("\u274C No API key configured. Run: agdi auth"));
4111
- return;
4112
- }
4113
- const llm = createLLMProvider(activeConfig.provider, {
4114
- apiKey: activeConfig.apiKey,
4115
- model: activeConfig.model
4116
- });
4117
- console.log(chalk13.cyan("\n\u{1F914} Analyzing requirements..."));
4118
- try {
4119
- const analysis = await llm.generate(prompt, `
4120
- You are a Senior Product Manager. Analyze this app idea.
4121
- If it is vague (e.g., "make a CRM"), generate 3 specific questions to clarify scope, tech stack, and features.
4122
- If it is detailed enough, return "DETAILED".
4123
-
4124
- Format:
4125
- Questions:
4126
- 1. [Question 1]
4127
- 2. [Question 2]
4128
- 3. [Question 3]
4129
- `);
4130
- if (!analysis.text.includes("DETAILED")) {
4131
- console.log(chalk13.yellow("\n\u{1F4A1} I need a few more details to build exactly what you want:"));
4132
- const questions = analysis.text.split("\n").filter((line) => line.match(/^\d+\./));
4133
- const answers = [];
4134
- for (const q of questions.slice(0, 3)) {
4135
- const answer = await input5({ message: q.replace(/^\d+\.\s*/, "") });
4136
- answers.push({ q, a: answer });
4137
- }
4138
- console.log(chalk13.cyan("\n\u{1F504} Synthesizing Master Plan..."));
4139
- const synthesis = await llm.generate(
4140
- `Original Request: ${prompt}
4141
-
4142
- Clarifications:
4143
- ${answers.map((x) => `Q: ${x.q}
4144
- A: ${x.a}`).join("\n")}
4145
-
4146
- Rewrite the original request into a comprehensive technical specification for a developer squad.`,
4147
- "You are a Technical Architect."
4148
- );
4149
- prompt = synthesis.text;
4150
- console.log(chalk13.gray("\nUpdated Spec: " + prompt.substring(0, 100) + "...\n"));
4151
- }
4152
- } catch (err) {
4153
- console.log(chalk13.gray("Skipping analysis (API unreachable), proceeding with raw prompt."));
4154
- }
4155
- console.log(chalk13.cyan("\n\u{1F680} Assembling the Squad..."));
4156
- console.log(chalk13.gray("Frontend, Backend, QA, and DevOps agents are coming online.\n"));
4157
- const config = loadConfig();
4158
- const canDeploy = !!(config.vercelToken || config.netlifyToken || config.railwayToken);
4159
- await runSquadCommand(prompt, llm, {
4160
- deploy: canDeploy,
4161
- // Auto-deploy if configured
4162
- output: "./",
4163
- // Current directory (safe because we checked safety earlier)
4164
- verbose: true
4165
- });
4166
- if (ui.flags.saas) {
4167
- console.log(chalk13.cyan("\nSaaS Quick Start:"));
4168
- console.log(chalk13.gray(" 1) npm install"));
4169
- console.log(chalk13.gray(" 2) cp .env.example .env"));
4170
- console.log(chalk13.gray(" 3) npx prisma generate"));
4171
- console.log(chalk13.gray(" 4) npx prisma db push"));
4172
- console.log(chalk13.gray(" 5) npm run dev\n"));
4173
- }
4174
- }
4175
- async function checkSafety() {
4176
- const cwd = process.cwd();
4177
- const home = os.homedir();
4178
- const root = path6.parse(cwd).root;
4179
- const isUnsafe = cwd === home || cwd === root;
4180
- if (isUnsafe) {
4181
- console.log(chalk13.yellow.bold("\n\u26A0\uFE0F Safety Warning"));
4182
- console.log(chalk13.gray(`You are running Agdi in ${chalk13.cyan(cwd)}.`));
4183
- console.log(chalk13.gray("Agdi writes files and runs commands. It needs its own space.\n"));
4184
- const action = await select3({
4185
- message: "What would you like to do?",
4186
- choices: [
4187
- { name: "\u{1F4C2} Create a new project folder (Recommended)", value: "create" },
4188
- { name: "\u{1F525} Run here anyway (Dangerous)", value: "unsafe" },
4189
- { name: "\u274C Cancel", value: "cancel" }
4190
- ]
4191
- });
4192
- if (action === "cancel") {
4193
- ui.safeExit(0);
4194
- }
4195
- if (action === "create") {
4196
- const folderName = await input5({
4197
- message: "Project name:",
4198
- default: "my-agdi-app",
4199
- validate: (v) => /^[a-z0-9-_]+$/i.test(v) ? true : "Invalid folder name"
4200
- });
4201
- const newPath = path6.join(cwd, folderName);
4202
- if (!fs6.existsSync(newPath)) {
4203
- fs6.mkdirSync(newPath);
4204
- }
4205
- process.chdir(newPath);
4206
- console.log(chalk13.green(`
4207
- \u{1F4C2} Switched to: ${chalk13.cyan(newPath)}
4208
- `));
4209
- }
4210
- }
4211
- }
4212
- async function setupOptionalTools() {
4213
- const config = loadConfig();
4214
- let configChanged = false;
4215
- if (!config.searchApiKey) {
4216
- console.log(chalk13.white.bold("\n\u{1F310} Web Access (Optional)\n"));
4217
- console.log(chalk13.gray("Giving Agdi web access allows it to find up-to-date docs and fix tricky bugs."));
4218
- const wantsSearch = await confirm({
4219
- message: "Enable web search capabilities?",
4220
- default: true
4221
- });
4222
- if (wantsSearch) {
4223
- const provider = await select3({
4224
- message: "Select Search Provider:",
4225
- choices: [
4226
- { name: "Brave Search (Recommended)", value: "brave" },
4227
- { name: "Tavily", value: "tavily" }
4228
- ]
4229
- });
4230
- const keyUrl = provider === "brave" ? "https://brave.com/search/api/" : "https://tavily.com/";
4231
- console.log(chalk13.gray(`Get your key at: ${chalk13.cyan(keyUrl)}
4232
- `));
4233
- const apiKey = await password3({
4234
- message: `Enter your ${provider} API key:`,
4235
- mask: "*"
4236
- });
4237
- if (apiKey) {
4238
- config.searchApiKey = apiKey;
4239
- config.searchProvider = provider;
4240
- config.searchEnabled = true;
4241
- configChanged = true;
4242
- console.log(chalk13.green("\u2705 Web search enabled!"));
4243
- }
4244
- }
4245
- }
4246
- if (!config.vercelToken && !config.netlifyToken && !config.railwayToken) {
4247
- console.log(chalk13.white.bold("\n\u{1F680} Deployment (Optional)\n"));
4248
- console.log(chalk13.gray("Agdi can automatically deploy your app to the cloud when finished."));
4249
- const wantsDeploy = await confirm({
4250
- message: "Enable auto-deployment?",
4251
- default: true
4252
- });
4253
- if (wantsDeploy) {
4254
- const provider = await select3({
4255
- message: "Select Deployment Target:",
4256
- choices: [
4257
- { name: "Vercel", value: "vercel" },
4258
- { name: "Railway", value: "railway" },
4259
- { name: "Netlify", value: "netlify" }
4260
- ]
4261
- });
4262
- const keyUrl = provider === "vercel" ? "https://vercel.com/account/tokens" : provider === "railway" ? "https://railway.app/account/tokens" : "https://app.netlify.com/user/applications#personal-access-tokens";
4263
- console.log(chalk13.gray(`Get your key at: ${chalk13.cyan(keyUrl)}
4264
- `));
4265
- const apiKey = await password3({
4266
- message: `Enter your ${provider} API token:`,
4267
- mask: "*"
4268
- });
4269
- if (apiKey) {
4270
- if (provider === "vercel") config.vercelToken = apiKey;
4271
- if (provider === "netlify") config.netlifyToken = apiKey;
4272
- if (provider === "railway") config.railwayToken = apiKey;
4273
- config.deploymentProvider = provider;
4274
- configChanged = true;
4275
- console.log(chalk13.green("\u2705 Auto-deployment enabled!"));
4276
- }
4277
- }
4278
- }
4279
- if (configChanged) {
4280
- saveConfig(config);
4281
- }
4282
- }
4283
-
4284
4110
  // src/commands/replay.ts
4285
- import chalk14 from "chalk";
4286
- import * as fs7 from "fs/promises";
4287
- import * as path7 from "path";
4111
+ import chalk13 from "chalk";
4112
+ import * as fs6 from "fs/promises";
4113
+ import * as path6 from "path";
4288
4114
  async function runReplayCommand(runId, llm, options = {}) {
4289
4115
  const workspaceRoot = options.workspace || process.cwd();
4290
- const runConfigPath = path7.join(workspaceRoot, "runs", runId, "run.json");
4291
- const outputsDir = path7.join(workspaceRoot, "runs", runId, "outputs");
4116
+ const runConfigPath = path6.join(workspaceRoot, "runs", runId, "run.json");
4117
+ const outputsDir = path6.join(workspaceRoot, "runs", runId, "outputs");
4292
4118
  try {
4293
- const raw = await fs7.readFile(runConfigPath, "utf-8");
4119
+ const raw = await fs6.readFile(runConfigPath, "utf-8");
4294
4120
  const runConfig = JSON.parse(raw);
4295
4121
  if (!runConfig.prompt) {
4296
- console.log(chalk14.red("\u274C Invalid run.json (missing prompt)"));
4122
+ console.log(chalk13.red("\u274C Invalid run.json (missing prompt)"));
4297
4123
  return null;
4298
4124
  }
4299
4125
  const config = {
@@ -4302,31 +4128,31 @@ async function runReplayCommand(runId, llm, options = {}) {
4302
4128
  verbose: options.verbose ?? runConfig.config?.verbose ?? true,
4303
4129
  autoDeploy: options.deploy ?? runConfig.config?.autoDeploy ?? false
4304
4130
  };
4305
- console.log(chalk14.cyan(`
4131
+ console.log(chalk13.cyan(`
4306
4132
  \u{1F501} Replaying run ${runId}`));
4307
4133
  if (options.exact !== false) {
4308
4134
  try {
4309
- const entries = await fs7.readdir(outputsDir, { withFileTypes: true });
4135
+ const entries = await fs6.readdir(outputsDir, { withFileTypes: true });
4310
4136
  if (entries.length === 0) {
4311
4137
  throw new Error("No outputs found");
4312
4138
  }
4313
4139
  const copyOutputs = async (dir, rel = "") => {
4314
- const files = await fs7.readdir(dir, { withFileTypes: true });
4140
+ const files = await fs6.readdir(dir, { withFileTypes: true });
4315
4141
  for (const file of files) {
4316
- const sourcePath = path7.join(dir, file.name);
4317
- const targetRel = path7.join(rel, file.name);
4318
- const targetPath = path7.join(workspaceRoot, targetRel);
4142
+ const sourcePath = path6.join(dir, file.name);
4143
+ const targetRel = path6.join(rel, file.name);
4144
+ const targetPath = path6.join(workspaceRoot, targetRel);
4319
4145
  if (file.isDirectory()) {
4320
4146
  await copyOutputs(sourcePath, targetRel);
4321
4147
  } else if (file.isFile()) {
4322
- await fs7.mkdir(path7.dirname(targetPath), { recursive: true });
4323
- const content = await fs7.readFile(sourcePath, "utf-8");
4324
- await fs7.writeFile(targetPath, content, "utf-8");
4148
+ await fs6.mkdir(path6.dirname(targetPath), { recursive: true });
4149
+ const content = await fs6.readFile(sourcePath, "utf-8");
4150
+ await fs6.writeFile(targetPath, content, "utf-8");
4325
4151
  }
4326
4152
  }
4327
4153
  };
4328
4154
  await copyOutputs(outputsDir);
4329
- console.log(chalk14.green("\u2705 Exact replay applied from stored outputs."));
4155
+ console.log(chalk13.green("\u2705 Exact replay applied from stored outputs."));
4330
4156
  return {
4331
4157
  success: true,
4332
4158
  projectSpec: { name: "replay", description: "Exact replay", type: "web-app", stack: {}, features: [] },
@@ -4337,34 +4163,309 @@ async function runReplayCommand(runId, llm, options = {}) {
4337
4163
  errors: []
4338
4164
  };
4339
4165
  } catch (error) {
4340
- console.log(chalk14.yellow("\u26A0\uFE0F Exact replay failed, falling back to rerun."));
4341
- console.log(chalk14.gray(String(error)));
4166
+ console.log(chalk13.yellow("\u26A0\uFE0F Exact replay failed, falling back to rerun."));
4167
+ console.log(chalk13.gray(String(error)));
4342
4168
  }
4343
4169
  }
4344
4170
  if (!llm) {
4345
- console.log(chalk14.red("\u274C No LLM provider available for replay."));
4171
+ console.log(chalk13.red("\u274C No LLM provider available for replay."));
4346
4172
  return null;
4347
4173
  }
4348
4174
  const orchestrator = new SquadOrchestrator(llm, config);
4349
4175
  return await orchestrator.run(runConfig.prompt);
4350
4176
  } catch (error) {
4351
- console.log(chalk14.red("\u274C Failed to load run config for replay"));
4352
- console.log(chalk14.gray(String(error)));
4177
+ console.log(chalk13.red("\u274C Failed to load run config for replay"));
4178
+ console.log(chalk13.gray(String(error)));
4353
4179
  return null;
4354
4180
  }
4355
4181
  }
4356
4182
 
4183
+ // src/commands/tui-entry.tsx
4184
+ import { render } from "ink";
4185
+
4186
+ // src/ui/tui.tsx
4187
+ import { useState, useEffect } from "react";
4188
+ import { Box, Text, useApp } from "ink";
4189
+ import BigText from "ink-big-text";
4190
+ import Spinner from "ink-spinner";
4191
+ import TextInput from "ink-text-input";
4192
+ import fs7 from "fs";
4193
+ import path7 from "path";
4194
+ import os from "os";
4195
+ import { jsx, jsxs } from "react/jsx-runtime";
4196
+ var BootScreen = ({ onComplete }) => {
4197
+ const [progress, setProgress] = useState(0);
4198
+ const [log, setLog] = useState("");
4199
+ const logs = [
4200
+ "Initializing core systems...",
4201
+ "Loading neural modules...",
4202
+ "Connecting to Agdi Cloud...",
4203
+ "Verifying agent credentials...",
4204
+ "Mounting virtual filesystem...",
4205
+ "Establishing secure uplink...",
4206
+ "Syncing global state...",
4207
+ "Boot sequence complete."
4208
+ ];
4209
+ useEffect(() => {
4210
+ const timer = setInterval(() => {
4211
+ setProgress((prev) => {
4212
+ const next = prev + 5;
4213
+ if (next >= 100) {
4214
+ clearInterval(timer);
4215
+ setTimeout(onComplete, 200);
4216
+ return 100;
4217
+ }
4218
+ return next;
4219
+ });
4220
+ const index = Math.floor(progress / 100 * logs.length);
4221
+ setLog(logs[index] || logs[logs.length - 1]);
4222
+ }, 30);
4223
+ return () => clearInterval(timer);
4224
+ }, [progress]);
4225
+ const width = 60;
4226
+ const filled = Math.floor(width * progress / 100);
4227
+ const bar = "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
4228
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", height: 20, children: [
4229
+ /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(BigText, { text: "AGDI OS", font: "block", align: "center", colors: ["cyan", "blue"] }) }),
4230
+ /* @__PURE__ */ jsx(Box, { marginY: 1, children: /* @__PURE__ */ jsxs(Text, { color: "cyan", children: [
4231
+ bar,
4232
+ " ",
4233
+ progress,
4234
+ "%"
4235
+ ] }) }),
4236
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
4237
+ "\u279C ",
4238
+ log
4239
+ ] })
4240
+ ] });
4241
+ };
4242
+ var FileExplorer = ({ cwd, lastChange }) => {
4243
+ const [files, setFiles] = useState([]);
4244
+ useEffect(() => {
4245
+ const refresh = () => {
4246
+ try {
4247
+ const list = fs7.readdirSync(cwd).filter((f) => !f.startsWith(".")).slice(0, 15);
4248
+ setFiles(list);
4249
+ } catch {
4250
+ setFiles(["<Error reading dir>"]);
4251
+ }
4252
+ };
4253
+ refresh();
4254
+ const timer = setInterval(refresh, 2e3);
4255
+ return () => clearInterval(timer);
4256
+ }, [cwd, lastChange]);
4257
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", title: " FILESYSTEM ", width: "30%", children: [
4258
+ /* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
4259
+ " ",
4260
+ cwd.length > 30 ? "..." + cwd.slice(-30) : cwd
4261
+ ] }),
4262
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
4263
+ files.map((f, i) => /* @__PURE__ */ jsxs(Text, { color: "white", children: [
4264
+ fs7.statSync(path7.join(cwd, f)).isDirectory() ? "\u{1F4C1} " : "\u{1F4C4} ",
4265
+ f
4266
+ ] }, i)),
4267
+ files.length === 0 && /* @__PURE__ */ jsx(Text, { color: "gray", children: " (empty)" })
4268
+ ] })
4269
+ ] });
4270
+ };
4271
+ var LogPanel = ({ logs }) => {
4272
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", title: " AGENT LOGS ", width: "70%", marginLeft: 1, children: [
4273
+ logs.slice(-12).map((log, i) => /* @__PURE__ */ jsxs(Text, { color: "green", children: [
4274
+ /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
4275
+ "[",
4276
+ (/* @__PURE__ */ new Date()).toLocaleTimeString(),
4277
+ "]"
4278
+ ] }),
4279
+ " ",
4280
+ log
4281
+ ] }, i)),
4282
+ logs.length === 0 && /* @__PURE__ */ jsx(Text, { color: "gray", children: "Waiting for agent activity..." })
4283
+ ] });
4284
+ };
4285
+ var ChatPanel = ({ history, onSend, placeholder = "" }) => {
4286
+ const [query, setQuery] = useState("");
4287
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", title: " MISSION CONTROL ", height: 12, children: [
4288
+ /* @__PURE__ */ jsx(Box, { flexDirection: "column", flexGrow: 1, justifyContent: "flex-end", children: history.slice(-5).map((msg, i) => /* @__PURE__ */ jsxs(Box, { marginY: 0, children: [
4289
+ /* @__PURE__ */ jsx(Text, { color: msg.role === "user" ? "cyan" : msg.role === "system" ? "yellow" : "magenta", bold: true, children: msg.role === "user" ? "YOU \u203A " : msg.role === "system" ? "SYS \u203A " : "AGDI \u203A " }),
4290
+ /* @__PURE__ */ jsx(Text, { children: msg.text })
4291
+ ] }, i)) }),
4292
+ /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "gray", marginTop: 1, children: [
4293
+ /* @__PURE__ */ jsx(Text, { color: "cyan", children: "\u279C " }),
4294
+ /* @__PURE__ */ jsx(
4295
+ TextInput,
4296
+ {
4297
+ value: query,
4298
+ onChange: setQuery,
4299
+ onSubmit: (val) => {
4300
+ onSend(val);
4301
+ setQuery("");
4302
+ },
4303
+ placeholder
4304
+ }
4305
+ )
4306
+ ] })
4307
+ ] });
4308
+ };
4309
+ var Dashboard = () => {
4310
+ const { exit } = useApp();
4311
+ const [cwd, setCwd] = useState(process.cwd());
4312
+ const [logs, setLogs] = useState(["System ready.", "Initializing Neural Link..."]);
4313
+ const [chatHistory, setChatHistory] = useState([]);
4314
+ const [step, setStep] = useState("safety");
4315
+ const [pendingAction, setPendingAction] = useState(null);
4316
+ const [lastFileChange, setLastFileChange] = useState(0);
4317
+ const [activeAgent, setActiveAgent] = useState("IDLE");
4318
+ useEffect(() => {
4319
+ const handleEvent = (event) => {
4320
+ if (event.type === "handoff") {
4321
+ setActiveAgent(event.role.toUpperCase());
4322
+ }
4323
+ if (event.type === "log" || event.type === "thought") {
4324
+ setLogs((prev) => [...prev, `[${event.agentName}] ${event.message}`]);
4325
+ }
4326
+ if (event.message.includes("Created:") || event.message.includes("Modified:")) {
4327
+ setLastFileChange(Date.now());
4328
+ }
4329
+ };
4330
+ agentEventBus.on("agent_event", handleEvent);
4331
+ return () => {
4332
+ agentEventBus.off("agent_event", handleEvent);
4333
+ };
4334
+ }, []);
4335
+ useEffect(() => {
4336
+ if (step === "safety") {
4337
+ const home = os.homedir();
4338
+ const root = path7.parse(cwd).root;
4339
+ const isUnsafe = cwd === home || cwd === root;
4340
+ if (isUnsafe) {
4341
+ setChatHistory([
4342
+ { role: "system", text: `\u26A0\uFE0F SAFETY WARNING: You are running in ${cwd}` },
4343
+ { role: "ai", text: "It is unsafe to run here. Should I create a new project folder for you? (yes/no)" }
4344
+ ]);
4345
+ setPendingAction("safety_confirm");
4346
+ } else {
4347
+ setStep("prompt");
4348
+ setChatHistory([{ role: "ai", text: "Safety check passed. What are we building today?" }]);
4349
+ }
4350
+ }
4351
+ }, []);
4352
+ const handleCommand = async (cmd) => {
4353
+ if (cmd === "/exit") exit();
4354
+ setChatHistory((prev) => [...prev, { role: "user", text: cmd }]);
4355
+ if (step === "safety" && pendingAction === "safety_confirm") {
4356
+ if (cmd.toLowerCase().startsWith("y")) {
4357
+ setChatHistory((prev) => [...prev, { role: "ai", text: "Great. Enter a name for your project folder:" }]);
4358
+ setPendingAction("create_folder");
4359
+ } else {
4360
+ setChatHistory((prev) => [...prev, { role: "ai", text: "Okay, proceeding in current directory (AT YOUR OWN RISK)." }]);
4361
+ setStep("prompt");
4362
+ setPendingAction(null);
4363
+ setTimeout(() => setChatHistory((prev) => [...prev, { role: "ai", text: "What are we building today?" }]), 500);
4364
+ }
4365
+ return;
4366
+ }
4367
+ if (step === "safety" && pendingAction === "create_folder") {
4368
+ const newPath = path7.join(cwd, cmd.replace(/[^a-z0-9-_]/gi, "-"));
4369
+ try {
4370
+ if (!fs7.existsSync(newPath)) fs7.mkdirSync(newPath);
4371
+ process.chdir(newPath);
4372
+ setCwd(newPath);
4373
+ setLogs((prev) => [...prev, `Switched directory to ${newPath}`]);
4374
+ setChatHistory((prev) => [...prev, { role: "system", text: `\u{1F4C2} Switched to ${newPath}` }]);
4375
+ setStep("prompt");
4376
+ setPendingAction(null);
4377
+ setTimeout(() => setChatHistory((prev) => [...prev, { role: "ai", text: "What are we building today?" }]), 500);
4378
+ } catch (e) {
4379
+ setChatHistory((prev) => [...prev, { role: "system", text: `Error creating folder: ${e}` }]);
4380
+ }
4381
+ return;
4382
+ }
4383
+ if (step === "prompt") {
4384
+ setChatHistory((prev) => [...prev, { role: "ai", text: "Analyzing requirements..." }]);
4385
+ setStep("active");
4386
+ setActiveAgent("MANAGER");
4387
+ const activeConfig = getActiveProvider();
4388
+ if (!activeConfig) {
4389
+ setChatHistory((prev) => [...prev, { role: "system", text: '\u274C No API key found. Run "agdi auth" first.' }]);
4390
+ return;
4391
+ }
4392
+ const llm = createLLMProvider(activeConfig.provider, {
4393
+ apiKey: activeConfig.apiKey,
4394
+ model: activeConfig.model
4395
+ });
4396
+ runSquadCommand(cmd, llm, {
4397
+ output: cwd,
4398
+ verbose: false,
4399
+ // We handle logs via event bus now
4400
+ deploy: false
4401
+ }).then(() => {
4402
+ setActiveAgent("IDLE");
4403
+ setChatHistory((prev) => [...prev, { role: "ai", text: "\u{1F680} Mission Complete! Check the files." }]);
4404
+ }).catch((err) => {
4405
+ setActiveAgent("ERROR");
4406
+ setChatHistory((prev) => [...prev, { role: "system", text: `\u274C Error: ${err.message}` }]);
4407
+ });
4408
+ }
4409
+ };
4410
+ const getStatusColor = () => {
4411
+ switch (activeAgent) {
4412
+ case "MANAGER":
4413
+ return "magenta";
4414
+ case "FRONTEND":
4415
+ return "cyan";
4416
+ case "BACKEND":
4417
+ return "blue";
4418
+ case "QA":
4419
+ return "yellow";
4420
+ case "DEVOPS":
4421
+ return "green";
4422
+ case "ERROR":
4423
+ return "red";
4424
+ default:
4425
+ return "gray";
4426
+ }
4427
+ };
4428
+ return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, height: "100%", children: [
4429
+ /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginBottom: 1, children: [
4430
+ /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "AGDI v3.3.2 [ONLINE]" }),
4431
+ /* @__PURE__ */ jsxs(Text, { color: getStatusColor(), children: [
4432
+ "AGENT: ",
4433
+ activeAgent,
4434
+ " ",
4435
+ activeAgent !== "IDLE" && /* @__PURE__ */ jsx(Spinner, { type: "dots" })
4436
+ ] }),
4437
+ /* @__PURE__ */ jsx(Text, { color: "gray", children: "NET: CONNECTED" })
4438
+ ] }),
4439
+ /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexGrow: 1, children: [
4440
+ /* @__PURE__ */ jsx(FileExplorer, { cwd, lastChange: lastFileChange }),
4441
+ /* @__PURE__ */ jsx(LogPanel, { logs })
4442
+ ] }),
4443
+ /* @__PURE__ */ jsx(Box, { marginTop: 0, children: /* @__PURE__ */ jsx(ChatPanel, { history: chatHistory, onSend: handleCommand, placeholder: step === "prompt" ? "Describe your app..." : "" }) })
4444
+ ] });
4445
+ };
4446
+ var App = () => {
4447
+ const [screen, setScreen] = useState("boot");
4448
+ return screen === "boot" ? /* @__PURE__ */ jsx(BootScreen, { onComplete: () => setScreen("dashboard") }) : /* @__PURE__ */ jsx(Dashboard, {});
4449
+ };
4450
+
4451
+ // src/commands/tui-entry.tsx
4452
+ import { jsx as jsx2 } from "react/jsx-runtime";
4453
+ function runTUI() {
4454
+ console.clear();
4455
+ render(/* @__PURE__ */ jsx2(App, {}));
4456
+ }
4457
+
4357
4458
  // src/index.ts
4358
4459
  var BANNER = `
4359
- ${chalk15.cyan(` ___ __ _ `)}
4360
- ${chalk15.cyan(` / | ____ _____/ /(_) `)}
4361
- ${chalk15.cyan(` / /| | / __ \`/ __ // / `)}
4362
- ${chalk15.cyan(` / ___ |/ /_/ / /_/ // / `)}
4363
- ${chalk15.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4364
- ${chalk15.cyan(` /____/ `)}
4460
+ ${chalk14.cyan(` ___ __ _ `)}
4461
+ ${chalk14.cyan(` / | ____ _____/ /(_) `)}
4462
+ ${chalk14.cyan(` / /| | / __ \`/ __ // / `)}
4463
+ ${chalk14.cyan(` / ___ |/ /_/ / /_/ // / `)}
4464
+ ${chalk14.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4465
+ ${chalk14.cyan(` /____/ `)}
4365
4466
  `;
4366
4467
  var program = new Command();
4367
- program.name("agdi").description(chalk15.cyan("\u{1F9B8} The Autonomous AI Employee")).version("3.2.0").option("-y, --yes", "Auto-approve all prompts (headless/CI mode)").option("-m, --minimal", "Generate only the requested file(s), not a full app").option("-d, --dry-run", "Show what would be created without writing files").option("--saas", "Generate a production SaaS blueprint (Next.js + Prisma + Postgres + Stripe)");
4468
+ program.name("agdi").description(chalk14.cyan("\u{1F9B8} The Autonomous AI Employee")).version("3.3.2").option("-y, --yes", "Auto-approve all prompts (headless/CI mode)").option("-m, --minimal", "Generate only the requested file(s), not a full app").option("-d, --dry-run", "Show what would be created without writing files").option("--saas", "Generate a production SaaS blueprint (Next.js + Prisma + Postgres + Stripe)");
4368
4469
  program.hook("preAction", (thisCommand) => {
4369
4470
  const opts = thisCommand.opts();
4370
4471
  if (opts.yes) {
@@ -4381,15 +4482,14 @@ program.hook("preAction", (thisCommand) => {
4381
4482
  }
4382
4483
  });
4383
4484
  program.addHelpText("beforeAll", () => {
4384
- return BANNER + "\n" + chalk15.gray(" The Autonomous AI Employee") + "\n" + chalk15.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");
4485
+ return BANNER + "\n" + chalk14.gray(" The Autonomous AI Employee") + "\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");
4385
4486
  });
4386
4487
  program.action(async () => {
4387
4488
  try {
4388
- await ui.renderBanner();
4389
- await runWizard();
4489
+ runTUI();
4390
4490
  } catch (error) {
4391
4491
  if (error.name === "ExitPromptError") {
4392
- console.log(chalk15.gray("\n\n\u{1F44B} Goodbye!\n"));
4492
+ console.log(chalk14.gray("\n\n\u{1F44B} Goodbye!\n"));
4393
4493
  try {
4394
4494
  ui.safeExit(0);
4395
4495
  } catch {
@@ -4411,7 +4511,7 @@ program.command("auth").description("Configure API keys").option("--status", "Sh
4411
4511
  }
4412
4512
  } catch (error) {
4413
4513
  if (error.name === "ExitPromptError") {
4414
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4514
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4415
4515
  try {
4416
4516
  ui.safeExit(0);
4417
4517
  } catch {
@@ -4429,7 +4529,7 @@ program.command("model").alias("models").description("Change AI model").action(a
4429
4529
  await selectModel();
4430
4530
  } catch (error) {
4431
4531
  if (error.name === "ExitPromptError") {
4432
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4532
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4433
4533
  try {
4434
4534
  ui.safeExit(0);
4435
4535
  } catch {
@@ -4450,7 +4550,7 @@ program.command("chat").description("Start a chat session").action(async () => {
4450
4550
  await startChat();
4451
4551
  } catch (error) {
4452
4552
  if (error.name === "ExitPromptError") {
4453
- console.log(chalk15.gray("\n\n\u{1F44B} Goodbye!\n"));
4553
+ console.log(chalk14.gray("\n\n\u{1F44B} Goodbye!\n"));
4454
4554
  try {
4455
4555
  ui.safeExit(0);
4456
4556
  } catch {
@@ -4468,7 +4568,7 @@ program.command("run [directory]").description("Run a generated project").action
4468
4568
  await runProject(directory);
4469
4569
  } catch (error) {
4470
4570
  if (error.name === "ExitPromptError") {
4471
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4571
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4472
4572
  try {
4473
4573
  ui.safeExit(0);
4474
4574
  } catch {
@@ -4491,7 +4591,7 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4491
4591
  }
4492
4592
  const activeConfig = getActiveProvider();
4493
4593
  if (!activeConfig) {
4494
- console.log(chalk15.red("\u274C No API key configured. Run: agdi auth"));
4594
+ console.log(chalk14.red("\u274C No API key configured. Run: agdi auth"));
4495
4595
  return;
4496
4596
  }
4497
4597
  const spinner = ora6("Generating application...").start();
@@ -4503,52 +4603,52 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4503
4603
  const pm = new ProjectManager();
4504
4604
  pm.create(options.output.replace("./", ""), prompt);
4505
4605
  const { plan, files } = await generateApp(prompt, llm, (step, file) => {
4506
- spinner.text = file ? `${step} ${chalk15.gray(file)}` : step;
4606
+ spinner.text = file ? `${step} ${chalk14.gray(file)}` : step;
4507
4607
  });
4508
4608
  pm.updateFiles(files);
4509
4609
  pm.updateDependencies(plan.dependencies);
4510
4610
  if (options.dryRun || ui.flags.dryRun) {
4511
4611
  spinner.stop();
4512
- console.log(chalk15.cyan.bold("\n\u{1F6A7} DRY RUN SUMMARY\n"));
4513
- console.log(chalk15.gray(`Project: ${plan.name}
4612
+ console.log(chalk14.cyan.bold("\n\u{1F6A7} DRY RUN SUMMARY\n"));
4613
+ console.log(chalk14.gray(`Project: ${plan.name}
4514
4614
  `));
4515
- console.log(chalk15.cyan("Files to be created:"));
4516
- files.forEach((f) => console.log(chalk15.gray(` \u{1F4C4} ${f.path}`)));
4517
- console.log(chalk15.cyan("\nDependencies:"));
4518
- console.log(chalk15.gray(` \u{1F4E6} ${plan.dependencies.join(", ")}`));
4519
- console.log(chalk15.green("\n\u2713 Dry run complete. No files written.\n"));
4615
+ console.log(chalk14.cyan("Files to be created:"));
4616
+ files.forEach((f) => console.log(chalk14.gray(` \u{1F4C4} ${f.path}`)));
4617
+ console.log(chalk14.cyan("\nDependencies:"));
4618
+ console.log(chalk14.gray(` \u{1F4E6} ${plan.dependencies.join(", ")}`));
4619
+ console.log(chalk14.green("\n\u2713 Dry run complete. No files written.\n"));
4520
4620
  return;
4521
4621
  }
4522
4622
  await writeProject(pm.get(), options.output);
4523
- spinner.succeed(chalk15.green("App generated!"));
4524
- console.log(chalk15.gray(`
4525
- \u{1F4C1} Created ${files.length} files in ${chalk15.cyan(options.output)}`));
4623
+ spinner.succeed(chalk14.green("App generated!"));
4624
+ console.log(chalk14.gray(`
4625
+ \u{1F4C1} Created ${files.length} files in ${chalk14.cyan(options.output)}`));
4526
4626
  if (ui.flags.saas || options.saas) {
4527
- console.log(chalk15.cyan("\nSaaS Quick Start:"));
4528
- console.log(chalk15.gray(` 1) cd ${options.output}`));
4529
- console.log(chalk15.gray(" 2) npm install"));
4530
- console.log(chalk15.gray(" 3) cp .env.example .env"));
4531
- console.log(chalk15.gray(" 4) npx prisma generate"));
4532
- console.log(chalk15.gray(" 5) npx prisma db push"));
4533
- console.log(chalk15.gray(" 6) npm run dev\n"));
4627
+ console.log(chalk14.cyan("\nSaaS Quick Start:"));
4628
+ console.log(chalk14.gray(` 1) cd ${options.output}`));
4629
+ console.log(chalk14.gray(" 2) npm install"));
4630
+ console.log(chalk14.gray(" 3) cp .env.example .env"));
4631
+ console.log(chalk14.gray(" 4) npx prisma generate"));
4632
+ console.log(chalk14.gray(" 5) npx prisma db push"));
4633
+ console.log(chalk14.gray(" 6) npm run dev\n"));
4534
4634
  } else {
4535
- console.log(chalk15.gray("\nNext: cd " + options.output + " && npm install && npm run dev\n"));
4635
+ console.log(chalk14.gray("\nNext: cd " + options.output + " && npm install && npm run dev\n"));
4536
4636
  }
4537
4637
  } catch (error) {
4538
4638
  spinner.fail("Generation failed");
4539
4639
  const msg = error instanceof Error ? error.message : String(error);
4540
4640
  if (msg.includes("429") || msg.includes("quota")) {
4541
- console.log(chalk15.yellow("\n\u26A0\uFE0F Quota exceeded. Run: agdi model\n"));
4641
+ console.log(chalk14.yellow("\n\u26A0\uFE0F Quota exceeded. Run: agdi model\n"));
4542
4642
  } else if (msg.includes("401") || msg.includes("403")) {
4543
- console.log(chalk15.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
4643
+ console.log(chalk14.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
4544
4644
  } else {
4545
- console.error(chalk15.red("\n" + msg + "\n"));
4645
+ console.error(chalk14.red("\n" + msg + "\n"));
4546
4646
  }
4547
4647
  ui.safeExit(1);
4548
4648
  }
4549
4649
  } catch (error) {
4550
4650
  if (error.name === "ExitPromptError") {
4551
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4651
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4552
4652
  try {
4553
4653
  ui.safeExit(0);
4554
4654
  } catch {
@@ -4564,11 +4664,11 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
4564
4664
  program.command("config").description("Show configuration").action(async () => {
4565
4665
  const config = loadConfig();
4566
4666
  const active = getActiveProvider();
4567
- console.log(chalk15.cyan.bold("\n\u2699\uFE0F Configuration\n"));
4568
- console.log(chalk15.gray(" Provider: ") + chalk15.cyan(config.defaultProvider || "not set"));
4569
- console.log(chalk15.gray(" Model: ") + chalk15.cyan(config.defaultModel || "not set"));
4570
- console.log(chalk15.gray(" Config: ") + chalk15.gray("~/.agdi/config.json"));
4571
- console.log(chalk15.cyan.bold("\n\u{1F510} API Keys\n"));
4667
+ console.log(chalk14.cyan.bold("\n\u2699\uFE0F Configuration\n"));
4668
+ console.log(chalk14.gray(" Provider: ") + chalk14.cyan(config.defaultProvider || "not set"));
4669
+ console.log(chalk14.gray(" Model: ") + chalk14.cyan(config.defaultModel || "not set"));
4670
+ console.log(chalk14.gray(" Config: ") + chalk14.gray("~/.agdi/config.json"));
4671
+ console.log(chalk14.cyan.bold("\n\u{1F510} API Keys\n"));
4572
4672
  const keys = [
4573
4673
  ["Gemini", config.geminiApiKey],
4574
4674
  ["OpenRouter", config.openrouterApiKey],
@@ -4577,13 +4677,13 @@ program.command("config").description("Show configuration").action(async () => {
4577
4677
  ["DeepSeek", config.deepseekApiKey]
4578
4678
  ];
4579
4679
  for (const [name, key] of keys) {
4580
- const status = key ? chalk15.green("\u2713") : chalk15.gray("\u2717");
4680
+ const status = key ? chalk14.green("\u2713") : chalk14.gray("\u2717");
4581
4681
  console.log(` ${status} ${name}`);
4582
4682
  }
4583
- console.log(chalk15.cyan.bold("\n\u{1F4CA} Telemetry\n"));
4683
+ console.log(chalk14.cyan.bold("\n\u{1F4CA} Telemetry\n"));
4584
4684
  const telemetryEnabled = config.telemetry?.enabled ?? false;
4585
- console.log(` ${telemetryEnabled ? chalk15.green("\u2713 Enabled") : chalk15.gray("\u2717 Disabled")}`);
4586
- console.log(chalk15.gray(" Change with: agdi config telemetry --enable | --disable"));
4685
+ console.log(` ${telemetryEnabled ? chalk14.green("\u2713 Enabled") : chalk14.gray("\u2717 Disabled")}`);
4686
+ console.log(chalk14.gray(" Change with: agdi config telemetry --enable | --disable"));
4587
4687
  console.log("");
4588
4688
  console.log("");
4589
4689
  });
@@ -4591,59 +4691,59 @@ program.command("config:telemetry").alias("telemetry").description("Manage telem
4591
4691
  const { isTelemetryEnabled, setTelemetryConsent, getTelemetryConfig } = await import("./config-ZFU7TSU2.js");
4592
4692
  const { generateSampleEvent, generateSanitizationDemo } = await import("./telemetry-service-OHU5NKON.js");
4593
4693
  if (options.dryRun || options.test) {
4594
- console.log(chalk15.cyan.bold("\n\u{1F50D} TELEMETRY TRANSPARENCY MODE\n"));
4595
- console.log(chalk15.gray("This is exactly what Agdi sends. Notice there is"));
4596
- console.log(chalk15.green.bold("NO source code, file paths, or API keys.\n"));
4597
- console.log(chalk15.white.bold('\u{1F4CA} Sample "Build Failed" Event:\n'));
4694
+ console.log(chalk14.cyan.bold("\n\u{1F50D} TELEMETRY TRANSPARENCY MODE\n"));
4695
+ console.log(chalk14.gray("This is exactly what Agdi sends. Notice there is"));
4696
+ console.log(chalk14.green.bold("NO source code, file paths, or API keys.\n"));
4697
+ console.log(chalk14.white.bold('\u{1F4CA} Sample "Build Failed" Event:\n'));
4598
4698
  const sample = generateSampleEvent();
4599
- console.log(chalk15.gray(JSON.stringify(sample, null, 2)));
4600
- console.log(chalk15.white.bold("\n\u{1F6E1}\uFE0F Sanitization Demo:\n"));
4601
- console.log(chalk15.gray("Even if sensitive data accidentally enters an error message,"));
4602
- console.log(chalk15.gray("our sanitization layer strips it before transmission:\n"));
4699
+ console.log(chalk14.gray(JSON.stringify(sample, null, 2)));
4700
+ console.log(chalk14.white.bold("\n\u{1F6E1}\uFE0F Sanitization Demo:\n"));
4701
+ console.log(chalk14.gray("Even if sensitive data accidentally enters an error message,"));
4702
+ console.log(chalk14.gray("our sanitization layer strips it before transmission:\n"));
4603
4703
  const demo = generateSanitizationDemo();
4604
- console.log(chalk15.red.bold("BEFORE sanitization (never sent):"));
4605
- console.log(chalk15.gray(JSON.stringify({
4704
+ console.log(chalk14.red.bold("BEFORE sanitization (never sent):"));
4705
+ console.log(chalk14.gray(JSON.stringify({
4606
4706
  errorCode: demo.before.errorCode,
4607
4707
  feedback: demo.before.feedback
4608
4708
  }, null, 2)));
4609
- console.log(chalk15.green.bold("\nAFTER sanitization (what we actually send):"));
4610
- console.log(chalk15.gray(JSON.stringify({
4709
+ console.log(chalk14.green.bold("\nAFTER sanitization (what we actually send):"));
4710
+ console.log(chalk14.gray(JSON.stringify({
4611
4711
  errorCode: demo.after.errorCode,
4612
4712
  feedback: demo.after.feedback
4613
4713
  }, null, 2)));
4614
- console.log(chalk15.cyan("\n\u2705 Your code and secrets are NEVER transmitted."));
4615
- console.log(chalk15.gray(" Learn more: https://agdi.dev/privacy\n"));
4714
+ console.log(chalk14.cyan("\n\u2705 Your code and secrets are NEVER transmitted."));
4715
+ console.log(chalk14.gray(" Learn more: https://agdi.dev/privacy\n"));
4616
4716
  return;
4617
4717
  }
4618
4718
  if (options.enable) {
4619
4719
  setTelemetryConsent(true);
4620
- console.log(chalk15.green("\n\u2705 Telemetry enabled"));
4621
- console.log(chalk15.gray(" We collect: success/fail, error types, model used"));
4622
- console.log(chalk15.gray(" We NEVER collect: source code, API keys, file paths"));
4623
- console.log(chalk15.gray(" Verify anytime: agdi config telemetry --dry-run\n"));
4720
+ console.log(chalk14.green("\n\u2705 Telemetry enabled"));
4721
+ console.log(chalk14.gray(" We collect: success/fail, error types, model used"));
4722
+ console.log(chalk14.gray(" We NEVER collect: source code, API keys, file paths"));
4723
+ console.log(chalk14.gray(" Verify anytime: agdi config telemetry --dry-run\n"));
4624
4724
  } else if (options.disable) {
4625
4725
  setTelemetryConsent(false);
4626
- console.log(chalk15.yellow("\n\u{1F4CA} Telemetry disabled"));
4627
- console.log(chalk15.gray(" You can re-enable anytime with: agdi config telemetry --enable\n"));
4726
+ console.log(chalk14.yellow("\n\u{1F4CA} Telemetry disabled"));
4727
+ console.log(chalk14.gray(" You can re-enable anytime with: agdi config telemetry --enable\n"));
4628
4728
  } else {
4629
4729
  const config = getTelemetryConfig();
4630
- console.log(chalk15.cyan.bold("\n\u{1F4CA} Telemetry Status\n"));
4631
- console.log(chalk15.gray(" Enabled: ") + (config.enabled ? chalk15.green("Yes") : chalk15.gray("No")));
4632
- console.log(chalk15.gray(" Consent: ") + (config.consentAsked ? chalk15.green("Asked") : chalk15.gray("Not asked")));
4730
+ console.log(chalk14.cyan.bold("\n\u{1F4CA} Telemetry Status\n"));
4731
+ console.log(chalk14.gray(" Enabled: ") + (config.enabled ? chalk14.green("Yes") : chalk14.gray("No")));
4732
+ console.log(chalk14.gray(" Consent: ") + (config.consentAsked ? chalk14.green("Asked") : chalk14.gray("Not asked")));
4633
4733
  if (config.anonymousId) {
4634
- console.log(chalk15.gray(" ID: ") + chalk15.gray(config.anonymousId.slice(0, 8) + "..."));
4734
+ console.log(chalk14.gray(" ID: ") + chalk14.gray(config.anonymousId.slice(0, 8) + "..."));
4635
4735
  }
4636
4736
  console.log("");
4637
- console.log(chalk15.gray(" Enable: agdi config telemetry --enable"));
4638
- console.log(chalk15.gray(" Disable: agdi config telemetry --disable"));
4639
- console.log(chalk15.gray(" Verify: agdi config telemetry --dry-run\n"));
4737
+ console.log(chalk14.gray(" Enable: agdi config telemetry --enable"));
4738
+ console.log(chalk14.gray(" Disable: agdi config telemetry --disable"));
4739
+ console.log(chalk14.gray(" Verify: agdi config telemetry --dry-run\n"));
4640
4740
  }
4641
4741
  });
4642
4742
  program.command("doctor").alias("doc").description("Run self-diagnosis checks").action(async () => {
4643
4743
  try {
4644
4744
  await runDoctor();
4645
4745
  } catch (error) {
4646
- console.error(chalk15.red("Diagnostic failed: " + error));
4746
+ console.error(chalk14.red("Diagnostic failed: " + error));
4647
4747
  ui.safeExit(1);
4648
4748
  }
4649
4749
  });
@@ -4654,7 +4754,7 @@ program.command("squad [prompt]").alias("s").description("\u{1F9B8} Autonomous m
4654
4754
  }
4655
4755
  const activeConfig = getActiveProvider();
4656
4756
  if (!activeConfig) {
4657
- console.log(chalk15.red("\u274C No API key configured. Run: agdi auth"));
4757
+ console.log(chalk14.red("\u274C No API key configured. Run: agdi auth"));
4658
4758
  return;
4659
4759
  }
4660
4760
  const llm = createLLMProvider(activeConfig.provider, {
@@ -4668,7 +4768,7 @@ program.command("squad [prompt]").alias("s").description("\u{1F9B8} Autonomous m
4668
4768
  });
4669
4769
  } catch (error) {
4670
4770
  if (error.name === "ExitPromptError") {
4671
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4771
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4672
4772
  try {
4673
4773
  ui.safeExit(0);
4674
4774
  } catch {
@@ -4696,7 +4796,7 @@ program.command("replay <runId>").description("\u{1F501} Replay a previous squad
4696
4796
  }
4697
4797
  const activeConfig = getActiveProvider();
4698
4798
  if (!activeConfig) {
4699
- console.log(chalk15.red("\u274C No API key configured. Run: agdi auth"));
4799
+ console.log(chalk14.red("\u274C No API key configured. Run: agdi auth"));
4700
4800
  return;
4701
4801
  }
4702
4802
  const llm = createLLMProvider(activeConfig.provider, {
@@ -4710,7 +4810,7 @@ program.command("replay <runId>").description("\u{1F501} Replay a previous squad
4710
4810
  });
4711
4811
  } catch (error) {
4712
4812
  if (error.name === "ExitPromptError") {
4713
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4813
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4714
4814
  try {
4715
4815
  ui.safeExit(0);
4716
4816
  } catch {
@@ -4728,7 +4828,7 @@ program.command("import <url>").alias("i").description("\u{1F4E6} Import a GitHu
4728
4828
  await runImportCommand(url, options.output);
4729
4829
  } catch (error) {
4730
4830
  if (error.name === "ExitPromptError") {
4731
- console.log(chalk15.gray("\n\n\u{1F44B} Cancelled.\n"));
4831
+ console.log(chalk14.gray("\n\n\u{1F44B} Cancelled.\n"));
4732
4832
  try {
4733
4833
  ui.safeExit(0);
4734
4834
  } catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdi",
3
- "version": "3.2.0",
3
+ "version": "3.3.2",
4
4
  "description": "AI-powered app generator - build full-stack apps from natural language in your terminal",
5
5
  "type": "module",
6
6
  "bin": {