agdi 3.3.2 → 3.3.5
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,45 @@
|
|
|
1
|
+
// src/core/event-bus.ts
|
|
2
|
+
import { EventEmitter } from "events";
|
|
3
|
+
var agentEventBus = new EventEmitter();
|
|
4
|
+
agentEventBus.setMaxListeners(50);
|
|
5
|
+
var thoughtFlushTimeout = null;
|
|
6
|
+
var pendingThought = null;
|
|
7
|
+
function emitAgentEvent(event) {
|
|
8
|
+
const fullEvent = {
|
|
9
|
+
...event,
|
|
10
|
+
timestamp: Date.now()
|
|
11
|
+
};
|
|
12
|
+
if (event.type === "thought") {
|
|
13
|
+
pendingThought = fullEvent;
|
|
14
|
+
if (!thoughtFlushTimeout) {
|
|
15
|
+
thoughtFlushTimeout = setTimeout(() => {
|
|
16
|
+
if (pendingThought) {
|
|
17
|
+
agentEventBus.emit("agent_event", pendingThought);
|
|
18
|
+
pendingThought = null;
|
|
19
|
+
}
|
|
20
|
+
thoughtFlushTimeout = null;
|
|
21
|
+
}, 100);
|
|
22
|
+
}
|
|
23
|
+
} else {
|
|
24
|
+
agentEventBus.emit("agent_event", fullEvent);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function cleanupEventBus() {
|
|
28
|
+
agentEventBus.removeAllListeners();
|
|
29
|
+
if (thoughtFlushTimeout) {
|
|
30
|
+
clearTimeout(thoughtFlushTimeout);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
process.on("exit", cleanupEventBus);
|
|
34
|
+
process.on("SIGINT", cleanupEventBus);
|
|
35
|
+
process.on("uncaughtException", (err) => {
|
|
36
|
+
console.error("Uncaught exception:", err);
|
|
37
|
+
cleanupEventBus();
|
|
38
|
+
process.exit(1);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export {
|
|
42
|
+
agentEventBus,
|
|
43
|
+
emitAgentEvent,
|
|
44
|
+
cleanupEventBus
|
|
45
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
agentEventBus,
|
|
4
4
|
emitAgentEvent
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-A5UTYKKM.js";
|
|
6
6
|
import {
|
|
7
7
|
loadConfig,
|
|
8
8
|
saveConfig
|
|
@@ -343,9 +343,9 @@ var errorGradient = gradient([THEME.red, "#b91c1c"]);
|
|
|
343
343
|
var goldGradient = gradient([THEME.yellow, "#fbbf24"]);
|
|
344
344
|
async function renderBanner(version = "v2.6.0") {
|
|
345
345
|
console.clear();
|
|
346
|
-
const text = await new Promise((
|
|
346
|
+
const text = await new Promise((resolve2) => {
|
|
347
347
|
figlet("AGDI", { font: "Slant" }, (err, data) => {
|
|
348
|
-
|
|
348
|
+
resolve2(data || "AGDI");
|
|
349
349
|
});
|
|
350
350
|
});
|
|
351
351
|
console.log(brandGradient.multiline(text));
|
|
@@ -1576,7 +1576,7 @@ async function runProject(targetDir) {
|
|
|
1576
1576
|
console.log(chalk6.yellow("\u{1F4E6} Installing dependencies...\n"));
|
|
1577
1577
|
const installSpinner = ora3("Running npm install...").start();
|
|
1578
1578
|
try {
|
|
1579
|
-
await new Promise((
|
|
1579
|
+
await new Promise((resolve2, reject) => {
|
|
1580
1580
|
const install = spawn("npm", ["install"], {
|
|
1581
1581
|
cwd: absoluteDir,
|
|
1582
1582
|
stdio: "inherit",
|
|
@@ -1585,7 +1585,7 @@ async function runProject(targetDir) {
|
|
|
1585
1585
|
install.on("close", (code) => {
|
|
1586
1586
|
if (code === 0) {
|
|
1587
1587
|
installSpinner.succeed("Dependencies installed!");
|
|
1588
|
-
|
|
1588
|
+
resolve2();
|
|
1589
1589
|
} else {
|
|
1590
1590
|
installSpinner.fail("npm install failed");
|
|
1591
1591
|
reject(new Error(`npm install exited with code ${code}`));
|
|
@@ -2101,8 +2101,9 @@ var BaseAgent = class {
|
|
|
2101
2101
|
}
|
|
2102
2102
|
/**
|
|
2103
2103
|
* Generate a response from the LLM
|
|
2104
|
+
* Includes timeout protection to prevent indefinite hanging
|
|
2104
2105
|
*/
|
|
2105
|
-
async think(prompt) {
|
|
2106
|
+
async think(prompt, timeoutMs = 12e4) {
|
|
2106
2107
|
this.log("Thinking...", "info");
|
|
2107
2108
|
emitAgentEvent({
|
|
2108
2109
|
type: "thought",
|
|
@@ -2110,7 +2111,12 @@ var BaseAgent = class {
|
|
|
2110
2111
|
role: this.role,
|
|
2111
2112
|
message: `Analyzing task...`
|
|
2112
2113
|
});
|
|
2113
|
-
const response = await
|
|
2114
|
+
const response = await Promise.race([
|
|
2115
|
+
this.llm.generate(prompt, this.getSystemPrompt()),
|
|
2116
|
+
new Promise(
|
|
2117
|
+
(_, reject) => setTimeout(() => reject(new Error(`LLM request timed out after ${timeoutMs / 1e3}s`)), timeoutMs)
|
|
2118
|
+
)
|
|
2119
|
+
]);
|
|
2114
2120
|
const summary = response.text.split("\n")[0].substring(0, 80) + "...";
|
|
2115
2121
|
emitAgentEvent({
|
|
2116
2122
|
type: "thought",
|
|
@@ -3148,12 +3154,17 @@ Requirements:
|
|
|
3148
3154
|
}
|
|
3149
3155
|
try {
|
|
3150
3156
|
const prodFlag = production ? "--prod" : "";
|
|
3151
|
-
const command = `npx vercel ${prodFlag} --yes
|
|
3152
|
-
this.log(`Running: npx vercel ${prodFlag} --yes
|
|
3157
|
+
const command = `npx vercel ${prodFlag} --yes`;
|
|
3158
|
+
this.log(`Running: npx vercel ${prodFlag} --yes`, "info");
|
|
3153
3159
|
const { stdout, stderr } = await execAsync2(command, {
|
|
3154
3160
|
cwd,
|
|
3155
|
-
timeout: 3e5
|
|
3161
|
+
timeout: 3e5,
|
|
3156
3162
|
// 5 minutes
|
|
3163
|
+
env: {
|
|
3164
|
+
...process.env,
|
|
3165
|
+
VERCEL_TOKEN: this.vercelToken
|
|
3166
|
+
// Pass via env, not CLI (security)
|
|
3167
|
+
}
|
|
3157
3168
|
});
|
|
3158
3169
|
const output = stdout + stderr;
|
|
3159
3170
|
const urlMatch = output.match(/https:\/\/[^\s]+\.vercel\.app/);
|
|
@@ -3203,10 +3214,15 @@ Requirements:
|
|
|
3203
3214
|
try {
|
|
3204
3215
|
const prodFlag = production ? "--prod" : "";
|
|
3205
3216
|
const outputDir = await detectBuildOutputDir(cwd);
|
|
3206
|
-
const command = `npx netlify deploy ${prodFlag} --
|
|
3217
|
+
const command = `npx netlify deploy ${prodFlag} --dir=${outputDir}`;
|
|
3207
3218
|
const { stdout, stderr } = await execAsync2(command, {
|
|
3208
3219
|
cwd,
|
|
3209
|
-
timeout: 3e5
|
|
3220
|
+
timeout: 3e5,
|
|
3221
|
+
env: {
|
|
3222
|
+
...process.env,
|
|
3223
|
+
NETLIFY_AUTH_TOKEN: this.netlifyToken
|
|
3224
|
+
// Pass via env, not CLI (security)
|
|
3225
|
+
}
|
|
3210
3226
|
});
|
|
3211
3227
|
const output = stdout + (stderr || "");
|
|
3212
3228
|
const urlMatch = output.match(/https:\/\/[^\s]+\.netlify\.app/);
|
|
@@ -3592,7 +3608,7 @@ ${qaResult.errors?.join("\n")}`,
|
|
|
3592
3608
|
*/
|
|
3593
3609
|
async executeTask(task) {
|
|
3594
3610
|
this.log(`[${task.assignee}] ${task.title}`, "task");
|
|
3595
|
-
const { emitAgentEvent: emitAgentEvent2 } = await import("./event-bus-
|
|
3611
|
+
const { emitAgentEvent: emitAgentEvent2 } = await import("./event-bus-Q3WCETQQ.js");
|
|
3596
3612
|
emitAgentEvent2({
|
|
3597
3613
|
type: "handoff",
|
|
3598
3614
|
agentName: task.assignee,
|
|
@@ -3647,10 +3663,21 @@ ${qaResult.errors?.join("\n")}`,
|
|
|
3647
3663
|
}
|
|
3648
3664
|
/**
|
|
3649
3665
|
* Write generated files to disk
|
|
3666
|
+
* SECURITY: All paths are validated to prevent directory traversal attacks
|
|
3650
3667
|
*/
|
|
3651
3668
|
async writeFiles(files, filesCreated, filesModified) {
|
|
3669
|
+
const workspaceRoot = path5.resolve(this.config.workspaceRoot);
|
|
3652
3670
|
for (const file of files) {
|
|
3653
|
-
const
|
|
3671
|
+
const validationResult = this.validateFilePath(file.path, workspaceRoot);
|
|
3672
|
+
if (!validationResult.valid) {
|
|
3673
|
+
this.log(`\u{1F6E1}\uFE0F Blocked unsafe path: ${file.path} - ${validationResult.error}`, "error");
|
|
3674
|
+
await this.appendTrace("file_blocked", {
|
|
3675
|
+
path: file.path,
|
|
3676
|
+
reason: validationResult.error
|
|
3677
|
+
});
|
|
3678
|
+
continue;
|
|
3679
|
+
}
|
|
3680
|
+
const fullPath = validationResult.resolvedPath;
|
|
3654
3681
|
const dir = path5.dirname(fullPath);
|
|
3655
3682
|
try {
|
|
3656
3683
|
await fs5.mkdir(dir, { recursive: true });
|
|
@@ -3665,7 +3692,7 @@ ${qaResult.errors?.join("\n")}`,
|
|
|
3665
3692
|
}
|
|
3666
3693
|
await fs5.writeFile(fullPath, file.content, "utf-8");
|
|
3667
3694
|
const afterContent = file.content;
|
|
3668
|
-
const outputPath = path5.join(this.runDir, "outputs",
|
|
3695
|
+
const outputPath = path5.join(this.runDir, "outputs", validationResult.normalizedPath);
|
|
3669
3696
|
await fs5.mkdir(path5.dirname(outputPath), { recursive: true });
|
|
3670
3697
|
await fs5.writeFile(outputPath, file.content, "utf-8");
|
|
3671
3698
|
const beforeHash = beforeContent ? this.hashContent(beforeContent) : null;
|
|
@@ -3692,6 +3719,54 @@ ${qaResult.errors?.join("\n")}`,
|
|
|
3692
3719
|
}
|
|
3693
3720
|
}
|
|
3694
3721
|
}
|
|
3722
|
+
/**
|
|
3723
|
+
* Validate a file path to prevent directory traversal attacks
|
|
3724
|
+
* SECURITY: Critical function - blocks paths that escape workspace root
|
|
3725
|
+
*/
|
|
3726
|
+
validateFilePath(filePath, workspaceRoot) {
|
|
3727
|
+
if (path5.isAbsolute(filePath)) {
|
|
3728
|
+
return {
|
|
3729
|
+
valid: false,
|
|
3730
|
+
error: "Absolute paths not allowed"
|
|
3731
|
+
};
|
|
3732
|
+
}
|
|
3733
|
+
const normalizedPath = path5.normalize(filePath).replace(/^(\.\.[\\/])+/, "");
|
|
3734
|
+
const resolvedPath = path5.resolve(workspaceRoot, filePath);
|
|
3735
|
+
if (filePath.includes("..")) {
|
|
3736
|
+
if (!resolvedPath.startsWith(workspaceRoot + path5.sep) && resolvedPath !== workspaceRoot) {
|
|
3737
|
+
return {
|
|
3738
|
+
valid: false,
|
|
3739
|
+
error: "Path traversal blocked: cannot escape workspace root"
|
|
3740
|
+
};
|
|
3741
|
+
}
|
|
3742
|
+
}
|
|
3743
|
+
if (!resolvedPath.startsWith(workspaceRoot)) {
|
|
3744
|
+
return {
|
|
3745
|
+
valid: false,
|
|
3746
|
+
error: "Path traversal blocked: resolved path outside workspace"
|
|
3747
|
+
};
|
|
3748
|
+
}
|
|
3749
|
+
const sensitivePatterns = [
|
|
3750
|
+
/^\.git\//,
|
|
3751
|
+
/^node_modules\//,
|
|
3752
|
+
/^\.env$/,
|
|
3753
|
+
/^\.env\./,
|
|
3754
|
+
/\/\.git\//
|
|
3755
|
+
];
|
|
3756
|
+
for (const pattern of sensitivePatterns) {
|
|
3757
|
+
if (pattern.test(normalizedPath)) {
|
|
3758
|
+
return {
|
|
3759
|
+
valid: false,
|
|
3760
|
+
error: `Blocked write to sensitive path: ${normalizedPath}`
|
|
3761
|
+
};
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
return {
|
|
3765
|
+
valid: true,
|
|
3766
|
+
resolvedPath,
|
|
3767
|
+
normalizedPath
|
|
3768
|
+
};
|
|
3769
|
+
}
|
|
3695
3770
|
async initializeRun(userPrompt) {
|
|
3696
3771
|
this.runId = uuidv42();
|
|
3697
3772
|
this.runDir = path5.join(this.config.workspaceRoot, "runs", this.runId);
|
|
@@ -4185,146 +4260,186 @@ import { render } from "ink";
|
|
|
4185
4260
|
|
|
4186
4261
|
// src/ui/tui.tsx
|
|
4187
4262
|
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";
|
|
4263
|
+
import { Box, Text, useApp, Spacer } from "ink";
|
|
4191
4264
|
import TextInput from "ink-text-input";
|
|
4192
4265
|
import fs7 from "fs";
|
|
4193
4266
|
import path7 from "path";
|
|
4194
4267
|
import os from "os";
|
|
4195
4268
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4269
|
+
var THEME2 = {
|
|
4270
|
+
bg: "black",
|
|
4271
|
+
// Main background
|
|
4272
|
+
text: "#E5E5E5",
|
|
4273
|
+
// Primary text
|
|
4274
|
+
dim: "#6B7280",
|
|
4275
|
+
// Secondary/Dim text
|
|
4276
|
+
accent: "#3B82F6",
|
|
4277
|
+
// Brand Blue
|
|
4278
|
+
border: "#374151",
|
|
4279
|
+
// Dark gray border
|
|
4280
|
+
success: "#10B981",
|
|
4281
|
+
warning: "#F59E0B",
|
|
4282
|
+
error: "#EF4444",
|
|
4283
|
+
cardBg: "#111827",
|
|
4284
|
+
// Slightly lighter bg for cards
|
|
4285
|
+
highlight: "#1F2937"
|
|
4286
|
+
// Hover/Selection state
|
|
4287
|
+
};
|
|
4196
4288
|
var BootScreen = ({ onComplete }) => {
|
|
4197
4289
|
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
4290
|
useEffect(() => {
|
|
4210
4291
|
const timer = setInterval(() => {
|
|
4211
4292
|
setProgress((prev) => {
|
|
4212
|
-
const next = prev +
|
|
4293
|
+
const next = prev + 10;
|
|
4213
4294
|
if (next >= 100) {
|
|
4214
4295
|
clearInterval(timer);
|
|
4215
|
-
setTimeout(onComplete,
|
|
4296
|
+
setTimeout(onComplete, 100);
|
|
4216
4297
|
return 100;
|
|
4217
4298
|
}
|
|
4218
4299
|
return next;
|
|
4219
4300
|
});
|
|
4220
|
-
|
|
4221
|
-
setLog(logs[index] || logs[logs.length - 1]);
|
|
4222
|
-
}, 30);
|
|
4301
|
+
}, 20);
|
|
4223
4302
|
return () => clearInterval(timer);
|
|
4224
|
-
}, [
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
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
|
|
4303
|
+
}, []);
|
|
4304
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", height: 15, children: [
|
|
4305
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.accent, bold: true, children: "Initializing Agdi Workspace..." }),
|
|
4306
|
+
/* @__PURE__ */ jsxs(Text, { color: THEME2.dim, children: [
|
|
4307
|
+
"\u2588",
|
|
4308
|
+
"\u2588".repeat(progress / 5)
|
|
4239
4309
|
] })
|
|
4240
4310
|
] });
|
|
4241
4311
|
};
|
|
4242
|
-
var
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
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
|
|
4312
|
+
var Header = () => {
|
|
4313
|
+
return /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: THEME2.border, paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [
|
|
4314
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
4315
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.warning, children: "\u26A1 " }),
|
|
4316
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: "Starter " }),
|
|
4317
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: os.homedir() })
|
|
4261
4318
|
] }),
|
|
4262
|
-
/* @__PURE__ */
|
|
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
|
-
] })
|
|
4319
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "Agdi v3.3.4" }) })
|
|
4269
4320
|
] });
|
|
4270
4321
|
};
|
|
4271
|
-
var
|
|
4272
|
-
return /* @__PURE__ */ jsxs(Box, {
|
|
4273
|
-
|
|
4274
|
-
/* @__PURE__ */
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4322
|
+
var Footer = ({ status }) => {
|
|
4323
|
+
return /* @__PURE__ */ jsxs(Box, { borderStyle: "single", borderColor: THEME2.border, borderTop: false, paddingX: 1, flexDirection: "row", justifyContent: "space-between", children: [
|
|
4324
|
+
/* @__PURE__ */ jsxs(Box, { children: [
|
|
4325
|
+
/* @__PURE__ */ jsx(Text, { color: status === "IDLE" ? THEME2.success : THEME2.warning, children: "\u25CF " }),
|
|
4326
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: status })
|
|
4327
|
+
] }),
|
|
4328
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "CONNECT TELEGRAM / WHATSAPP (ALPHA)" }) }),
|
|
4329
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: THEME2.error, children: "Stop & Disconnect" }) })
|
|
4330
|
+
] });
|
|
4331
|
+
};
|
|
4332
|
+
var Sidebar = ({ history }) => {
|
|
4333
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: 32, borderStyle: "single", borderColor: THEME2.border, borderRight: false, borderTop: false, borderBottom: false, paddingX: 1, children: [
|
|
4334
|
+
/* @__PURE__ */ jsx(Box, { marginBottom: 1, borderStyle: "round", borderColor: THEME2.text, justifyContent: "center", paddingX: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: "+ New task" }) }),
|
|
4335
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, bold: true, children: "RECENTS" }),
|
|
4336
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", marginTop: 0, children: history.length === 0 ? /* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "No recent sessions" }) : history.map((h, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "space-between", marginBottom: 0, children: [
|
|
4337
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.text, children: h.length > 18 ? h.substring(0, 15) + "..." : h }),
|
|
4338
|
+
/* @__PURE__ */ jsx(Box, { borderStyle: "single", borderColor: THEME2.dim, paddingX: 1, marginLeft: 1, children: /* @__PURE__ */ jsx(Text, { color: THEME2.dim, dimColor: true, children: "STARTER" }) })
|
|
4339
|
+
] }, i)) })
|
|
4340
|
+
] });
|
|
4341
|
+
};
|
|
4342
|
+
var ContextPanel = ({ files, agentStatus }) => {
|
|
4343
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: 35, borderStyle: "single", borderColor: THEME2.border, borderLeft: false, borderTop: false, borderBottom: false, paddingX: 1, children: [
|
|
4344
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: "single", borderColor: THEME2.border, padding: 0, children: [
|
|
4345
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: " Context" }),
|
|
4346
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 1, flexDirection: "column", children: [
|
|
4347
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, bold: true, children: "WORKING FILES" }),
|
|
4348
|
+
files.length === 0 ? /* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "None yet." }) : files.slice(0, 5).map((f, i) => (
|
|
4349
|
+
// @ts-expect-error: Ink type definition mismatch for key prop
|
|
4350
|
+
/* @__PURE__ */ jsxs(Text, { color: THEME2.accent, children: [
|
|
4351
|
+
"\u{1F4C4} ",
|
|
4352
|
+
f
|
|
4353
|
+
] }, i)
|
|
4354
|
+
))
|
|
4355
|
+
] })
|
|
4356
|
+
] }),
|
|
4357
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: "single", borderColor: THEME2.border, padding: 0, children: [
|
|
4358
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: " Plugins" }),
|
|
4359
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 1, flexDirection: "column", children: [
|
|
4360
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.success, children: "\u2022 Scheduler" }),
|
|
4361
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: " Run scheduled jobs" })
|
|
4362
|
+
] })
|
|
4363
|
+
] }),
|
|
4364
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: "single", borderColor: THEME2.border, padding: 0, children: [
|
|
4365
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: " MCP" }),
|
|
4366
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 1, flexDirection: "column", children: [
|
|
4367
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.success, children: "\u2022 chrome-devtools" }),
|
|
4368
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: " Connected - npx -y chrome..." })
|
|
4369
|
+
] })
|
|
4370
|
+
] }),
|
|
4371
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "single", borderColor: THEME2.border, padding: 0, children: [
|
|
4372
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: " Skills" }),
|
|
4373
|
+
/* @__PURE__ */ jsxs(Box, { marginLeft: 1, flexDirection: "column", children: [
|
|
4374
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "\u2394 Agent Creator" }),
|
|
4375
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, dimColor: true, children: " bash" }),
|
|
4376
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "\u2394 Command Creator" }),
|
|
4377
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, dimColor: true, children: " bash" })
|
|
4378
|
+
] })
|
|
4379
|
+
] })
|
|
4283
4380
|
] });
|
|
4284
4381
|
};
|
|
4285
|
-
var
|
|
4382
|
+
var ChatArea = ({ history, onSend, placeholder }) => {
|
|
4286
4383
|
const [query, setQuery] = useState("");
|
|
4287
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", borderStyle: "
|
|
4288
|
-
/* @__PURE__ */ jsx(Box, { flexDirection: "column", flexGrow: 1, justifyContent: "flex-end", children: history.
|
|
4289
|
-
/* @__PURE__ */ jsx(
|
|
4290
|
-
/* @__PURE__ */ jsx(Text, {
|
|
4384
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, borderStyle: "single", borderColor: THEME2.border, borderTop: false, borderBottom: false, marginLeft: 0, marginRight: 0, children: [
|
|
4385
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", flexGrow: 1, padding: 1, justifyContent: "flex-end", children: history.length === 0 ? /* @__PURE__ */ jsxs(Box, { flexDirection: "column", alignItems: "center", justifyContent: "center", height: 10, children: [
|
|
4386
|
+
/* @__PURE__ */ jsx(Box, { borderStyle: "round", borderColor: THEME2.border, padding: 1, marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "\u26A1" }) }),
|
|
4387
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: THEME2.text, children: "Start a conversation" }),
|
|
4388
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "Describe what you want to do, and Agdi will take it" }),
|
|
4389
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "from there." })
|
|
4390
|
+
] }) : history.slice(-10).map((msg, i) => /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginBottom: 1, borderStyle: "single", borderColor: THEME2.border, padding: 1, children: [
|
|
4391
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", justifyContent: "space-between", children: [
|
|
4392
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: msg.role === "user" ? THEME2.text : THEME2.accent, children: msg.role === "user" ? "You" : "Agdi" }),
|
|
4393
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: msg.role === "system" ? "System" : "Unknown Model" })
|
|
4394
|
+
] }),
|
|
4395
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.text, children: msg.text })
|
|
4291
4396
|
] }, i)) }),
|
|
4292
|
-
/* @__PURE__ */ jsxs(Box, { borderStyle: "
|
|
4293
|
-
/* @__PURE__ */ jsx(Text, { color:
|
|
4294
|
-
/* @__PURE__ */
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4397
|
+
/* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: THEME2.dim, paddingX: 1, marginX: 2, marginBottom: 1, flexDirection: "column", children: [
|
|
4398
|
+
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { color: THEME2.dim, italic: true, children: "OpenCode Zen \u2022 Big Pickle \u2022 Variant X-High" }) }),
|
|
4399
|
+
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", children: [
|
|
4400
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "> " }),
|
|
4401
|
+
/* @__PURE__ */ jsx(
|
|
4402
|
+
TextInput,
|
|
4403
|
+
{
|
|
4404
|
+
value: query,
|
|
4405
|
+
onChange: setQuery,
|
|
4406
|
+
onSubmit: (val) => {
|
|
4407
|
+
onSend(val);
|
|
4408
|
+
setQuery("");
|
|
4409
|
+
},
|
|
4410
|
+
placeholder
|
|
4411
|
+
}
|
|
4412
|
+
)
|
|
4413
|
+
] }),
|
|
4414
|
+
/* @__PURE__ */ jsxs(Box, { marginTop: 0, justifyContent: "flex-end", flexDirection: "row", children: [
|
|
4415
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "@ Default agent" }),
|
|
4416
|
+
/* @__PURE__ */ jsx(Spacer, {}),
|
|
4417
|
+
/* @__PURE__ */ jsx(Text, { color: THEME2.dim, children: "\u{1F4CE} \u2794" })
|
|
4418
|
+
] })
|
|
4306
4419
|
] })
|
|
4307
4420
|
] });
|
|
4308
4421
|
};
|
|
4309
4422
|
var Dashboard = () => {
|
|
4310
4423
|
const { exit } = useApp();
|
|
4311
4424
|
const [cwd, setCwd] = useState(process.cwd());
|
|
4312
|
-
const [logs, setLogs] = useState(["System ready.", "Initializing Neural Link..."]);
|
|
4313
4425
|
const [chatHistory, setChatHistory] = useState([]);
|
|
4314
4426
|
const [step, setStep] = useState("safety");
|
|
4315
4427
|
const [pendingAction, setPendingAction] = useState(null);
|
|
4316
|
-
const [
|
|
4317
|
-
const [
|
|
4428
|
+
const [activeFiles, setActiveFiles] = useState([]);
|
|
4429
|
+
const [agentStatus, setAgentStatus] = useState("IDLE");
|
|
4318
4430
|
useEffect(() => {
|
|
4319
4431
|
const handleEvent = (event) => {
|
|
4320
4432
|
if (event.type === "handoff") {
|
|
4321
|
-
|
|
4433
|
+
setAgentStatus(event.role.toUpperCase());
|
|
4322
4434
|
}
|
|
4323
|
-
if (event.type === "
|
|
4324
|
-
|
|
4435
|
+
if (event.type === "thought") {
|
|
4436
|
+
if (!event.message.startsWith("Analyzing")) {
|
|
4437
|
+
setChatHistory((prev) => [...prev, { role: "system", text: `[${event.agentName}] ${event.message}` }]);
|
|
4438
|
+
}
|
|
4325
4439
|
}
|
|
4326
|
-
if (event.message.includes("Created:")
|
|
4327
|
-
|
|
4440
|
+
if (event.message.includes("Created:")) {
|
|
4441
|
+
const filename = event.message.split("Created:")[1].trim();
|
|
4442
|
+
setActiveFiles((prev) => [filename, ...prev].slice(0, 5));
|
|
4328
4443
|
}
|
|
4329
4444
|
};
|
|
4330
4445
|
agentEventBus.on("agent_event", handleEvent);
|
|
@@ -4339,13 +4454,12 @@ var Dashboard = () => {
|
|
|
4339
4454
|
const isUnsafe = cwd === home || cwd === root;
|
|
4340
4455
|
if (isUnsafe) {
|
|
4341
4456
|
setChatHistory([
|
|
4342
|
-
{ role: "system", text: `\u26A0\uFE0F
|
|
4343
|
-
{ role: "ai", text: "
|
|
4457
|
+
{ role: "system", text: `\u26A0\uFE0F Safety Check: Running in ${cwd}` },
|
|
4458
|
+
{ role: "ai", text: "This directory is too broad. Should I create a new project folder? (yes/no)" }
|
|
4344
4459
|
]);
|
|
4345
4460
|
setPendingAction("safety_confirm");
|
|
4346
4461
|
} else {
|
|
4347
4462
|
setStep("prompt");
|
|
4348
|
-
setChatHistory([{ role: "ai", text: "Safety check passed. What are we building today?" }]);
|
|
4349
4463
|
}
|
|
4350
4464
|
}
|
|
4351
4465
|
}, []);
|
|
@@ -4354,13 +4468,12 @@ var Dashboard = () => {
|
|
|
4354
4468
|
setChatHistory((prev) => [...prev, { role: "user", text: cmd }]);
|
|
4355
4469
|
if (step === "safety" && pendingAction === "safety_confirm") {
|
|
4356
4470
|
if (cmd.toLowerCase().startsWith("y")) {
|
|
4357
|
-
setChatHistory((prev) => [...prev, { role: "ai", text: "
|
|
4471
|
+
setChatHistory((prev) => [...prev, { role: "ai", text: "Name your project:" }]);
|
|
4358
4472
|
setPendingAction("create_folder");
|
|
4359
4473
|
} else {
|
|
4360
|
-
setChatHistory((prev) => [...prev, { role: "ai", text: "
|
|
4474
|
+
setChatHistory((prev) => [...prev, { role: "ai", text: "Proceeding in current directory." }]);
|
|
4361
4475
|
setStep("prompt");
|
|
4362
4476
|
setPendingAction(null);
|
|
4363
|
-
setTimeout(() => setChatHistory((prev) => [...prev, { role: "ai", text: "What are we building today?" }]), 500);
|
|
4364
4477
|
}
|
|
4365
4478
|
return;
|
|
4366
4479
|
}
|
|
@@ -4370,20 +4483,17 @@ var Dashboard = () => {
|
|
|
4370
4483
|
if (!fs7.existsSync(newPath)) fs7.mkdirSync(newPath);
|
|
4371
4484
|
process.chdir(newPath);
|
|
4372
4485
|
setCwd(newPath);
|
|
4373
|
-
setLogs((prev) => [...prev, `Switched directory to ${newPath}`]);
|
|
4374
4486
|
setChatHistory((prev) => [...prev, { role: "system", text: `\u{1F4C2} Switched to ${newPath}` }]);
|
|
4375
4487
|
setStep("prompt");
|
|
4376
4488
|
setPendingAction(null);
|
|
4377
|
-
setTimeout(() => setChatHistory((prev) => [...prev, { role: "ai", text: "What are we building today?" }]), 500);
|
|
4378
4489
|
} catch (e) {
|
|
4379
|
-
setChatHistory((prev) => [...prev, { role: "system", text: `Error
|
|
4490
|
+
setChatHistory((prev) => [...prev, { role: "system", text: `Error: ${e}` }]);
|
|
4380
4491
|
}
|
|
4381
4492
|
return;
|
|
4382
4493
|
}
|
|
4383
4494
|
if (step === "prompt") {
|
|
4384
|
-
setChatHistory((prev) => [...prev, { role: "ai", text: "Analyzing requirements..." }]);
|
|
4385
4495
|
setStep("active");
|
|
4386
|
-
|
|
4496
|
+
setAgentStatus("MANAGER");
|
|
4387
4497
|
const activeConfig = getActiveProvider();
|
|
4388
4498
|
if (!activeConfig) {
|
|
4389
4499
|
setChatHistory((prev) => [...prev, { role: "system", text: '\u274C No API key found. Run "agdi auth" first.' }]);
|
|
@@ -4396,51 +4506,31 @@ var Dashboard = () => {
|
|
|
4396
4506
|
runSquadCommand(cmd, llm, {
|
|
4397
4507
|
output: cwd,
|
|
4398
4508
|
verbose: false,
|
|
4399
|
-
// We handle logs via event bus now
|
|
4400
4509
|
deploy: false
|
|
4401
4510
|
}).then(() => {
|
|
4402
|
-
|
|
4403
|
-
setChatHistory((prev) => [...prev, { role: "ai", text: "
|
|
4511
|
+
setAgentStatus("IDLE");
|
|
4512
|
+
setChatHistory((prev) => [...prev, { role: "ai", text: "Task completed." }]);
|
|
4404
4513
|
}).catch((err) => {
|
|
4405
|
-
|
|
4406
|
-
setChatHistory((prev) => [...prev, { role: "system", text:
|
|
4514
|
+
setAgentStatus("ERROR");
|
|
4515
|
+
setChatHistory((prev) => [...prev, { role: "system", text: `Error: ${err.message}` }]);
|
|
4407
4516
|
});
|
|
4408
4517
|
}
|
|
4409
4518
|
};
|
|
4410
|
-
|
|
4411
|
-
|
|
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
|
-
] }),
|
|
4519
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", height: 35, width: 120, children: [
|
|
4520
|
+
/* @__PURE__ */ jsx(Header, {}),
|
|
4439
4521
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "row", flexGrow: 1, children: [
|
|
4440
|
-
/* @__PURE__ */ jsx(
|
|
4441
|
-
/* @__PURE__ */ jsx(
|
|
4522
|
+
/* @__PURE__ */ jsx(Sidebar, { history: ["New session - " + (/* @__PURE__ */ new Date()).toLocaleDateString()] }),
|
|
4523
|
+
/* @__PURE__ */ jsx(
|
|
4524
|
+
ChatArea,
|
|
4525
|
+
{
|
|
4526
|
+
history: chatHistory,
|
|
4527
|
+
onSend: handleCommand,
|
|
4528
|
+
placeholder: step === "prompt" ? "Ask Agdi..." : "Reply..."
|
|
4529
|
+
}
|
|
4530
|
+
),
|
|
4531
|
+
/* @__PURE__ */ jsx(ContextPanel, { files: activeFiles, agentStatus })
|
|
4442
4532
|
] }),
|
|
4443
|
-
/* @__PURE__ */ jsx(
|
|
4533
|
+
/* @__PURE__ */ jsx(Footer, { status: agentStatus })
|
|
4444
4534
|
] });
|
|
4445
4535
|
};
|
|
4446
4536
|
var App = () => {
|
|
@@ -4465,7 +4555,7 @@ ${chalk14.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
|
|
|
4465
4555
|
${chalk14.cyan(` /____/ `)}
|
|
4466
4556
|
`;
|
|
4467
4557
|
var program = new Command();
|
|
4468
|
-
program.name("agdi").description(chalk14.cyan("\u{1F9B8} The Autonomous AI Employee")).version("3.3.
|
|
4558
|
+
program.name("agdi").description(chalk14.cyan("\u{1F9B8} The Autonomous AI Employee")).version("3.3.4").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)");
|
|
4469
4559
|
program.hook("preAction", (thisCommand) => {
|
|
4470
4560
|
const opts = thisCommand.opts();
|
|
4471
4561
|
if (opts.yes) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agdi",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.5",
|
|
4
4
|
"description": "AI-powered app generator - build full-stack apps from natural language in your terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -90,4 +90,4 @@
|
|
|
90
90
|
"ts-node": "^10.9.2",
|
|
91
91
|
"uuid": "^13.0.0"
|
|
92
92
|
}
|
|
93
|
-
}
|
|
93
|
+
}
|
package/dist/chunk-AEWEBMJY.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
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
|
-
};
|