agdi 2.11.0 → 2.11.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/dist/chunk-EAQYK3U2.js +41 -0
- package/dist/{chunk-S45VXJEO.js → chunk-OPFFFAQC.js} +19 -1
- package/dist/chunk-OXDKL57B.js +9748 -0
- package/dist/chunk-SQLXP7LT.js +4792 -0
- package/dist/{chunk-M2FF7ETI.js → chunk-UN5WZ5PG.js} +9 -5
- package/dist/{config-3NUXIWMF.js → config-LBIRRMSE.js} +3 -3
- package/dist/config-U2UXLNRN.js +13 -0
- package/dist/dist-4NXQ5YFU.js +1244 -0
- package/dist/index.js +501 -272
- package/dist/lib-CAJYQA32.js +5 -0
- package/dist/multipart-parser-DV373IRF.js +371 -0
- package/dist/node-N4X4IEWV.js +31333 -0
- package/dist/{rag-QRHMEDK6.js → rag-Z66L77H2.js} +1 -1
- package/dist/src-T5RRS2HN.js +1408 -0
- package/dist/{telemetry-service-43MELMA3.js → telemetry-service-D4P7B4B4.js} +8 -7
- package/package.json +42 -76
- package/bin/agdi.js +0 -7
- package/dist/chunk-3RG5ZIWI.js +0 -10
package/dist/index.js
CHANGED
|
@@ -3,18 +3,22 @@ import {
|
|
|
3
3
|
indexProject,
|
|
4
4
|
searchCodebase
|
|
5
5
|
} from "./chunk-NP7LCL7Q.js";
|
|
6
|
+
import {
|
|
7
|
+
require_lib
|
|
8
|
+
} from "./chunk-OXDKL57B.js";
|
|
6
9
|
import {
|
|
7
10
|
loadConfig,
|
|
8
11
|
saveConfig
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-OPFFFAQC.js";
|
|
10
13
|
import {
|
|
11
|
-
__require
|
|
12
|
-
|
|
14
|
+
__require,
|
|
15
|
+
__toESM
|
|
16
|
+
} from "./chunk-EAQYK3U2.js";
|
|
13
17
|
|
|
14
18
|
// src/index.ts
|
|
15
19
|
import { Command } from "commander";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
20
|
+
import chalk19 from "chalk";
|
|
21
|
+
import ora6 from "ora";
|
|
18
22
|
|
|
19
23
|
// src/core/llm/index.ts
|
|
20
24
|
var PuterProvider = class {
|
|
@@ -23,6 +27,7 @@ var PuterProvider = class {
|
|
|
23
27
|
this.model = config.model || "gpt-4.1-nano";
|
|
24
28
|
}
|
|
25
29
|
async generate(prompt, systemPrompt) {
|
|
30
|
+
var _a, _b, _c, _d;
|
|
26
31
|
const response = await fetch("https://api.puter.com/ai/chat", {
|
|
27
32
|
method: "POST",
|
|
28
33
|
headers: {
|
|
@@ -43,13 +48,13 @@ var PuterProvider = class {
|
|
|
43
48
|
let text = "";
|
|
44
49
|
if (typeof data === "string") {
|
|
45
50
|
text = data;
|
|
46
|
-
} else if (data.message
|
|
51
|
+
} else if ((_a = data.message) == null ? void 0 : _a.content) {
|
|
47
52
|
if (Array.isArray(data.message.content)) {
|
|
48
53
|
text = data.message.content.map((c) => c.text || "").join("");
|
|
49
54
|
} else {
|
|
50
55
|
text = data.message.content;
|
|
51
56
|
}
|
|
52
|
-
} else if (data.choices
|
|
57
|
+
} else if ((_d = (_c = (_b = data.choices) == null ? void 0 : _b[0]) == null ? void 0 : _c.message) == null ? void 0 : _d.content) {
|
|
53
58
|
text = data.choices[0].message.content;
|
|
54
59
|
}
|
|
55
60
|
return {
|
|
@@ -58,6 +63,7 @@ var PuterProvider = class {
|
|
|
58
63
|
};
|
|
59
64
|
}
|
|
60
65
|
async chat(messages) {
|
|
66
|
+
var _a, _b, _c, _d;
|
|
61
67
|
const response = await fetch("https://api.puter.com/ai/chat", {
|
|
62
68
|
method: "POST",
|
|
63
69
|
headers: {
|
|
@@ -75,13 +81,13 @@ var PuterProvider = class {
|
|
|
75
81
|
let text = "";
|
|
76
82
|
if (typeof data === "string") {
|
|
77
83
|
text = data;
|
|
78
|
-
} else if (data.message
|
|
84
|
+
} else if ((_a = data.message) == null ? void 0 : _a.content) {
|
|
79
85
|
if (Array.isArray(data.message.content)) {
|
|
80
86
|
text = data.message.content.map((c) => c.text || "").join("");
|
|
81
87
|
} else {
|
|
82
88
|
text = data.message.content;
|
|
83
89
|
}
|
|
84
|
-
} else if (data.choices
|
|
90
|
+
} else if ((_d = (_c = (_b = data.choices) == null ? void 0 : _b[0]) == null ? void 0 : _c.message) == null ? void 0 : _d.content) {
|
|
85
91
|
text = data.choices[0].message.content;
|
|
86
92
|
}
|
|
87
93
|
return {
|
|
@@ -96,7 +102,8 @@ var GeminiProvider = class {
|
|
|
96
102
|
this.config = config;
|
|
97
103
|
}
|
|
98
104
|
async generate(prompt, systemPrompt) {
|
|
99
|
-
|
|
105
|
+
var _a, _b, _c, _d, _e;
|
|
106
|
+
const { GoogleGenAI } = await import("./node-N4X4IEWV.js");
|
|
100
107
|
const ai = new GoogleGenAI({ apiKey: this.config.apiKey });
|
|
101
108
|
const contents = [];
|
|
102
109
|
if (systemPrompt) {
|
|
@@ -108,14 +115,15 @@ var GeminiProvider = class {
|
|
|
108
115
|
model: this.config.model || "gemini-2.5-flash",
|
|
109
116
|
contents
|
|
110
117
|
});
|
|
111
|
-
const text = response.candidates
|
|
118
|
+
const text = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
|
|
112
119
|
return {
|
|
113
120
|
text,
|
|
114
121
|
usage: void 0
|
|
115
122
|
};
|
|
116
123
|
}
|
|
117
124
|
async chat(messages) {
|
|
118
|
-
|
|
125
|
+
var _a, _b, _c, _d, _e;
|
|
126
|
+
const { GoogleGenAI } = await import("./node-N4X4IEWV.js");
|
|
119
127
|
const ai = new GoogleGenAI({ apiKey: this.config.apiKey });
|
|
120
128
|
const contents = messages.map((m) => {
|
|
121
129
|
if (m.role === "system") {
|
|
@@ -130,7 +138,7 @@ var GeminiProvider = class {
|
|
|
130
138
|
model: this.config.model || "gemini-2.5-flash",
|
|
131
139
|
contents
|
|
132
140
|
});
|
|
133
|
-
const text = response.candidates
|
|
141
|
+
const text = ((_e = (_d = (_c = (_b = (_a = response.candidates) == null ? void 0 : _a[0]) == null ? void 0 : _b.content) == null ? void 0 : _c.parts) == null ? void 0 : _d[0]) == null ? void 0 : _e.text) || "";
|
|
134
142
|
return {
|
|
135
143
|
text,
|
|
136
144
|
usage: void 0
|
|
@@ -143,6 +151,7 @@ var OpenRouterProvider = class {
|
|
|
143
151
|
this.config = config;
|
|
144
152
|
}
|
|
145
153
|
async generate(prompt, systemPrompt) {
|
|
154
|
+
var _a, _b, _c;
|
|
146
155
|
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
|
147
156
|
method: "POST",
|
|
148
157
|
headers: {
|
|
@@ -165,7 +174,7 @@ var OpenRouterProvider = class {
|
|
|
165
174
|
}
|
|
166
175
|
const data = await response.json();
|
|
167
176
|
return {
|
|
168
|
-
text: data.choices
|
|
177
|
+
text: ((_c = (_b = (_a = data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) || "",
|
|
169
178
|
usage: data.usage ? {
|
|
170
179
|
inputTokens: data.usage.prompt_tokens,
|
|
171
180
|
outputTokens: data.usage.completion_tokens
|
|
@@ -173,6 +182,7 @@ var OpenRouterProvider = class {
|
|
|
173
182
|
};
|
|
174
183
|
}
|
|
175
184
|
async chat(messages) {
|
|
185
|
+
var _a, _b, _c;
|
|
176
186
|
const response = await fetch("https://openrouter.ai/api/v1/chat/completions", {
|
|
177
187
|
method: "POST",
|
|
178
188
|
headers: {
|
|
@@ -192,7 +202,7 @@ var OpenRouterProvider = class {
|
|
|
192
202
|
}
|
|
193
203
|
const data = await response.json();
|
|
194
204
|
return {
|
|
195
|
-
text: data.choices
|
|
205
|
+
text: ((_c = (_b = (_a = data.choices) == null ? void 0 : _a[0]) == null ? void 0 : _b.message) == null ? void 0 : _c.content) || "",
|
|
196
206
|
usage: data.usage ? {
|
|
197
207
|
inputTokens: data.usage.prompt_tokens,
|
|
198
208
|
outputTokens: data.usage.completion_tokens
|
|
@@ -291,7 +301,7 @@ var ProjectManager = class {
|
|
|
291
301
|
};
|
|
292
302
|
|
|
293
303
|
// src/core/io/index.ts
|
|
294
|
-
|
|
304
|
+
var import_jszip = __toESM(require_lib(), 1);
|
|
295
305
|
|
|
296
306
|
// src/utils/ui.ts
|
|
297
307
|
import chalk from "chalk";
|
|
@@ -405,10 +415,11 @@ var GracefulExitError = class extends Error {
|
|
|
405
415
|
}
|
|
406
416
|
};
|
|
407
417
|
function safeExit(code = 0) {
|
|
418
|
+
var _a, _b;
|
|
408
419
|
if (activeReadlineInterface) {
|
|
409
420
|
try {
|
|
410
|
-
activeReadlineInterface.close
|
|
411
|
-
activeReadlineInterface.destroy
|
|
421
|
+
(_a = activeReadlineInterface.close) == null ? void 0 : _a.call(activeReadlineInterface);
|
|
422
|
+
(_b = activeReadlineInterface.destroy) == null ? void 0 : _b.call(activeReadlineInterface);
|
|
412
423
|
} catch {
|
|
413
424
|
}
|
|
414
425
|
activeReadlineInterface = null;
|
|
@@ -423,6 +434,11 @@ async function smartConfirm(message, defaultValue = false) {
|
|
|
423
434
|
console.log(chalk.gray(` [Auto-approved: ${message}]`));
|
|
424
435
|
return true;
|
|
425
436
|
}
|
|
437
|
+
const config = loadConfig();
|
|
438
|
+
if (config.autonomyMode) {
|
|
439
|
+
console.log(chalk.magenta(` [Autonomy] Auto-approved: ${message}`));
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
426
442
|
if (!process.stdout.isTTY) {
|
|
427
443
|
console.warn(chalk.yellow("\u26A0\uFE0F Non-interactive session detected. Use --yes to approve actions."));
|
|
428
444
|
return false;
|
|
@@ -431,8 +447,9 @@ async function smartConfirm(message, defaultValue = false) {
|
|
|
431
447
|
return confirm4({ message, default: defaultValue });
|
|
432
448
|
}
|
|
433
449
|
async function smartSelect(message, choices, defaultValue) {
|
|
450
|
+
var _a;
|
|
434
451
|
if (!process.stdout.isTTY || flags.headless) {
|
|
435
|
-
const result = defaultValue || choices[0]
|
|
452
|
+
const result = defaultValue || ((_a = choices[0]) == null ? void 0 : _a.value);
|
|
436
453
|
if (result) {
|
|
437
454
|
console.log(chalk.gray(` [Auto-selected: ${result}]`));
|
|
438
455
|
}
|
|
@@ -539,17 +556,17 @@ Return ONLY the file content, no markdown code blocks.`;
|
|
|
539
556
|
};
|
|
540
557
|
}
|
|
541
558
|
async function generateApp(prompt, llm, onProgress) {
|
|
542
|
-
onProgress
|
|
559
|
+
onProgress == null ? void 0 : onProgress("Planning app architecture...");
|
|
543
560
|
const plan = await generatePlan(prompt, llm);
|
|
544
|
-
onProgress
|
|
561
|
+
onProgress == null ? void 0 : onProgress("Generating files...");
|
|
545
562
|
const files = [];
|
|
546
563
|
for (const fileSpec of plan.files) {
|
|
547
|
-
onProgress
|
|
564
|
+
onProgress == null ? void 0 : onProgress(`Creating ${fileSpec.path}...`, fileSpec.path);
|
|
548
565
|
const file = await generateFile(fileSpec.path, fileSpec.description, plan, llm);
|
|
549
566
|
files.push(file);
|
|
550
567
|
}
|
|
551
568
|
if (!ui.flags.minimal) {
|
|
552
|
-
onProgress
|
|
569
|
+
onProgress == null ? void 0 : onProgress("Creating package.json...", "package.json");
|
|
553
570
|
files.push({
|
|
554
571
|
path: "package.json",
|
|
555
572
|
content: JSON.stringify({
|
|
@@ -1399,11 +1416,11 @@ import { select as select2, password as password2 } from "@inquirer/prompts";
|
|
|
1399
1416
|
import chalk7 from "chalk";
|
|
1400
1417
|
var PROVIDER_MODELS = {
|
|
1401
1418
|
gemini: [
|
|
1402
|
-
{ name: "Gemini
|
|
1403
|
-
{ name: "Gemini
|
|
1404
|
-
{ name: "Gemini
|
|
1405
|
-
{ name: "Gemini
|
|
1406
|
-
{ name: "Gemini
|
|
1419
|
+
{ name: "Gemini 2.5 Pro (Most Capable)", value: "gemini-2.5-pro" },
|
|
1420
|
+
{ name: "Gemini 2.5 Flash (Recommended)", value: "gemini-2.5-flash" },
|
|
1421
|
+
{ name: "Gemini 2.5 Flash-Lite (Fast & Cheap)", value: "gemini-2.5-flash-lite" },
|
|
1422
|
+
{ name: "Gemini 3 Pro Preview (Latest)", value: "gemini-3-pro-preview" },
|
|
1423
|
+
{ name: "Gemini 3 Flash Preview", value: "gemini-3-flash-preview" },
|
|
1407
1424
|
{ name: "Gemini 2.0 Flash", value: "gemini-2.0-flash" }
|
|
1408
1425
|
],
|
|
1409
1426
|
openrouter: [
|
|
@@ -1456,13 +1473,19 @@ var PROVIDER_MODELS = {
|
|
|
1456
1473
|
{ name: "Grok 3 (Latest)", value: "grok-3" },
|
|
1457
1474
|
{ name: "Grok 2", value: "grok-2" },
|
|
1458
1475
|
{ name: "Grok 2 Mini", value: "grok-2-mini" }
|
|
1476
|
+
],
|
|
1477
|
+
ollama: [
|
|
1478
|
+
{ name: "Llama 3 (Local)", value: "llama3" },
|
|
1479
|
+
{ name: "Mistral (Local)", value: "mistral" },
|
|
1480
|
+
{ name: "Gemma (Local)", value: "gemma" }
|
|
1459
1481
|
]
|
|
1460
1482
|
};
|
|
1461
1483
|
function needsOnboarding() {
|
|
1462
1484
|
const config = loadConfig();
|
|
1463
|
-
return !(config.geminiApiKey || config.openrouterApiKey || config.openaiApiKey || config.anthropicApiKey || config.deepseekApiKey || config.xaiApiKey);
|
|
1485
|
+
return !(config.geminiApiKey || config.openrouterApiKey || config.openaiApiKey || config.anthropicApiKey || config.deepseekApiKey || config.xaiApiKey || config.ollamaUrl);
|
|
1464
1486
|
}
|
|
1465
1487
|
function getActiveProvider() {
|
|
1488
|
+
var _a, _b, _c, _d;
|
|
1466
1489
|
const config = loadConfig();
|
|
1467
1490
|
const provider = config.defaultProvider;
|
|
1468
1491
|
const keyMap = {
|
|
@@ -1471,14 +1494,16 @@ function getActiveProvider() {
|
|
|
1471
1494
|
openai: config.openaiApiKey,
|
|
1472
1495
|
anthropic: config.anthropicApiKey,
|
|
1473
1496
|
deepseek: config.deepseekApiKey,
|
|
1474
|
-
xai: config.xaiApiKey
|
|
1497
|
+
xai: config.xaiApiKey,
|
|
1498
|
+
ollama: "local"
|
|
1499
|
+
// Ollama doesn't typically need a key for local, but we return a placeholder
|
|
1475
1500
|
};
|
|
1476
1501
|
const apiKey = keyMap[provider];
|
|
1477
1502
|
if (apiKey) {
|
|
1478
1503
|
return {
|
|
1479
1504
|
provider,
|
|
1480
1505
|
apiKey,
|
|
1481
|
-
model: config.defaultModel || PROVIDER_MODELS[provider]
|
|
1506
|
+
model: config.defaultModel || ((_b = (_a = PROVIDER_MODELS[provider]) == null ? void 0 : _a[0]) == null ? void 0 : _b.value) || "gemini-3-flash-preview"
|
|
1482
1507
|
};
|
|
1483
1508
|
}
|
|
1484
1509
|
for (const [p, key] of Object.entries(keyMap)) {
|
|
@@ -1486,95 +1511,150 @@ function getActiveProvider() {
|
|
|
1486
1511
|
return {
|
|
1487
1512
|
provider: p,
|
|
1488
1513
|
apiKey: key,
|
|
1489
|
-
model: config.defaultModel || PROVIDER_MODELS[p]
|
|
1514
|
+
model: config.defaultModel || ((_d = (_c = PROVIDER_MODELS[p]) == null ? void 0 : _c[0]) == null ? void 0 : _d.value) || "gemini-3-flash-preview"
|
|
1490
1515
|
};
|
|
1491
1516
|
}
|
|
1492
1517
|
}
|
|
1493
1518
|
return null;
|
|
1494
1519
|
}
|
|
1495
1520
|
async function runOnboarding() {
|
|
1521
|
+
var _a;
|
|
1496
1522
|
console.log(chalk7.cyan.bold("\n\u{1F680} Welcome to Agdi!\n"));
|
|
1497
|
-
console.log(chalk7.gray("Let's set up your AI
|
|
1523
|
+
console.log(chalk7.gray("Let's set up your AI environment.\n"));
|
|
1498
1524
|
const config = loadConfig();
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1525
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
1526
|
+
let addingProviders = true;
|
|
1527
|
+
let firstProvider = true;
|
|
1528
|
+
while (addingProviders) {
|
|
1529
|
+
if (!firstProvider) {
|
|
1530
|
+
const addAnother = await confirm4({
|
|
1531
|
+
message: "Do you want to add another AI provider?",
|
|
1532
|
+
default: false
|
|
1533
|
+
});
|
|
1534
|
+
if (!addAnother) {
|
|
1535
|
+
addingProviders = false;
|
|
1536
|
+
break;
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
console.log(chalk7.white.bold(firstProvider ? "\nStep 1: Select your AI provider\n" : "\nSelect additional provider\n"));
|
|
1540
|
+
const provider = await select2({
|
|
1541
|
+
message: "Which AI provider would you like to use?",
|
|
1542
|
+
choices: [
|
|
1543
|
+
{ name: "Google Gemini (Free tier available)", value: "gemini" },
|
|
1544
|
+
{ name: "OpenRouter (Best for variety)", value: "openrouter" },
|
|
1545
|
+
{ name: "Ollama (Local / Offline)", value: "ollama" },
|
|
1546
|
+
{ name: "OpenAI (GPT-4o)", value: "openai" },
|
|
1547
|
+
{ name: "Anthropic (Claude)", value: "anthropic" },
|
|
1548
|
+
{ name: "DeepSeek", value: "deepseek" },
|
|
1549
|
+
{ name: "xAI (Grok)", value: "xai" }
|
|
1550
|
+
]
|
|
1551
|
+
});
|
|
1552
|
+
if (provider === "ollama") {
|
|
1553
|
+
console.log(chalk7.gray("\nAssuming Ollama is running at http://localhost:11434"));
|
|
1554
|
+
config.ollamaUrl = "http://localhost:11434";
|
|
1555
|
+
} else {
|
|
1556
|
+
console.log(chalk7.white.bold(`
|
|
1557
|
+
Enter API key for ${provider}
|
|
1521
1558
|
`));
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1559
|
+
const keyUrls = {
|
|
1560
|
+
gemini: "https://aistudio.google.com/apikey",
|
|
1561
|
+
openrouter: "https://openrouter.ai/keys",
|
|
1562
|
+
openai: "https://platform.openai.com/api-keys",
|
|
1563
|
+
anthropic: "https://console.anthropic.com/",
|
|
1564
|
+
deepseek: "https://platform.deepseek.com/",
|
|
1565
|
+
xai: "https://console.x.ai/"
|
|
1566
|
+
};
|
|
1567
|
+
if (keyUrls[provider]) {
|
|
1568
|
+
console.log(chalk7.gray(`Get your key at: ${chalk7.cyan(keyUrls[provider])}
|
|
1569
|
+
`));
|
|
1570
|
+
}
|
|
1571
|
+
const apiKey = await password2({
|
|
1572
|
+
message: `Enter your ${provider} API key:`,
|
|
1573
|
+
mask: "*"
|
|
1574
|
+
});
|
|
1575
|
+
switch (provider) {
|
|
1576
|
+
case "gemini":
|
|
1577
|
+
config.geminiApiKey = apiKey;
|
|
1578
|
+
break;
|
|
1579
|
+
case "openrouter":
|
|
1580
|
+
config.openrouterApiKey = apiKey;
|
|
1581
|
+
break;
|
|
1582
|
+
case "openai":
|
|
1583
|
+
config.openaiApiKey = apiKey;
|
|
1584
|
+
break;
|
|
1585
|
+
case "anthropic":
|
|
1586
|
+
config.anthropicApiKey = apiKey;
|
|
1587
|
+
break;
|
|
1588
|
+
case "deepseek":
|
|
1589
|
+
config.deepseekApiKey = apiKey;
|
|
1590
|
+
break;
|
|
1591
|
+
case "xai":
|
|
1592
|
+
config.xaiApiKey = apiKey;
|
|
1593
|
+
break;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
if (firstProvider) {
|
|
1597
|
+
config.defaultProvider = provider;
|
|
1598
|
+
const models = PROVIDER_MODELS[provider] || PROVIDER_MODELS.gemini;
|
|
1599
|
+
const model = await select2({
|
|
1600
|
+
message: `Select default model for ${provider}:`,
|
|
1601
|
+
choices: models
|
|
1602
|
+
});
|
|
1603
|
+
config.defaultModel = model;
|
|
1604
|
+
}
|
|
1605
|
+
firstProvider = false;
|
|
1545
1606
|
}
|
|
1546
|
-
config.defaultProvider = provider;
|
|
1547
|
-
console.log(chalk7.white.bold("\nStep 3/3: Choose your default model\n"));
|
|
1548
|
-
const models = PROVIDER_MODELS[provider] || PROVIDER_MODELS.gemini;
|
|
1549
|
-
const model = await select2({
|
|
1550
|
-
message: "Select your default model:",
|
|
1551
|
-
choices: models
|
|
1552
|
-
});
|
|
1553
|
-
config.defaultModel = model;
|
|
1554
1607
|
saveConfig(config);
|
|
1555
|
-
console.log(chalk7.white.bold("\
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
1560
|
-
const enableTelemetry = await confirm4({
|
|
1561
|
-
message: "Enable crash reporting? (helps us fix bugs)",
|
|
1562
|
-
default: false
|
|
1608
|
+
console.log(chalk7.white.bold("\nStep 2: Deployment Configuration\n"));
|
|
1609
|
+
const setupDeployment = await confirm4({
|
|
1610
|
+
message: 'Do you want to configure a deployment provider now? (Recommended for "Live URL")',
|
|
1611
|
+
default: true
|
|
1563
1612
|
});
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1613
|
+
if (setupDeployment) {
|
|
1614
|
+
const deployProvider = await select2({
|
|
1615
|
+
message: "Which Deployment provider do you want to use?",
|
|
1616
|
+
choices: [
|
|
1617
|
+
{ name: "Vercel (Recommended)", value: "vercel" },
|
|
1618
|
+
{ name: "Netlify", value: "netlify" }
|
|
1619
|
+
]
|
|
1620
|
+
});
|
|
1621
|
+
config.deploymentProvider = deployProvider;
|
|
1622
|
+
if (deployProvider === "vercel") {
|
|
1623
|
+
console.log(chalk7.gray("\nCreate a Vercel Token at: https://vercel.com/account/tokens"));
|
|
1624
|
+
const token = await password2({
|
|
1625
|
+
message: "Enter your Vercel Token:",
|
|
1626
|
+
mask: "*"
|
|
1627
|
+
});
|
|
1628
|
+
config.vercelToken = token;
|
|
1629
|
+
} else {
|
|
1630
|
+
console.log(chalk7.gray("\nCreate a Netlify Token at: https://app.netlify.com/user/applications"));
|
|
1631
|
+
const token = await password2({
|
|
1632
|
+
message: "Enter your Netlify Access Token:",
|
|
1633
|
+
mask: "*"
|
|
1634
|
+
});
|
|
1635
|
+
config.netlifyToken = token;
|
|
1636
|
+
}
|
|
1637
|
+
saveConfig(config);
|
|
1638
|
+
}
|
|
1639
|
+
if (((_a = config.telemetry) == null ? void 0 : _a.consentAsked) !== true) {
|
|
1640
|
+
console.log(chalk7.white.bold("\n\u{1F527} Help us improve?\n"));
|
|
1641
|
+
const enableTelemetry = await confirm4({
|
|
1642
|
+
message: "Enable anonymous error reporting? (Helps fix bugs)",
|
|
1643
|
+
default: false
|
|
1644
|
+
});
|
|
1645
|
+
const { setTelemetryConsent, markConsentAsked } = await import("./config-LBIRRMSE.js");
|
|
1646
|
+
if (enableTelemetry) {
|
|
1647
|
+
setTelemetryConsent(true);
|
|
1648
|
+
console.log(chalk7.green(" Thanks! \u2764\uFE0F"));
|
|
1649
|
+
} else {
|
|
1650
|
+
markConsentAsked();
|
|
1651
|
+
console.log(chalk7.gray(" No problem."));
|
|
1652
|
+
}
|
|
1572
1653
|
}
|
|
1573
1654
|
console.log(chalk7.green("\n\u2705 Setup complete!"));
|
|
1574
|
-
console.log(chalk7.gray(`Provider: ${chalk7.cyan(
|
|
1575
|
-
console.log(chalk7.gray(`Model: ${chalk7.cyan(
|
|
1655
|
+
console.log(chalk7.gray(`Default Provider: ${chalk7.cyan(config.defaultProvider)}`));
|
|
1656
|
+
console.log(chalk7.gray(`Default Model: ${chalk7.cyan(config.defaultModel)}
|
|
1576
1657
|
`));
|
|
1577
|
-
return { provider, apiKey, model };
|
|
1578
1658
|
}
|
|
1579
1659
|
async function selectModel() {
|
|
1580
1660
|
const config = loadConfig();
|
|
@@ -1932,13 +2012,14 @@ function truncateOutput(output) {
|
|
|
1932
2012
|
return output.substring(0, MAX_OUTPUT_LENGTH) + `... (truncated, ${output.length} total chars)`;
|
|
1933
2013
|
}
|
|
1934
2014
|
function logEvent(event) {
|
|
2015
|
+
var _a;
|
|
1935
2016
|
ensureLogDir();
|
|
1936
2017
|
const fullEvent = {
|
|
1937
2018
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1938
2019
|
sessionId: getSessionId(),
|
|
1939
2020
|
...event
|
|
1940
2021
|
};
|
|
1941
|
-
if (fullEvent.result
|
|
2022
|
+
if ((_a = fullEvent.result) == null ? void 0 : _a.output) {
|
|
1942
2023
|
fullEvent.result.output = truncateOutput(fullEvent.result.output);
|
|
1943
2024
|
}
|
|
1944
2025
|
try {
|
|
@@ -2262,6 +2343,7 @@ var READ_COMMANDS = {
|
|
|
2262
2343
|
type: [0]
|
|
2263
2344
|
};
|
|
2264
2345
|
function extractPaths(parsed) {
|
|
2346
|
+
var _a, _b;
|
|
2265
2347
|
const paths = [];
|
|
2266
2348
|
const cmd = parsed.command.toLowerCase();
|
|
2267
2349
|
const rawCmd = parsed.rawCommand;
|
|
@@ -2279,9 +2361,9 @@ function extractPaths(parsed) {
|
|
|
2279
2361
|
continue;
|
|
2280
2362
|
}
|
|
2281
2363
|
let operation = "unknown";
|
|
2282
|
-
if (WRITE_COMMANDS[cmd]
|
|
2364
|
+
if ((_a = WRITE_COMMANDS[cmd]) == null ? void 0 : _a.includes(i)) {
|
|
2283
2365
|
operation = "write";
|
|
2284
|
-
} else if (READ_COMMANDS[cmd]
|
|
2366
|
+
} else if ((_b = READ_COMMANDS[cmd]) == null ? void 0 : _b.includes(i)) {
|
|
2285
2367
|
operation = "read";
|
|
2286
2368
|
}
|
|
2287
2369
|
paths.push({
|
|
@@ -2596,10 +2678,11 @@ function getMostRestrictiveTier(tiers) {
|
|
|
2596
2678
|
return Math.max(...tiers, 0);
|
|
2597
2679
|
}
|
|
2598
2680
|
function isHighRiskWrapper(result) {
|
|
2681
|
+
var _a;
|
|
2599
2682
|
if (result.isComplex) {
|
|
2600
2683
|
return true;
|
|
2601
2684
|
}
|
|
2602
|
-
if (result.embeddedScript
|
|
2685
|
+
if ((_a = result.embeddedScript) == null ? void 0 : _a.includes("encodedcommand")) {
|
|
2603
2686
|
return true;
|
|
2604
2687
|
}
|
|
2605
2688
|
return false;
|
|
@@ -2795,6 +2878,7 @@ function checkHardViolations(command) {
|
|
|
2795
2878
|
return violations;
|
|
2796
2879
|
}
|
|
2797
2880
|
function evaluateCommand(command, cwd) {
|
|
2881
|
+
var _a, _b, _c, _d, _e;
|
|
2798
2882
|
const env = getEnvironment();
|
|
2799
2883
|
const effectiveCwd = cwd || env.cwd;
|
|
2800
2884
|
const parsed = parseArgv(command);
|
|
@@ -2831,16 +2915,16 @@ function evaluateCommand(command, cwd) {
|
|
|
2831
2915
|
let reason;
|
|
2832
2916
|
if (hasHardViolation) {
|
|
2833
2917
|
decision = "deny";
|
|
2834
|
-
reason = violations.find((v) => v.severity === "hard")
|
|
2918
|
+
reason = ((_a = violations.find((v) => v.severity === "hard")) == null ? void 0 : _a.message) || "Security violation";
|
|
2835
2919
|
} else if (ruleResult.decision === "forbid") {
|
|
2836
2920
|
decision = "deny";
|
|
2837
|
-
reason = ruleResult.mostRestrictive
|
|
2921
|
+
reason = ((_b = ruleResult.mostRestrictive) == null ? void 0 : _b.description) || "Forbidden by rule";
|
|
2838
2922
|
} else if (hasPromptableViolation) {
|
|
2839
2923
|
decision = "prompt";
|
|
2840
|
-
reason = violations.find((v) => v.severity === "promptable")
|
|
2924
|
+
reason = ((_c = violations.find((v) => v.severity === "promptable")) == null ? void 0 : _c.message) || "Approval required";
|
|
2841
2925
|
} else if (ruleResult.decision === "allow" && riskTier <= 1) {
|
|
2842
2926
|
decision = "allow";
|
|
2843
|
-
reason = ruleResult.mostRestrictive
|
|
2927
|
+
reason = ((_d = ruleResult.mostRestrictive) == null ? void 0 : _d.description) || "Allowed by rule";
|
|
2844
2928
|
} else {
|
|
2845
2929
|
decision = "prompt";
|
|
2846
2930
|
reason = getRiskDescription(riskTier, parsed.argv);
|
|
@@ -2856,7 +2940,7 @@ function evaluateCommand(command, cwd) {
|
|
|
2856
2940
|
domains,
|
|
2857
2941
|
reason,
|
|
2858
2942
|
violations,
|
|
2859
|
-
matchedRuleId: ruleResult.mostRestrictive
|
|
2943
|
+
matchedRuleId: (_e = ruleResult.mostRestrictive) == null ? void 0 : _e.id,
|
|
2860
2944
|
isShellWrapper: wrapperResult.isWrapper,
|
|
2861
2945
|
subCommands: wrapperResult.subCommands
|
|
2862
2946
|
};
|
|
@@ -2878,7 +2962,7 @@ function getRiskDescription(tier, argv) {
|
|
|
2878
2962
|
// src/security/workspace-trust.ts
|
|
2879
2963
|
import { select as select3 } from "@inquirer/prompts";
|
|
2880
2964
|
import chalk9 from "chalk";
|
|
2881
|
-
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
|
|
2965
|
+
import { existsSync as existsSync5, readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, readdirSync } from "fs";
|
|
2882
2966
|
import { join as join3, resolve as resolve3 } from "path";
|
|
2883
2967
|
import { homedir as homedir4 } from "os";
|
|
2884
2968
|
var CONFIG_DIR = join3(homedir4(), ".agdi");
|
|
@@ -2926,27 +3010,65 @@ function trustWorkspace(workspacePath) {
|
|
|
2926
3010
|
}
|
|
2927
3011
|
async function promptWorkspaceTrust(workspacePath) {
|
|
2928
3012
|
if (isWorkspaceTrusted(workspacePath)) {
|
|
2929
|
-
console.log(chalk9.green("\u2713 Workspace is trusted\n"));
|
|
2930
3013
|
return "persistent";
|
|
2931
3014
|
}
|
|
2932
|
-
|
|
2933
|
-
|
|
3015
|
+
const sensitivePaths = [
|
|
3016
|
+
homedir4(),
|
|
3017
|
+
resolve3(homedir4(), "Desktop"),
|
|
3018
|
+
resolve3(homedir4(), "Downloads"),
|
|
3019
|
+
resolve3(homedir4(), "Documents"),
|
|
3020
|
+
resolve3("C:\\Windows"),
|
|
3021
|
+
resolve3("C:\\Program Files")
|
|
3022
|
+
].map((p) => normalizePath(p));
|
|
3023
|
+
const normalizedCurrent = normalizePath(workspacePath);
|
|
3024
|
+
const isSensitive = sensitivePaths.includes(normalizedCurrent);
|
|
3025
|
+
if (isSensitive) {
|
|
3026
|
+
console.log(chalk9.red.bold("\n\u{1F6D1} Security Warning: Sensitive Directory Detected"));
|
|
3027
|
+
console.log(chalk9.yellow(` You are trying to run Agdi in: ${workspacePath}`));
|
|
3028
|
+
console.log(chalk9.gray(" This is a system or personal root folder. We highly recommend running in a subfolder."));
|
|
3029
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
3030
|
+
const proceed = await confirm4({
|
|
3031
|
+
message: "Are you sure you want to open this workspace?",
|
|
3032
|
+
default: false
|
|
3033
|
+
});
|
|
3034
|
+
if (!proceed) {
|
|
3035
|
+
console.log(chalk9.gray("\nGood choice. Exiting.\n"));
|
|
3036
|
+
process.exit(0);
|
|
3037
|
+
}
|
|
3038
|
+
}
|
|
3039
|
+
let isEmpty = false;
|
|
3040
|
+
try {
|
|
3041
|
+
const files = readdirSync(workspacePath);
|
|
3042
|
+
const visibleFiles = files.filter((f) => !f.startsWith("."));
|
|
3043
|
+
isEmpty = visibleFiles.length === 0;
|
|
3044
|
+
} catch {
|
|
3045
|
+
isEmpty = false;
|
|
3046
|
+
}
|
|
3047
|
+
if (isEmpty) {
|
|
3048
|
+
console.log(chalk9.cyan.bold("\n\u{1F195} Workspace status: Not trusted yet"));
|
|
3049
|
+
console.log(chalk9.gray(` ${workspacePath}
|
|
3050
|
+
`));
|
|
3051
|
+
console.log(chalk9.gray("This appears to be a new or empty project."));
|
|
3052
|
+
} else {
|
|
3053
|
+
console.log(chalk9.yellow.bold("\n\u26A0\uFE0F Untrusted Workspace"));
|
|
3054
|
+
console.log(chalk9.gray(` ${workspacePath}
|
|
2934
3055
|
`));
|
|
2935
|
-
|
|
2936
|
-
|
|
3056
|
+
console.log(chalk9.gray("Agdi can run commands in this workspace."));
|
|
3057
|
+
console.log(chalk9.gray("Do you trust the contents of this folder?\n"));
|
|
3058
|
+
}
|
|
2937
3059
|
const choice = await select3({
|
|
2938
|
-
message: "Trust this workspace?",
|
|
3060
|
+
message: isEmpty ? "Initialize this workspace?" : "Trust this workspace?",
|
|
2939
3061
|
choices: [
|
|
2940
|
-
{
|
|
2941
|
-
name: "Trust for this session only",
|
|
2942
|
-
value: "session",
|
|
2943
|
-
description: "Allow commands for this session, ask again next time"
|
|
2944
|
-
},
|
|
2945
3062
|
{
|
|
2946
3063
|
name: "Trust and remember",
|
|
2947
3064
|
value: "persistent",
|
|
2948
3065
|
description: "Always trust this workspace"
|
|
2949
3066
|
},
|
|
3067
|
+
{
|
|
3068
|
+
name: "Trust for this session only",
|
|
3069
|
+
value: "session",
|
|
3070
|
+
description: "Allow commands for this session"
|
|
3071
|
+
},
|
|
2950
3072
|
{
|
|
2951
3073
|
name: "Exit (don't trust)",
|
|
2952
3074
|
value: "exit",
|
|
@@ -2984,6 +3106,7 @@ async function ensureTrusted(workspacePath) {
|
|
|
2984
3106
|
|
|
2985
3107
|
// src/core/image-generator.ts
|
|
2986
3108
|
async function generateImage(prompt, apiKey, options = {}) {
|
|
3109
|
+
var _a;
|
|
2987
3110
|
const { width = 1024, height = 1024, style } = options;
|
|
2988
3111
|
let enhancedPrompt = prompt;
|
|
2989
3112
|
if (style === "tech") {
|
|
@@ -3015,7 +3138,7 @@ async function generateImage(prompt, apiKey, options = {}) {
|
|
|
3015
3138
|
throw new Error(`Image generation failed: ${response.status} - ${error}`);
|
|
3016
3139
|
}
|
|
3017
3140
|
const data = await response.json();
|
|
3018
|
-
const imageData = data.data
|
|
3141
|
+
const imageData = (_a = data.data) == null ? void 0 : _a[0];
|
|
3019
3142
|
if (!imageData) {
|
|
3020
3143
|
throw new Error("No image data returned from API");
|
|
3021
3144
|
}
|
|
@@ -3128,25 +3251,43 @@ async function executeAction(action) {
|
|
|
3128
3251
|
case "exec": {
|
|
3129
3252
|
const cwd = action.cwd ? resolve4(env.workspaceRoot, action.cwd) : env.workspaceRoot;
|
|
3130
3253
|
const command = action.argv.join(" ");
|
|
3254
|
+
const isInstall = command.includes("npm install") || command.includes("pnpm install") || command.includes("yarn install");
|
|
3131
3255
|
return new Promise((resolvePromise) => {
|
|
3256
|
+
var _a, _b;
|
|
3132
3257
|
let output = "";
|
|
3133
3258
|
let error = "";
|
|
3259
|
+
let spinner = null;
|
|
3260
|
+
if (isInstall) {
|
|
3261
|
+
spinner = ui.createSpinner(`Running: ${command}`).start();
|
|
3262
|
+
}
|
|
3134
3263
|
const child = spawn2(action.argv[0], action.argv.slice(1), {
|
|
3135
3264
|
cwd,
|
|
3136
3265
|
shell: true,
|
|
3137
3266
|
stdio: "pipe"
|
|
3138
3267
|
});
|
|
3139
|
-
child.stdout
|
|
3268
|
+
(_a = child.stdout) == null ? void 0 : _a.on("data", (data) => {
|
|
3140
3269
|
const text = data.toString();
|
|
3141
3270
|
output += text;
|
|
3142
|
-
|
|
3271
|
+
if (!isInstall) {
|
|
3272
|
+
process.stdout.write(text);
|
|
3273
|
+
}
|
|
3143
3274
|
});
|
|
3144
|
-
child.stderr
|
|
3275
|
+
(_b = child.stderr) == null ? void 0 : _b.on("data", (data) => {
|
|
3145
3276
|
const text = data.toString();
|
|
3146
3277
|
error += text;
|
|
3147
|
-
|
|
3278
|
+
if (!isInstall) {
|
|
3279
|
+
process.stderr.write(text);
|
|
3280
|
+
}
|
|
3148
3281
|
});
|
|
3149
3282
|
child.on("close", (code) => {
|
|
3283
|
+
if (isInstall) {
|
|
3284
|
+
if (code === 0) {
|
|
3285
|
+
spinner.succeed(`Completed: ${command}`);
|
|
3286
|
+
} else {
|
|
3287
|
+
spinner.fail(`Failed: ${command}`);
|
|
3288
|
+
console.error(chalk10.red(error || output));
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3150
3291
|
resolvePromise({
|
|
3151
3292
|
action,
|
|
3152
3293
|
success: code === 0,
|
|
@@ -3155,6 +3296,9 @@ async function executeAction(action) {
|
|
|
3155
3296
|
});
|
|
3156
3297
|
});
|
|
3157
3298
|
child.on("error", (err) => {
|
|
3299
|
+
if (isInstall) {
|
|
3300
|
+
spinner.fail(`Error: ${command}`);
|
|
3301
|
+
}
|
|
3158
3302
|
resolvePromise({
|
|
3159
3303
|
action,
|
|
3160
3304
|
success: false,
|
|
@@ -3201,6 +3345,7 @@ async function executeAction(action) {
|
|
|
3201
3345
|
}
|
|
3202
3346
|
}
|
|
3203
3347
|
async function executePlan(plan) {
|
|
3348
|
+
var _a;
|
|
3204
3349
|
const env = getEnvironment();
|
|
3205
3350
|
const results = [];
|
|
3206
3351
|
const filesCreated = [];
|
|
@@ -3297,7 +3442,7 @@ Target: ${env.workspaceRoot}`
|
|
|
3297
3442
|
const action = plan.actions[i];
|
|
3298
3443
|
displayActionProgress(action, i, plan.actions.length);
|
|
3299
3444
|
if (ui.flags.dryRun) {
|
|
3300
|
-
console.log(chalk10.yellow(` [DRY RUN] Would execute: ${action.type} ${action.path || action.argv
|
|
3445
|
+
console.log(chalk10.yellow(` [DRY RUN] Would execute: ${action.type} ${action.path || ((_a = action.argv) == null ? void 0 : _a.join(" "))}`));
|
|
3301
3446
|
results.push({ action, success: true, output: "(dry run)" });
|
|
3302
3447
|
continue;
|
|
3303
3448
|
}
|
|
@@ -3356,7 +3501,7 @@ async function parseAndExecutePlan(response) {
|
|
|
3356
3501
|
}
|
|
3357
3502
|
|
|
3358
3503
|
// src/core/context-manager.ts
|
|
3359
|
-
import { readdirSync, readFileSync as readFileSync5, statSync, existsSync as existsSync6 } from "fs";
|
|
3504
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync5, statSync, existsSync as existsSync6 } from "fs";
|
|
3360
3505
|
import { join as join4, basename } from "path";
|
|
3361
3506
|
var IGNORED_DIRS = /* @__PURE__ */ new Set([
|
|
3362
3507
|
"node_modules",
|
|
@@ -3403,7 +3548,7 @@ function buildTree(dir, prefix, lines, depth, maxDepth) {
|
|
|
3403
3548
|
}
|
|
3404
3549
|
let entries;
|
|
3405
3550
|
try {
|
|
3406
|
-
entries =
|
|
3551
|
+
entries = readdirSync2(dir);
|
|
3407
3552
|
} catch {
|
|
3408
3553
|
return;
|
|
3409
3554
|
}
|
|
@@ -3511,6 +3656,7 @@ import { spawnSync } from "child_process";
|
|
|
3511
3656
|
import { existsSync as existsSync7 } from "fs";
|
|
3512
3657
|
import { join as join5 } from "path";
|
|
3513
3658
|
function execGit(args, cwd) {
|
|
3659
|
+
var _a;
|
|
3514
3660
|
const env = getEnvironment();
|
|
3515
3661
|
const workDir = cwd || env.workspaceRoot;
|
|
3516
3662
|
try {
|
|
@@ -3522,7 +3668,7 @@ function execGit(args, cwd) {
|
|
|
3522
3668
|
if (result.error) {
|
|
3523
3669
|
throw result.error;
|
|
3524
3670
|
}
|
|
3525
|
-
return result.stdout
|
|
3671
|
+
return ((_a = result.stdout) == null ? void 0 : _a.trim()) || "";
|
|
3526
3672
|
} catch (error) {
|
|
3527
3673
|
return "";
|
|
3528
3674
|
}
|
|
@@ -3852,11 +3998,12 @@ var ConversationManager = class _ConversationManager {
|
|
|
3852
3998
|
* Save session to disk
|
|
3853
3999
|
*/
|
|
3854
4000
|
save() {
|
|
4001
|
+
var _a;
|
|
3855
4002
|
this.ensureDirectories();
|
|
3856
4003
|
const session = {
|
|
3857
4004
|
id: this.sessionId,
|
|
3858
4005
|
messages: this.messages,
|
|
3859
|
-
createdAt: this.messages[0]
|
|
4006
|
+
createdAt: ((_a = this.messages[0]) == null ? void 0 : _a.timestamp) || Date.now(),
|
|
3860
4007
|
updatedAt: Date.now()
|
|
3861
4008
|
};
|
|
3862
4009
|
const filePath = join6(SESSIONS_DIR, `${this.sessionId}.json`);
|
|
@@ -3887,8 +4034,8 @@ var ConversationManager = class _ConversationManager {
|
|
|
3887
4034
|
if (!existsSync8(SESSIONS_DIR)) {
|
|
3888
4035
|
return [];
|
|
3889
4036
|
}
|
|
3890
|
-
const { readdirSync:
|
|
3891
|
-
const files =
|
|
4037
|
+
const { readdirSync: readdirSync3 } = __require("fs");
|
|
4038
|
+
const files = readdirSync3(SESSIONS_DIR);
|
|
3892
4039
|
return files.filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", "")).sort().reverse();
|
|
3893
4040
|
}
|
|
3894
4041
|
/**
|
|
@@ -4156,11 +4303,11 @@ registerTool({
|
|
|
4156
4303
|
{ name: "path", type: "string", description: "Directory path", required: false, default: "." }
|
|
4157
4304
|
],
|
|
4158
4305
|
execute: async (params) => {
|
|
4159
|
-
const { readdirSync:
|
|
4306
|
+
const { readdirSync: readdirSync3, statSync: statSync3 } = await import("fs");
|
|
4160
4307
|
const { resolve: resolve5, join: join11 } = await import("path");
|
|
4161
4308
|
try {
|
|
4162
4309
|
const dirPath = resolve5(process.cwd(), params.path || ".");
|
|
4163
|
-
const entries =
|
|
4310
|
+
const entries = readdirSync3(dirPath);
|
|
4164
4311
|
const files = [];
|
|
4165
4312
|
const dirs = [];
|
|
4166
4313
|
for (const entry of entries) {
|
|
@@ -4197,7 +4344,7 @@ registerTool({
|
|
|
4197
4344
|
{ name: "limit", type: "number", description: "Max results", required: false, default: 5 }
|
|
4198
4345
|
],
|
|
4199
4346
|
execute: async (params) => {
|
|
4200
|
-
const { searchCodebase: searchCodebase2 } = await import("./rag-
|
|
4347
|
+
const { searchCodebase: searchCodebase2 } = await import("./rag-Z66L77H2.js");
|
|
4201
4348
|
const results = searchCodebase2(
|
|
4202
4349
|
process.cwd(),
|
|
4203
4350
|
params.query,
|
|
@@ -4282,18 +4429,23 @@ function getMemoryStats() {
|
|
|
4282
4429
|
|
|
4283
4430
|
// src/commands/agdi-dev.ts
|
|
4284
4431
|
async function collectMultiLineInput(message) {
|
|
4285
|
-
|
|
4286
|
-
|
|
4432
|
+
let lines = [];
|
|
4433
|
+
let prompt = message;
|
|
4287
4434
|
while (true) {
|
|
4288
|
-
const line = await input5({
|
|
4289
|
-
|
|
4290
|
-
|
|
4435
|
+
const line = await input5({
|
|
4436
|
+
message: prompt,
|
|
4437
|
+
validate: (value) => {
|
|
4438
|
+
if (lines.length === 0 && !value.trim()) return "Please enter a command or prompt";
|
|
4439
|
+
return true;
|
|
4440
|
+
}
|
|
4441
|
+
});
|
|
4442
|
+
if (line.trim().endsWith("\\")) {
|
|
4443
|
+
lines.push(line.trim().slice(0, -1));
|
|
4444
|
+
prompt = chalk12.gray(".. ");
|
|
4291
4445
|
continue;
|
|
4292
4446
|
}
|
|
4293
4447
|
lines.push(line);
|
|
4294
|
-
|
|
4295
|
-
break;
|
|
4296
|
-
}
|
|
4448
|
+
break;
|
|
4297
4449
|
}
|
|
4298
4450
|
return lines.join("\n").trim();
|
|
4299
4451
|
}
|
|
@@ -4924,8 +5076,7 @@ async function runDoctor() {
|
|
|
4924
5076
|
}
|
|
4925
5077
|
|
|
4926
5078
|
// src/commands/squad.ts
|
|
4927
|
-
import
|
|
4928
|
-
import ora5 from "ora";
|
|
5079
|
+
import chalk17 from "chalk";
|
|
4929
5080
|
import { input as input6 } from "@inquirer/prompts";
|
|
4930
5081
|
|
|
4931
5082
|
// src/agents/core/squad-orchestrator.ts
|
|
@@ -5068,6 +5219,7 @@ var ManagerAgent = class extends BaseAgent {
|
|
|
5068
5219
|
* Analyze user request and generate project specification
|
|
5069
5220
|
*/
|
|
5070
5221
|
async analyzeRequest(userPrompt) {
|
|
5222
|
+
var _a;
|
|
5071
5223
|
this.log("Analyzing project requirements...");
|
|
5072
5224
|
const response = await this.think(`
|
|
5073
5225
|
User Request: "${userPrompt}"
|
|
@@ -5089,7 +5241,7 @@ Include all pages, API endpoints, and database models needed.
|
|
|
5089
5241
|
apiEndpoints: []
|
|
5090
5242
|
};
|
|
5091
5243
|
const spec = this.parseJSON(response, fallbackSpec);
|
|
5092
|
-
this.log(`Project "${spec.name}" spec created with ${spec.pages
|
|
5244
|
+
this.log(`Project "${spec.name}" spec created with ${((_a = spec.pages) == null ? void 0 : _a.length) || 0} pages`, "success");
|
|
5093
5245
|
return spec;
|
|
5094
5246
|
}
|
|
5095
5247
|
/**
|
|
@@ -5198,7 +5350,8 @@ Include all pages, API endpoints, and database models needed.
|
|
|
5198
5350
|
* Execute manager task (for orchestrator compatibility)
|
|
5199
5351
|
*/
|
|
5200
5352
|
async execute(task) {
|
|
5201
|
-
|
|
5353
|
+
var _a;
|
|
5354
|
+
const userPrompt = ((_a = task.input) == null ? void 0 : _a.prompt) || task.description;
|
|
5202
5355
|
const spec = await this.analyzeRequest(userPrompt);
|
|
5203
5356
|
const tasks = this.generateTasks(spec);
|
|
5204
5357
|
return {
|
|
@@ -5334,13 +5487,14 @@ Each component should:
|
|
|
5334
5487
|
* Execute a frontend task
|
|
5335
5488
|
*/
|
|
5336
5489
|
async execute(task) {
|
|
5490
|
+
var _a;
|
|
5337
5491
|
this.log(`Executing: ${task.title}`);
|
|
5338
5492
|
let files = [];
|
|
5339
5493
|
const errors = [];
|
|
5340
5494
|
try {
|
|
5341
5495
|
if (task.title.toLowerCase().includes("shared") || task.title.toLowerCase().includes("ui component")) {
|
|
5342
5496
|
files = await this.generateUIKit();
|
|
5343
|
-
} else if (task.input
|
|
5497
|
+
} else if ((_a = task.input) == null ? void 0 : _a.page) {
|
|
5344
5498
|
files = await this.generatePage(task.input.page);
|
|
5345
5499
|
} else {
|
|
5346
5500
|
files = await this.generateComponent(
|
|
@@ -5516,23 +5670,24 @@ Requirements:
|
|
|
5516
5670
|
* Execute a backend task
|
|
5517
5671
|
*/
|
|
5518
5672
|
async execute(task) {
|
|
5673
|
+
var _a, _b, _c, _d, _e;
|
|
5519
5674
|
this.log(`Executing: ${task.title}`);
|
|
5520
5675
|
let files = [];
|
|
5521
5676
|
try {
|
|
5522
5677
|
if (task.title.toLowerCase().includes("initialize") || task.title.toLowerCase().includes("setup")) {
|
|
5523
|
-
const spec = task.input
|
|
5678
|
+
const spec = ((_a = task.input) == null ? void 0 : _a.spec) || ((_b = this.context) == null ? void 0 : _b.projectSpec);
|
|
5524
5679
|
if (spec) {
|
|
5525
5680
|
files = await this.generateProjectSetup(spec);
|
|
5526
5681
|
} else {
|
|
5527
5682
|
throw new Error("No project spec provided for initialization");
|
|
5528
5683
|
}
|
|
5529
5684
|
} else if (task.title.toLowerCase().includes("schema") || task.title.toLowerCase().includes("database")) {
|
|
5530
|
-
const spec = task.input
|
|
5685
|
+
const spec = ((_c = task.input) == null ? void 0 : _c.spec) || ((_d = this.context) == null ? void 0 : _d.projectSpec);
|
|
5531
5686
|
if (spec) {
|
|
5532
5687
|
files = await this.generateSchema(spec);
|
|
5533
5688
|
files.push(...await this.generateDBUtils());
|
|
5534
5689
|
}
|
|
5535
|
-
} else if (task.input
|
|
5690
|
+
} else if ((_e = task.input) == null ? void 0 : _e.endpoint) {
|
|
5536
5691
|
files = await this.generateEndpoint(task.input.endpoint);
|
|
5537
5692
|
} else {
|
|
5538
5693
|
const endpoint = {
|
|
@@ -5717,8 +5872,9 @@ Only fix what's broken. Keep the rest intact.
|
|
|
5717
5872
|
* Execute QA task
|
|
5718
5873
|
*/
|
|
5719
5874
|
async execute(task) {
|
|
5875
|
+
var _a;
|
|
5720
5876
|
this.log(`Executing: ${task.title}`);
|
|
5721
|
-
const cwd = this.context
|
|
5877
|
+
const cwd = ((_a = this.context) == null ? void 0 : _a.workspaceRoot) || process.cwd();
|
|
5722
5878
|
try {
|
|
5723
5879
|
return await this.buildFixLoop(cwd);
|
|
5724
5880
|
} catch (error) {
|
|
@@ -5845,8 +6001,8 @@ Requirements:
|
|
|
5845
6001
|
return { success: true, url };
|
|
5846
6002
|
} else {
|
|
5847
6003
|
const anyUrl = output.match(/https:\/\/[^\s]+/);
|
|
5848
|
-
this.log(`Deployed: ${anyUrl
|
|
5849
|
-
return { success: true, url: anyUrl
|
|
6004
|
+
this.log(`Deployed: ${(anyUrl == null ? void 0 : anyUrl[0]) || "Success"}`, "success");
|
|
6005
|
+
return { success: true, url: anyUrl == null ? void 0 : anyUrl[0] };
|
|
5850
6006
|
}
|
|
5851
6007
|
} catch (error) {
|
|
5852
6008
|
const execError = error;
|
|
@@ -5911,8 +6067,9 @@ Requirements:
|
|
|
5911
6067
|
* Execute devops task
|
|
5912
6068
|
*/
|
|
5913
6069
|
async execute(task) {
|
|
6070
|
+
var _a;
|
|
5914
6071
|
this.log(`Executing: ${task.title}`);
|
|
5915
|
-
const cwd = this.context
|
|
6072
|
+
const cwd = ((_a = this.context) == null ? void 0 : _a.workspaceRoot) || process.cwd();
|
|
5916
6073
|
const files = [];
|
|
5917
6074
|
const commands = [];
|
|
5918
6075
|
const errors = [];
|
|
@@ -6000,14 +6157,17 @@ var SquadOrchestrator = class {
|
|
|
6000
6157
|
* Main entry point - run the full squad pipeline
|
|
6001
6158
|
*/
|
|
6002
6159
|
async run(userPrompt) {
|
|
6160
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
6003
6161
|
const startTime = Date.now();
|
|
6004
6162
|
const filesCreated = [];
|
|
6005
6163
|
const filesModified = [];
|
|
6006
6164
|
const tasksSummary = [];
|
|
6007
6165
|
const errors = [];
|
|
6166
|
+
(_b = (_a = this.config).onProgress) == null ? void 0 : _b.call(_a, "interfaces", "Initializing Squad Interfaces...");
|
|
6008
6167
|
this.log("\u{1F680} Agdi Squad Activated!", "header");
|
|
6009
6168
|
this.log(`Goal: "${userPrompt}"`, "info");
|
|
6010
6169
|
try {
|
|
6170
|
+
(_d = (_c = this.config).onProgress) == null ? void 0 : _d.call(_c, "manager", "Manager Agent analyzing requirements...");
|
|
6011
6171
|
this.log("\u{1F4CB} Phase 1: Planning", "phase");
|
|
6012
6172
|
const projectSpec = await this.manager.analyzeRequest(userPrompt);
|
|
6013
6173
|
this.tasks = this.manager.generateTasks(projectSpec);
|
|
@@ -6023,8 +6183,10 @@ var SquadOrchestrator = class {
|
|
|
6023
6183
|
this.qa.setContext(this.context);
|
|
6024
6184
|
this.devops.setContext(this.context);
|
|
6025
6185
|
this.log(`Created ${this.tasks.length} tasks`, "success");
|
|
6186
|
+
(_f = (_e = this.config).onProgress) == null ? void 0 : _f.call(_e, "squad", "Squad Agents building application...");
|
|
6026
6187
|
this.log("\u26A1 Phase 2: Execution", "phase");
|
|
6027
6188
|
await this.executeTasks(filesCreated, filesModified, tasksSummary, errors);
|
|
6189
|
+
(_h = (_g = this.config).onProgress) == null ? void 0 : _h.call(_g, "self-healing", "Running Self-Healing checks...");
|
|
6028
6190
|
this.log("\u2705 Phase 3: Validation", "phase");
|
|
6029
6191
|
const qaTask = this.tasks.find((t) => t.assignee === "qa");
|
|
6030
6192
|
if (qaTask) {
|
|
@@ -6045,6 +6207,7 @@ var SquadOrchestrator = class {
|
|
|
6045
6207
|
}
|
|
6046
6208
|
let deploymentUrl;
|
|
6047
6209
|
if (this.config.autoDeploy) {
|
|
6210
|
+
(_j = (_i = this.config).onProgress) == null ? void 0 : _j.call(_i, "deploy", "Deploying to cloud...");
|
|
6048
6211
|
this.log("\u{1F680} Phase 4: Deployment", "phase");
|
|
6049
6212
|
const devopsTask = this.tasks.find((t) => t.assignee === "devops");
|
|
6050
6213
|
if (devopsTask) {
|
|
@@ -6062,6 +6225,7 @@ var SquadOrchestrator = class {
|
|
|
6062
6225
|
});
|
|
6063
6226
|
}
|
|
6064
6227
|
}
|
|
6228
|
+
(_l = (_k = this.config).onProgress) == null ? void 0 : _l.call(_k, "complete", "Mission Accomplished!");
|
|
6065
6229
|
const duration = Date.now() - startTime;
|
|
6066
6230
|
this.log("\u{1F389} Squad Mission Complete!", "header");
|
|
6067
6231
|
this.log(`Duration: ${(duration / 1e3).toFixed(1)}s`, "info");
|
|
@@ -6206,15 +6370,65 @@ ${"\u2550".repeat(50)}`));
|
|
|
6206
6370
|
case "error":
|
|
6207
6371
|
console.log(chalk15.red(` \u2717 ${message}`));
|
|
6208
6372
|
break;
|
|
6373
|
+
case "info":
|
|
6209
6374
|
default:
|
|
6210
6375
|
console.log(chalk15.gray(` ${message}`));
|
|
6211
6376
|
}
|
|
6212
6377
|
}
|
|
6213
6378
|
};
|
|
6214
6379
|
|
|
6380
|
+
// src/utils/squad-ui.ts
|
|
6381
|
+
import chalk16 from "chalk";
|
|
6382
|
+
import logUpdate from "log-update";
|
|
6383
|
+
var STAGES = [
|
|
6384
|
+
{ id: "interfaces", label: "INTERFACES", icon: "\u{1F7E6}", color: chalk16.cyan },
|
|
6385
|
+
{ id: "manager", label: "MANAGER", icon: "\u{1F7EA}", color: chalk16.magenta },
|
|
6386
|
+
{ id: "squad", label: "SQUAD", icon: "\u{1F4A1}", color: chalk16.yellow },
|
|
6387
|
+
{ id: "self-healing", label: "HEALING", icon: "\u{1F7E5}", color: chalk16.red },
|
|
6388
|
+
{ id: "deploy", label: "DEPLOY", icon: "\u{1F7E9}", color: chalk16.green }
|
|
6389
|
+
];
|
|
6390
|
+
function renderSquadPipeline(activeStage, message = "") {
|
|
6391
|
+
const activeIndex = STAGES.findIndex((s) => s.id === activeStage);
|
|
6392
|
+
const isComplete = activeStage === "complete";
|
|
6393
|
+
const pipeline = STAGES.map((stage, idx) => {
|
|
6394
|
+
let content = "";
|
|
6395
|
+
const isActive = stage.id === activeStage;
|
|
6396
|
+
const isPast = activeIndex > idx || isComplete;
|
|
6397
|
+
const label = isActive ? chalk16.bold.underline(stage.label) : stage.label;
|
|
6398
|
+
const icon = stage.icon;
|
|
6399
|
+
const connector = idx < STAGES.length - 1 ? chalk16.gray(isActive || isPast ? " \u2550\u2550> " : " \u2500\u2500> ") : "";
|
|
6400
|
+
if (isActive) {
|
|
6401
|
+
content = stage.color(`[ ${icon} ${label} ]`);
|
|
6402
|
+
} else if (isPast) {
|
|
6403
|
+
content = chalk16.dim(`[ ${icon} ${label} ]`);
|
|
6404
|
+
} else {
|
|
6405
|
+
content = chalk16.gray(`[ ${icon} ${label} ]`);
|
|
6406
|
+
}
|
|
6407
|
+
return content + connector;
|
|
6408
|
+
}).join("");
|
|
6409
|
+
let statusLine = "";
|
|
6410
|
+
if (activeStage !== "complete") {
|
|
6411
|
+
const activeConfig = STAGES.find((s) => s.id === activeStage);
|
|
6412
|
+
if (activeConfig) {
|
|
6413
|
+
const spinner = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"][Math.floor(Date.now() / 80) % 10];
|
|
6414
|
+
statusLine = `
|
|
6415
|
+
${activeConfig.color(spinner)} ${chalk16.white(message)}`;
|
|
6416
|
+
}
|
|
6417
|
+
} else {
|
|
6418
|
+
statusLine = `
|
|
6419
|
+
${chalk16.green("\u2714")} ${chalk16.white(message)}`;
|
|
6420
|
+
}
|
|
6421
|
+
logUpdate(
|
|
6422
|
+
"\n" + pipeline + "\n" + statusLine + "\n"
|
|
6423
|
+
);
|
|
6424
|
+
}
|
|
6425
|
+
function clearSquadPipeline() {
|
|
6426
|
+
logUpdate.clear();
|
|
6427
|
+
}
|
|
6428
|
+
|
|
6215
6429
|
// src/commands/squad.ts
|
|
6216
6430
|
async function runSquadCommand(prompt, llm, options = {}) {
|
|
6217
|
-
console.log(
|
|
6431
|
+
console.log(chalk17.cyan.bold("\n\u{1F9B8} Agdi Squad - Autonomous Development Team\n"));
|
|
6218
6432
|
let userPrompt = prompt;
|
|
6219
6433
|
if (!userPrompt) {
|
|
6220
6434
|
userPrompt = await input6({
|
|
@@ -6223,53 +6437,67 @@ async function runSquadCommand(prompt, llm, options = {}) {
|
|
|
6223
6437
|
});
|
|
6224
6438
|
}
|
|
6225
6439
|
if (!userPrompt.trim()) {
|
|
6226
|
-
console.log(
|
|
6440
|
+
console.log(chalk17.red("Error: Please provide a project description."));
|
|
6227
6441
|
return null;
|
|
6228
6442
|
}
|
|
6443
|
+
const { loadConfig: loadConfig2, saveConfig: saveConfig3 } = await import("./config-U2UXLNRN.js");
|
|
6444
|
+
const userConfig = loadConfig2();
|
|
6445
|
+
if (userConfig.autonomyMode === void 0) {
|
|
6446
|
+
console.log(chalk17.white.bold("\n\u{1F916} Autonomy Configuration\n"));
|
|
6447
|
+
const { confirm: confirm4 } = await import("@inquirer/prompts");
|
|
6448
|
+
const enableAutonomy = await confirm4({
|
|
6449
|
+
message: "Enable Full Autonomy Mode? (The agent will plan, execute, and deploy without asking)",
|
|
6450
|
+
default: false
|
|
6451
|
+
});
|
|
6452
|
+
userConfig.autonomyMode = enableAutonomy;
|
|
6453
|
+
saveConfig3(userConfig);
|
|
6454
|
+
if (enableAutonomy) {
|
|
6455
|
+
console.log(chalk17.green("\n\u2705 Full Autonomy Enabled. Sit back and relax. \u2615\n"));
|
|
6456
|
+
} else {
|
|
6457
|
+
console.log(chalk17.gray("\n\u{1F44C} Manual Mode. We will ask for permission before dangerous actions.\n"));
|
|
6458
|
+
}
|
|
6459
|
+
}
|
|
6229
6460
|
const config = {
|
|
6230
6461
|
workspaceRoot: options.output || process.cwd(),
|
|
6231
6462
|
verbose: options.verbose ?? true,
|
|
6232
6463
|
autoDeploy: options.deploy ?? false
|
|
6233
6464
|
};
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
if (options.deploy) {
|
|
6243
|
-
console.log(chalk16.gray(" \u{1F680} DevOps - Deploys to production"));
|
|
6244
|
-
}
|
|
6245
|
-
console.log("");
|
|
6465
|
+
console.clear();
|
|
6466
|
+
renderSquadPipeline("interfaces", "Initializing Squad...");
|
|
6467
|
+
const orchestrator = new SquadOrchestrator(llm, {
|
|
6468
|
+
...config,
|
|
6469
|
+
onProgress: (stage, message) => {
|
|
6470
|
+
renderSquadPipeline(stage, message);
|
|
6471
|
+
}
|
|
6472
|
+
});
|
|
6246
6473
|
const result = await orchestrator.run(userPrompt);
|
|
6474
|
+
clearSquadPipeline();
|
|
6247
6475
|
console.log("\n");
|
|
6248
6476
|
if (result.success) {
|
|
6249
|
-
console.log(
|
|
6477
|
+
console.log(chalk17.green.bold("\u2705 Mission Accomplished!\n"));
|
|
6250
6478
|
} else {
|
|
6251
|
-
console.log(
|
|
6479
|
+
console.log(chalk17.yellow.bold("\u26A0\uFE0F Mission Completed with Issues\n"));
|
|
6252
6480
|
}
|
|
6253
|
-
console.log(
|
|
6254
|
-
console.log(
|
|
6255
|
-
console.log(
|
|
6256
|
-
console.log(
|
|
6481
|
+
console.log(chalk17.white("Summary:"));
|
|
6482
|
+
console.log(chalk17.gray(` Duration: ${(result.duration / 1e3).toFixed(1)}s`));
|
|
6483
|
+
console.log(chalk17.gray(` Files Created: ${result.filesCreated.length}`));
|
|
6484
|
+
console.log(chalk17.gray(` Files Modified: ${result.filesModified.length}`));
|
|
6257
6485
|
if (result.deploymentUrl) {
|
|
6258
|
-
console.log(
|
|
6486
|
+
console.log(chalk17.green(` Live URL: ${result.deploymentUrl}`));
|
|
6259
6487
|
}
|
|
6260
6488
|
if (result.errors.length > 0) {
|
|
6261
|
-
console.log(
|
|
6489
|
+
console.log(chalk17.red("\nErrors:"));
|
|
6262
6490
|
result.errors.forEach((err) => {
|
|
6263
|
-
console.log(
|
|
6491
|
+
console.log(chalk17.red(` \u2022 ${err}`));
|
|
6264
6492
|
});
|
|
6265
6493
|
}
|
|
6266
6494
|
if (result.filesCreated.length > 0) {
|
|
6267
|
-
console.log(
|
|
6495
|
+
console.log(chalk17.white("\nCreated Files:"));
|
|
6268
6496
|
result.filesCreated.slice(0, 10).forEach((file) => {
|
|
6269
|
-
console.log(
|
|
6497
|
+
console.log(chalk17.green(` \u2713 ${file}`));
|
|
6270
6498
|
});
|
|
6271
6499
|
if (result.filesCreated.length > 10) {
|
|
6272
|
-
console.log(
|
|
6500
|
+
console.log(chalk17.gray(` ... and ${result.filesCreated.length - 10} more`));
|
|
6273
6501
|
}
|
|
6274
6502
|
}
|
|
6275
6503
|
console.log("");
|
|
@@ -6277,8 +6505,8 @@ async function runSquadCommand(prompt, llm, options = {}) {
|
|
|
6277
6505
|
}
|
|
6278
6506
|
|
|
6279
6507
|
// src/commands/import.ts
|
|
6280
|
-
import
|
|
6281
|
-
import
|
|
6508
|
+
import chalk18 from "chalk";
|
|
6509
|
+
import ora5 from "ora";
|
|
6282
6510
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
6283
6511
|
import { join as join10, dirname as dirname3 } from "path";
|
|
6284
6512
|
function parseGitHubUrl(url) {
|
|
@@ -6327,7 +6555,7 @@ async function fetchRepoAsZip(owner, repo, branch) {
|
|
|
6327
6555
|
return response.arrayBuffer();
|
|
6328
6556
|
}
|
|
6329
6557
|
async function extractZipToFiles(buffer) {
|
|
6330
|
-
const JSZip2 = (await import("
|
|
6558
|
+
const JSZip2 = (await import("./lib-CAJYQA32.js")).default;
|
|
6331
6559
|
const zip = await JSZip2.loadAsync(buffer);
|
|
6332
6560
|
const files = [];
|
|
6333
6561
|
const promises = [];
|
|
@@ -6365,8 +6593,8 @@ async function writeFiles(files, outputDir) {
|
|
|
6365
6593
|
}
|
|
6366
6594
|
}
|
|
6367
6595
|
async function runImportCommand(url, outputDir) {
|
|
6368
|
-
console.log(
|
|
6369
|
-
const spinner =
|
|
6596
|
+
console.log(chalk18.cyan.bold("\n\u{1F4E6} Agdi Import\n"));
|
|
6597
|
+
const spinner = ora5("Parsing GitHub URL...").start();
|
|
6370
6598
|
try {
|
|
6371
6599
|
const { owner, repo, branch } = parseGitHubUrl(url);
|
|
6372
6600
|
const targetDir = outputDir || `./${repo}`;
|
|
@@ -6380,17 +6608,17 @@ async function runImportCommand(url, outputDir) {
|
|
|
6380
6608
|
}
|
|
6381
6609
|
spinner.text = `Writing ${files.length} files to ${targetDir}...`;
|
|
6382
6610
|
await writeFiles(files, targetDir);
|
|
6383
|
-
spinner.succeed(
|
|
6384
|
-
console.log(
|
|
6611
|
+
spinner.succeed(chalk18.green(`Imported ${files.length} files to ${chalk18.cyan(targetDir)}`));
|
|
6612
|
+
console.log(chalk18.gray(`
|
|
6385
6613
|
Next steps:`));
|
|
6386
|
-
console.log(
|
|
6387
|
-
console.log(
|
|
6388
|
-
console.log(
|
|
6614
|
+
console.log(chalk18.gray(` cd ${targetDir}`));
|
|
6615
|
+
console.log(chalk18.gray(` npm install`));
|
|
6616
|
+
console.log(chalk18.gray(` npm run dev
|
|
6389
6617
|
`));
|
|
6390
6618
|
} catch (error) {
|
|
6391
6619
|
spinner.fail("Import failed");
|
|
6392
6620
|
const msg = error instanceof Error ? error.message : String(error);
|
|
6393
|
-
console.error(
|
|
6621
|
+
console.error(chalk18.red(`
|
|
6394
6622
|
${msg}
|
|
6395
6623
|
`));
|
|
6396
6624
|
process.exit(1);
|
|
@@ -6399,15 +6627,15 @@ ${msg}
|
|
|
6399
6627
|
|
|
6400
6628
|
// src/index.ts
|
|
6401
6629
|
var BANNER = `
|
|
6402
|
-
${
|
|
6403
|
-
${
|
|
6404
|
-
${
|
|
6405
|
-
${
|
|
6406
|
-
${
|
|
6407
|
-
${
|
|
6630
|
+
${chalk19.cyan(` ___ __ _ `)}
|
|
6631
|
+
${chalk19.cyan(` / | ____ _____/ /(_) `)}
|
|
6632
|
+
${chalk19.cyan(` / /| | / __ \`/ __ // / `)}
|
|
6633
|
+
${chalk19.cyan(` / ___ |/ /_/ / /_/ // / `)}
|
|
6634
|
+
${chalk19.cyan(`/_/ |_|\\_, /\\__,_//_/ `)}
|
|
6635
|
+
${chalk19.cyan(` /____/ `)}
|
|
6408
6636
|
`;
|
|
6409
6637
|
var program = new Command();
|
|
6410
|
-
program.name("agdi").description(
|
|
6638
|
+
program.name("agdi").description(chalk19.cyan("\u{1F680} AI-powered coding assistant")).version("2.10.5").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");
|
|
6411
6639
|
program.hook("preAction", (thisCommand) => {
|
|
6412
6640
|
const opts = thisCommand.opts();
|
|
6413
6641
|
if (opts.yes) {
|
|
@@ -6421,7 +6649,7 @@ program.hook("preAction", (thisCommand) => {
|
|
|
6421
6649
|
}
|
|
6422
6650
|
});
|
|
6423
6651
|
program.addHelpText("beforeAll", () => {
|
|
6424
|
-
return BANNER + "\n" +
|
|
6652
|
+
return BANNER + "\n" + chalk19.gray(" The Open Source AI Architect") + "\n" + chalk19.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");
|
|
6425
6653
|
});
|
|
6426
6654
|
program.action(async () => {
|
|
6427
6655
|
try {
|
|
@@ -6432,7 +6660,7 @@ program.action(async () => {
|
|
|
6432
6660
|
await startCodingMode();
|
|
6433
6661
|
} catch (error) {
|
|
6434
6662
|
if (error.name === "ExitPromptError") {
|
|
6435
|
-
console.log(
|
|
6663
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Goodbye!\n"));
|
|
6436
6664
|
try {
|
|
6437
6665
|
ui.safeExit(0);
|
|
6438
6666
|
} catch {
|
|
@@ -6454,7 +6682,7 @@ program.command("auth").description("Configure API keys").option("--status", "Sh
|
|
|
6454
6682
|
}
|
|
6455
6683
|
} catch (error) {
|
|
6456
6684
|
if (error.name === "ExitPromptError") {
|
|
6457
|
-
console.log(
|
|
6685
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Cancelled.\n"));
|
|
6458
6686
|
try {
|
|
6459
6687
|
ui.safeExit(0);
|
|
6460
6688
|
} catch {
|
|
@@ -6472,7 +6700,7 @@ program.command("model").alias("models").description("Change AI model").action(a
|
|
|
6472
6700
|
await selectModel();
|
|
6473
6701
|
} catch (error) {
|
|
6474
6702
|
if (error.name === "ExitPromptError") {
|
|
6475
|
-
console.log(
|
|
6703
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Cancelled.\n"));
|
|
6476
6704
|
try {
|
|
6477
6705
|
ui.safeExit(0);
|
|
6478
6706
|
} catch {
|
|
@@ -6493,7 +6721,7 @@ program.command("chat").description("Start a chat session").action(async () => {
|
|
|
6493
6721
|
await startChat();
|
|
6494
6722
|
} catch (error) {
|
|
6495
6723
|
if (error.name === "ExitPromptError") {
|
|
6496
|
-
console.log(
|
|
6724
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Goodbye!\n"));
|
|
6497
6725
|
try {
|
|
6498
6726
|
ui.safeExit(0);
|
|
6499
6727
|
} catch {
|
|
@@ -6511,7 +6739,7 @@ program.command("run [directory]").description("Run a generated project").action
|
|
|
6511
6739
|
await runProject(directory);
|
|
6512
6740
|
} catch (error) {
|
|
6513
6741
|
if (error.name === "ExitPromptError") {
|
|
6514
|
-
console.log(
|
|
6742
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Cancelled.\n"));
|
|
6515
6743
|
try {
|
|
6516
6744
|
ui.safeExit(0);
|
|
6517
6745
|
} catch {
|
|
@@ -6531,10 +6759,10 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
|
|
|
6531
6759
|
}
|
|
6532
6760
|
const activeConfig = getActiveProvider();
|
|
6533
6761
|
if (!activeConfig) {
|
|
6534
|
-
console.log(
|
|
6762
|
+
console.log(chalk19.red("\u274C No API key configured. Run: agdi auth"));
|
|
6535
6763
|
return;
|
|
6536
6764
|
}
|
|
6537
|
-
const spinner =
|
|
6765
|
+
const spinner = ora6("Generating application...").start();
|
|
6538
6766
|
try {
|
|
6539
6767
|
const llm = createLLMProvider(activeConfig.provider, {
|
|
6540
6768
|
apiKey: activeConfig.apiKey,
|
|
@@ -6543,42 +6771,42 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
|
|
|
6543
6771
|
const pm = new ProjectManager();
|
|
6544
6772
|
pm.create(options.output.replace("./", ""), prompt);
|
|
6545
6773
|
const { plan, files } = await generateApp(prompt, llm, (step, file) => {
|
|
6546
|
-
spinner.text = file ? `${step} ${
|
|
6774
|
+
spinner.text = file ? `${step} ${chalk19.gray(file)}` : step;
|
|
6547
6775
|
});
|
|
6548
6776
|
pm.updateFiles(files);
|
|
6549
6777
|
pm.updateDependencies(plan.dependencies);
|
|
6550
6778
|
if (options.dryRun || ui.flags.dryRun) {
|
|
6551
6779
|
spinner.stop();
|
|
6552
|
-
console.log(
|
|
6553
|
-
console.log(
|
|
6780
|
+
console.log(chalk19.cyan.bold("\n\u{1F6A7} DRY RUN SUMMARY\n"));
|
|
6781
|
+
console.log(chalk19.gray(`Project: ${plan.name}
|
|
6554
6782
|
`));
|
|
6555
|
-
console.log(
|
|
6556
|
-
files.forEach((f) => console.log(
|
|
6557
|
-
console.log(
|
|
6558
|
-
console.log(
|
|
6559
|
-
console.log(
|
|
6783
|
+
console.log(chalk19.cyan("Files to be created:"));
|
|
6784
|
+
files.forEach((f) => console.log(chalk19.gray(` \u{1F4C4} ${f.path}`)));
|
|
6785
|
+
console.log(chalk19.cyan("\nDependencies:"));
|
|
6786
|
+
console.log(chalk19.gray(` \u{1F4E6} ${plan.dependencies.join(", ")}`));
|
|
6787
|
+
console.log(chalk19.green("\n\u2713 Dry run complete. No files written.\n"));
|
|
6560
6788
|
return;
|
|
6561
6789
|
}
|
|
6562
6790
|
await writeProject(pm.get(), options.output);
|
|
6563
|
-
spinner.succeed(
|
|
6564
|
-
console.log(
|
|
6565
|
-
\u{1F4C1} Created ${files.length} files in ${
|
|
6566
|
-
console.log(
|
|
6791
|
+
spinner.succeed(chalk19.green("App generated!"));
|
|
6792
|
+
console.log(chalk19.gray(`
|
|
6793
|
+
\u{1F4C1} Created ${files.length} files in ${chalk19.cyan(options.output)}`));
|
|
6794
|
+
console.log(chalk19.gray("\nNext: cd " + options.output + " && npm install && npm run dev\n"));
|
|
6567
6795
|
} catch (error) {
|
|
6568
6796
|
spinner.fail("Generation failed");
|
|
6569
6797
|
const msg = error instanceof Error ? error.message : String(error);
|
|
6570
6798
|
if (msg.includes("429") || msg.includes("quota")) {
|
|
6571
|
-
console.log(
|
|
6799
|
+
console.log(chalk19.yellow("\n\u26A0\uFE0F Quota exceeded. Run: agdi model\n"));
|
|
6572
6800
|
} else if (msg.includes("401") || msg.includes("403")) {
|
|
6573
|
-
console.log(
|
|
6801
|
+
console.log(chalk19.red("\n\u{1F511} Invalid API key. Run: agdi auth\n"));
|
|
6574
6802
|
} else {
|
|
6575
|
-
console.error(
|
|
6803
|
+
console.error(chalk19.red("\n" + msg + "\n"));
|
|
6576
6804
|
}
|
|
6577
6805
|
ui.safeExit(1);
|
|
6578
6806
|
}
|
|
6579
6807
|
} catch (error) {
|
|
6580
6808
|
if (error.name === "ExitPromptError") {
|
|
6581
|
-
console.log(
|
|
6809
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Cancelled.\n"));
|
|
6582
6810
|
try {
|
|
6583
6811
|
ui.safeExit(0);
|
|
6584
6812
|
} catch {
|
|
@@ -6592,13 +6820,14 @@ program.command("build <prompt>").alias("b").description("Generate an app from a
|
|
|
6592
6820
|
}
|
|
6593
6821
|
});
|
|
6594
6822
|
program.command("config").description("Show configuration").action(async () => {
|
|
6823
|
+
var _a;
|
|
6595
6824
|
const config = loadConfig();
|
|
6596
6825
|
const active = getActiveProvider();
|
|
6597
|
-
console.log(
|
|
6598
|
-
console.log(
|
|
6599
|
-
console.log(
|
|
6600
|
-
console.log(
|
|
6601
|
-
console.log(
|
|
6826
|
+
console.log(chalk19.cyan.bold("\n\u2699\uFE0F Configuration\n"));
|
|
6827
|
+
console.log(chalk19.gray(" Provider: ") + chalk19.cyan(config.defaultProvider || "not set"));
|
|
6828
|
+
console.log(chalk19.gray(" Model: ") + chalk19.cyan(config.defaultModel || "not set"));
|
|
6829
|
+
console.log(chalk19.gray(" Config: ") + chalk19.gray("~/.agdi/config.json"));
|
|
6830
|
+
console.log(chalk19.cyan.bold("\n\u{1F510} API Keys\n"));
|
|
6602
6831
|
const keys = [
|
|
6603
6832
|
["Gemini", config.geminiApiKey],
|
|
6604
6833
|
["OpenRouter", config.openrouterApiKey],
|
|
@@ -6607,73 +6836,73 @@ program.command("config").description("Show configuration").action(async () => {
|
|
|
6607
6836
|
["DeepSeek", config.deepseekApiKey]
|
|
6608
6837
|
];
|
|
6609
6838
|
for (const [name, key] of keys) {
|
|
6610
|
-
const status = key ?
|
|
6839
|
+
const status = key ? chalk19.green("\u2713") : chalk19.gray("\u2717");
|
|
6611
6840
|
console.log(` ${status} ${name}`);
|
|
6612
6841
|
}
|
|
6613
|
-
console.log(
|
|
6614
|
-
const telemetryEnabled = config.telemetry
|
|
6615
|
-
console.log(` ${telemetryEnabled ?
|
|
6616
|
-
console.log(
|
|
6842
|
+
console.log(chalk19.cyan.bold("\n\u{1F4CA} Telemetry\n"));
|
|
6843
|
+
const telemetryEnabled = ((_a = config.telemetry) == null ? void 0 : _a.enabled) ?? false;
|
|
6844
|
+
console.log(` ${telemetryEnabled ? chalk19.green("\u2713 Enabled") : chalk19.gray("\u2717 Disabled")}`);
|
|
6845
|
+
console.log(chalk19.gray(" Change with: agdi config telemetry --enable | --disable"));
|
|
6617
6846
|
console.log("");
|
|
6618
6847
|
console.log("");
|
|
6619
6848
|
});
|
|
6620
6849
|
program.command("config:telemetry").alias("telemetry").description("Manage telemetry settings").option("--enable", "Enable anonymous telemetry").option("--disable", "Disable telemetry").option("--status", "Show current telemetry status").option("--dry-run", "Show exactly what data would be sent (transparency mode)").option("--test", "Alias for --dry-run").action(async (options) => {
|
|
6621
|
-
const { isTelemetryEnabled, setTelemetryConsent, getTelemetryConfig } = await import("./config-
|
|
6622
|
-
const { generateSampleEvent, generateSanitizationDemo } = await import("./telemetry-service-
|
|
6850
|
+
const { isTelemetryEnabled, setTelemetryConsent, getTelemetryConfig } = await import("./config-LBIRRMSE.js");
|
|
6851
|
+
const { generateSampleEvent, generateSanitizationDemo } = await import("./telemetry-service-D4P7B4B4.js");
|
|
6623
6852
|
if (options.dryRun || options.test) {
|
|
6624
|
-
console.log(
|
|
6625
|
-
console.log(
|
|
6626
|
-
console.log(
|
|
6627
|
-
console.log(
|
|
6853
|
+
console.log(chalk19.cyan.bold("\n\u{1F50D} TELEMETRY TRANSPARENCY MODE\n"));
|
|
6854
|
+
console.log(chalk19.gray("This is exactly what Agdi sends. Notice there is"));
|
|
6855
|
+
console.log(chalk19.green.bold("NO source code, file paths, or API keys.\n"));
|
|
6856
|
+
console.log(chalk19.white.bold('\u{1F4CA} Sample "Build Failed" Event:\n'));
|
|
6628
6857
|
const sample = generateSampleEvent();
|
|
6629
|
-
console.log(
|
|
6630
|
-
console.log(
|
|
6631
|
-
console.log(
|
|
6632
|
-
console.log(
|
|
6858
|
+
console.log(chalk19.gray(JSON.stringify(sample, null, 2)));
|
|
6859
|
+
console.log(chalk19.white.bold("\n\u{1F6E1}\uFE0F Sanitization Demo:\n"));
|
|
6860
|
+
console.log(chalk19.gray("Even if sensitive data accidentally enters an error message,"));
|
|
6861
|
+
console.log(chalk19.gray("our sanitization layer strips it before transmission:\n"));
|
|
6633
6862
|
const demo = generateSanitizationDemo();
|
|
6634
|
-
console.log(
|
|
6635
|
-
console.log(
|
|
6863
|
+
console.log(chalk19.red.bold("BEFORE sanitization (never sent):"));
|
|
6864
|
+
console.log(chalk19.gray(JSON.stringify({
|
|
6636
6865
|
errorCode: demo.before.errorCode,
|
|
6637
6866
|
feedback: demo.before.feedback
|
|
6638
6867
|
}, null, 2)));
|
|
6639
|
-
console.log(
|
|
6640
|
-
console.log(
|
|
6868
|
+
console.log(chalk19.green.bold("\nAFTER sanitization (what we actually send):"));
|
|
6869
|
+
console.log(chalk19.gray(JSON.stringify({
|
|
6641
6870
|
errorCode: demo.after.errorCode,
|
|
6642
6871
|
feedback: demo.after.feedback
|
|
6643
6872
|
}, null, 2)));
|
|
6644
|
-
console.log(
|
|
6645
|
-
console.log(
|
|
6873
|
+
console.log(chalk19.cyan("\n\u2705 Your code and secrets are NEVER transmitted."));
|
|
6874
|
+
console.log(chalk19.gray(" Learn more: https://agdi.dev/privacy\n"));
|
|
6646
6875
|
return;
|
|
6647
6876
|
}
|
|
6648
6877
|
if (options.enable) {
|
|
6649
6878
|
setTelemetryConsent(true);
|
|
6650
|
-
console.log(
|
|
6651
|
-
console.log(
|
|
6652
|
-
console.log(
|
|
6653
|
-
console.log(
|
|
6879
|
+
console.log(chalk19.green("\n\u2705 Telemetry enabled"));
|
|
6880
|
+
console.log(chalk19.gray(" We collect: success/fail, error types, model used"));
|
|
6881
|
+
console.log(chalk19.gray(" We NEVER collect: source code, API keys, file paths"));
|
|
6882
|
+
console.log(chalk19.gray(" Verify anytime: agdi config telemetry --dry-run\n"));
|
|
6654
6883
|
} else if (options.disable) {
|
|
6655
6884
|
setTelemetryConsent(false);
|
|
6656
|
-
console.log(
|
|
6657
|
-
console.log(
|
|
6885
|
+
console.log(chalk19.yellow("\n\u{1F4CA} Telemetry disabled"));
|
|
6886
|
+
console.log(chalk19.gray(" You can re-enable anytime with: agdi config telemetry --enable\n"));
|
|
6658
6887
|
} else {
|
|
6659
6888
|
const config = getTelemetryConfig();
|
|
6660
|
-
console.log(
|
|
6661
|
-
console.log(
|
|
6662
|
-
console.log(
|
|
6889
|
+
console.log(chalk19.cyan.bold("\n\u{1F4CA} Telemetry Status\n"));
|
|
6890
|
+
console.log(chalk19.gray(" Enabled: ") + (config.enabled ? chalk19.green("Yes") : chalk19.gray("No")));
|
|
6891
|
+
console.log(chalk19.gray(" Consent: ") + (config.consentAsked ? chalk19.green("Asked") : chalk19.gray("Not asked")));
|
|
6663
6892
|
if (config.anonymousId) {
|
|
6664
|
-
console.log(
|
|
6893
|
+
console.log(chalk19.gray(" ID: ") + chalk19.gray(config.anonymousId.slice(0, 8) + "..."));
|
|
6665
6894
|
}
|
|
6666
6895
|
console.log("");
|
|
6667
|
-
console.log(
|
|
6668
|
-
console.log(
|
|
6669
|
-
console.log(
|
|
6896
|
+
console.log(chalk19.gray(" Enable: agdi config telemetry --enable"));
|
|
6897
|
+
console.log(chalk19.gray(" Disable: agdi config telemetry --disable"));
|
|
6898
|
+
console.log(chalk19.gray(" Verify: agdi config telemetry --dry-run\n"));
|
|
6670
6899
|
}
|
|
6671
6900
|
});
|
|
6672
6901
|
program.command("doctor").alias("doc").description("Run self-diagnosis checks").action(async () => {
|
|
6673
6902
|
try {
|
|
6674
6903
|
await runDoctor();
|
|
6675
6904
|
} catch (error) {
|
|
6676
|
-
console.error(
|
|
6905
|
+
console.error(chalk19.red("Diagnostic failed: " + error));
|
|
6677
6906
|
ui.safeExit(1);
|
|
6678
6907
|
}
|
|
6679
6908
|
});
|
|
@@ -6684,7 +6913,7 @@ program.command("squad [prompt]").alias("s").description("\u{1F9B8} Autonomous m
|
|
|
6684
6913
|
}
|
|
6685
6914
|
const activeConfig = getActiveProvider();
|
|
6686
6915
|
if (!activeConfig) {
|
|
6687
|
-
console.log(
|
|
6916
|
+
console.log(chalk19.red("\u274C No API key configured. Run: agdi auth"));
|
|
6688
6917
|
return;
|
|
6689
6918
|
}
|
|
6690
6919
|
const llm = createLLMProvider(activeConfig.provider, {
|
|
@@ -6698,7 +6927,7 @@ program.command("squad [prompt]").alias("s").description("\u{1F9B8} Autonomous m
|
|
|
6698
6927
|
});
|
|
6699
6928
|
} catch (error) {
|
|
6700
6929
|
if (error.name === "ExitPromptError") {
|
|
6701
|
-
console.log(
|
|
6930
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Cancelled.\n"));
|
|
6702
6931
|
try {
|
|
6703
6932
|
ui.safeExit(0);
|
|
6704
6933
|
} catch {
|
|
@@ -6716,7 +6945,7 @@ program.command("import <url>").alias("i").description("\u{1F4E6} Import a GitHu
|
|
|
6716
6945
|
await runImportCommand(url, options.output);
|
|
6717
6946
|
} catch (error) {
|
|
6718
6947
|
if (error.name === "ExitPromptError") {
|
|
6719
|
-
console.log(
|
|
6948
|
+
console.log(chalk19.gray("\n\n\u{1F44B} Cancelled.\n"));
|
|
6720
6949
|
try {
|
|
6721
6950
|
ui.safeExit(0);
|
|
6722
6951
|
} catch {
|