ultra-dex 2.2.1 → 3.2.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 +112 -151
- package/assets/agents/00-AGENT_INDEX.md +1 -1
- 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/assets/docs/LAUNCH-POSTS.md +1 -1
- package/assets/docs/QUICK-REFERENCE.md +9 -4
- package/assets/docs/VISION-V2.md +1 -1
- package/assets/hooks/pre-commit +98 -0
- package/assets/saas-plan/04-Imp-Template.md +1 -1
- package/bin/ultra-dex.js +132 -4
- package/lib/commands/advanced.js +471 -0
- package/lib/commands/agent-builder.js +226 -0
- package/lib/commands/agents.js +102 -42
- package/lib/commands/auto-implement.js +68 -0
- package/lib/commands/banner.js +43 -21
- package/lib/commands/build.js +78 -183
- package/lib/commands/ci-monitor.js +84 -0
- package/lib/commands/config.js +207 -0
- package/lib/commands/dashboard.js +770 -0
- package/lib/commands/diff.js +233 -0
- package/lib/commands/doctor.js +416 -0
- package/lib/commands/export.js +408 -0
- package/lib/commands/fix.js +96 -0
- package/lib/commands/generate.js +105 -78
- package/lib/commands/hooks.js +251 -76
- package/lib/commands/init.js +102 -54
- package/lib/commands/memory.js +80 -0
- package/lib/commands/plan.js +82 -0
- package/lib/commands/review.js +34 -5
- package/lib/commands/run.js +233 -0
- package/lib/commands/scaffold.js +151 -0
- package/lib/commands/serve.js +179 -146
- package/lib/commands/state.js +327 -0
- package/lib/commands/swarm.js +306 -0
- package/lib/commands/sync.js +82 -23
- package/lib/commands/team.js +275 -0
- package/lib/commands/upgrade.js +190 -0
- package/lib/commands/validate.js +34 -0
- package/lib/commands/verify.js +81 -0
- package/lib/commands/watch.js +79 -0
- package/lib/config/theme.js +47 -0
- package/lib/mcp/graph.js +92 -0
- package/lib/mcp/memory.js +95 -0
- package/lib/mcp/resources.js +152 -0
- package/lib/mcp/server.js +34 -0
- package/lib/mcp/tools.js +481 -0
- package/lib/mcp/websocket.js +117 -0
- package/lib/providers/index.js +49 -4
- package/lib/providers/ollama.js +136 -0
- package/lib/providers/router.js +63 -0
- package/lib/quality/scanner.js +128 -0
- package/lib/swarm/coordinator.js +97 -0
- package/lib/swarm/index.js +598 -0
- package/lib/swarm/protocol.js +677 -0
- package/lib/swarm/tiers.js +485 -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/templates/custom-agent.md +10 -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/files.js +14 -0
- package/lib/utils/graph.js +108 -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 +31 -13
package/lib/commands/agents.js
CHANGED
|
@@ -4,8 +4,11 @@ import path from 'path';
|
|
|
4
4
|
import { ASSETS_ROOT, ROOT_FALLBACK } from '../config/paths.js';
|
|
5
5
|
import { githubBlobUrl } from '../config/urls.js';
|
|
6
6
|
import { readWithFallback } from '../utils/fallback.js';
|
|
7
|
+
import { pathExists } from '../utils/files.js';
|
|
8
|
+
import { showAgentsTable } from '../utils/tables.js';
|
|
7
9
|
|
|
8
10
|
export const AGENTS = [
|
|
11
|
+
{ name: 'orchestrator', description: 'Multi-agent coordination', file: '0-orchestration/orchestrator.md', tier: 'Orchestration' },
|
|
9
12
|
{ name: 'cto', description: 'Architecture & tech decisions', file: '1-leadership/cto.md', tier: 'Leadership' },
|
|
10
13
|
{ name: 'planner', description: 'Task breakdown & planning', file: '1-leadership/planner.md', tier: 'Leadership' },
|
|
11
14
|
{ name: 'research', description: 'Technology evaluation & comparison', file: '1-leadership/research.md', tier: 'Leadership' },
|
|
@@ -23,63 +26,120 @@ export const AGENTS = [
|
|
|
23
26
|
{ name: 'refactoring', description: 'Code quality & design patterns', file: '6-specialist/refactoring.md', tier: 'Specialist' },
|
|
24
27
|
];
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
const CUSTOM_AGENTS_DIR = path.join(process.cwd(), '.ultra-dex', 'custom-agents');
|
|
30
|
+
|
|
31
|
+
export function findBuiltInAgent(name) {
|
|
32
|
+
return AGENTS.find(a => a.name.toLowerCase() === name.toLowerCase());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export async function listCustomAgents() {
|
|
36
|
+
try {
|
|
37
|
+
const entries = await fs.readdir(CUSTOM_AGENTS_DIR, { withFileTypes: true });
|
|
38
|
+
return entries
|
|
39
|
+
.filter(entry => entry.isFile() && entry.name.endsWith('.md'))
|
|
40
|
+
.map(entry => entry.name.replace(/\.md$/, ''));
|
|
41
|
+
} catch {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export async function getCustomAgentPath(name) {
|
|
47
|
+
const filePath = path.join(CUSTOM_AGENTS_DIR, `${name}.md`);
|
|
48
|
+
if (await pathExists(filePath)) {
|
|
49
|
+
return filePath;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function readCustomAgent(name) {
|
|
55
|
+
const filePath = await getCustomAgentPath(name);
|
|
56
|
+
if (!filePath) {
|
|
57
|
+
throw new Error(`Custom agent "${name}" not found.`);
|
|
58
|
+
}
|
|
59
|
+
return fs.readFile(filePath, 'utf-8');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function readAgentPrompt(agent) {
|
|
27
63
|
const agentPath = path.join(ASSETS_ROOT, 'agents', agent.file);
|
|
28
64
|
const fallbackPath = path.join(ROOT_FALLBACK, 'agents', agent.file);
|
|
29
65
|
return readWithFallback(agentPath, fallbackPath, 'utf-8');
|
|
30
66
|
}
|
|
31
67
|
|
|
32
68
|
export function registerAgentsCommand(program) {
|
|
33
|
-
program
|
|
69
|
+
const agents = program
|
|
34
70
|
.command('agents')
|
|
35
71
|
.description('List available AI agent prompts')
|
|
36
|
-
.action(() => {
|
|
37
|
-
|
|
38
|
-
console.log(chalk.gray('Organized by tier for production pipeline\n'));
|
|
39
|
-
|
|
40
|
-
let currentTier = '';
|
|
41
|
-
AGENTS.forEach((agent) => {
|
|
42
|
-
if (agent.tier !== currentTier) {
|
|
43
|
-
currentTier = agent.tier;
|
|
44
|
-
console.log(chalk.bold(`\n ${currentTier} Tier:`));
|
|
45
|
-
}
|
|
46
|
-
console.log(chalk.cyan(` ${agent.name}`) + chalk.gray(` - ${agent.description}`));
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
console.log('\n' + chalk.bold('Usage:'));
|
|
50
|
-
console.log(chalk.gray(' ultra-dex agent <name> Show agent prompt'));
|
|
51
|
-
console.log(chalk.gray(' ultra-dex agent backend Example: show backend agent'));
|
|
52
|
-
|
|
53
|
-
console.log(`\n${chalk.gray(`Agent Index: ${githubBlobUrl('agents/00-AGENT_INDEX.md')}\n`)}`);
|
|
72
|
+
.action(async () => {
|
|
73
|
+
await listAgents();
|
|
54
74
|
});
|
|
55
75
|
|
|
56
76
|
program
|
|
57
|
-
.command('agent
|
|
58
|
-
.description('Show a specific agent prompt')
|
|
77
|
+
.command('agent [name]')
|
|
78
|
+
.description('Show a specific agent prompt or list all agents')
|
|
59
79
|
.action(async (name) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
console.log(chalk.gray('Available agents:'));
|
|
65
|
-
AGENTS.forEach(a => console.log(chalk.cyan(` - ${a.name}`)));
|
|
66
|
-
console.log('\n' + chalk.gray('Run "ultra-dex agents" to see all agents.\n'));
|
|
67
|
-
process.exit(1);
|
|
80
|
+
if (!name) {
|
|
81
|
+
await listAgents();
|
|
82
|
+
} else {
|
|
83
|
+
await showAgent(name);
|
|
68
84
|
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
69
87
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
88
|
+
async function listAgents() {
|
|
89
|
+
const customAgents = await listCustomAgents();
|
|
90
|
+
const totalAgents = AGENTS.length + customAgents.length;
|
|
91
|
+
console.log(chalk.bold(`\n🤖 Ultra-Dex AI Agents (${totalAgents} Total)\n`));
|
|
92
|
+
|
|
93
|
+
// Format agents for the table
|
|
94
|
+
const agentsForTable = AGENTS.map(agent => ({
|
|
95
|
+
tier: agent.tier,
|
|
96
|
+
name: agent.name,
|
|
97
|
+
status: 'ready'
|
|
98
|
+
}));
|
|
99
|
+
|
|
100
|
+
if (customAgents.length > 0) {
|
|
101
|
+
customAgents.forEach(name => {
|
|
102
|
+
agentsForTable.push({
|
|
103
|
+
tier: 'Custom',
|
|
104
|
+
name: name,
|
|
105
|
+
status: 'ready'
|
|
106
|
+
});
|
|
82
107
|
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
showAgentsTable(agentsForTable);
|
|
111
|
+
|
|
112
|
+
console.log('\n' + chalk.bold('Usage:'));
|
|
113
|
+
console.log(chalk.gray(' ultra-dex agent show <name> Show agent prompt'));
|
|
114
|
+
console.log(chalk.gray(' ultra-dex pack <name> Package agent + context'));
|
|
115
|
+
|
|
116
|
+
console.log(`\n${chalk.gray(`Agent Index: ${githubBlobUrl('agents/00-AGENT_INDEX.md')}\n`)}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function showAgent(name) {
|
|
120
|
+
const agent = AGENTS.find(a => a.name.toLowerCase() === name.toLowerCase());
|
|
121
|
+
if (!agent) {
|
|
122
|
+
const custom = await getCustomAgentPath(name);
|
|
123
|
+
if (custom) {
|
|
124
|
+
const content = await fs.readFile(custom, 'utf-8');
|
|
125
|
+
console.log(chalk.bold(`\n🤖 Custom Agent: ${name}\n`));
|
|
126
|
+
console.log(content);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
console.log(chalk.red(`\n❌ Agent "${name}" not found.`));
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const prompt = await readAgentPrompt(agent);
|
|
135
|
+
console.log(chalk.bold(`\n🤖 Agent: ${agent.name} (${agent.tier})\n`));
|
|
136
|
+
console.log(chalk.gray(agent.description) + '\n');
|
|
137
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
138
|
+
console.log(prompt);
|
|
139
|
+
console.log(chalk.gray('─'.repeat(60)));
|
|
140
|
+
} catch (err) {
|
|
141
|
+
console.log(chalk.red(`\n❌ Could not read prompt for ${agent.name}`));
|
|
142
|
+
}
|
|
83
143
|
}
|
|
84
144
|
|
|
85
145
|
export function registerPackCommand(program) {
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ultra-dex auto-implement command
|
|
3
|
+
* Fully autonomous feature implementation (GOD MODE)
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import { updateState } from './state.js';
|
|
9
|
+
import { buildGraph } from '../utils/graph.js';
|
|
10
|
+
import { createProvider, getDefaultProvider } from '../providers/index.js';
|
|
11
|
+
import { runAgentLoop } from './run.js';
|
|
12
|
+
|
|
13
|
+
export function registerAutoImplementCommand(program) {
|
|
14
|
+
program
|
|
15
|
+
.command('auto-implement <feature>')
|
|
16
|
+
.description('Autonomous implementation: Plan -> Code -> Verify (God Mode)')
|
|
17
|
+
.option('-p, --provider <provider>', 'AI provider (defaults to router if configured)')
|
|
18
|
+
.option('--dry-run', 'Show plan without making changes')
|
|
19
|
+
.action(async (feature, options) => {
|
|
20
|
+
console.log(chalk.cyan('\n🚀 Ultra-Dex Autonomous Implementation Engine\n'));
|
|
21
|
+
console.log(chalk.bold(`Target Feature: ${feature}\n`));
|
|
22
|
+
|
|
23
|
+
const providerId = options.provider || getDefaultProvider() || 'router';
|
|
24
|
+
const provider = createProvider(providerId);
|
|
25
|
+
|
|
26
|
+
const spinner = ora('Initializing God Mode Swarm...').start();
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
// 1. Structural Awareness (CPG)
|
|
30
|
+
const graph = await buildGraph();
|
|
31
|
+
spinner.text = 'Analyzing architectural impact...';
|
|
32
|
+
|
|
33
|
+
// 2. Planning Phase (@Planner)
|
|
34
|
+
spinner.text = '@Planner is breaking down the feature...';
|
|
35
|
+
const projectContext = {
|
|
36
|
+
context: `Feature Request: ${feature}\nCodebase Nodes: ${graph.nodes.length}\nEdges: ${graph.edges.length}`,
|
|
37
|
+
graph
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const plan = await runAgentLoop('planner', `Break down this feature: ${feature}`, provider, projectContext);
|
|
41
|
+
|
|
42
|
+
if (options.dryRun) {
|
|
43
|
+
spinner.succeed('Planning complete (Dry Run)');
|
|
44
|
+
console.log(chalk.white('\nProposed Plan:'));
|
|
45
|
+
console.log(chalk.gray(plan));
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 3. Execution Phase (@Backend/@Frontend)
|
|
50
|
+
spinner.text = 'Agents are implementing code...';
|
|
51
|
+
await runAgentLoop('orchestrator', `Coordinate the implementation of this plan:\n${plan}`, provider, projectContext);
|
|
52
|
+
|
|
53
|
+
// 4. Verification Phase (@Testing)
|
|
54
|
+
spinner.text = '@Testing is verifying changes...';
|
|
55
|
+
const verification = await runAgentLoop('testing', `Verify the implementation of: ${feature}`, provider, projectContext);
|
|
56
|
+
|
|
57
|
+
// 5. Finalize
|
|
58
|
+
await updateState();
|
|
59
|
+
spinner.succeed(chalk.green('Feature implemented autonomously!'));
|
|
60
|
+
|
|
61
|
+
console.log(chalk.bold('\nFinal Report:'));
|
|
62
|
+
console.log(chalk.gray(verification));
|
|
63
|
+
|
|
64
|
+
} catch (e) {
|
|
65
|
+
spinner.fail(chalk.red(`Auto-Implementation failed: ${e.message}`));
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
package/lib/commands/banner.js
CHANGED
|
@@ -1,21 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
1
|
+
import gradient from 'gradient-string';
|
|
2
|
+
import boxen from 'boxen';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
const ultraGradient = gradient(['#6366f1', '#8b5cf6', '#d946ef']);
|
|
6
|
+
|
|
7
|
+
const asciiLogo = `
|
|
8
|
+
██╗ ██╗██╗ ████████╗██████╗ █████╗ ██████╗ ███████╗██╗ ██╗
|
|
9
|
+
██║ ██║██║ ╚══██╔══╝██╔══██╗██╔══██╗ ██╔══██╗██╔════╝╚██╗██╔╝
|
|
10
|
+
██║ ██║██║ ██║ ██████╔╝███████║█████╗██║ ██║█████╗ ╚███╔╝
|
|
11
|
+
██║ ██║██║ ██║ ██╔══██╗██╔══██║╚════╝██║ ██║██╔══╝ ██╔██╗
|
|
12
|
+
╚██████╔╝███████╗██║ ██║ ██║██║ ██║ ██████╔╝███████╗██╔╝ ██╗
|
|
13
|
+
╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝`;
|
|
14
|
+
|
|
15
|
+
export const banner = asciiLogo;
|
|
16
|
+
|
|
17
|
+
export function showBanner(version = '3.2.0') {
|
|
18
|
+
console.log(ultraGradient(asciiLogo));
|
|
19
|
+
console.log(boxen(
|
|
20
|
+
`${chalk.hex('#8b5cf6').bold('🪐 Ultra-Dex')} ${chalk.dim('v' + version)}
|
|
21
|
+
|
|
22
|
+
` +
|
|
23
|
+
`${chalk.hex('#6366f1')('AI Orchestration Meta-Layer')}
|
|
24
|
+
|
|
25
|
+
` +
|
|
26
|
+
`${chalk.dim('github.com/Srujan0798/Ultra-Dex')}`,
|
|
27
|
+
{
|
|
28
|
+
padding: 1,
|
|
29
|
+
margin: 1,
|
|
30
|
+
borderStyle: 'round',
|
|
31
|
+
borderColor: '#8b5cf6',
|
|
32
|
+
dimBorder: true
|
|
33
|
+
}
|
|
34
|
+
));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function showCompactBanner() {
|
|
38
|
+
console.log(` ${chalk.hex('#8b5cf6').bold('🪐 Ultra-Dex')} ${chalk.dim('v3.2.0')}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function showWelcome() {
|
|
42
|
+
showBanner();
|
|
43
|
+
}
|
package/lib/commands/build.js
CHANGED
|
@@ -1,213 +1,108 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ultra-dex build command
|
|
3
|
-
* Auto-
|
|
3
|
+
* Auto-Pilot: Finds the next pending task and executes it using Agents.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
import ora from 'ora';
|
|
8
|
-
import inquirer from 'inquirer';
|
|
9
8
|
import fs from 'fs/promises';
|
|
10
9
|
import path from 'path';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
auth: { name: '@Auth', tier: 'Security', task: 'Authentication and authorization' },
|
|
24
|
-
security: { name: '@Security', tier: 'Security', task: 'Security audit' },
|
|
25
|
-
testing: { name: '@Testing', tier: 'Quality', task: 'Write and run tests' },
|
|
26
|
-
reviewer: { name: '@Reviewer', tier: 'Quality', task: 'Code review' },
|
|
27
|
-
devops: { name: '@DevOps', tier: 'DevOps', task: 'Deployment and CI/CD' },
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
async function readFileSafe(filePath) {
|
|
31
|
-
try {
|
|
32
|
-
return await fs.readFile(filePath, 'utf-8');
|
|
33
|
-
} catch {
|
|
34
|
-
return null;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function fileExists(filePath) {
|
|
39
|
-
try {
|
|
40
|
-
await fs.access(filePath);
|
|
41
|
-
return true;
|
|
42
|
-
} catch {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
10
|
+
import { loadState } from './plan.js';
|
|
11
|
+
import { runAgentLoop } from './run.js';
|
|
12
|
+
import { createProvider, getDefaultProvider, checkConfiguredProviders } from '../providers/index.js';
|
|
13
|
+
import { showProgress } from '../utils/progress.js';
|
|
14
|
+
import { getRandomMessage } from '../utils/messages.js';
|
|
15
|
+
|
|
16
|
+
async function readProjectContext() {
|
|
17
|
+
const context = {};
|
|
18
|
+
try { context.plan = await fs.readFile('IMPLEMENTATION-PLAN.md', 'utf8'); } catch { context.plan = null; }
|
|
19
|
+
try { context.context = await fs.readFile('CONTEXT.md', 'utf8'); } catch { context.context = null; }
|
|
20
|
+
context.state = await loadState();
|
|
21
|
+
return context;
|
|
45
22
|
}
|
|
46
23
|
|
|
47
24
|
export function registerBuildCommand(program) {
|
|
48
25
|
program
|
|
49
26
|
.command('build')
|
|
50
|
-
.description('
|
|
51
|
-
.option('-
|
|
52
|
-
.option('-
|
|
53
|
-
.option('--
|
|
54
|
-
.option('--cursor', 'Open in Cursor IDE')
|
|
27
|
+
.description('Auto-Pilot: Execute the next pending task from the plan')
|
|
28
|
+
.option('-p, --provider <provider>', 'AI provider')
|
|
29
|
+
.option('-k, --key <apiKey>', 'API key')
|
|
30
|
+
.option('--dry-run', 'Preview the task without executing')
|
|
55
31
|
.action(async (options) => {
|
|
56
|
-
console.log(chalk.cyan('\n
|
|
57
|
-
|
|
58
|
-
// Check for
|
|
59
|
-
const
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
console.log(chalk.
|
|
65
|
-
console.log(chalk.white('Run one of these first:'));
|
|
66
|
-
console.log(chalk.gray(' npx ultra-dex init # Create from template'));
|
|
67
|
-
console.log(chalk.gray(' npx ultra-dex generate # Generate from idea\n'));
|
|
32
|
+
console.log(chalk.cyan('\n⚡ Ultra-Dex Auto-Pilot\n'));
|
|
33
|
+
|
|
34
|
+
// Check for API key
|
|
35
|
+
const configured = checkConfiguredProviders();
|
|
36
|
+
const hasProvider = configured.some(p => p.configured) || options.key;
|
|
37
|
+
|
|
38
|
+
if (!hasProvider && !options.dryRun) {
|
|
39
|
+
console.log(chalk.yellow('⚠️ No API keys found.'));
|
|
40
|
+
console.log(chalk.white('Set an API key to enable Auto-Pilot.'));
|
|
68
41
|
return;
|
|
69
42
|
}
|
|
70
43
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const quickStart = await readFileSafe('QUICK-START.md');
|
|
44
|
+
const state = await loadState();
|
|
45
|
+
if (!state) {
|
|
46
|
+
console.log(chalk.red('❌ No project state found. Run "ultra-dex init" first.'));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
77
49
|
|
|
78
|
-
|
|
50
|
+
// Find next pending task
|
|
51
|
+
let nextTask = null;
|
|
52
|
+
let currentPhase = null;
|
|
79
53
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
message: 'Select an agent:',
|
|
88
|
-
choices: [
|
|
89
|
-
new inquirer.Separator('── Leadership ──'),
|
|
90
|
-
{ name: '📋 @Planner - Break down tasks', value: 'planner' },
|
|
91
|
-
{ name: '🏗️ @CTO - Architecture decisions', value: 'cto' },
|
|
92
|
-
new inquirer.Separator('── Development ──'),
|
|
93
|
-
{ name: '⚙️ @Backend - API endpoints', value: 'backend' },
|
|
94
|
-
{ name: '🎨 @Frontend - UI components', value: 'frontend' },
|
|
95
|
-
{ name: '🗄️ @Database - Schema design', value: 'database' },
|
|
96
|
-
new inquirer.Separator('── Security ──'),
|
|
97
|
-
{ name: '🔐 @Auth - Authentication', value: 'auth' },
|
|
98
|
-
{ name: '🛡️ @Security - Security audit', value: 'security' },
|
|
99
|
-
new inquirer.Separator('── Quality ──'),
|
|
100
|
-
{ name: '🧪 @Testing - Write tests', value: 'testing' },
|
|
101
|
-
{ name: '👁️ @Reviewer - Code review', value: 'reviewer' },
|
|
102
|
-
new inquirer.Separator('── DevOps ──'),
|
|
103
|
-
{ name: '🚀 @DevOps - Deployment', value: 'devops' },
|
|
104
|
-
],
|
|
105
|
-
},
|
|
106
|
-
]);
|
|
107
|
-
agent = selectedAgent;
|
|
54
|
+
for (const phase of state.phases) {
|
|
55
|
+
const pending = phase.steps.find(s => s.status !== 'completed');
|
|
56
|
+
if (pending) {
|
|
57
|
+
nextTask = pending;
|
|
58
|
+
currentPhase = phase;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
108
61
|
}
|
|
109
62
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
console.log(chalk.red(`Unknown agent: ${agent}`));
|
|
113
|
-
console.log(chalk.gray(`Available: ${Object.keys(AGENTS).join(', ')}`));
|
|
63
|
+
if (!nextTask) {
|
|
64
|
+
console.log(chalk.green('✅ All phases completed! The project is ready.'));
|
|
114
65
|
return;
|
|
115
66
|
}
|
|
116
67
|
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
68
|
+
// Show Progress
|
|
69
|
+
showProgress([`Phase: ${currentPhase.name}`, `Target: ${nextTask.task}`]);
|
|
70
|
+
|
|
71
|
+
// Heuristic to pick agent (naive)
|
|
72
|
+
let agentName = 'backend'; // default
|
|
73
|
+
const taskLower = nextTask.task.toLowerCase();
|
|
74
|
+
if (taskLower.includes('ui') || taskLower.includes('component') || taskLower.includes('page')) agentName = 'frontend';
|
|
75
|
+
if (taskLower.includes('db') || taskLower.includes('schema') || taskLower.includes('database')) agentName = 'database';
|
|
76
|
+
if (taskLower.includes('plan') || taskLower.includes('break down')) agentName = 'planner';
|
|
77
|
+
if (taskLower.includes('test')) agentName = 'testing';
|
|
78
|
+
|
|
79
|
+
console.log(chalk.gray(`Activating Agent: @${agentName}`));
|
|
80
|
+
|
|
81
|
+
if (options.dryRun) {
|
|
82
|
+
console.log(chalk.yellow('\nDry run mode. Exiting.'));
|
|
83
|
+
return;
|
|
129
84
|
}
|
|
130
85
|
|
|
131
|
-
|
|
132
|
-
const
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
## Output Format
|
|
152
|
-
- For code: Include full file paths and production-ready code
|
|
153
|
-
- For plans: Use atomic tasks (4-9 hours each)
|
|
154
|
-
- For reviews: Use severity levels (critical, warning, info)
|
|
155
|
-
|
|
156
|
-
Begin working on: ${task}
|
|
157
|
-
`;
|
|
158
|
-
|
|
159
|
-
// Output the prompt
|
|
160
|
-
console.log(chalk.green(`\n✅ ${agentConfig.name} prompt ready\n`));
|
|
161
|
-
|
|
162
|
-
if (options.copy) {
|
|
163
|
-
// Copy to clipboard
|
|
164
|
-
try {
|
|
165
|
-
const platform = process.platform;
|
|
166
|
-
if (platform === 'darwin') {
|
|
167
|
-
await execAsync(`echo ${JSON.stringify(prompt)} | pbcopy`);
|
|
168
|
-
} else if (platform === 'linux') {
|
|
169
|
-
await execAsync(`echo ${JSON.stringify(prompt)} | xclip -selection clipboard`);
|
|
170
|
-
} else if (platform === 'win32') {
|
|
171
|
-
await execAsync(`echo ${JSON.stringify(prompt)} | clip`);
|
|
172
|
-
}
|
|
173
|
-
console.log(chalk.cyan('📋 Prompt copied to clipboard!'));
|
|
174
|
-
console.log(chalk.gray('Paste into your AI tool (Cursor, Claude, ChatGPT)\n'));
|
|
175
|
-
} catch {
|
|
176
|
-
console.log(chalk.yellow('Could not copy to clipboard. Displaying prompt instead:\n'));
|
|
177
|
-
console.log(chalk.gray('─'.repeat(60)));
|
|
178
|
-
console.log(prompt);
|
|
179
|
-
console.log(chalk.gray('─'.repeat(60)));
|
|
180
|
-
}
|
|
181
|
-
} else if (options.cursor) {
|
|
182
|
-
// Save prompt and open Cursor
|
|
183
|
-
const promptPath = path.join('.ultra-dex', 'current-prompt.md');
|
|
184
|
-
await fs.mkdir('.ultra-dex', { recursive: true });
|
|
185
|
-
await fs.writeFile(promptPath, prompt);
|
|
186
|
-
|
|
187
|
-
console.log(chalk.gray(`Prompt saved to: ${promptPath}`));
|
|
188
|
-
console.log(chalk.cyan('Opening Cursor...\n'));
|
|
189
|
-
|
|
190
|
-
try {
|
|
191
|
-
await execAsync('cursor .');
|
|
192
|
-
} catch {
|
|
193
|
-
console.log(chalk.yellow('Could not open Cursor. Is it installed?'));
|
|
194
|
-
console.log(chalk.gray('Install: https://cursor.sh'));
|
|
195
|
-
}
|
|
196
|
-
} else {
|
|
197
|
-
// Display the prompt
|
|
198
|
-
console.log(chalk.gray('─'.repeat(60)));
|
|
199
|
-
console.log(prompt);
|
|
200
|
-
console.log(chalk.gray('─'.repeat(60)));
|
|
201
|
-
|
|
202
|
-
console.log(chalk.cyan('\n📋 Copy this prompt into your AI tool'));
|
|
203
|
-
console.log(chalk.gray('Or use --copy to copy to clipboard\n'));
|
|
86
|
+
const providerId = options.provider || getDefaultProvider();
|
|
87
|
+
const provider = createProvider(providerId, { apiKey: options.key, maxTokens: 8000 });
|
|
88
|
+
const context = await readProjectContext();
|
|
89
|
+
|
|
90
|
+
console.log(chalk.gray('─'.repeat(50)));
|
|
91
|
+
|
|
92
|
+
const spinner = ora(getRandomMessage('loading')).start();
|
|
93
|
+
try {
|
|
94
|
+
const result = await runAgentLoop(agentName, nextTask.task, provider, context);
|
|
95
|
+
spinner.succeed(chalk.green('Task execution completed'));
|
|
96
|
+
|
|
97
|
+
// Save output
|
|
98
|
+
const filename = `task-${nextTask.id}-${agentName}.md`;
|
|
99
|
+
await fs.writeFile(filename, result);
|
|
100
|
+
console.log(chalk.green(`\n✅ Task output saved to ${filename}`));
|
|
101
|
+
console.log(chalk.gray('Review the code and mark the task as completed in .ultra/state.json'));
|
|
102
|
+
} catch (error) {
|
|
103
|
+
spinner.fail(chalk.red('Task execution failed'));
|
|
104
|
+
console.error(error);
|
|
204
105
|
}
|
|
205
|
-
|
|
206
|
-
// Show next steps
|
|
207
|
-
console.log(chalk.white('Tips:'));
|
|
208
|
-
console.log(chalk.gray(' • Paste the prompt into Cursor, Claude, or ChatGPT'));
|
|
209
|
-
console.log(chalk.gray(' • Use "npx ultra-dex serve" for MCP-compatible context'));
|
|
210
|
-
console.log(chalk.gray(' • Run "npx ultra-dex review" after making changes\n'));
|
|
211
106
|
});
|
|
212
107
|
}
|
|
213
108
|
|