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.
Files changed (87) hide show
  1. package/README.md +112 -151
  2. package/assets/agents/00-AGENT_INDEX.md +1 -1
  3. package/assets/code-patterns/clerk-middleware.ts +138 -0
  4. package/assets/code-patterns/prisma-schema.prisma +224 -0
  5. package/assets/code-patterns/rls-policies.sql +246 -0
  6. package/assets/code-patterns/server-actions.ts +191 -0
  7. package/assets/code-patterns/trpc-router.ts +258 -0
  8. package/assets/cursor-rules/13-ai-integration.mdc +155 -0
  9. package/assets/cursor-rules/14-server-components.mdc +81 -0
  10. package/assets/cursor-rules/15-server-actions.mdc +102 -0
  11. package/assets/cursor-rules/16-edge-middleware.mdc +105 -0
  12. package/assets/cursor-rules/17-streaming-ssr.mdc +138 -0
  13. package/assets/docs/LAUNCH-POSTS.md +1 -1
  14. package/assets/docs/QUICK-REFERENCE.md +9 -4
  15. package/assets/docs/VISION-V2.md +1 -1
  16. package/assets/hooks/pre-commit +98 -0
  17. package/assets/saas-plan/04-Imp-Template.md +1 -1
  18. package/bin/ultra-dex.js +132 -4
  19. package/lib/commands/advanced.js +471 -0
  20. package/lib/commands/agent-builder.js +226 -0
  21. package/lib/commands/agents.js +102 -42
  22. package/lib/commands/auto-implement.js +68 -0
  23. package/lib/commands/banner.js +43 -21
  24. package/lib/commands/build.js +78 -183
  25. package/lib/commands/ci-monitor.js +84 -0
  26. package/lib/commands/config.js +207 -0
  27. package/lib/commands/dashboard.js +770 -0
  28. package/lib/commands/diff.js +233 -0
  29. package/lib/commands/doctor.js +416 -0
  30. package/lib/commands/export.js +408 -0
  31. package/lib/commands/fix.js +96 -0
  32. package/lib/commands/generate.js +105 -78
  33. package/lib/commands/hooks.js +251 -76
  34. package/lib/commands/init.js +102 -54
  35. package/lib/commands/memory.js +80 -0
  36. package/lib/commands/plan.js +82 -0
  37. package/lib/commands/review.js +34 -5
  38. package/lib/commands/run.js +233 -0
  39. package/lib/commands/scaffold.js +151 -0
  40. package/lib/commands/serve.js +179 -146
  41. package/lib/commands/state.js +327 -0
  42. package/lib/commands/swarm.js +306 -0
  43. package/lib/commands/sync.js +82 -23
  44. package/lib/commands/team.js +275 -0
  45. package/lib/commands/upgrade.js +190 -0
  46. package/lib/commands/validate.js +34 -0
  47. package/lib/commands/verify.js +81 -0
  48. package/lib/commands/watch.js +79 -0
  49. package/lib/config/theme.js +47 -0
  50. package/lib/mcp/graph.js +92 -0
  51. package/lib/mcp/memory.js +95 -0
  52. package/lib/mcp/resources.js +152 -0
  53. package/lib/mcp/server.js +34 -0
  54. package/lib/mcp/tools.js +481 -0
  55. package/lib/mcp/websocket.js +117 -0
  56. package/lib/providers/index.js +49 -4
  57. package/lib/providers/ollama.js +136 -0
  58. package/lib/providers/router.js +63 -0
  59. package/lib/quality/scanner.js +128 -0
  60. package/lib/swarm/coordinator.js +97 -0
  61. package/lib/swarm/index.js +598 -0
  62. package/lib/swarm/protocol.js +677 -0
  63. package/lib/swarm/tiers.js +485 -0
  64. package/lib/templates/code/clerk-middleware.ts +138 -0
  65. package/lib/templates/code/prisma-schema.prisma +224 -0
  66. package/lib/templates/code/rls-policies.sql +246 -0
  67. package/lib/templates/code/server-actions.ts +191 -0
  68. package/lib/templates/code/trpc-router.ts +258 -0
  69. package/lib/templates/custom-agent.md +10 -0
  70. package/lib/themes/doomsday.js +229 -0
  71. package/lib/ui/index.js +5 -0
  72. package/lib/ui/interface.js +241 -0
  73. package/lib/ui/spinners.js +116 -0
  74. package/lib/ui/theme.js +183 -0
  75. package/lib/utils/agents.js +32 -0
  76. package/lib/utils/files.js +14 -0
  77. package/lib/utils/graph.js +108 -0
  78. package/lib/utils/help.js +64 -0
  79. package/lib/utils/messages.js +35 -0
  80. package/lib/utils/progress.js +24 -0
  81. package/lib/utils/prompts.js +47 -0
  82. package/lib/utils/spinners.js +46 -0
  83. package/lib/utils/status.js +31 -0
  84. package/lib/utils/tables.js +41 -0
  85. package/lib/utils/theme-state.js +9 -0
  86. package/lib/utils/version-display.js +32 -0
  87. package/package.json +31 -13
