ultra-dex 2.2.1 → 3.1.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 (54) hide show
  1. package/README.md +84 -128
  2. package/assets/agents/00-AGENT_INDEX.md +1 -1
  3. package/assets/docs/LAUNCH-POSTS.md +1 -1
  4. package/assets/docs/QUICK-REFERENCE.md +9 -4
  5. package/assets/docs/VISION-V2.md +1 -1
  6. package/assets/hooks/pre-commit +98 -0
  7. package/assets/saas-plan/04-Imp-Template.md +1 -1
  8. package/bin/ultra-dex.js +95 -4
  9. package/lib/commands/advanced.js +471 -0
  10. package/lib/commands/agent-builder.js +226 -0
  11. package/lib/commands/agents.js +99 -42
  12. package/lib/commands/auto-implement.js +68 -0
  13. package/lib/commands/build.js +73 -187
  14. package/lib/commands/ci-monitor.js +84 -0
  15. package/lib/commands/config.js +207 -0
  16. package/lib/commands/dashboard.js +770 -0
  17. package/lib/commands/diff.js +233 -0
  18. package/lib/commands/doctor.js +397 -0
  19. package/lib/commands/export.js +408 -0
  20. package/lib/commands/fix.js +96 -0
  21. package/lib/commands/generate.js +96 -72
  22. package/lib/commands/hooks.js +251 -76
  23. package/lib/commands/init.js +53 -1
  24. package/lib/commands/memory.js +80 -0
  25. package/lib/commands/plan.js +82 -0
  26. package/lib/commands/review.js +34 -5
  27. package/lib/commands/run.js +233 -0
  28. package/lib/commands/serve.js +177 -146
  29. package/lib/commands/state.js +354 -0
  30. package/lib/commands/swarm.js +284 -0
  31. package/lib/commands/sync.js +82 -23
  32. package/lib/commands/team.js +275 -0
  33. package/lib/commands/upgrade.js +190 -0
  34. package/lib/commands/validate.js +34 -0
  35. package/lib/commands/verify.js +81 -0
  36. package/lib/commands/watch.js +79 -0
  37. package/lib/mcp/graph.js +92 -0
  38. package/lib/mcp/memory.js +95 -0
  39. package/lib/mcp/resources.js +152 -0
  40. package/lib/mcp/server.js +34 -0
  41. package/lib/mcp/tools.js +481 -0
  42. package/lib/mcp/websocket.js +117 -0
  43. package/lib/providers/index.js +49 -4
  44. package/lib/providers/ollama.js +136 -0
  45. package/lib/providers/router.js +63 -0
  46. package/lib/quality/scanner.js +128 -0
  47. package/lib/swarm/coordinator.js +97 -0
  48. package/lib/swarm/index.js +598 -0
  49. package/lib/swarm/protocol.js +677 -0
  50. package/lib/swarm/tiers.js +485 -0
  51. package/lib/templates/custom-agent.md +10 -0
  52. package/lib/utils/files.js +14 -0
  53. package/lib/utils/graph.js +108 -0
  54. package/package.json +22 -13
