agdi 3.3.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.
@@ -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
@@ -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,
@@ -4155,9 +4187,11 @@ import { render } from "ink";
4155
4187
  import { useState, useEffect } from "react";
4156
4188
  import { Box, Text, useApp } from "ink";
4157
4189
  import BigText from "ink-big-text";
4190
+ import Spinner from "ink-spinner";
4158
4191
  import TextInput from "ink-text-input";
4159
4192
  import fs7 from "fs";
4160
4193
  import path7 from "path";
4194
+ import os from "os";
4161
4195
  import { jsx, jsxs } from "react/jsx-runtime";
4162
4196
  var BootScreen = ({ onComplete }) => {
4163
4197
  const [progress, setProgress] = useState(0);
@@ -4175,10 +4209,10 @@ var BootScreen = ({ onComplete }) => {
4175
4209
  useEffect(() => {
4176
4210
  const timer = setInterval(() => {
4177
4211
  setProgress((prev) => {
4178
- const next = prev + 2;
4212
+ const next = prev + 5;
4179
4213
  if (next >= 100) {
4180
4214
  clearInterval(timer);
4181
- setTimeout(onComplete, 500);
4215
+ setTimeout(onComplete, 200);
4182
4216
  return 100;
4183
4217
  }
4184
4218
  return next;
@@ -4205,20 +4239,25 @@ var BootScreen = ({ onComplete }) => {
4205
4239
  ] })
4206
4240
  ] });
4207
4241
  };
4208
- var FileExplorer = ({ cwd }) => {
4242
+ var FileExplorer = ({ cwd, lastChange }) => {
4209
4243
  const [files, setFiles] = useState([]);
4210
4244
  useEffect(() => {
4211
- try {
4212
- const list = fs7.readdirSync(cwd).filter((f) => !f.startsWith(".")).slice(0, 15);
4213
- setFiles(list);
4214
- } catch {
4215
- setFiles(["<Error reading dir>"]);
4216
- }
4217
- }, [cwd]);
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]);
4218
4257
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", title: " FILESYSTEM ", width: "30%", children: [
4219
4258
  /* @__PURE__ */ jsxs(Text, { color: "cyan", bold: true, children: [
4220
4259
  " ",
4221
- cwd
4260
+ cwd.length > 30 ? "..." + cwd.slice(-30) : cwd
4222
4261
  ] }),
4223
4262
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
4224
4263
  files.map((f, i) => /* @__PURE__ */ jsxs(Text, { color: "white", children: [
@@ -4231,7 +4270,7 @@ var FileExplorer = ({ cwd }) => {
4231
4270
  };
4232
4271
  var LogPanel = ({ logs }) => {
4233
4272
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", title: " AGENT LOGS ", width: "70%", marginLeft: 1, children: [
4234
- logs.slice(-10).map((log, i) => /* @__PURE__ */ jsxs(Text, { color: "green", children: [
4273
+ logs.slice(-12).map((log, i) => /* @__PURE__ */ jsxs(Text, { color: "green", children: [
4235
4274
  /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
4236
4275
  "[",
4237
4276
  (/* @__PURE__ */ new Date()).toLocaleTimeString(),
@@ -4243,11 +4282,11 @@ var LogPanel = ({ logs }) => {
4243
4282
  logs.length === 0 && /* @__PURE__ */ jsx(Text, { color: "gray", children: "Waiting for agent activity..." })
4244
4283
  ] });
4245
4284
  };
4246
- var ChatPanel = ({ history, onSend }) => {
4285
+ var ChatPanel = ({ history, onSend, placeholder = "" }) => {
4247
4286
  const [query, setQuery] = useState("");
4248
4287
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", title: " MISSION CONTROL ", height: 12, children: [
4249
4288
  /* @__PURE__ */ jsx(Box, { flexDirection: "column", flexGrow: 1, justifyContent: "flex-end", children: history.slice(-5).map((msg, i) => /* @__PURE__ */ jsxs(Box, { marginY: 0, children: [
4250
- /* @__PURE__ */ jsx(Text, { color: msg.role === "user" ? "cyan" : "magenta", bold: true, children: msg.role === "user" ? "YOU \u203A " : "AGDI \u203A " }),
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 " }),
4251
4290
  /* @__PURE__ */ jsx(Text, { children: msg.text })
4252
4291
  ] }, i)) }),
4253
4292
  /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: "gray", marginTop: 1, children: [
@@ -4260,7 +4299,8 @@ var ChatPanel = ({ history, onSend }) => {
4260
4299
  onSubmit: (val) => {
4261
4300
  onSend(val);
4262
4301
  setQuery("");
4263
- }
4302
+ },
4303
+ placeholder
4264
4304
  }
4265
4305
  )
4266
4306
  ] })
@@ -4268,28 +4308,139 @@ var ChatPanel = ({ history, onSend }) => {
4268
4308
  };
4269
4309
  var Dashboard = () => {
4270
4310
  const { exit } = useApp();
4271
- const [logs, setLogs] = useState(["System ready.", "Waiting for instructions."]);
4311
+ const [cwd, setCwd] = useState(process.cwd());
4312
+ const [logs, setLogs] = useState(["System ready.", "Initializing Neural Link..."]);
4272
4313
  const [chatHistory, setChatHistory] = useState([]);
4273
- const addLog = (msg) => setLogs((prev) => [...prev, msg]);
4274
- const handleCommand = (cmd) => {
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) => {
4275
4353
  if (cmd === "/exit") exit();
4276
4354
  setChatHistory((prev) => [...prev, { role: "user", text: cmd }]);
4277
- addLog(`Processing command: ${cmd}`);
4278
- setTimeout(() => {
4279
- setChatHistory((prev) => [...prev, { role: "ai", text: `I'm analyzing your request to "${cmd}"...` }]);
4280
- addLog("Agent [Manager] started planning phase.");
4281
- }, 800);
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
+ }
4282
4427
  };
4283
4428
  return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", padding: 1, height: "100%", children: [
4284
4429
  /* @__PURE__ */ jsxs(Box, { justifyContent: "space-between", marginBottom: 1, children: [
4285
- /* @__PURE__ */ jsx(Text, { bold: true, color: "cyan", children: "AGDI v3.3.0 [ONLINE]" }),
4286
- /* @__PURE__ */ jsx(Text, { color: "gray", children: "CPU: 12% | MEM: 450MB | NET: CONNECTED" })
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" })
4287
4438
  ] }),
4288
4439
  /* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexGrow: 1, children: [
4289
- /* @__PURE__ */ jsx(FileExplorer, { cwd: process.cwd() }),
4440
+ /* @__PURE__ */ jsx(FileExplorer, { cwd, lastChange: lastFileChange }),
4290
4441
  /* @__PURE__ */ jsx(LogPanel, { logs })
4291
4442
  ] }),
4292
- /* @__PURE__ */ jsx(Box, { marginTop: 0, children: /* @__PURE__ */ jsx(ChatPanel, { history: chatHistory, onSend: handleCommand }) })
4443
+ /* @__PURE__ */ jsx(Box, { marginTop: 0, children: /* @__PURE__ */ jsx(ChatPanel, { history: chatHistory, onSend: handleCommand, placeholder: step === "prompt" ? "Describe your app..." : "" }) })
4293
4444
  ] });
4294
4445
  };
4295
4446
  var App = () => {
@@ -4314,7 +4465,7 @@ ${chalk14.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
4314
4465
  ${chalk14.cyan(` /____/ `)}
4315
4466
  `;
4316
4467
  var program = new Command();
4317
- program.name("agdi").description(chalk14.cyan("\u{1F9B8} The Autonomous AI Employee")).version("3.3.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)");
4318
4469
  program.hook("preAction", (thisCommand) => {
4319
4470
  const opts = thisCommand.opts();
4320
4471
  if (opts.yes) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agdi",
3
- "version": "3.3.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": {