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
@@ -2,172 +2,205 @@ import chalk from 'chalk';
2
2
  import http from 'http';
3
3
  import fs from 'fs/promises';
4
4
  import path from 'path';
5
- import { readFileSafe } from '../utils/files.js';
5
+ import { loadState, generateMarkdown } from './plan.js';
6
+ import { startMcpServer } from '../mcp/server.js';
7
+ import { projectGraph } from '../mcp/graph.js';
8
+ import { UltraDexSocket } from '../mcp/websocket.js';
9
+ import { swarmCommand } from './swarm.js';
10
+ import { glob } from 'glob';
11
+ import { execSync, spawn } from 'child_process';
12
+ import { getRandomMessage } from '../utils/messages.js';
6
13
 
7
- // State management helpers
8
- async function loadState() {
14
+ export function registerServeCommand(program) {
15
+ program
16
+ .command('serve')
17
+ .description('Open the Multiverse Portal (Active Kernel)')
18
+ .option('-p, --port <port>', 'Port to listen on', '3001')
19
+ .option('--stdio', 'Run in Stdio mode (MCP Standard Only)', false)
20
+ .action(async (options) => {
21
+ if (options.stdio) {
22
+ // Run only MCP Stdio server
23
+ try {
24
+ await startMcpServer();
25
+ } catch (error) {
26
+ console.error("Failed to start MCP Server:", error);
27
+ process.exit(1);
28
+ }
29
+ } else {
30
+ // Run full Unified Kernel (HTTP + WebSocket + Dashboard + MCP over HTTP)
31
+ await startUnifiedKernel(options.port);
32
+ }
33
+ });
34
+ }
35
+
36
+ async function getGitInfo() {
9
37
  try {
10
- const content = await fs.readFile(path.resolve(process.cwd(), '.ultra/state.json'), 'utf8');
11
- return JSON.parse(content);
38
+ const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();
39
+ const lastCommit = execSync('git log -1 --format="%h %s" 2>/dev/null', { encoding: 'utf8' }).trim();
40
+ const status = execSync('git status --porcelain 2>/dev/null', { encoding: 'utf8' });
41
+ const changedFiles = status.split('\n').filter(l => l.trim()).length;
42
+ return { branch, lastCommit, changedFiles };
12
43
  } catch {
13
- return null;
44
+ return { branch: 'unknown', lastCommit: 'N/A', changedFiles: 0 };
14
45
  }
15
46
  }
16
47
 
17
- async function computeState() {
18
- const state = {
19
- version: '2.1.0',
20
- updatedAt: new Date().toISOString(),
21
- project: { name: path.basename(process.cwd()) },
22
- files: {},
23
- sections: { total: 34, completed: 0, list: [] },
24
- score: 0
25
- };
26
-
27
- const coreFiles = ['CONTEXT.md', 'IMPLEMENTATION-PLAN.md', 'CHECKLIST.md', 'QUICK-START.md'];
28
- for (const file of coreFiles) {
29
- try {
30
- const stat = await fs.stat(path.resolve(process.cwd(), file));
31
- state.files[file] = { exists: true, size: stat.size };
32
- } catch {
33
- state.files[file] = { exists: false };
34
- }
35
- }
48
+ // Re-using dashboard HTML generation logic (modularized)
49
+ async function getDashboardHTML() {
50
+ const { generateDashboardHTML } = await import('./dashboard.js');
51
+ const state = await loadState();
52
+ const gitInfo = await getGitInfo();
53
+ await projectGraph.scan();
54
+ const summary = projectGraph.getSummary();
55
+ return generateDashboardHTML(state, gitInfo, { nodes: summary.nodeCount, edges: summary.edgeCount });
56
+ }
57
+
58
+ async function startUnifiedKernel(portStr) {
59
+ const port = Number.parseInt(portStr, 10);
60
+
61
+ console.log(chalk.bold.hex('#7c3aed')('\nšŸš€ Opening Multiverse Portal (Infinity Kernel)...\n'));
62
+ console.log(chalk.italic(chalk.gray(`"${getRandomMessage('loading')}"`)));
36
63
 
64
+ // Initialize Graph
65
+ console.log(chalk.gray('🧠 Linking Neural Interface (Code Graph)...'));
37
66
  try {
38
- const plan = await fs.readFile(path.resolve(process.cwd(), 'IMPLEMENTATION-PLAN.md'), 'utf8');
39
- const sectionRegex = /^##\s+(\d+)\.\s+(.+)$/gm;
40
- let match;
41
- while ((match = sectionRegex.exec(plan)) !== null) {
42
- state.sections.list.push({ number: parseInt(match[1]), title: match[2].trim() });
43
- }
44
- state.sections.completed = state.sections.list.length;
45
- } catch { /* no plan */ }
67
+ await projectGraph.scan();
68
+ console.log(chalk.green(`āœ… Graph stabilized: ${projectGraph.nodes.size} nodes`));
69
+ } catch (e) {
70
+ console.log(chalk.yellow(`āš ļø Graph alignment failed: ${e.message}`));
71
+ }
46
72
 
47
- const fileScore = Object.values(state.files).filter(f => f.exists).length / coreFiles.length * 40;
48
- const sectionScore = state.sections.completed / state.sections.total * 60;
49
- state.score = Math.round(fileScore + sectionScore);
73
+ const server = http.createServer(async (req, res) => {
74
+ // CORS headers for local tools
75
+ res.setHeader('Access-Control-Allow-Origin', '*');
76
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
77
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
50
78
 
51
- return state;
52
- }
79
+ if (req.method === 'OPTIONS') {
80
+ res.writeHead(204);
81
+ res.end();
82
+ return;
83
+ }
53
84
 
54
- const BUILD_AGENTS = [
55
- { name: 'planner', tier: 'architect', task: 'Break down requirements into tasks' },
56
- { name: 'cto', tier: 'architect', task: 'Technical decisions & architecture' },
57
- { name: 'backend', tier: 'core', task: 'API, business logic, services' },
58
- { name: 'frontend', tier: 'core', task: 'UI components, pages, styling' },
59
- { name: 'database', tier: 'core', task: 'Schema design, migrations, queries' },
60
- { name: 'auth', tier: 'specialist', task: 'Authentication & authorization' },
61
- { name: 'security', tier: 'specialist', task: 'Security audit & hardening' },
62
- { name: 'testing', tier: 'specialist', task: 'Test strategy & implementation' },
63
- { name: 'reviewer', tier: 'quality', task: 'Code review & best practices' },
64
- { name: 'devops', tier: 'quality', task: 'CI/CD, deployment, infrastructure' }
65
- ];
85
+ const url = new URL(req.url, `http://${req.headers.host}`);
86
+ const pathname = url.pathname;
66
87
 
67
- export function registerServeCommand(program) {
68
- program
69
- .command('serve')
70
- .description('Serve Ultra-Dex context over HTTP (MCP-compatible)')
71
- .option('-p, --port <port>', 'Port to listen on', '3001')
72
- .action(async (options) => {
73
- const port = Number.parseInt(options.port, 10);
74
- if (Number.isNaN(port)) {
75
- console.log(chalk.red('Invalid port. Use a numeric value.'));
76
- process.exit(1);
88
+ try {
89
+ // Dashboard UI
90
+ if (pathname === '/' || pathname === '/dashboard') {
91
+ const html = await getDashboardHTML();
92
+ res.writeHead(200, { 'Content-Type': 'text/html' });
93
+ res.end(html);
94
+ return;
77
95
  }
78
96
 
79
- const server = http.createServer(async (req, res) => {
80
- res.setHeader('Access-Control-Allow-Origin', '*');
81
-
82
- if (!req.url || req.url === '/') {
83
- res.writeHead(200, { 'Content-Type': 'application/json' });
84
- res.end(JSON.stringify({
85
- name: 'Ultra-Dex MCP Server',
86
- version: '2.1.0',
87
- endpoints: ['/context', '/state', '/score', '/agents', '/agent/:name', '/refresh']
88
- }));
89
- return;
90
- }
97
+ // Endpoint: /api/info
98
+ if (pathname === '/api/info') {
99
+ res.writeHead(200, { 'Content-Type': 'application/json' });
100
+ res.end(JSON.stringify({
101
+ name: 'Ultra-Dex Multiverse Kernel',
102
+ version: '3.1.0',
103
+ status: 'online',
104
+ endpoints: ['/api/state', '/api/plan', '/api/context', '/api/graph', '/api/swarm']
105
+ }, null, 2));
106
+ return;
107
+ }
91
108
 
92
- if (req.url === '/context') {
93
- const meta = {
94
- protocol: 'mcp-lite',
95
- version: '0.1',
96
- generatedAt: new Date().toISOString(),
97
- };
98
- const [context, plan, quickStart] = await Promise.all([
99
- readFileSafe('CONTEXT.md', 'CONTEXT.md'),
100
- readFileSafe('IMPLEMENTATION-PLAN.md', 'IMPLEMENTATION-PLAN.md'),
101
- readFileSafe('QUICK-START.md', 'QUICK-START.md'),
102
- ]);
103
-
104
- res.writeHead(200, { 'Content-Type': 'application/json' });
105
- res.end(JSON.stringify({ meta, files: [context, plan, quickStart] }));
106
- return;
107
- }
109
+ // Endpoint: /api/graph
110
+ if (pathname === '/api/graph' || pathname === '/graph') {
111
+ const summary = projectGraph.getSummary();
112
+ res.writeHead(200, { 'Content-Type': 'application/json' });
113
+ res.end(JSON.stringify(summary, null, 2));
114
+ return;
115
+ }
108
116
 
109
- // /state - returns .ultra/state.json
110
- if (req.url === '/state') {
111
- let state = await loadState();
112
- if (!state) state = await computeState();
113
- res.writeHead(200, { 'Content-Type': 'application/json' });
114
- res.end(JSON.stringify(state));
115
- return;
116
- }
117
+ // Endpoint: /api/state
118
+ if (pathname === '/api/state' || pathname === '/state') {
119
+ const state = await loadState();
120
+ res.writeHead(200, { 'Content-Type': 'application/json' });
121
+ res.end(JSON.stringify(state, null, 2));
122
+ return;
123
+ }
117
124
 
118
- // /score - quick alignment score
119
- if (req.url === '/score') {
120
- const state = await computeState();
121
- res.writeHead(200, { 'Content-Type': 'application/json' });
122
- res.end(JSON.stringify({ score: state.score, sections: state.sections.completed, total: 34 }));
123
- return;
124
- }
125
+ // Endpoint: /api/swarm (Execute Swarm)
126
+ if ((pathname === '/api/swarm' || pathname === '/swarm') && req.method === 'POST') {
127
+ let body = '';
128
+ req.on('data', chunk => body += chunk);
129
+ req.on('end', async () => {
130
+ try {
131
+ const { task, feature, parallel } = JSON.parse(body);
132
+ const objective = task || feature;
133
+ if (!objective) throw new Error('Task/Feature objective is required');
134
+
135
+ // Run swarm
136
+ swarmCommand(objective, { parallel, dryRun: false }).catch(err => console.error(err));
137
+
138
+ res.writeHead(202, { 'Content-Type': 'application/json' });
139
+ res.end(JSON.stringify({ status: 'accepted', message: 'Swarm initiated' }));
140
+ } catch (e) {
141
+ res.writeHead(400, { 'Content-Type': 'application/json' });
142
+ res.end(JSON.stringify({ error: e.message }));
143
+ }
144
+ });
145
+ return;
146
+ }
125
147
 
126
- // /agents - list available agents
127
- if (req.url === '/agents') {
128
- res.writeHead(200, { 'Content-Type': 'application/json' });
129
- res.end(JSON.stringify({ agents: BUILD_AGENTS }));
130
- return;
131
- }
148
+ // Endpoint: /api/plan
149
+ if (pathname === '/api/plan' || pathname === '/plan') {
150
+ const state = await loadState();
151
+ const markdown = generateMarkdown(state);
152
+ res.writeHead(200, { 'Content-Type': 'text/markdown' });
153
+ res.end(markdown);
154
+ return;
155
+ }
132
156
 
133
- // /agent/:name - get specific agent prompt
134
- if (req.url.startsWith('/agent/')) {
135
- const agentName = req.url.replace('/agent/', '');
136
- try {
137
- const agentPath = path.resolve(process.cwd(), `agents/${agentName}.md`);
138
- const content = await fs.readFile(agentPath, 'utf8');
139
- res.writeHead(200, { 'Content-Type': 'application/json' });
140
- res.end(JSON.stringify({ agent: agentName, prompt: content }));
141
- } catch {
142
- res.writeHead(404, { 'Content-Type': 'application/json' });
143
- res.end(JSON.stringify({ error: `Agent ${agentName} not found` }));
144
- }
157
+ // SSE Events for Dashboard
158
+ if (pathname === '/events') {
159
+ res.writeHead(200, {
160
+ 'Content-Type': 'text/event-stream',
161
+ 'Cache-Control': 'no-cache',
162
+ 'Connection': 'keep-alive'
163
+ });
164
+ res.write(`data: ${JSON.stringify({ type: 'log', message: 'Connected to Multiverse Kernel' })}\n\n`);
165
+ // We'd need to manage clients here if we wanted to push updates
145
166
  return;
146
- }
167
+ }
147
168
 
148
- // /refresh - force state refresh
149
- if (req.url === '/refresh') {
150
- const state = await computeState();
151
- res.writeHead(200, { 'Content-Type': 'application/json' });
152
- res.end(JSON.stringify({ refreshed: true, score: state.score }));
153
- return;
154
- }
169
+ res.writeHead(404, { 'Content-Type': 'application/json' });
170
+ res.end(JSON.stringify({ error: 'Not found in this timeline' }));
155
171
 
156
- res.writeHead(404, { 'Content-Type': 'application/json' });
157
- res.end(JSON.stringify({ error: 'Not found' }));
158
- });
159
-
160
- server.listen(port, () => {
161
- console.log(chalk.green(`\nāœ… Ultra-Dex MCP server running on http://localhost:${port}`));
162
- console.log(chalk.bold('\nšŸ“” Endpoints:'));
163
- console.log(chalk.gray(' GET / → Server info & endpoint list'));
164
- console.log(chalk.gray(' GET /context → All context files'));
165
- console.log(chalk.gray(' GET /state → Full project state'));
166
- console.log(chalk.gray(' GET /score → Quick alignment score'));
167
- console.log(chalk.gray(' GET /agents → List available agents'));
168
- console.log(chalk.gray(' GET /agent/:n → Get specific agent prompt'));
169
- console.log(chalk.gray(' GET /refresh → Force state refresh'));
170
- console.log(chalk.cyan('\nšŸ’” Connect your AI tool to this server for live context.\n'));
171
- });
172
+ } catch (error) {
173
+ res.writeHead(500, { 'Content-Type': 'application/json' });
174
+ res.end(JSON.stringify({ error: error.message }));
175
+ }
176
+ });
177
+
178
+ const wss = new UltraDexSocket(server);
179
+
180
+ server.listen(port, () => {
181
+ console.log(chalk.green(`āœ… Portal Stabilized at http://localhost:${port}`));
182
+ console.log(chalk.gray(` • Dashboard: http://localhost:${port}/`));
183
+ console.log(chalk.gray(` • MCP API: http://localhost:${port}/api/info`));
184
+
185
+ console.log(chalk.bold.hex('#dc2626')('\nšŸ”Œ Weapon Integration (IDE):'));
186
+ console.log(chalk.white(' Cursor IDE: '));
187
+ console.log(chalk.cyan(` URL: http://localhost:${port}/api/info`));
188
+ console.log(chalk.white(' Claude Desktop:'));
189
+ console.log(chalk.cyan(` Run "ultra-dex config --mcp" to register.`));
190
+
191
+ // Auto-Pilot
192
+ fs.watch(process.cwd(), { recursive: true }, async (eventType, filename) => {
193
+ if (!filename || filename.includes('node_modules') || filename.includes('.git') || filename.includes('IMPLEMENTATION-PLAN.md')) return;
194
+
195
+ console.log(chalk.gray(`\nšŸ”„ Timeline Shift detected in ${filename}. Synchronizing...`));
196
+ try {
197
+ const state = await loadState();
198
+ if (state) {
199
+ const markdown = generateMarkdown(state);
200
+ await fs.writeFile(path.resolve(process.cwd(), 'IMPLEMENTATION-PLAN.md'), markdown);
201
+ wss.sendStateUpdate(state);
202
+ }
203
+ } catch (e) {}
172
204
  });
173
- }
205
+ });
206
+ }