@@ -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
- async function readAgentPrompt(agent) {
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
- console.log(chalk.bold('\n🤖 Ultra-Dex AI Agents (15 Total)\n'));
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 <name>')
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
- const agent = AGENTS.find(a => a.name.toLowerCase() === name.toLowerCase());
61
-
62
- if (!agent) {
63
- console.log(chalk.red(`\n❌ Agent "${name}" not found.\n`));
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
- try {
71
- const content = await readAgentPrompt(agent);
72
- console.log(chalk.bold(`\n🤖 ${agent.name.toUpperCase()} Agent\n`));
73
- console.log(chalk.gray('─'.repeat(60)));
74
- console.log(content);
75
- console.log(chalk.gray('─'.repeat(60)));
76
- console.log(chalk.bold('\n📋 Copy the above prompt and paste into your AI tool.\n'));
77
- } catch (err) {
78
- console.log(chalk.bold(`\n🤖 ${agent.name.toUpperCase()} Agent\n`));
79
- console.log(chalk.gray('View full prompt on GitHub:'));
80
- console.log(chalk.blue(` ${githubBlobUrl(`agents/${agent.file}`)}\n`));
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
+ }
@@ -1,21 +1,43 @@
1
- export const banner = `
2
- ╔═══════════════════════════════════════════════════════════╗
3
- ║ ║
4
- ║ ██╗ ██╗██╗ ████████╗██████╗ █████╗ ║
5
- ║ ██║ ██║██║ ╚══██╔══╝██╔══██╗██╔══██╗ ║
6
- ║ ██║ ██║██║ ██║ ██████╔╝███████║ ║
7
- ║ ██║ ██║██║ ██║ ██╔══██╗██╔══██║ ║
8
- ╚██████╔╝███████╗██║ ██║ ██║██║ ██║ ║
9
- ║ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ║
10
- ║ ║
11
- ██████╗ ███████╗██╗ ██╗ ║
12
- ██╔══██╗██╔════╝╚██╗██╔╝ ║
13
- ██║ ██║█████╗ ╚███╔╝ ║
14
- ║ ██║ ██║██╔══╝ ██╔██╗ ║
15
- ║ ██████╔╝███████╗██╔╝ ██╗ ║
16
- ║ ╚═════╝ ╚══════╝╚═╝ ╚═╝ ║
17
- ║ ║
18
- ║ From Idea to Production-Ready SaaS ║
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
+ }
@@ -1,213 +1,108 @@
1
1
  /**
2
2
  * ultra-dex build command
3
- * Auto-loads context and starts AI-assisted development
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 { exec } from 'child_process';
12
- import { promisify } from 'util';
13
-
14
- const execAsync = promisify(exec);
15
-
16
- // Agent configurations
17
- const AGENTS = {
18
- planner: { name: '@Planner', tier: 'Leadership', task: 'Break down features into atomic tasks' },
19
- cto: { name: '@CTO', tier: 'Leadership', task: 'Architecture decisions' },
20
- backend: { name: '@Backend', tier: 'Development', task: 'API endpoints and business logic' },
21
- frontend: { name: '@Frontend', tier: 'Development', task: 'UI components and pages' },
22
- database: { name: '@Database', tier: 'Development', task: 'Schema design and migrations' },
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('Start AI-assisted development with auto-loaded context')
51
- .option('-a, --agent <agent>', 'Agent to use (planner, backend, frontend, etc.)')
52
- .option('-t, --task <task>', 'Specific task to work on')
53
- .option('--copy', 'Copy prompt to clipboard instead of displaying')
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🔧 Ultra-Dex Build Mode\n'));
57
-
58
- // Check for required files
59
- const hasContext = await fileExists('CONTEXT.md');
60
- const hasPlan = await fileExists('IMPLEMENTATION-PLAN.md');
61
- const hasQuickStart = await fileExists('QUICK-START.md');
62
-
63
- if (!hasContext && !hasPlan) {
64
- console.log(chalk.yellow('⚠️ No Ultra-Dex project found in current directory.\n'));
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
- // Load context files
72
- const spinner = ora('Loading project context...').start();
73
-
74
- const context = await readFileSafe('CONTEXT.md');
75
- const plan = await readFileSafe('IMPLEMENTATION-PLAN.md');
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
- spinner.succeed('Context loaded');
50
+ // Find next pending task
51
+ let nextTask = null;
52
+ let currentPhase = null;
79
53
 
80
- // Select agent if not provided
81
- let agent = options.agent;
82
- if (!agent) {
83
- const { selectedAgent } = await inquirer.prompt([
84
- {
85
- type: 'list',
86
- name: 'selectedAgent',
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
- const agentConfig = AGENTS[agent];
111
- if (!agentConfig) {
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
- // Get task if not provided
118
- let task = options.task;
119
- if (!task) {
120
- const { taskInput } = await inquirer.prompt([
121
- {
122
- type: 'input',
123
- name: 'taskInput',
124
- message: `What should ${agentConfig.name} do?`,
125
- default: agentConfig.task,
126
- },
127
- ]);
128
- task = taskInput;
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
- // Build the prompt
132
- const contextSection = context ? `## Project Context\n${context}\n` : '';
133
- const planSection = plan ? `## Implementation Plan (Summary)\n${plan.slice(0, 8000)}...\n[Full plan in IMPLEMENTATION-PLAN.md]\n` : '';
134
-
135
- const prompt = `# ${agentConfig.name} Agent Session
136
-
137
- You are acting as ${agentConfig.name} for this project.
138
-
139
- ${contextSection}
140
- ${planSection}
141
-
142
- ## Your Task
143
- ${task}
144
-
145
- ## Instructions
146
- 1. Read the context and plan carefully
147
- 2. Focus ONLY on your assigned task
148
- 3. Follow Ultra-Dex 21-step verification for any code changes
149
- 4. Document your work in a way the next agent can continue
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