ultra-dex 3.1.0 ā 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +79 -74
- package/assets/code-patterns/clerk-middleware.ts +138 -0
- package/assets/code-patterns/prisma-schema.prisma +224 -0
- package/assets/code-patterns/rls-policies.sql +246 -0
- package/assets/code-patterns/server-actions.ts +191 -0
- package/assets/code-patterns/trpc-router.ts +258 -0
- package/assets/cursor-rules/13-ai-integration.mdc +155 -0
- package/assets/cursor-rules/14-server-components.mdc +81 -0
- package/assets/cursor-rules/15-server-actions.mdc +102 -0
- package/assets/cursor-rules/16-edge-middleware.mdc +105 -0
- package/assets/cursor-rules/17-streaming-ssr.mdc +138 -0
- package/bin/ultra-dex.js +50 -1
- package/lib/commands/agents.js +16 -13
- package/lib/commands/banner.js +43 -21
- package/lib/commands/build.js +26 -17
- package/lib/commands/cloud.js +780 -0
- package/lib/commands/doctor.js +98 -79
- package/lib/commands/exec.js +434 -0
- package/lib/commands/generate.js +19 -16
- package/lib/commands/github.js +475 -0
- package/lib/commands/init.js +52 -56
- package/lib/commands/scaffold.js +151 -0
- package/lib/commands/search.js +477 -0
- package/lib/commands/serve.js +15 -13
- package/lib/commands/state.js +43 -70
- package/lib/commands/swarm.js +31 -9
- package/lib/config/theme.js +47 -0
- package/lib/mcp/client.js +502 -0
- package/lib/providers/agent-sdk.js +630 -0
- package/lib/providers/anthropic-agents.js +580 -0
- package/lib/templates/code/clerk-middleware.ts +138 -0
- package/lib/templates/code/prisma-schema.prisma +224 -0
- package/lib/templates/code/rls-policies.sql +246 -0
- package/lib/templates/code/server-actions.ts +191 -0
- package/lib/templates/code/trpc-router.ts +258 -0
- package/lib/themes/doomsday.js +229 -0
- package/lib/ui/index.js +5 -0
- package/lib/ui/interface.js +241 -0
- package/lib/ui/spinners.js +116 -0
- package/lib/ui/theme.js +183 -0
- package/lib/utils/agents.js +32 -0
- package/lib/utils/browser.js +373 -0
- package/lib/utils/help.js +64 -0
- package/lib/utils/messages.js +35 -0
- package/lib/utils/progress.js +24 -0
- package/lib/utils/prompts.js +47 -0
- package/lib/utils/spinners.js +46 -0
- package/lib/utils/status.js +31 -0
- package/lib/utils/tables.js +41 -0
- package/lib/utils/theme-state.js +9 -0
- package/lib/utils/version-display.js +32 -0
- package/package.json +19 -4
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ultra-dex exec command
|
|
3
|
+
* Docker-based code execution sandbox for running generated code safely
|
|
4
|
+
* This is what makes Ultra-Dex truly autonomous - it can VERIFY code works
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import ora from 'ora';
|
|
9
|
+
import fs from 'fs/promises';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import { spawn, exec as execCallback } from 'child_process';
|
|
12
|
+
import { promisify } from 'util';
|
|
13
|
+
|
|
14
|
+
const execAsync = promisify(execCallback);
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// SANDBOX CONFIGURATION
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
const SANDBOX_CONFIG = {
|
|
21
|
+
// Docker image for sandboxed execution
|
|
22
|
+
defaultImage: 'node:20-alpine',
|
|
23
|
+
|
|
24
|
+
// Language-specific images
|
|
25
|
+
images: {
|
|
26
|
+
javascript: 'node:20-alpine',
|
|
27
|
+
typescript: 'node:20-alpine',
|
|
28
|
+
python: 'python:3.12-alpine',
|
|
29
|
+
rust: 'rust:1.75-alpine',
|
|
30
|
+
go: 'golang:1.22-alpine',
|
|
31
|
+
ruby: 'ruby:3.3-alpine',
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
// Resource limits
|
|
35
|
+
limits: {
|
|
36
|
+
memory: '512m',
|
|
37
|
+
cpus: '1.0',
|
|
38
|
+
timeout: 60000, // 60 seconds
|
|
39
|
+
networkDisabled: true,
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
// Workspace settings
|
|
43
|
+
workspace: {
|
|
44
|
+
containerPath: '/workspace',
|
|
45
|
+
tempDir: '.ultra-dex/sandbox',
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// ============================================================================
|
|
50
|
+
// DOCKER UTILITIES
|
|
51
|
+
// ============================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Check if Docker is available
|
|
55
|
+
*/
|
|
56
|
+
async function checkDocker() {
|
|
57
|
+
try {
|
|
58
|
+
await execAsync('docker --version');
|
|
59
|
+
return true;
|
|
60
|
+
} catch {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Pull Docker image if not available
|
|
67
|
+
*/
|
|
68
|
+
async function ensureImage(image, spinner) {
|
|
69
|
+
try {
|
|
70
|
+
await execAsync(`docker image inspect ${image} > /dev/null 2>&1`);
|
|
71
|
+
return true;
|
|
72
|
+
} catch {
|
|
73
|
+
spinner.text = `Pulling Docker image: ${image}...`;
|
|
74
|
+
try {
|
|
75
|
+
await execAsync(`docker pull ${image}`);
|
|
76
|
+
return true;
|
|
77
|
+
} catch (err) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Detect language from file extension
|
|
85
|
+
*/
|
|
86
|
+
function detectLanguage(filepath) {
|
|
87
|
+
const ext = path.extname(filepath).toLowerCase();
|
|
88
|
+
const langMap = {
|
|
89
|
+
'.js': 'javascript',
|
|
90
|
+
'.mjs': 'javascript',
|
|
91
|
+
'.ts': 'typescript',
|
|
92
|
+
'.tsx': 'typescript',
|
|
93
|
+
'.py': 'python',
|
|
94
|
+
'.rs': 'rust',
|
|
95
|
+
'.go': 'go',
|
|
96
|
+
'.rb': 'ruby',
|
|
97
|
+
};
|
|
98
|
+
return langMap[ext] || 'javascript';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Get execution command for language
|
|
103
|
+
*/
|
|
104
|
+
function getExecCommand(language, filename) {
|
|
105
|
+
const commands = {
|
|
106
|
+
javascript: `node ${filename}`,
|
|
107
|
+
typescript: `npx tsx ${filename}`,
|
|
108
|
+
python: `python ${filename}`,
|
|
109
|
+
rust: `rustc ${filename} -o /tmp/out && /tmp/out`,
|
|
110
|
+
go: `go run ${filename}`,
|
|
111
|
+
ruby: `ruby ${filename}`,
|
|
112
|
+
};
|
|
113
|
+
return commands[language] || `node ${filename}`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ============================================================================
|
|
117
|
+
// SANDBOX EXECUTOR
|
|
118
|
+
// ============================================================================
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Execute code in Docker sandbox
|
|
122
|
+
*/
|
|
123
|
+
export async function executeInSandbox(code, options = {}) {
|
|
124
|
+
const {
|
|
125
|
+
language = 'javascript',
|
|
126
|
+
filename = 'main.js',
|
|
127
|
+
timeout = SANDBOX_CONFIG.limits.timeout,
|
|
128
|
+
allowNetwork = false,
|
|
129
|
+
env = {},
|
|
130
|
+
workdir = process.cwd(),
|
|
131
|
+
} = options;
|
|
132
|
+
|
|
133
|
+
const image = SANDBOX_CONFIG.images[language] || SANDBOX_CONFIG.defaultImage;
|
|
134
|
+
const tempDir = path.join(workdir, SANDBOX_CONFIG.workspace.tempDir);
|
|
135
|
+
const tempFile = path.join(tempDir, filename);
|
|
136
|
+
|
|
137
|
+
// Ensure temp directory exists
|
|
138
|
+
await fs.mkdir(tempDir, { recursive: true });
|
|
139
|
+
|
|
140
|
+
// Write code to temp file
|
|
141
|
+
await fs.writeFile(tempFile, code, 'utf8');
|
|
142
|
+
|
|
143
|
+
// Build Docker command
|
|
144
|
+
const dockerArgs = [
|
|
145
|
+
'run',
|
|
146
|
+
'--rm',
|
|
147
|
+
'-i',
|
|
148
|
+
`--memory=${SANDBOX_CONFIG.limits.memory}`,
|
|
149
|
+
`--cpus=${SANDBOX_CONFIG.limits.cpus}`,
|
|
150
|
+
allowNetwork ? '' : '--network=none',
|
|
151
|
+
`-v`, `${tempDir}:${SANDBOX_CONFIG.workspace.containerPath}:ro`,
|
|
152
|
+
`-w`, SANDBOX_CONFIG.workspace.containerPath,
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
// Add environment variables
|
|
156
|
+
for (const [key, value] of Object.entries(env)) {
|
|
157
|
+
dockerArgs.push('-e', `${key}=${value}`);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
dockerArgs.push(image);
|
|
161
|
+
|
|
162
|
+
// Add execution command
|
|
163
|
+
const execCmd = getExecCommand(language, filename);
|
|
164
|
+
dockerArgs.push('sh', '-c', execCmd);
|
|
165
|
+
|
|
166
|
+
// Filter empty strings
|
|
167
|
+
const filteredArgs = dockerArgs.filter(Boolean);
|
|
168
|
+
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const result = {
|
|
171
|
+
stdout: '',
|
|
172
|
+
stderr: '',
|
|
173
|
+
exitCode: null,
|
|
174
|
+
timedOut: false,
|
|
175
|
+
duration: 0,
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const startTime = Date.now();
|
|
179
|
+
const proc = spawn('docker', filteredArgs);
|
|
180
|
+
|
|
181
|
+
const timeoutId = setTimeout(() => {
|
|
182
|
+
result.timedOut = true;
|
|
183
|
+
proc.kill('SIGKILL');
|
|
184
|
+
}, timeout);
|
|
185
|
+
|
|
186
|
+
proc.stdout.on('data', (data) => {
|
|
187
|
+
result.stdout += data.toString();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
proc.stderr.on('data', (data) => {
|
|
191
|
+
result.stderr += data.toString();
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
proc.on('close', (code) => {
|
|
195
|
+
clearTimeout(timeoutId);
|
|
196
|
+
result.exitCode = code;
|
|
197
|
+
result.duration = Date.now() - startTime;
|
|
198
|
+
resolve(result);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
proc.on('error', (err) => {
|
|
202
|
+
clearTimeout(timeoutId);
|
|
203
|
+
reject(err);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Execute a file in sandbox
|
|
210
|
+
*/
|
|
211
|
+
export async function executeFile(filepath, options = {}) {
|
|
212
|
+
const code = await fs.readFile(filepath, 'utf8');
|
|
213
|
+
const language = detectLanguage(filepath);
|
|
214
|
+
const filename = path.basename(filepath);
|
|
215
|
+
|
|
216
|
+
return executeInSandbox(code, {
|
|
217
|
+
...options,
|
|
218
|
+
language,
|
|
219
|
+
filename,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Execute npm/shell command in sandbox
|
|
225
|
+
*/
|
|
226
|
+
export async function executeCommand(command, options = {}) {
|
|
227
|
+
const {
|
|
228
|
+
timeout = SANDBOX_CONFIG.limits.timeout,
|
|
229
|
+
workdir = process.cwd(),
|
|
230
|
+
allowNetwork = true, // Commands often need network
|
|
231
|
+
} = options;
|
|
232
|
+
|
|
233
|
+
const tempDir = path.join(workdir, SANDBOX_CONFIG.workspace.tempDir);
|
|
234
|
+
await fs.mkdir(tempDir, { recursive: true });
|
|
235
|
+
|
|
236
|
+
const dockerArgs = [
|
|
237
|
+
'run',
|
|
238
|
+
'--rm',
|
|
239
|
+
'-i',
|
|
240
|
+
`--memory=${SANDBOX_CONFIG.limits.memory}`,
|
|
241
|
+
`--cpus=${SANDBOX_CONFIG.limits.cpus}`,
|
|
242
|
+
allowNetwork ? '' : '--network=none',
|
|
243
|
+
`-v`, `${workdir}:${SANDBOX_CONFIG.workspace.containerPath}`,
|
|
244
|
+
`-w`, SANDBOX_CONFIG.workspace.containerPath,
|
|
245
|
+
SANDBOX_CONFIG.defaultImage,
|
|
246
|
+
'sh', '-c', command,
|
|
247
|
+
].filter(Boolean);
|
|
248
|
+
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
const result = {
|
|
251
|
+
stdout: '',
|
|
252
|
+
stderr: '',
|
|
253
|
+
exitCode: null,
|
|
254
|
+
timedOut: false,
|
|
255
|
+
duration: 0,
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
const startTime = Date.now();
|
|
259
|
+
const proc = spawn('docker', dockerArgs);
|
|
260
|
+
|
|
261
|
+
const timeoutId = setTimeout(() => {
|
|
262
|
+
result.timedOut = true;
|
|
263
|
+
proc.kill('SIGKILL');
|
|
264
|
+
}, timeout);
|
|
265
|
+
|
|
266
|
+
proc.stdout.on('data', (data) => {
|
|
267
|
+
result.stdout += data.toString();
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
proc.stderr.on('data', (data) => {
|
|
271
|
+
result.stderr += data.toString();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
proc.on('close', (code) => {
|
|
275
|
+
clearTimeout(timeoutId);
|
|
276
|
+
result.exitCode = code;
|
|
277
|
+
result.duration = Date.now() - startTime;
|
|
278
|
+
resolve(result);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
proc.on('error', (err) => {
|
|
282
|
+
clearTimeout(timeoutId);
|
|
283
|
+
reject(err);
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// ============================================================================
|
|
289
|
+
// TEST RUNNER
|
|
290
|
+
// ============================================================================
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Run tests in sandbox
|
|
294
|
+
*/
|
|
295
|
+
export async function runTests(testCommand = 'npm test', options = {}) {
|
|
296
|
+
const spinner = ora('Running tests in sandbox...').start();
|
|
297
|
+
|
|
298
|
+
try {
|
|
299
|
+
const result = await executeCommand(testCommand, {
|
|
300
|
+
...options,
|
|
301
|
+
allowNetwork: true, // Tests may need to install deps
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
if (result.exitCode === 0) {
|
|
305
|
+
spinner.succeed(chalk.green('Tests passed!'));
|
|
306
|
+
} else {
|
|
307
|
+
spinner.fail(chalk.red('Tests failed'));
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return result;
|
|
311
|
+
} catch (err) {
|
|
312
|
+
spinner.fail(chalk.red(`Test execution failed: ${err.message}`));
|
|
313
|
+
throw err;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// CLI COMMAND
|
|
319
|
+
// ============================================================================
|
|
320
|
+
|
|
321
|
+
export function registerExecCommand(program) {
|
|
322
|
+
program
|
|
323
|
+
.command('exec [file]')
|
|
324
|
+
.description('Execute code in isolated Docker sandbox')
|
|
325
|
+
.option('-c, --code <code>', 'Execute inline code')
|
|
326
|
+
.option('-l, --language <lang>', 'Language (js, ts, py, go, rs, rb)')
|
|
327
|
+
.option('-t, --timeout <ms>', 'Timeout in milliseconds', '60000')
|
|
328
|
+
.option('--allow-network', 'Allow network access in sandbox')
|
|
329
|
+
.option('--command <cmd>', 'Run shell command instead of file')
|
|
330
|
+
.option('--test', 'Run npm test in sandbox')
|
|
331
|
+
.action(async (file, options) => {
|
|
332
|
+
console.log(chalk.cyan('\nš³ Ultra-Dex Code Sandbox\n'));
|
|
333
|
+
|
|
334
|
+
// Check Docker availability
|
|
335
|
+
const spinner = ora('Checking Docker...').start();
|
|
336
|
+
const hasDocker = await checkDocker();
|
|
337
|
+
|
|
338
|
+
if (!hasDocker) {
|
|
339
|
+
spinner.fail(chalk.red('Docker not found. Please install Docker to use the sandbox.'));
|
|
340
|
+
console.log(chalk.yellow('\nInstall Docker: https://docs.docker.com/get-docker/'));
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
spinner.succeed('Docker available');
|
|
344
|
+
|
|
345
|
+
const timeout = parseInt(options.timeout, 10);
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
let result;
|
|
349
|
+
|
|
350
|
+
if (options.test) {
|
|
351
|
+
// Run tests
|
|
352
|
+
result = await runTests('npm test', { timeout, allowNetwork: true });
|
|
353
|
+
} else if (options.command) {
|
|
354
|
+
// Run shell command
|
|
355
|
+
spinner.start(`Executing: ${options.command}`);
|
|
356
|
+
result = await executeCommand(options.command, {
|
|
357
|
+
timeout,
|
|
358
|
+
allowNetwork: options.allowNetwork,
|
|
359
|
+
});
|
|
360
|
+
} else if (options.code) {
|
|
361
|
+
// Execute inline code
|
|
362
|
+
const language = options.language || 'javascript';
|
|
363
|
+
const image = SANDBOX_CONFIG.images[language];
|
|
364
|
+
|
|
365
|
+
spinner.start('Preparing sandbox...');
|
|
366
|
+
await ensureImage(image, spinner);
|
|
367
|
+
|
|
368
|
+
spinner.text = 'Executing code...';
|
|
369
|
+
result = await executeInSandbox(options.code, {
|
|
370
|
+
language,
|
|
371
|
+
timeout,
|
|
372
|
+
allowNetwork: options.allowNetwork,
|
|
373
|
+
});
|
|
374
|
+
} else if (file) {
|
|
375
|
+
// Execute file
|
|
376
|
+
const language = options.language || detectLanguage(file);
|
|
377
|
+
const image = SANDBOX_CONFIG.images[language];
|
|
378
|
+
|
|
379
|
+
spinner.start('Preparing sandbox...');
|
|
380
|
+
await ensureImage(image, spinner);
|
|
381
|
+
|
|
382
|
+
spinner.text = `Executing ${file}...`;
|
|
383
|
+
result = await executeFile(file, {
|
|
384
|
+
timeout,
|
|
385
|
+
allowNetwork: options.allowNetwork,
|
|
386
|
+
});
|
|
387
|
+
} else {
|
|
388
|
+
spinner.fail('No code, file, or command specified');
|
|
389
|
+
console.log(chalk.yellow('\nUsage:'));
|
|
390
|
+
console.log(' ultra-dex exec script.js');
|
|
391
|
+
console.log(' ultra-dex exec -c "console.log(1+1)"');
|
|
392
|
+
console.log(' ultra-dex exec --command "npm test"');
|
|
393
|
+
console.log(' ultra-dex exec --test');
|
|
394
|
+
return;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Show results
|
|
398
|
+
if (result.timedOut) {
|
|
399
|
+
spinner.fail(chalk.red(`Execution timed out after ${timeout}ms`));
|
|
400
|
+
} else if (result.exitCode === 0) {
|
|
401
|
+
spinner.succeed(chalk.green(`Completed in ${result.duration}ms`));
|
|
402
|
+
} else {
|
|
403
|
+
spinner.warn(chalk.yellow(`Exited with code ${result.exitCode}`));
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Print output
|
|
407
|
+
if (result.stdout) {
|
|
408
|
+
console.log(chalk.bold('\nš¤ Output:'));
|
|
409
|
+
console.log(result.stdout);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
if (result.stderr) {
|
|
413
|
+
console.log(chalk.bold('\nā ļø Stderr:'));
|
|
414
|
+
console.log(chalk.red(result.stderr));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Summary
|
|
418
|
+
console.log(chalk.gray(`\nā±ļø Duration: ${result.duration}ms`));
|
|
419
|
+
console.log(chalk.gray(`š Network: ${options.allowNetwork ? 'Enabled' : 'Disabled'}`));
|
|
420
|
+
|
|
421
|
+
} catch (err) {
|
|
422
|
+
spinner.fail(chalk.red(`Execution failed: ${err.message}`));
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export default {
|
|
428
|
+
registerExecCommand,
|
|
429
|
+
executeInSandbox,
|
|
430
|
+
executeFile,
|
|
431
|
+
executeCommand,
|
|
432
|
+
runTests,
|
|
433
|
+
checkDocker,
|
|
434
|
+
};
|
package/lib/commands/generate.js
CHANGED
|
@@ -13,11 +13,12 @@ import { SYSTEM_PROMPT, generateUserPrompt } from '../templates/prompts/generate
|
|
|
13
13
|
import { validateSafePath } from '../utils/validation.js';
|
|
14
14
|
import { githubTreeUrl, githubWebUrl } from '../config/urls.js';
|
|
15
15
|
import { saveState } from './plan.js';
|
|
16
|
+
import { getRandomMessage } from '../utils/messages.js';
|
|
16
17
|
|
|
17
18
|
export function registerGenerateCommand(program) {
|
|
18
19
|
program
|
|
19
20
|
.command('generate [idea]')
|
|
20
|
-
.description('
|
|
21
|
+
.description('Create the plan (Thanos style) - AI Generates Full Plan')
|
|
21
22
|
.option('-p, --provider <provider>', 'AI provider (claude, openai, gemini)')
|
|
22
23
|
.option('-m, --model <model>', 'Specific model to use')
|
|
23
24
|
.option('-o, --output <directory>', 'Output directory', '.')
|
|
@@ -25,7 +26,9 @@ export function registerGenerateCommand(program) {
|
|
|
25
26
|
.option('--stream', 'Stream output in real-time', true)
|
|
26
27
|
.option('--no-stream', 'Disable streaming')
|
|
27
28
|
.action(async (idea, options) => {
|
|
28
|
-
console.log(chalk.cyan('\nš Ultra-Dex Plan Generator\n'));
|
|
29
|
+
console.log(chalk.cyan('\nš Ultra-Dex Plan Generator (Reality Stone Mode)\n'));
|
|
30
|
+
console.log(chalk.hex('#7c3aed').italic(`"${getRandomMessage('start')}"`));
|
|
31
|
+
console.log('');
|
|
29
32
|
|
|
30
33
|
const dirValidation = validateSafePath(options.output, 'Output directory');
|
|
31
34
|
if (dirValidation !== true) {
|
|
@@ -38,7 +41,7 @@ export function registerGenerateCommand(program) {
|
|
|
38
41
|
const hasProvider = configured.some(p => p.configured) || options.key;
|
|
39
42
|
|
|
40
43
|
if (!hasProvider) {
|
|
41
|
-
console.log(chalk.yellow('ā ļø No AI
|
|
44
|
+
console.log(chalk.yellow('ā ļø No Infinity Stones (AI Keys) configured.\n'));
|
|
42
45
|
console.log(chalk.white('Set one of these environment variables:'));
|
|
43
46
|
configured.forEach(p => {
|
|
44
47
|
console.log(chalk.gray(` export ${p.envKey}=your-key-here`));
|
|
@@ -54,7 +57,7 @@ export function registerGenerateCommand(program) {
|
|
|
54
57
|
{
|
|
55
58
|
type: 'input',
|
|
56
59
|
name: 'idea',
|
|
57
|
-
message: 'Describe
|
|
60
|
+
message: 'Describe the reality you wish to create:',
|
|
58
61
|
validate: input => input.trim().length > 10 || 'Please provide a more detailed description',
|
|
59
62
|
},
|
|
60
63
|
]);
|
|
@@ -85,7 +88,7 @@ export function registerGenerateCommand(program) {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
// Generate the plan
|
|
88
|
-
const spinner = ora('
|
|
91
|
+
const spinner = ora('Reshaping reality (Generating Plan)...').start();
|
|
89
92
|
const startTime = Date.now();
|
|
90
93
|
|
|
91
94
|
try {
|
|
@@ -94,7 +97,7 @@ export function registerGenerateCommand(program) {
|
|
|
94
97
|
|
|
95
98
|
if (options.stream) {
|
|
96
99
|
spinner.stop();
|
|
97
|
-
console.log(chalk.cyan('š
|
|
100
|
+
console.log(chalk.cyan('š Manifesting Reality:\n'));
|
|
98
101
|
console.log(chalk.gray('ā'.repeat(60)));
|
|
99
102
|
|
|
100
103
|
result = await provider.generateStream(
|
|
@@ -128,7 +131,7 @@ export function registerGenerateCommand(program) {
|
|
|
128
131
|
// Add header to plan
|
|
129
132
|
const header = `# Implementation Plan
|
|
130
133
|
|
|
131
|
-
> Generated by Ultra-Dex AI Plan Generator
|
|
134
|
+
> Generated by Ultra-Dex AI Plan Generator (Doomsday Edition)
|
|
132
135
|
|
|
133
136
|
`;
|
|
134
137
|
if (!planContent.startsWith('#')) {
|
|
@@ -208,17 +211,17 @@ ${idea}
|
|
|
208
211
|
2. Start with the first feature
|
|
209
212
|
3. Use Ultra-Dex agents for guidance
|
|
210
213
|
|
|
211
|
-
## AI Agents
|
|
212
|
-
- @Planner: Break down tasks
|
|
213
|
-
- @CTO: Architecture decisions
|
|
214
|
-
- @Backend: API logic
|
|
215
|
-
- @Frontend: UI components
|
|
216
|
-
- @Testing: QA and tests
|
|
214
|
+
## AI Agents (The Avengers)
|
|
215
|
+
- @Planner (Nick Fury): Break down tasks
|
|
216
|
+
- @CTO (Iron Man): Architecture decisions
|
|
217
|
+
- @Backend (Thor): API logic
|
|
218
|
+
- @Frontend (Spider-Man): UI components
|
|
219
|
+
- @Testing (Ant-Man): QA and tests
|
|
217
220
|
`;
|
|
218
221
|
|
|
219
222
|
await fs.writeFile(quickStartPath, quickStartContent);
|
|
220
223
|
|
|
221
|
-
spinner.succeed('
|
|
224
|
+
spinner.succeed(chalk.green('Reality successfully rewritten!'));
|
|
222
225
|
|
|
223
226
|
console.log(chalk.green('\nā
Files created:'));
|
|
224
227
|
console.log(chalk.gray(` ${planPath}`));
|
|
@@ -232,9 +235,9 @@ ${idea}
|
|
|
232
235
|
console.log(chalk.cyan(' 1. Review IMPLEMENTATION-PLAN.md'));
|
|
233
236
|
console.log(chalk.cyan(' 2. Run `ultra-dex dashboard` to visualize your progress'));
|
|
234
237
|
console.log(chalk.cyan(' 3. Run `ultra-dex build` to let Auto-Pilot take the first task'));
|
|
235
|
-
console.log(chalk.cyan(' 4.
|
|
238
|
+
console.log(chalk.cyan(' 4. Summon Avengers (AI agents) for guidance\n'));
|
|
236
239
|
} catch (err) {
|
|
237
|
-
spinner.fail('Failed to
|
|
240
|
+
spinner.fail(chalk.red('Failed to manifest reality'));
|
|
238
241
|
console.error(chalk.red('Error:'), err.message);
|
|
239
242
|
}
|
|
240
243
|
});
|