@@ -0,0 +1,677 @@
1
+ /**
2
+ * Ultra-Dex Agent Communication Protocol v3.0
3
+ * Defines schema for agent handoffs, execution state, and rollback support.
4
+ */
5
+
6
+ // ============================================================================
7
+ // AGENT MESSAGE CLASS
8
+ // ============================================================================
9
+
10
+ /**
11
+ * Represents a message passed between agents in the swarm.
12
+ */
13
+ export class AgentMessage {
14
+ constructor(from, to, content, context = {}) {
15
+ this.id = crypto.randomUUID();
16
+ this.from = from;
17
+ this.to = to;
18
+ this.content = content;
19
+ this.context = context;
20
+ this.timestamp = new Date().toISOString();
21
+ this.metadata = {
22
+ retryCount: 0,
23
+ priority: 'normal',
24
+ tags: []
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Create a reply message to this message.
30
+ */
31
+ reply(content, additionalContext = {}) {
32
+ return new AgentMessage(
33
+ this.to,
34
+ this.from,
35
+ content,
36
+ { ...this.context, ...additionalContext }
37
+ );
38
+ }
39
+
40
+ /**
41
+ * Forward this message to another agent.
42
+ */
43
+ forward(newTo, additionalContent = '') {
44
+ const forwardedContent = additionalContent
45
+ ? `${additionalContent}\n\n---\nForwarded from ${this.from}:\n${this.content}`
46
+ : this.content;
47
+ return new AgentMessage(this.to, newTo, forwardedContent, this.context);
48
+ }
49
+
50
+ /**
51
+ * Serialize to JSON.
52
+ */
53
+ toJSON() {
54
+ return {
55
+ id: this.id,
56
+ from: this.from,
57
+ to: this.to,
58
+ content: this.content,
59
+ context: this.context,
60
+ timestamp: this.timestamp,
61
+ metadata: this.metadata
62
+ };
63
+ }
64
+
65
+ /**
66
+ * Create from JSON object.
67
+ */
68
+ static fromJSON(json) {
69
+ const msg = new AgentMessage(json.from, json.to, json.content, json.context);
70
+ msg.id = json.id;
71
+ msg.timestamp = json.timestamp;
72
+ msg.metadata = json.metadata || { retryCount: 0, priority: 'normal', tags: [] };
73
+ return msg;
74
+ }
75
+ }
76
+
77
+ // ============================================================================
78
+ // HANDOFF PAYLOAD CLASS
79
+ // ============================================================================
80
+
81
+ /**
82
+ * Represents the data passed during agent handoffs.
83
+ */
84
+ export class HandoffPayload {
85
+ constructor(previousAgent, nextAgent, options = {}) {
86
+ this.id = crypto.randomUUID();
87
+ this.previousAgent = previousAgent;
88
+ this.nextAgent = nextAgent;
89
+ this.summary = options.summary || '';
90
+ this.artifacts = options.artifacts || [];
91
+ this.decisions = options.decisions || [];
92
+ this.constraints = options.constraints || [];
93
+ this.nextTask = options.nextTask || '';
94
+ this.context = options.context || {};
95
+ this.timestamp = new Date().toISOString();
96
+ }
97
+
98
+ /**
99
+ * Add an artifact to the handoff.
100
+ */
101
+ addArtifact(filePath, description = '') {
102
+ this.artifacts.push({ path: filePath, description });
103
+ return this;
104
+ }
105
+
106
+ /**
107
+ * Add a decision made by the previous agent.
108
+ */
109
+ addDecision(decision) {
110
+ this.decisions.push(decision);
111
+ return this;
112
+ }
113
+
114
+ /**
115
+ * Add a constraint for the next agent.
116
+ */
117
+ addConstraint(constraint) {
118
+ this.constraints.push(constraint);
119
+ return this;
120
+ }
121
+
122
+ /**
123
+ * Generate handoff message for the next agent.
124
+ */
125
+ toMessage() {
126
+ const content = `
127
+ ## Handoff: ${this.previousAgent} → ${this.nextAgent}
128
+
129
+ ### Summary
130
+ ${this.summary}
131
+
132
+ ### Artifacts
133
+ ${this.artifacts.map(a => `- ${a.path}${a.description ? `: ${a.description}` : ''}`).join('\n') || 'None'}
134
+
135
+ ### Decisions Made
136
+ ${this.decisions.map(d => `- ${d}`).join('\n') || 'None'}
137
+
138
+ ### Constraints
139
+ ${this.constraints.map(c => `- ${c}`).join('\n') || 'None'}
140
+
141
+ ### Your Task
142
+ ${this.nextTask}
143
+ `.trim();
144
+
145
+ return new AgentMessage(this.previousAgent, this.nextAgent, content, this.context);
146
+ }
147
+
148
+ /**
149
+ * Serialize to JSON.
150
+ */
151
+ toJSON() {
152
+ return {
153
+ id: this.id,
154
+ previousAgent: this.previousAgent,
155
+ nextAgent: this.nextAgent,
156
+ summary: this.summary,
157
+ artifacts: this.artifacts,
158
+ decisions: this.decisions,
159
+ constraints: this.constraints,
160
+ nextTask: this.nextTask,
161
+ context: this.context,
162
+ timestamp: this.timestamp
163
+ };
164
+ }
165
+
166
+ /**
167
+ * Create from JSON object.
168
+ */
169
+ static fromJSON(json) {
170
+ const payload = new HandoffPayload(json.previousAgent, json.nextAgent, {
171
+ summary: json.summary,
172
+ artifacts: json.artifacts,
173
+ decisions: json.decisions,
174
+ constraints: json.constraints,
175
+ nextTask: json.nextTask,
176
+ context: json.context
177
+ });
178
+ payload.id = json.id;
179
+ payload.timestamp = json.timestamp;
180
+ return payload;
181
+ }
182
+ }
183
+
184
+ // ============================================================================
185
+ // EXECUTION TRACE CLASS
186
+ // ============================================================================
187
+
188
+ /**
189
+ * Tracks the execution history of a swarm task.
190
+ */
191
+ export class ExecutionTrace {
192
+ constructor(taskId, goal) {
193
+ this.taskId = taskId || crypto.randomUUID();
194
+ this.goal = goal || '';
195
+ this.status = 'pending'; // pending | planning | executing | completed | failed | rolled_back
196
+ this.pipeline = [];
197
+ this.results = {};
198
+ this.errors = [];
199
+ this.checkpoints = [];
200
+ this.rollbackHistory = [];
201
+ this.startTime = null;
202
+ this.endTime = null;
203
+ this.metadata = {
204
+ complexity: 'unknown',
205
+ tiersUsed: [],
206
+ parallelExecutions: 0
207
+ };
208
+ }
209
+
210
+ /**
211
+ * Start execution tracking.
212
+ */
213
+ start() {
214
+ this.status = 'executing';
215
+ this.startTime = new Date().toISOString();
216
+ return this;
217
+ }
218
+
219
+ /**
220
+ * Add a step to the pipeline.
221
+ */
222
+ addStep(step, agent, task, dependencies = []) {
223
+ this.pipeline.push({
224
+ step,
225
+ agent,
226
+ task,
227
+ dependencies,
228
+ status: 'pending',
229
+ startTime: null,
230
+ endTime: null
231
+ });
232
+ return this;
233
+ }
234
+
235
+ /**
236
+ * Mark a step as started.
237
+ */
238
+ startStep(step) {
239
+ const pipelineStep = this.pipeline.find(s => s.step === step);
240
+ if (pipelineStep) {
241
+ pipelineStep.status = 'executing';
242
+ pipelineStep.startTime = new Date().toISOString();
243
+ }
244
+ return this;
245
+ }
246
+
247
+ /**
248
+ * Record result from an agent.
249
+ */
250
+ recordResult(agent, output, success = true) {
251
+ const step = this.pipeline.find(s => s.agent === agent && s.status === 'executing');
252
+ if (step) {
253
+ step.status = success ? 'completed' : 'failed';
254
+ step.endTime = new Date().toISOString();
255
+ }
256
+
257
+ this.results[agent] = {
258
+ success,
259
+ output,
260
+ timestamp: new Date().toISOString()
261
+ };
262
+
263
+ if (!success) {
264
+ this.errors.push({
265
+ agent,
266
+ error: output,
267
+ timestamp: new Date().toISOString()
268
+ });
269
+ }
270
+ return this;
271
+ }
272
+
273
+ /**
274
+ * Create a checkpoint for potential rollback.
275
+ */
276
+ createCheckpoint(name, state = {}) {
277
+ const checkpoint = {
278
+ id: crypto.randomUUID(),
279
+ name,
280
+ step: this.pipeline.filter(s => s.status === 'completed').length,
281
+ state: JSON.parse(JSON.stringify(state)),
282
+ timestamp: new Date().toISOString()
283
+ };
284
+ this.checkpoints.push(checkpoint);
285
+ return checkpoint;
286
+ }
287
+
288
+ /**
289
+ * Get the last checkpoint.
290
+ */
291
+ getLastCheckpoint() {
292
+ return this.checkpoints[this.checkpoints.length - 1] || null;
293
+ }
294
+
295
+ /**
296
+ * Rollback to a specific checkpoint.
297
+ */
298
+ rollbackTo(checkpointId) {
299
+ const checkpointIndex = this.checkpoints.findIndex(c => c.id === checkpointId);
300
+ if (checkpointIndex === -1) {
301
+ throw new Error(`Checkpoint ${checkpointId} not found`);
302
+ }
303
+
304
+ const checkpoint = this.checkpoints[checkpointIndex];
305
+
306
+ // Record rollback action
307
+ this.rollbackHistory.push({
308
+ fromStep: this.pipeline.filter(s => s.status === 'completed').length,
309
+ toCheckpoint: checkpointId,
310
+ timestamp: new Date().toISOString()
311
+ });
312
+
313
+ // Reset steps after checkpoint
314
+ for (const step of this.pipeline) {
315
+ if (step.step > checkpoint.step) {
316
+ step.status = 'pending';
317
+ step.startTime = null;
318
+ step.endTime = null;
319
+ delete this.results[step.agent];
320
+ }
321
+ }
322
+
323
+ // Remove errors after checkpoint
324
+ this.errors = this.errors.filter(e => {
325
+ const step = this.pipeline.find(s => s.agent === e.agent);
326
+ return step && step.step <= checkpoint.step;
327
+ });
328
+
329
+ this.status = 'executing';
330
+ return checkpoint.state;
331
+ }
332
+
333
+ /**
334
+ * Mark execution as complete.
335
+ */
336
+ complete(success = true) {
337
+ this.status = success ? 'completed' : 'failed';
338
+ this.endTime = new Date().toISOString();
339
+ return this;
340
+ }
341
+
342
+ /**
343
+ * Get execution duration in milliseconds.
344
+ */
345
+ getDuration() {
346
+ if (!this.startTime) return 0;
347
+ const end = this.endTime ? new Date(this.endTime) : new Date();
348
+ return end - new Date(this.startTime);
349
+ }
350
+
351
+ /**
352
+ * Get formatted duration string.
353
+ */
354
+ getDurationFormatted() {
355
+ const ms = this.getDuration();
356
+ const seconds = Math.floor(ms / 1000);
357
+ const minutes = Math.floor(seconds / 60);
358
+ const hours = Math.floor(minutes / 60);
359
+
360
+ if (hours > 0) return `${hours}h ${minutes % 60}m`;
361
+ if (minutes > 0) return `${minutes}m ${seconds % 60}s`;
362
+ return `${seconds}s`;
363
+ }
364
+
365
+ /**
366
+ * Get list of all artifacts from results.
367
+ */
368
+ getArtifacts() {
369
+ const artifacts = [];
370
+ for (const [agent, result] of Object.entries(this.results)) {
371
+ if (result.success && result.output?.artifacts) {
372
+ artifacts.push(...result.output.artifacts);
373
+ }
374
+ }
375
+ return artifacts;
376
+ }
377
+
378
+ /**
379
+ * Get execution summary.
380
+ */
381
+ getSummary() {
382
+ const completed = this.pipeline.filter(s => s.status === 'completed').length;
383
+ const failed = this.pipeline.filter(s => s.status === 'failed').length;
384
+ const pending = this.pipeline.filter(s => s.status === 'pending').length;
385
+
386
+ return {
387
+ taskId: this.taskId,
388
+ goal: this.goal,
389
+ status: this.status,
390
+ duration: this.getDurationFormatted(),
391
+ progress: {
392
+ completed,
393
+ failed,
394
+ pending,
395
+ total: this.pipeline.length
396
+ },
397
+ agents: this.pipeline.map(s => s.agent),
398
+ errors: this.errors.length,
399
+ rollbacks: this.rollbackHistory.length
400
+ };
401
+ }
402
+
403
+ /**
404
+ * Serialize to JSON.
405
+ */
406
+ toJSON() {
407
+ return {
408
+ taskId: this.taskId,
409
+ goal: this.goal,
410
+ status: this.status,
411
+ pipeline: this.pipeline,
412
+ results: this.results,
413
+ errors: this.errors,
414
+ checkpoints: this.checkpoints,
415
+ rollbackHistory: this.rollbackHistory,
416
+ startTime: this.startTime,
417
+ endTime: this.endTime,
418
+ metadata: this.metadata
419
+ };
420
+ }
421
+
422
+ /**
423
+ * Create from JSON object.
424
+ */
425
+ static fromJSON(json) {
426
+ const trace = new ExecutionTrace(json.taskId, json.goal);
427
+ trace.status = json.status;
428
+ trace.pipeline = json.pipeline;
429
+ trace.results = json.results;
430
+ trace.errors = json.errors;
431
+ trace.checkpoints = json.checkpoints;
432
+ trace.rollbackHistory = json.rollbackHistory;
433
+ trace.startTime = json.startTime;
434
+ trace.endTime = json.endTime;
435
+ trace.metadata = json.metadata;
436
+ return trace;
437
+ }
438
+ }
439
+
440
+ // ============================================================================
441
+ // SCHEMA DEFINITIONS
442
+ // ============================================================================
443
+
444
+ /**
445
+ * Input/Output schemas for each agent type.
446
+ */
447
+ export const AgentSchemas = {
448
+ // Leadership Tier
449
+ planner: {
450
+ input: {
451
+ feature: 'string',
452
+ constraints: 'string[]',
453
+ timeEstimate: 'string?'
454
+ },
455
+ output: {
456
+ tasks: 'Task[]',
457
+ timeline: 'string',
458
+ risks: 'string[]'
459
+ }
460
+ },
461
+ cto: {
462
+ input: {
463
+ decision: 'string',
464
+ options: 'string[]',
465
+ context: 'string'
466
+ },
467
+ output: {
468
+ recommendation: 'string',
469
+ reasoning: 'string',
470
+ tradeoffs: 'string[]'
471
+ }
472
+ },
473
+ research: {
474
+ input: {
475
+ topic: 'string',
476
+ criteria: 'string[]'
477
+ },
478
+ output: {
479
+ findings: 'Finding[]',
480
+ recommendation: 'string',
481
+ sources: 'string[]'
482
+ }
483
+ },
484
+
485
+ // Development Tier
486
+ backend: {
487
+ input: {
488
+ task: 'string',
489
+ requirements: 'string[]',
490
+ existingCode: 'string?'
491
+ },
492
+ output: {
493
+ code: 'string',
494
+ files: 'FileChange[]',
495
+ tests: 'string[]'
496
+ }
497
+ },
498
+ frontend: {
499
+ input: {
500
+ component: 'string',
501
+ design: 'string?',
502
+ requirements: 'string[]'
503
+ },
504
+ output: {
505
+ code: 'string',
506
+ files: 'FileChange[]',
507
+ styles: 'string?'
508
+ }
509
+ },
510
+ database: {
511
+ input: {
512
+ schema: 'string',
513
+ requirements: 'string[]'
514
+ },
515
+ output: {
516
+ migration: 'string',
517
+ files: 'FileChange[]',
518
+ queries: 'string[]'
519
+ }
520
+ },
521
+
522
+ // Security Tier
523
+ auth: {
524
+ input: {
525
+ authType: 'string',
526
+ requirements: 'string[]'
527
+ },
528
+ output: {
529
+ implementation: 'string',
530
+ files: 'FileChange[]',
531
+ config: 'object'
532
+ }
533
+ },
534
+ security: {
535
+ input: {
536
+ target: 'string',
537
+ scope: 'string[]'
538
+ },
539
+ output: {
540
+ vulnerabilities: 'Vulnerability[]',
541
+ recommendations: 'string[]',
542
+ severity: 'string'
543
+ }
544
+ },
545
+
546
+ // DevOps Tier
547
+ devops: {
548
+ input: {
549
+ task: 'string',
550
+ environment: 'string',
551
+ config: 'object?'
552
+ },
553
+ output: {
554
+ commands: 'string[]',
555
+ files: 'FileChange[]',
556
+ status: 'string'
557
+ }
558
+ },
559
+
560
+ // Quality Tier
561
+ testing: {
562
+ input: {
563
+ target: 'string',
564
+ testType: 'string',
565
+ coverage: 'number?'
566
+ },
567
+ output: {
568
+ tests: 'Test[]',
569
+ files: 'FileChange[]',
570
+ coverage: 'number'
571
+ }
572
+ },
573
+ reviewer: {
574
+ input: {
575
+ code: 'string',
576
+ context: 'string'
577
+ },
578
+ output: {
579
+ approved: 'boolean',
580
+ comments: 'Comment[]',
581
+ suggestions: 'string[]'
582
+ }
583
+ },
584
+ debugger: {
585
+ input: {
586
+ issue: 'string',
587
+ logs: 'string?',
588
+ reproduction: 'string?'
589
+ },
590
+ output: {
591
+ rootCause: 'string',
592
+ fix: 'string',
593
+ files: 'FileChange[]'
594
+ }
595
+ },
596
+ documentation: {
597
+ input: {
598
+ target: 'string',
599
+ docType: 'string'
600
+ },
601
+ output: {
602
+ content: 'string',
603
+ files: 'FileChange[]'
604
+ }
605
+ },
606
+
607
+ // Specialist Tier
608
+ performance: {
609
+ input: {
610
+ target: 'string',
611
+ metrics: 'string[]?'
612
+ },
613
+ output: {
614
+ analysis: 'string',
615
+ optimizations: 'Optimization[]',
616
+ files: 'FileChange[]'
617
+ }
618
+ },
619
+ refactoring: {
620
+ input: {
621
+ target: 'string',
622
+ goals: 'string[]'
623
+ },
624
+ output: {
625
+ changes: 'string',
626
+ files: 'FileChange[]',
627
+ improvements: 'string[]'
628
+ }
629
+ }
630
+ };
631
+
632
+ // ============================================================================
633
+ // LEGACY COMPATIBILITY
634
+ // ============================================================================
635
+
636
+ /**
637
+ * Legacy protocol object for backward compatibility.
638
+ */
639
+ export const AgentProtocol = {
640
+ Message: {
641
+ id: 'uuid',
642
+ from: 'agent_name',
643
+ to: 'agent_name',
644
+ content: 'string',
645
+ context: {},
646
+ timestamp: 'ISO8601'
647
+ },
648
+ SwarmState: {
649
+ taskId: 'uuid',
650
+ status: 'planning|executing|reviewing|completed|failed',
651
+ pipeline: [],
652
+ results: {},
653
+ errors: [],
654
+ startTime: 'ISO8601',
655
+ endTime: 'ISO8601'
656
+ },
657
+ Handover: {
658
+ previousAgent: 'string',
659
+ nextAgent: 'string',
660
+ artifacts: [],
661
+ summary: 'string'
662
+ }
663
+ };
664
+
665
+ /**
666
+ * Legacy function for creating messages.
667
+ */
668
+ export function createMessage(from, to, content, context = {}) {
669
+ return new AgentMessage(from, to, content, context);
670
+ }
671
+
672
+ /**
673
+ * Legacy function for creating handovers.
674
+ */
675
+ export function createHandover(previousAgent, nextAgent, summary, artifacts = []) {
676
+ return new HandoffPayload(previousAgent, nextAgent, { summary, artifacts });
677
+ }