dialectic 0.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 (119) hide show
  1. package/.cursor/commands/setup-test.mdc +175 -0
  2. package/.cursor/rules/basic-code-cleanup.mdc +1110 -0
  3. package/.cursor/rules/riper5.mdc +96 -0
  4. package/.env.example +6 -0
  5. package/AGENTS.md +1052 -0
  6. package/LICENSE +21 -0
  7. package/README.md +93 -0
  8. package/WARP.md +113 -0
  9. package/dialectic-1.0.0.tgz +0 -0
  10. package/dialectic.js +10 -0
  11. package/docs/commands.md +375 -0
  12. package/docs/configuration.md +882 -0
  13. package/docs/context_summarization.md +1023 -0
  14. package/docs/debate_flow.md +1127 -0
  15. package/docs/eval_flow.md +795 -0
  16. package/docs/evaluator.md +141 -0
  17. package/examples/debate-config-openrouter.json +48 -0
  18. package/examples/debate_config1.json +48 -0
  19. package/examples/eval/eval1/eval_config1.json +13 -0
  20. package/examples/eval/eval1/result1.json +62 -0
  21. package/examples/eval/eval1/result2.json +97 -0
  22. package/examples/eval_summary_format.md +11 -0
  23. package/examples/example3/debate-config.json +64 -0
  24. package/examples/example3/eval_config2.json +25 -0
  25. package/examples/example3/problem.md +17 -0
  26. package/examples/example3/rounds_test/eval_run.sh +16 -0
  27. package/examples/example3/rounds_test/run_test.sh +16 -0
  28. package/examples/kata1/architect-only-solution_2-rounds.json +121 -0
  29. package/examples/kata1/architect-perf-solution_2-rounds.json +234 -0
  30. package/examples/kata1/debate-config-kata1.json +54 -0
  31. package/examples/kata1/eval_architect-only_2-rounds.json +97 -0
  32. package/examples/kata1/eval_architect-perf_2-rounds.json +97 -0
  33. package/examples/kata1/kata1-report.md +12224 -0
  34. package/examples/kata1/kata1-report_temps-01_01_01_07.md +2451 -0
  35. package/examples/kata1/kata1.md +5 -0
  36. package/examples/kata1/meta.txt +1 -0
  37. package/examples/kata2/debate-config.json +54 -0
  38. package/examples/kata2/eval_config1.json +21 -0
  39. package/examples/kata2/eval_config2.json +25 -0
  40. package/examples/kata2/kata2.md +5 -0
  41. package/examples/kata2/only_architect/debate-config.json +45 -0
  42. package/examples/kata2/only_architect/eval_run.sh +11 -0
  43. package/examples/kata2/only_architect/run_test.sh +5 -0
  44. package/examples/kata2/rounds_test/eval_run.sh +11 -0
  45. package/examples/kata2/rounds_test/run_test.sh +5 -0
  46. package/examples/kata2/summary_length_test/eval_run.sh +11 -0
  47. package/examples/kata2/summary_length_test/eval_run_w_clarify.sh +7 -0
  48. package/examples/kata2/summary_length_test/run_test.sh +5 -0
  49. package/examples/task-queue/debate-config.json +76 -0
  50. package/examples/task-queue/debate_report.md +566 -0
  51. package/examples/task-queue/task-queue-system.md +25 -0
  52. package/jest.config.ts +13 -0
  53. package/multi_agent_debate_spec.md +2980 -0
  54. package/package.json +38 -0
  55. package/sanity-check-problem.txt +9 -0
  56. package/src/agents/prompts/architect-prompts.ts +203 -0
  57. package/src/agents/prompts/generalist-prompts.ts +157 -0
  58. package/src/agents/prompts/index.ts +41 -0
  59. package/src/agents/prompts/judge-prompts.ts +19 -0
  60. package/src/agents/prompts/kiss-prompts.ts +230 -0
  61. package/src/agents/prompts/performance-prompts.ts +142 -0
  62. package/src/agents/prompts/prompt-types.ts +68 -0
  63. package/src/agents/prompts/security-prompts.ts +149 -0
  64. package/src/agents/prompts/shared.ts +144 -0
  65. package/src/agents/prompts/testing-prompts.ts +149 -0
  66. package/src/agents/role-based-agent.ts +386 -0
  67. package/src/cli/commands/debate.ts +761 -0
  68. package/src/cli/commands/eval.ts +475 -0
  69. package/src/cli/commands/report.ts +265 -0
  70. package/src/cli/index.ts +79 -0
  71. package/src/core/agent.ts +198 -0
  72. package/src/core/clarifications.ts +34 -0
  73. package/src/core/judge.ts +257 -0
  74. package/src/core/orchestrator.ts +432 -0
  75. package/src/core/state-manager.ts +322 -0
  76. package/src/eval/evaluator-agent.ts +130 -0
  77. package/src/eval/prompts/system.md +41 -0
  78. package/src/eval/prompts/user.md +64 -0
  79. package/src/providers/llm-provider.ts +25 -0
  80. package/src/providers/openai-provider.ts +84 -0
  81. package/src/providers/openrouter-provider.ts +122 -0
  82. package/src/providers/provider-factory.ts +64 -0
  83. package/src/types/agent.types.ts +141 -0
  84. package/src/types/config.types.ts +47 -0
  85. package/src/types/debate.types.ts +237 -0
  86. package/src/types/eval.types.ts +85 -0
  87. package/src/utils/common.ts +104 -0
  88. package/src/utils/context-formatter.ts +102 -0
  89. package/src/utils/context-summarizer.ts +143 -0
  90. package/src/utils/env-loader.ts +46 -0
  91. package/src/utils/exit-codes.ts +5 -0
  92. package/src/utils/id.ts +11 -0
  93. package/src/utils/logger.ts +48 -0
  94. package/src/utils/paths.ts +10 -0
  95. package/src/utils/progress-ui.ts +313 -0
  96. package/src/utils/prompt-loader.ts +79 -0
  97. package/src/utils/report-generator.ts +301 -0
  98. package/tests/clarifications.spec.ts +128 -0
  99. package/tests/cli.debate.spec.ts +144 -0
  100. package/tests/config-loading.spec.ts +206 -0
  101. package/tests/context-summarizer.spec.ts +131 -0
  102. package/tests/debate-config-custom.json +38 -0
  103. package/tests/env-loader.spec.ts +149 -0
  104. package/tests/eval.command.spec.ts +1191 -0
  105. package/tests/logger.spec.ts +19 -0
  106. package/tests/openai-provider.spec.ts +26 -0
  107. package/tests/openrouter-provider.spec.ts +279 -0
  108. package/tests/orchestrator-summary.spec.ts +386 -0
  109. package/tests/orchestrator.spec.ts +207 -0
  110. package/tests/prompt-loader.spec.ts +52 -0
  111. package/tests/prompts/architect.md +16 -0
  112. package/tests/provider-factory.spec.ts +150 -0
  113. package/tests/report.command.spec.ts +546 -0
  114. package/tests/role-based-agent-summary.spec.ts +476 -0
  115. package/tests/security-agent.spec.ts +221 -0
  116. package/tests/shared-prompts.spec.ts +318 -0
  117. package/tests/state-manager.spec.ts +251 -0
  118. package/tests/summary-prompts.spec.ts +153 -0
  119. package/tsconfig.json +49 -0
@@ -0,0 +1,2980 @@
1
+ # Multi-Agent Debate System - Technical Specification
2
+
3
+ ## Overview
4
+
5
+ This document specifies a multi-agent debate system where AI agents collaboratively solve software design problems through structured debate.
6
+ The system starts as a CLI tool and is designed to extend to a web interface.
7
+
8
+ **Technology Stack**: TypeScript, Node.js, LLM APIs (OpenAI, Anthropic, etc.)
9
+
10
+ ---
11
+
12
+ ## Core Concepts
13
+
14
+ ### What is Multi-Agent Debate?
15
+
16
+ Multiple AI agents with different perspectives analyze a problem, propose solutions, critique each other, and iteratively refine their approaches until reaching a high-quality final solution.
17
+
18
+ **Example Flow**:
19
+ ```
20
+ User: "Design a rate limiting system for an API"
21
+ ├── Agent 1 (Architect): Proposes token bucket algorithm
22
+ ├── Agent 2 (Security): Proposes Redis-based distributed solution
23
+ └── Agent 3 (Performance): Proposes in-memory solution with sync
24
+
25
+ Round 1 Debate:
26
+ ├── Security critiques Agent 3's in-memory approach (no distribution)
27
+ ├── Performance critiques Agent 2's Redis latency
28
+ └── Architect synthesizes: Token bucket + Redis with local cache
29
+
30
+ Final Solution: Hybrid approach with best of all perspectives
31
+ ```
32
+
33
+ ---
34
+
35
+ ## System Architecture
36
+
37
+ ### High-Level Components
38
+
39
+ ```
40
+ ┌─────────────────────────────────────────────────────────┐
41
+ │ CLI Interface │
42
+ │ (commands: debate, configure, history, export) │
43
+ └────────────────────┬────────────────────────────────────┘
44
+
45
+ ┌────────────────────▼────────────────────────────────────┐
46
+ │ Debate Orchestrator │
47
+ │ - Manages debate flow │
48
+ │ - Coordinates agents │
49
+ │ - Handles state transitions │
50
+ └────────────────────┬────────────────────────────────────┘
51
+
52
+ ┌────────────┼────────────┐
53
+ │ │ │
54
+ ┌───────▼──────┐ ┌──▼──────┐ ┌──▼──────────┐
55
+ │ Agent │ │ Agent │ │ Judge │
56
+ │ Manager │ │ Pool │ │ Service │
57
+ └───────┬──────┘ └──┬──────┘ └──┬──────────┘
58
+ │ │ │
59
+ ┌───────▼───────────▼────────────▼──────────┐
60
+ │ State Manager │
61
+ │ - Conversation history │
62
+ │ - Proposals & critiques │
63
+ │ - Debate rounds │
64
+ └────────────────────┬───────────────────────┘
65
+
66
+ ┌────────────────────▼───────────────────────┐
67
+ │ LLM Provider Layer │
68
+ │ (OpenAI, Anthropic, custom adapters) │
69
+ └────────────────────────────────────────────┘
70
+ ```
71
+
72
+ ### Directory Structure
73
+
74
+ ```
75
+ multi-agent-debate/
76
+ ├── src/
77
+ │ ├── cli/
78
+ │ │ ├── commands/
79
+ │ │ │ ├── debate.ts # Main debate command
80
+ │ │ │ ├── configure.ts # Configuration management
81
+ │ │ │ ├── history.ts # View past debates
82
+ │ │ │ └── export.ts # Export results
83
+ │ │ └── index.ts # CLI entry point
84
+ │ │
85
+ │ ├── core/
86
+ │ │ ├── orchestrator.ts # Debate orchestration logic
87
+ │ │ ├── agent.ts # Agent base class
88
+ │ │ ├── judge.ts # Judge/synthesizer
89
+ │ │ └── state-manager.ts # State management
90
+ │ │
91
+ │ ├── agents/
92
+ │ │ ├── architect-agent.ts # System design focus
93
+ │ │ ├── security-agent.ts # Security focus
94
+ │ │ ├── performance-agent.ts # Performance focus
95
+ │ │ └── testing-agent.ts # Testing focus
96
+ │ │
97
+ │ ├── providers/
98
+ │ │ ├── llm-provider.ts # Provider interface
99
+ │ │ ├── openai-provider.ts # OpenAI implementation
100
+ │ │ └── anthropic-provider.ts # Anthropic implementation
101
+ │ │
102
+ │ ├── utils/
103
+ │ │ ├── prompt-builder.ts # Prompt construction
104
+ │ │ ├── logger.ts # Logging utilities
105
+ │ │ └── storage.ts # File/DB storage
106
+ │ │
107
+ │ └── types/
108
+ │ ├── agent.types.ts
109
+ │ ├── debate.types.ts
110
+ │ └── config.types.ts
111
+
112
+ ├── config/
113
+ │ └── default-config.json # Default configuration
114
+
115
+ ├── tests/
116
+ │ ├── unit/
117
+ │ └── integration/
118
+
119
+ └── package.json
120
+ ```
121
+
122
+ ---
123
+
124
+ ## Core Data Models
125
+
126
+ ### Agent Configuration
127
+
128
+ ```typescript
129
+ interface AgentConfig {
130
+ id: string; // Unique identifier
131
+ name: string; // Human-readable name
132
+ role: AgentRole; // Architect, Security, Performance, Testing
133
+ model: string; // e.g., "gpt-4", "claude-3-opus"
134
+ provider: "openai" | "anthropic";
135
+ temperature: number; // 0.0 - 1.0
136
+ systemPrompt: string; // Role-specific instructions
137
+ enabled: boolean; // Can be disabled
138
+ }
139
+
140
+ type AgentRole = "architect" | "security" | "performance" | "testing" | "generalist";
141
+ ```
142
+
143
+ **Example**:
144
+ ```json
145
+ {
146
+ "id": "agent-architect-001",
147
+ "name": "System Architect",
148
+ "role": "architect",
149
+ "model": "gpt-4",
150
+ "provider": "openai",
151
+ "temperature": 0.7,
152
+ "systemPrompt": "You are an expert system architect...",
153
+ "enabled": true
154
+ }
155
+ ```
156
+
157
+ ### Debate Configuration
158
+
159
+ ```typescript
160
+ interface DebateConfig {
161
+ rounds: number; // Number of debate rounds (default: 3)
162
+ terminationCondition: {
163
+ type: "fixed" | "convergence" | "quality";
164
+ threshold?: number; // For convergence/quality
165
+ };
166
+ synthesisMethod: "judge" | "voting" | "merge";
167
+ includeFullHistory: boolean; // Full context vs summarized
168
+ timeoutPerRound: number; // Milliseconds
169
+ }
170
+ ```
171
+
172
+ ### Debate State
173
+
174
+ ```typescript
175
+ interface DebateState {
176
+ id: string; // Unique debate session ID
177
+ problem: string; // Original problem statement
178
+ context?: string; // Additional context
179
+ status: "pending" | "running" | "completed" | "failed";
180
+ currentRound: number;
181
+ rounds: DebateRound[];
182
+ finalSolution?: Solution;
183
+ createdAt: Date;
184
+ updatedAt: Date;
185
+ }
186
+
187
+ interface DebateRound {
188
+ roundNumber: number;
189
+ phase: "proposal" | "critique" | "refinement";
190
+ contributions: Contribution[];
191
+ timestamp: Date;
192
+ }
193
+
194
+ interface Contribution {
195
+ agentId: string;
196
+ agentRole: AgentRole;
197
+ type: "proposal" | "critique" | "refinement";
198
+ content: string;
199
+ targetAgentId?: string; // For critiques
200
+ metadata: {
201
+ tokensUsed: number;
202
+ latencyMs: number;
203
+ model: string;
204
+ };
205
+ }
206
+
207
+ interface Solution {
208
+ description: string;
209
+ implementation?: string; // Code if applicable
210
+ tradeoffs: string[];
211
+ recommendations: string[];
212
+ confidence: number; // 0-100
213
+ synthesizedBy: string; // Judge agent ID
214
+ }
215
+ ```
216
+
217
+ ---
218
+
219
+ ## High-Level Flows
220
+
221
+ ### Flow 1: Simple Debate (Fixed Rounds)
222
+
223
+ ```
224
+ ┌─────────────────────────────────────────────────────────┐
225
+ │ 1. User submits problem via CLI │
226
+ │ $ debate "Design a caching layer for microservices" │
227
+ └────────────────┬────────────────────────────────────────┘
228
+
229
+ ┌────────────────▼────────────────────────────────────────┐
230
+ │ 2. Orchestrator initializes debate │
231
+ │ - Create debate state │
232
+ │ - Load agent configurations │
233
+ │ - Validate inputs │
234
+ └────────────────┬────────────────────────────────────────┘
235
+
236
+ ┌────────────────▼────────────────────────────────────────┐
237
+ │ 3. ROUND 1: Proposal Phase │
238
+ │ - Each agent analyzes problem independently │
239
+ │ - Generates initial solution proposal │
240
+ │ Output: │
241
+ │ Agent A: "Redis-based distributed cache..." │
242
+ │ Agent B: "Multi-tier caching with CDN..." │
243
+ │ Agent C: "In-memory cache with invalidation..." │
244
+ └────────────────┬────────────────────────────────────────┘
245
+
246
+ ┌────────────────▼────────────────────────────────────────┐
247
+ │ 4. ROUND 2: Critique Phase │
248
+ │ - Each agent reviews others' proposals │
249
+ │ - Identifies strengths and weaknesses │
250
+ │ Output: │
251
+ │ Agent A critiques B: "CDN adds latency..." │
252
+ │ Agent B critiques C: "No distribution..." │
253
+ │ Agent C critiques A: "Redis SPOF concern..." │
254
+ └────────────────┬────────────────────────────────────────┘
255
+
256
+ ┌────────────────▼────────────────────────────────────────┐
257
+ │ 5. ROUND 3: Refinement Phase │
258
+ │ - Each agent refines based on critiques │
259
+ │ - Addresses concerns raised │
260
+ │ Output: │
261
+ │ Agent A: "Redis cluster with sentinels..." │
262
+ │ Agent B: "CDN for static + Redis for dynamic..." │
263
+ │ Agent C: "Distributed in-memory with gossip..." │
264
+ └────────────────┬────────────────────────────────────────┘
265
+
266
+ ┌────────────────▼────────────────────────────────────────┐
267
+ │ 6. Judge Synthesis │
268
+ │ - Judge agent reviews all rounds │
269
+ │ - Identifies best ideas from each proposal │
270
+ │ - Creates unified solution │
271
+ │ Output: "Hybrid approach: Local cache (L1) + │
272
+ │ Redis cluster (L2) + CDN (L3)..." │
273
+ └────────────────┬────────────────────────────────────────┘
274
+
275
+ ┌────────────────▼────────────────────────────────────────┐
276
+ │ 7. Present Results │
277
+ │ - Display final solution │
278
+ │ - Show debate history (optional) │
279
+ │ - Save to storage │
280
+ │ - Export options (JSON, Markdown, etc.) │
281
+ └─────────────────────────────────────────────────────────┘
282
+ ```
283
+
284
+ ### Flow 2: Convergence-Based Debate
285
+
286
+ ```
287
+ 1. User submits problem
288
+ 2. Orchestrator initializes with convergence detection
289
+ 3. Round N:
290
+ ├── Agents propose/critique/refine
291
+ ├── Calculate similarity between proposals
292
+ │ (using embeddings or text similarity)
293
+ └── If similarity > threshold → converged
294
+ 4. If converged → Judge synthesis
295
+ 5. If not converged and rounds < max → Next round
296
+ 6. Present results
297
+ ```
298
+
299
+ **Convergence Detection**:
300
+ ```typescript
301
+ function calculateConvergence(proposals: string[]): number {
302
+ // Option 1: Embedding similarity
303
+ const embeddings = await generateEmbeddings(proposals);
304
+ const similarity = cosineSimilarity(embeddings);
305
+ return similarity;
306
+
307
+ // Option 2: Key concept overlap
308
+ const concepts = proposals.map(extractKeyConcepts);
309
+ const overlap = calculateOverlap(concepts);
310
+ return overlap;
311
+ }
312
+ ```
313
+
314
+ ### Flow 3: Tournament-Style Debate
315
+
316
+ ```
317
+ 1. User submits problem
318
+ 2. All agents propose independently (N proposals)
319
+ 3. Pairwise comparisons:
320
+ ├── Agent pairs debate each other
321
+ └── Judge picks winner of each pair
322
+ 4. Winners advance to next round
323
+ 5. Repeat until 1 winner or synthesis
324
+ 6. Present results
325
+ ```
326
+
327
+ ---
328
+
329
+ ## CLI Interface Specification
330
+
331
+ ### Commands
332
+
333
+ #### 1. `debate` - Start a new debate
334
+
335
+ ```bash
336
+ # Basic usage
337
+ $ debate "Design a rate limiting system"
338
+
339
+ # With options
340
+ $ debate "Design a rate limiting system" \
341
+ --agents architect,security,performance \
342
+ --rounds 3 \
343
+ --config custom-config.json \
344
+ --output debate-results.json
345
+
346
+ # Interactive mode
347
+ $ debate --interactive
348
+ ? Enter your problem: Design a rate limiting system
349
+ ? Select agents: [x] Architect [ ] Security [x] Performance
350
+ ? Number of rounds: 3
351
+ ? Enable detailed logging: Yes
352
+ ```
353
+
354
+ **Options**:
355
+ - `--agents <list>`: Comma-separated agent roles (default: all enabled)
356
+ - `--rounds <n>`: Number of debate rounds (default: 3)
357
+ - `--config <path>`: Custom configuration file
358
+ - `--output <path>`: Save results to file
359
+ - `--interactive`: Interactive mode with prompts
360
+ - `--verbose`: Show detailed progress
361
+ - `--context <path>`: Additional context file
362
+
363
+ **Output**:
364
+ ```
365
+ 🤖 Multi-Agent Debate System
366
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
367
+
368
+ Problem: Design a rate limiting system
369
+
370
+ Active Agents:
371
+ ✓ System Architect (GPT-4)
372
+ ✓ Security Expert (Claude-3)
373
+ ✓ Performance Engineer (GPT-4)
374
+
375
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
376
+
377
+ Round 1/3: Proposal Phase
378
+ [Architect] Analyzing problem... ✓ (2.3s)
379
+ [Security] Analyzing problem... ✓ (1.9s)
380
+ [Performance] Analyzing problem... ✓ (2.1s)
381
+
382
+ Round 2/3: Critique Phase
383
+ [Architect] Reviewing proposals... ✓ (1.8s)
384
+ [Security] Reviewing proposals... ✓ (2.0s)
385
+ [Performance] Reviewing proposals... ✓ (1.7s)
386
+
387
+ Round 3/3: Refinement Phase
388
+ [Architect] Refining solution... ✓ (2.2s)
389
+ [Security] Refining solution... ✓ (2.1s)
390
+ [Performance] Refining solution... ✓ (1.9s)
391
+
392
+ Synthesizing final solution... ✓ (3.1s)
393
+
394
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
395
+
396
+ FINAL SOLUTION
397
+
398
+ Recommended Approach: Token Bucket with Redis Backend
399
+
400
+ Overview:
401
+ Implement a distributed rate limiting system using the token
402
+ bucket algorithm with Redis as the shared state store and
403
+ local in-memory caching for performance.
404
+
405
+ Key Components:
406
+ 1. Token Bucket Algorithm
407
+ - Configurable rates per user/API key
408
+ - Burst allowance for traffic spikes
409
+
410
+ 2. Redis Cluster
411
+ - Distributed state management
412
+ - Lua scripts for atomic operations
413
+ - Failover with Sentinel
414
+
415
+ 3. Local Cache Layer
416
+ - Reduces Redis load
417
+ - 1-second TTL for rate counters
418
+ - Eventual consistency acceptable
419
+
420
+ Trade-offs:
421
+ ✓ Pros: Scalable, distributed, precise
422
+ ✗ Cons: Redis dependency, slight complexity
423
+
424
+ Implementation Complexity: Medium
425
+ Confidence Score: 87/100
426
+
427
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
428
+
429
+ 💾 Results saved to: ./debates/debate-20240315-143022.json
430
+ 📊 View details: debate history show debate-20240315-143022
431
+ ```
432
+
433
+ #### 2. `configure` - Manage configuration
434
+
435
+ ```bash
436
+ # View current configuration
437
+ $ debate configure show
438
+
439
+ # Edit configuration
440
+ $ debate configure edit
441
+
442
+ # Add/modify agent
443
+ $ debate configure agent add \
444
+ --name "Code Reviewer" \
445
+ --role generalist \
446
+ --model gpt-4 \
447
+ --temperature 0.5
448
+
449
+ # Set default rounds
450
+ $ debate configure set rounds 5
451
+
452
+ # Reset to defaults
453
+ $ debate configure reset
454
+ ```
455
+
456
+ #### 3. `history` - View past debates
457
+
458
+ ```bash
459
+ # List all debates
460
+ $ debate history list
461
+
462
+ # Show specific debate
463
+ $ debate history show <debate-id>
464
+
465
+ # Filter by date
466
+ $ debate history list --from 2024-03-01 --to 2024-03-15
467
+
468
+ # Search by keyword
469
+ $ debate history search "rate limiting"
470
+
471
+ # Export history
472
+ $ debate history export --format csv --output debates.csv
473
+ ```
474
+
475
+ **Example Output**:
476
+ ```
477
+ Recent Debates:
478
+
479
+ ID Date Problem Agents Status
480
+ ──────────────────────────────────────────────────────────────────────
481
+ deb-20240315 2024-03-15 Rate limiting system 3 ✓ Complete
482
+ deb-20240314 2024-03-14 Authentication service 4 ✓ Complete
483
+ deb-20240313 2024-03-13 Database sharding 3 ✗ Failed
484
+ ```
485
+
486
+ #### 4. `export` - Export debate results
487
+
488
+ ```bash
489
+ # Export as markdown
490
+ $ debate export <debate-id> --format markdown --output report.md
491
+
492
+ # Export as JSON
493
+ $ debate export <debate-id> --format json --output data.json
494
+
495
+ # Export with code samples
496
+ $ debate export <debate-id> --include-code --output solution.md
497
+
498
+ # Export comparison chart
499
+ $ debate export <debate-id> --format html --include-charts
500
+ ```
501
+
502
+ ---
503
+
504
+ ## Agent Specifications
505
+
506
+ ### Base Agent Interface
507
+
508
+ ```typescript
509
+ abstract class Agent {
510
+ constructor(
511
+ protected config: AgentConfig,
512
+ protected provider: LLMProvider
513
+ ) {}
514
+
515
+ // Generate initial solution proposal
516
+ abstract async propose(
517
+ problem: string,
518
+ context: DebateContext
519
+ ): Promise<Proposal>;
520
+
521
+ // Critique another agent's proposal
522
+ abstract async critique(
523
+ proposal: Proposal,
524
+ context: DebateContext
525
+ ): Promise<Critique>;
526
+
527
+ // Refine own proposal based on critiques
528
+ abstract async refine(
529
+ originalProposal: Proposal,
530
+ critiques: Critique[],
531
+ context: DebateContext
532
+ ): Promise<Proposal>;
533
+
534
+ // Internal method to call LLM
535
+ protected async callLLM(prompt: string): Promise<string> {
536
+ return this.provider.complete({
537
+ model: this.config.model,
538
+ temperature: this.config.temperature,
539
+ systemPrompt: this.config.systemPrompt,
540
+ userPrompt: prompt,
541
+ });
542
+ }
543
+ }
544
+ ```
545
+
546
+ ### Specialized Agents
547
+
548
+ #### Architect Agent
549
+
550
+ **Role**: Focus on system design, scalability, architecture patterns
551
+
552
+ **System Prompt**:
553
+ ```
554
+ You are an expert software architect specializing in distributed systems
555
+ and scalable architecture design. When analyzing problems:
556
+
557
+ 1. Consider scalability and performance
558
+ 2. Think about component boundaries and interfaces
559
+ 3. Evaluate architectural patterns (microservices, event-driven, etc.)
560
+ 4. Consider data flow and state management
561
+ 5. Think about operational concerns (deployment, monitoring)
562
+
563
+ When proposing solutions:
564
+ - Start with high-level architecture
565
+ - Identify key components and their responsibilities
566
+ - Explain communication patterns
567
+ - Consider failure modes
568
+ - Provide clear diagrams or descriptions
569
+
570
+ When critiquing:
571
+ - Look for scalability bottlenecks
572
+ - Identify missing components
573
+ - Evaluate architectural coherence
574
+ - Consider operational complexity
575
+ ```
576
+
577
+ #### Security Agent
578
+
579
+ **Role**: Focus on security, authentication, authorization, data protection
580
+
581
+ **System Prompt**:
582
+ ```
583
+ You are a security expert specializing in application security, threat
584
+ modeling, and secure system design. When analyzing problems:
585
+
586
+ 1. Identify potential security threats
587
+ 2. Consider authentication and authorization
588
+ 3. Evaluate data protection (encryption, privacy)
589
+ 4. Think about attack vectors
590
+ 5. Consider compliance requirements (GDPR, SOC2, etc.)
591
+
592
+ When proposing solutions:
593
+ - Identify security requirements
594
+ - Suggest security controls
595
+ - Consider defense in depth
596
+ - Evaluate trust boundaries
597
+ - Think about secrets management
598
+
599
+ When critiquing:
600
+ - Look for security vulnerabilities
601
+ - Identify missing security controls
602
+ - Evaluate authentication/authorization gaps
603
+ - Consider data exposure risks
604
+ ```
605
+
606
+ #### Performance Agent
607
+
608
+ **Role**: Focus on performance, optimization, resource efficiency
609
+
610
+ **System Prompt**:
611
+ ```
612
+ You are a performance engineer specializing in system optimization,
613
+ profiling, and resource management. When analyzing problems:
614
+
615
+ 1. Consider performance characteristics (latency, throughput)
616
+ 2. Think about resource utilization (CPU, memory, network)
617
+ 3. Evaluate caching strategies
618
+ 4. Consider algorithmic complexity
619
+ 5. Think about performance testing and monitoring
620
+
621
+ When proposing solutions:
622
+ - Identify performance requirements
623
+ - Suggest optimization strategies
624
+ - Consider caching and precomputation
625
+ - Evaluate resource trade-offs
626
+ - Think about performance metrics
627
+
628
+ When critiquing:
629
+ - Look for performance bottlenecks
630
+ - Identify inefficient algorithms or data structures
631
+ - Evaluate resource usage
632
+ - Consider scalability limits
633
+ ```
634
+
635
+ #### Testing Agent
636
+
637
+ **Role**: Focus on testability, quality assurance, reliability
638
+
639
+ **System Prompt**:
640
+ ```
641
+ You are a quality engineer specializing in testing strategies, test
642
+ automation, and system reliability. When analyzing problems:
643
+
644
+ 1. Consider testability of the solution
645
+ 2. Think about test coverage and strategies
646
+ 3. Evaluate error handling and edge cases
647
+ 4. Consider observability and debugging
648
+ 5. Think about reliability and fault tolerance
649
+
650
+ When proposing solutions:
651
+ - Identify testing requirements
652
+ - Suggest testing strategies (unit, integration, e2e)
653
+ - Consider error scenarios
654
+ - Evaluate observability needs
655
+ - Think about chaos testing
656
+
657
+ When critiquing:
658
+ - Look for untestable components
659
+ - Identify missing error handling
660
+ - Evaluate edge case coverage
661
+ - Consider debugging difficulty
662
+ ```
663
+
664
+ ---
665
+
666
+ ## Orchestrator Logic
667
+
668
+ ### Orchestrator Class
669
+
670
+ ```typescript
671
+ class DebateOrchestrator {
672
+ constructor(
673
+ private agents: Agent[],
674
+ private judge: JudgeAgent,
675
+ private stateManager: StateManager,
676
+ private config: DebateConfig
677
+ ) {}
678
+
679
+ async runDebate(
680
+ problem: string,
681
+ context?: string
682
+ ): Promise<DebateResult> {
683
+ // Initialize debate state
684
+ const state = await this.stateManager.createDebate(problem, context);
685
+
686
+ try {
687
+ // Main debate loop
688
+ for (let round = 1; round <= this.config.rounds; round++) {
689
+ console.log(`\nRound ${round}/${this.config.rounds}`);
690
+
691
+ // Phase 1: Proposal (first round) or Refinement (subsequent rounds)
692
+ if (round === 1) {
693
+ await this.proposalPhase(state);
694
+ } else {
695
+ await this.refinementPhase(state);
696
+ }
697
+
698
+ // Phase 2: Critique (except last round)
699
+ if (round < this.config.rounds) {
700
+ await this.critiquePhase(state);
701
+ }
702
+
703
+ // Check termination conditions
704
+ if (await this.shouldTerminate(state)) {
705
+ break;
706
+ }
707
+ }
708
+
709
+ // Synthesis
710
+ const solution = await this.synthesisPhase(state);
711
+
712
+ // Finalize
713
+ await this.stateManager.completeDebate(state.id, solution);
714
+
715
+ return {
716
+ debateId: state.id,
717
+ solution,
718
+ rounds: state.rounds,
719
+ metadata: {
720
+ totalRounds: state.currentRound,
721
+ totalTokens: this.calculateTotalTokens(state),
722
+ duration: Date.now() - state.createdAt.getTime(),
723
+ },
724
+ };
725
+ } catch (error) {
726
+ await this.stateManager.failDebate(state.id, error);
727
+ throw error;
728
+ }
729
+ }
730
+
731
+ private async proposalPhase(state: DebateState): Promise<void> {
732
+ console.log(' Proposal Phase');
733
+
734
+ const proposals = await Promise.all(
735
+ this.agents.map(async (agent) => {
736
+ console.log(` [${agent.config.name}] Proposing solution...`);
737
+
738
+ const proposal = await agent.propose(
739
+ state.problem,
740
+ this.buildContext(state)
741
+ );
742
+
743
+ await this.stateManager.addContribution(state.id, {
744
+ agentId: agent.config.id,
745
+ agentRole: agent.config.role,
746
+ type: 'proposal',
747
+ content: proposal.content,
748
+ metadata: proposal.metadata,
749
+ });
750
+
751
+ return proposal;
752
+ })
753
+ );
754
+ }
755
+
756
+ private async critiquePhase(state: DebateState): Promise<void> {
757
+ console.log(' Critique Phase');
758
+
759
+ // Get all proposals from current round
760
+ const currentRound = state.rounds[state.currentRound - 1];
761
+ const proposals = currentRound.contributions.filter(
762
+ c => c.type === 'proposal'
763
+ );
764
+
765
+ // Each agent critiques others' proposals
766
+ for (const agent of this.agents) {
767
+ const otherProposals = proposals.filter(
768
+ p => p.agentId !== agent.config.id
769
+ );
770
+
771
+ for (const proposal of otherProposals) {
772
+ console.log(
773
+ ` [${agent.config.name}] Critiquing ${proposal.agentId}...`
774
+ );
775
+
776
+ const critique = await agent.critique(
777
+ proposal,
778
+ this.buildContext(state)
779
+ );
780
+
781
+ await this.stateManager.addContribution(state.id, {
782
+ agentId: agent.config.id,
783
+ agentRole: agent.config.role,
784
+ type: 'critique',
785
+ content: critique.content,
786
+ targetAgentId: proposal.agentId,
787
+ metadata: critique.metadata,
788
+ });
789
+ }
790
+ }
791
+ }
792
+
793
+ private async refinementPhase(state: DebateState): Promise<void> {
794
+ console.log(' Refinement Phase');
795
+
796
+ // Get proposals and critiques from previous round
797
+ const prevRound = state.rounds[state.currentRound - 2];
798
+
799
+ for (const agent of this.agents) {
800
+ // Find agent's original proposal
801
+ const originalProposal = prevRound.contributions.find(
802
+ c => c.agentId === agent.config.id && c.type === 'proposal'
803
+ );
804
+
805
+ // Find critiques targeting this agent
806
+ const critiques = prevRound.contributions.filter(
807
+ c => c.type === 'critique' && c.targetAgentId === agent.config.id
808
+ );
809
+
810
+ console.log(` [${agent.config.name}] Refining solution...`);
811
+
812
+ const refinedProposal = await agent.refine(
813
+ originalProposal,
814
+ critiques,
815
+ this.buildContext(state)
816
+ );
817
+
818
+ await this.stateManager.addContribution(state.id, {
819
+ agentId: agent.config.id,
820
+ agentRole: agent.config.role,
821
+ type: 'proposal',
822
+ content: refinedProposal.content,
823
+ metadata: refinedProposal.metadata,
824
+ });
825
+ }
826
+ }
827
+
828
+ private async synthesisPhase(state: DebateState): Promise<Solution> {
829
+ console.log('\n Synthesizing final solution...');
830
+
831
+ const solution = await this.judge.synthesize(
832
+ state.problem,
833
+ state.rounds,
834
+ this.buildContext(state)
835
+ );
836
+
837
+ return solution;
838
+ }
839
+
840
+ private async shouldTerminate(state: DebateState): Promise<boolean> {
841
+ switch (this.config.terminationCondition.type) {
842
+ case 'fixed':
843
+ return state.currentRound >= this.config.rounds;
844
+
845
+ case 'convergence':
846
+ return await this.checkConvergence(state);
847
+
848
+ case 'quality':
849
+ return await this.checkQualityThreshold(state);
850
+
851
+ default:
852
+ return false;
853
+ }
854
+ }
855
+
856
+ private buildContext(state: DebateState): DebateContext {
857
+ if (this.config.includeFullHistory) {
858
+ return {
859
+ problem: state.problem,
860
+ context: state.context,
861
+ history: state.rounds,
862
+ };
863
+ } else {
864
+ // Summarized context
865
+ return {
866
+ problem: state.problem,
867
+ context: state.context,
868
+ summary: this.summarizeHistory(state.rounds),
869
+ };
870
+ }
871
+ }
872
+ }
873
+ ```
874
+
875
+ ---
876
+
877
+ ## Judge/Synthesizer Logic
878
+
879
+ ```typescript
880
+ class JudgeAgent {
881
+ constructor(
882
+ private config: AgentConfig,
883
+ private provider: LLMProvider
884
+ ) {}
885
+
886
+ async synthesize(
887
+ problem: string,
888
+ rounds: DebateRound[],
889
+ context: DebateContext
890
+ ): Promise<Solution> {
891
+ const prompt = this.buildSynthesisPrompt(problem, rounds, context);
892
+
893
+ const response = await this.provider.complete({
894
+ model: this.config.model,
895
+ temperature: 0.3, // Lower temperature for consistency
896
+ systemPrompt: this.getJudgeSystemPrompt(),
897
+ userPrompt: prompt,
898
+ });
899
+
900
+ return this.parseSolution(response);
901
+ }
902
+
903
+ private getJudgeSystemPrompt(): string {
904
+ return `
905
+ You are an expert technical judge responsible for synthesizing the best
906
+ solution from multiple agent proposals and debates.
907
+
908
+ Your role:
909
+ 1. Review all proposals and critiques objectively
910
+ 2. Identify the strongest ideas from each agent
911
+ 3. Reconcile conflicting viewpoints
912
+ 4. Create a unified, coherent solution
913
+ 5. Acknowledge trade-offs and alternatives
914
+
915
+ When synthesizing:
916
+ - Be objective and evidence-based
917
+ - Consider all perspectives fairly
918
+ - Combine complementary ideas
919
+ - Address major concerns raised
920
+ - Provide clear recommendations
921
+ - Rate confidence in the solution
922
+
923
+ Output format:
924
+ - Solution description
925
+ - Key components
926
+ - Trade-offs
927
+ - Implementation recommendations
928
+ - Confidence score (0-100)
929
+ `;
930
+ }
931
+
932
+ private buildSynthesisPrompt(
933
+ problem: string,
934
+ rounds: DebateRound[],
935
+ context: DebateContext
936
+ ): string {
937
+ let prompt = `Problem: ${problem}\n\n`;
938
+
939
+ // Add debate history
940
+ rounds.forEach((round, idx) => {
941
+ prompt += `Round ${idx + 1}:\n`;
942
+ round.contributions.forEach((contrib) => {
943
+ prompt += `[${contrib.agentRole}] ${contrib.type}:\n`;
944
+ prompt += `${contrib.content}\n\n`;
945
+ });
946
+ });
947
+
948
+ prompt += `
949
+ Based on the above debate, synthesize the best solution that:
950
+ 1. Incorporates the strongest ideas from all agents
951
+ 2. Addresses the major concerns raised
952
+ 3. Provides a practical, implementable approach
953
+ 4. Acknowledges trade-offs
954
+
955
+ Provide a comprehensive final solution.
956
+ `;
957
+
958
+ return prompt;
959
+ }
960
+
961
+ private parseSolution(response: string): Solution {
962
+ // Parse structured response
963
+ // Could use JSON mode or structured output parsing
964
+ return {
965
+ description: response,
966
+ tradeoffs: this.extractTradeoffs(response),
967
+ recommendations: this.extractRecommendations(response),
968
+ confidence: this.extractConfidence(response),
969
+ synthesizedBy: this.config.id,
970
+ };
971
+ }
972
+ }
973
+ ```
974
+
975
+ ---
976
+
977
+ ## State Management
978
+
979
+ ```typescript
980
+ class StateManager {
981
+ private debates: Map<string, DebateState> = new Map();
982
+ private storage: Storage;
983
+
984
+ constructor(storage: Storage) {
985
+ this.storage = storage;
986
+ }
987
+
988
+ async createDebate(
989
+ problem: string,
990
+ context?: string
991
+ ): Promise<DebateState> {
992
+ const state: DebateState = {
993
+ id: generateId(),
994
+ problem,
995
+ context,
996
+ status: 'running',
997
+ currentRound: 0,
998
+ rounds: [],
999
+ createdAt: new Date(),
1000
+ updatedAt: new Date(),
1001
+ };
1002
+
1003
+ this.debates.set(state.id, state);
1004
+ await this.storage.save(state);
1005
+
1006
+ return state;
1007
+ }
1008
+
1009
+ async addContribution(
1010
+ debateId: string,
1011
+ contribution: Contribution
1012
+ ): Promise<void> {
1013
+ const state = this.debates.get(debateId);
1014
+ if (!state) throw new Error(`Debate ${debateId} not found`);
1015
+
1016
+ // Get or create current round
1017
+ let currentRound = state.rounds[state.currentRound];
1018
+ if (!currentRound) {
1019
+ currentRound = {
1020
+ roundNumber: state.currentRound + 1,
1021
+ phase: contribution.type === 'proposal' ? 'proposal' : 'critique',
1022
+ contributions: [],
1023
+ timestamp: new Date(),
1024
+ };
1025
+ state.rounds.push(currentRound);
1026
+ state.currentRound = currentRound.roundNumber;
1027
+ }
1028
+
1029
+ // Add contribution
1030
+ currentRound.contributions.push({
1031
+ ...contribution,
1032
+ metadata: {
1033
+ ...contribution.metadata,
1034
+ timestamp: new Date(),
1035
+ },
1036
+ });
1037
+
1038
+ state.updatedAt = new Date();
1039
+ await this.storage.save(state);
1040
+ }
1041
+
1042
+ async completeDebate(
1043
+ debateId: string,
1044
+ solution: Solution
1045
+ ): Promise<void> {
1046
+ const state = this.debates.get(debateId);
1047
+ if (!state) throw new Error(`Debate ${debateId} not found`);
1048
+
1049
+ state.status = 'completed';
1050
+ state.finalSolution = solution;
1051
+ state.updatedAt = new Date();
1052
+
1053
+ await this.storage.save(state);
1054
+ }
1055
+
1056
+ async failDebate(debateId: string, error: Error): Promise<void> {
1057
+ const state = this.debates.get(debateId);
1058
+ if (!state) return;
1059
+
1060
+ state.status = 'failed';
1061
+ state.updatedAt = new Date();
1062
+
1063
+ await this.storage.save(state);
1064
+ }
1065
+
1066
+ async getDebate(debateId: string): Promise<DebateState | null> {
1067
+ if (this.debates.has(debateId)) {
1068
+ return this.debates.get(debateId)!;
1069
+ }
1070
+ return await this.storage.load(debateId);
1071
+ }
1072
+
1073
+ async listDebates(filter?: DebateFilter): Promise<DebateState[]> {
1074
+ return await this.storage.list(filter);
1075
+ }
1076
+ }
1077
+ ```
1078
+
1079
+ ---
1080
+
1081
+ ## LLM Provider Layer
1082
+
1083
+ ### Provider Interface
1084
+
1085
+ ```typescript
1086
+ interface LLMProvider {
1087
+ complete(request: CompletionRequest): Promise<string>;
1088
+ stream(request: CompletionRequest): AsyncIterator<string>;
1089
+ generateEmbedding(text: string): Promise<number[]>;
1090
+ }
1091
+
1092
+ interface CompletionRequest {
1093
+ model: string;
1094
+ systemPrompt: string;
1095
+ userPrompt: string;
1096
+ temperature: number;
1097
+ maxTokens?: number;
1098
+ stopSequences?: string[];
1099
+ }
1100
+ ```
1101
+
1102
+ ### OpenAI Provider Implementation
1103
+
1104
+ ```typescript
1105
+ class OpenAIProvider implements LLMProvider {
1106
+ private client: OpenAI;
1107
+
1108
+ constructor(apiKey: string) {
1109
+ this.client = new OpenAI({ apiKey });
1110
+ }
1111
+
1112
+ async complete(request: CompletionRequest): Promise<string> {
1113
+ const response = await this.client.chat.completions.create({
1114
+ model: request.model,
1115
+ messages: [
1116
+ { role: 'system', content: request.systemPrompt },
1117
+ { role: 'user', content: request.userPrompt },
1118
+ ],
1119
+ temperature: request.temperature,
1120
+ max_tokens: request.maxTokens,
1121
+ stop: request.stopSequences,
1122
+ });
1123
+
1124
+ return response.choices[0].message.content || '';
1125
+ }
1126
+
1127
+ async *stream(request: CompletionRequest): AsyncIterator<string> {
1128
+ const stream = await this.client.chat.completions.create({
1129
+ model: request.model,
1130
+ messages: [
1131
+ { role: 'system', content: request.systemPrompt },
1132
+ { role: 'user', content: request.userPrompt },
1133
+ ],
1134
+ temperature: request.temperature,
1135
+ stream: true,
1136
+ });
1137
+
1138
+ for await (const chunk of stream) {
1139
+ const content = chunk.choices[0]?.delta?.content;
1140
+ if (content) yield content;
1141
+ }
1142
+ }
1143
+
1144
+ async generateEmbedding(text: string): Promise<number[]> {
1145
+ const response = await this.client.embeddings.create({
1146
+ model: 'text-embedding-3-small',
1147
+ input: text,
1148
+ });
1149
+
1150
+ return response.data[0].embedding;
1151
+ }
1152
+ }
1153
+ ```
1154
+
1155
+ ### Anthropic Provider Implementation
1156
+
1157
+ ```typescript
1158
+ class AnthropicProvider implements LLMProvider {
1159
+ private client: Anthropic;
1160
+
1161
+ constructor(apiKey: string) {
1162
+ this.client = new Anthropic({ apiKey });
1163
+ }
1164
+
1165
+ async complete(request: CompletionRequest): Promise<string> {
1166
+ const response = await this.client.messages.create({
1167
+ model: request.model,
1168
+ max_tokens: request.maxTokens || 4096,
1169
+ system: request.systemPrompt,
1170
+ messages: [
1171
+ { role: 'user', content: request.userPrompt },
1172
+ ],
1173
+ temperature: request.temperature,
1174
+ stop_sequences: request.stopSequences,
1175
+ });
1176
+
1177
+ return response.content[0].type === 'text'
1178
+ ? response.content[0].text
1179
+ : '';
1180
+ }
1181
+
1182
+ async *stream(request: CompletionRequest): AsyncIterator<string> {
1183
+ const stream = await this.client.messages.stream({
1184
+ model: request.model,
1185
+ max_tokens: request.maxTokens || 4096,
1186
+ system: request.systemPrompt,
1187
+ messages: [
1188
+ { role: 'user', content: request.userPrompt },
1189
+ ],
1190
+ temperature: request.temperature,
1191
+ });
1192
+
1193
+ for await (const event of stream) {
1194
+ if (event.type === 'content_block_delta' &&
1195
+ event.delta.type === 'text_delta') {
1196
+ yield event.delta.text;
1197
+ }
1198
+ }
1199
+ }
1200
+
1201
+ async generateEmbedding(text: string): Promise<number[]> {
1202
+ // Anthropic doesn't provide embeddings, use OpenAI or other service
1203
+ throw new Error('Embeddings not supported by Anthropic provider');
1204
+ }
1205
+ }
1206
+ ```
1207
+
1208
+ ---
1209
+
1210
+ ## Storage Implementation
1211
+
1212
+ ### File-Based Storage
1213
+
1214
+ ```typescript
1215
+ class FileStorage implements Storage {
1216
+ private baseDir: string;
1217
+
1218
+ constructor(baseDir: string = './debates') {
1219
+ this.baseDir = baseDir;
1220
+ this.ensureDirectoryExists();
1221
+ }
1222
+
1223
+ async save(state: DebateState): Promise<void> {
1224
+ const filePath = path.join(this.baseDir, `${state.id}.json`);
1225
+ await fs.promises.writeFile(
1226
+ filePath,
1227
+ JSON.stringify(state, null, 2),
1228
+ 'utf-8'
1229
+ );
1230
+ }
1231
+
1232
+ async load(debateId: string): Promise<DebateState | null> {
1233
+ const filePath = path.join(this.baseDir, `${debateId}.json`);
1234
+
1235
+ try {
1236
+ const content = await fs.promises.readFile(filePath, 'utf-8');
1237
+ return JSON.parse(content);
1238
+ } catch (error) {
1239
+ if (error.code === 'ENOENT') return null;
1240
+ throw error;
1241
+ }
1242
+ }
1243
+
1244
+ async list(filter?: DebateFilter): Promise<DebateState[]> {
1245
+ const files = await fs.promises.readdir(this.baseDir);
1246
+ const debates: DebateState[] = [];
1247
+
1248
+ for (const file of files) {
1249
+ if (!file.endsWith('.json')) continue;
1250
+
1251
+ const debate = await this.load(file.replace('.json', ''));
1252
+ if (debate && this.matchesFilter(debate, filter)) {
1253
+ debates.push(debate);
1254
+ }
1255
+ }
1256
+
1257
+ return debates.sort((a, b) =>
1258
+ b.createdAt.getTime() - a.createdAt.getTime()
1259
+ );
1260
+ }
1261
+
1262
+ private matchesFilter(
1263
+ debate: DebateState,
1264
+ filter?: DebateFilter
1265
+ ): boolean {
1266
+ if (!filter) return true;
1267
+
1268
+ if (filter.status && debate.status !== filter.status) {
1269
+ return false;
1270
+ }
1271
+
1272
+ if (filter.from && debate.createdAt < filter.from) {
1273
+ return false;
1274
+ }
1275
+
1276
+ if (filter.to && debate.createdAt > filter.to) {
1277
+ return false;
1278
+ }
1279
+
1280
+ if (filter.searchTerm) {
1281
+ const searchLower = filter.searchTerm.toLowerCase();
1282
+ if (!debate.problem.toLowerCase().includes(searchLower)) {
1283
+ return false;
1284
+ }
1285
+ }
1286
+
1287
+ return true;
1288
+ }
1289
+
1290
+ private ensureDirectoryExists(): void {
1291
+ if (!fs.existsSync(this.baseDir)) {
1292
+ fs.mkdirSync(this.baseDir, { recursive: true });
1293
+ }
1294
+ }
1295
+ }
1296
+ ```
1297
+
1298
+ ---
1299
+
1300
+ ## Configuration Management
1301
+
1302
+ ### Default Configuration File
1303
+
1304
+ ```json
1305
+ {
1306
+ "debate": {
1307
+ "rounds": 3,
1308
+ "terminationCondition": {
1309
+ "type": "fixed"
1310
+ },
1311
+ "synthesisMethod": "judge",
1312
+ "includeFullHistory": true,
1313
+ "timeoutPerRound": 300000
1314
+ },
1315
+ "agents": [
1316
+ {
1317
+ "id": "agent-architect",
1318
+ "name": "System Architect",
1319
+ "role": "architect",
1320
+ "model": "gpt-4",
1321
+ "provider": "openai",
1322
+ "temperature": 0.7,
1323
+ "enabled": true
1324
+ },
1325
+ {
1326
+ "id": "agent-security",
1327
+ "name": "Security Expert",
1328
+ "role": "security",
1329
+ "model": "claude-3-opus",
1330
+ "provider": "anthropic",
1331
+ "temperature": 0.6,
1332
+ "enabled": true
1333
+ },
1334
+ {
1335
+ "id": "agent-performance",
1336
+ "name": "Performance Engineer",
1337
+ "role": "performance",
1338
+ "model": "gpt-4",
1339
+ "provider": "openai",
1340
+ "temperature": 0.7,
1341
+ "enabled": true
1342
+ },
1343
+ {
1344
+ "id": "agent-testing",
1345
+ "name": "Quality Engineer",
1346
+ "role": "testing",
1347
+ "model": "gpt-4",
1348
+ "provider": "openai",
1349
+ "temperature": 0.6,
1350
+ "enabled": false
1351
+ }
1352
+ ],
1353
+ "judge": {
1354
+ "id": "judge-main",
1355
+ "name": "Technical Judge",
1356
+ "model": "gpt-4",
1357
+ "provider": "openai",
1358
+ "temperature": 0.3
1359
+ },
1360
+ "providers": {
1361
+ "openai": {
1362
+ "apiKeyEnv": "OPENAI_API_KEY"
1363
+ },
1364
+ "anthropic": {
1365
+ "apiKeyEnv": "ANTHROPIC_API_KEY"
1366
+ }
1367
+ }
1368
+ }
1369
+ ```
1370
+
1371
+ ### Configuration Loader
1372
+
1373
+ ```typescript
1374
+ class ConfigurationManager {
1375
+ private config: SystemConfig;
1376
+ private configPath: string;
1377
+
1378
+ constructor(configPath?: string) {
1379
+ this.configPath = configPath || './config/default-config.json';
1380
+ this.config = this.loadConfig();
1381
+ }
1382
+
1383
+ private loadConfig(): SystemConfig {
1384
+ if (fs.existsSync(this.configPath)) {
1385
+ const content = fs.readFileSync(this.configPath, 'utf-8');
1386
+ return JSON.parse(content);
1387
+ }
1388
+
1389
+ return this.getDefaultConfig();
1390
+ }
1391
+
1392
+ async saveConfig(): Promise<void> {
1393
+ const content = JSON.stringify(this.config, null, 2);
1394
+ await fs.promises.writeFile(this.configPath, content, 'utf-8');
1395
+ }
1396
+
1397
+ getDebateConfig(): DebateConfig {
1398
+ return this.config.debate;
1399
+ }
1400
+
1401
+ getAgentConfigs(): AgentConfig[] {
1402
+ return this.config.agents.filter(a => a.enabled);
1403
+ }
1404
+
1405
+ getJudgeConfig(): AgentConfig {
1406
+ return this.config.judge;
1407
+ }
1408
+
1409
+ updateAgent(agentId: string, updates: Partial<AgentConfig>): void {
1410
+ const agent = this.config.agents.find(a => a.id === agentId);
1411
+ if (agent) {
1412
+ Object.assign(agent, updates);
1413
+ }
1414
+ }
1415
+
1416
+ addAgent(agent: AgentConfig): void {
1417
+ this.config.agents.push(agent);
1418
+ }
1419
+
1420
+ removeAgent(agentId: string): void {
1421
+ this.config.agents = this.config.agents.filter(
1422
+ a => a.id !== agentId
1423
+ );
1424
+ }
1425
+
1426
+ private getDefaultConfig(): SystemConfig {
1427
+ // Return built-in defaults if no config file exists
1428
+ return require('../config/default-config.json');
1429
+ }
1430
+ }
1431
+ ```
1432
+
1433
+ ---
1434
+
1435
+ ## Utility Functions
1436
+
1437
+ ### Prompt Builder
1438
+
1439
+ ```typescript
1440
+ class PromptBuilder {
1441
+ static buildProposalPrompt(
1442
+ problem: string,
1443
+ role: AgentRole,
1444
+ context?: DebateContext
1445
+ ): string {
1446
+ let prompt = `Problem to solve:\n${problem}\n\n`;
1447
+
1448
+ if (context?.context) {
1449
+ prompt += `Additional context:\n${context.context}\n\n`;
1450
+ }
1451
+
1452
+ prompt += `As a ${role} expert, propose a comprehensive solution. Include:
1453
+ 1. Your recommended approach
1454
+ 2. Key components or considerations
1455
+ 3. Potential challenges
1456
+ 4. Why this approach is suitable
1457
+
1458
+ Be specific and detailed in your proposal.`;
1459
+
1460
+ return prompt;
1461
+ }
1462
+
1463
+ static buildCritiquePrompt(
1464
+ proposal: Proposal,
1465
+ proposerRole: AgentRole,
1466
+ criticRole: AgentRole
1467
+ ): string {
1468
+ return `You are reviewing a proposal from a ${proposerRole} expert.
1469
+
1470
+ Their proposal:
1471
+ ${proposal.content}
1472
+
1473
+ As a ${criticRole} expert, provide constructive critique:
1474
+ 1. Identify strengths of the proposal
1475
+ 2. Identify weaknesses or concerns from your perspective
1476
+ 3. Suggest specific improvements
1477
+ 4. Highlight any critical issues
1478
+
1479
+ Be objective and constructive in your critique.`;
1480
+ }
1481
+
1482
+ static buildRefinementPrompt(
1483
+ originalProposal: Proposal,
1484
+ critiques: Critique[],
1485
+ role: AgentRole
1486
+ ): string {
1487
+ let prompt = `Your original proposal:\n${originalProposal.content}\n\n`;
1488
+
1489
+ prompt += `Critiques from other experts:\n`;
1490
+ critiques.forEach((critique, idx) => {
1491
+ prompt += `\nCritique ${idx + 1}:\n${critique.content}\n`;
1492
+ });
1493
+
1494
+ prompt += `\nAs a ${role} expert, refine your proposal by:
1495
+ 1. Addressing valid concerns raised
1496
+ 2. Incorporating good suggestions
1497
+ 3. Defending aspects you still believe are correct
1498
+ 4. Providing a stronger, more complete solution
1499
+
1500
+ Produce an improved version of your proposal.`;
1501
+
1502
+ return prompt;
1503
+ }
1504
+
1505
+ static buildSummaryPrompt(rounds: DebateRound[]): string {
1506
+ return `Summarize the following debate rounds concisely, highlighting:
1507
+ 1. Main proposals from each agent
1508
+ 2. Key points of agreement
1509
+ 3. Key points of disagreement
1510
+ 4. Evolution of ideas across rounds
1511
+
1512
+ Keep the summary under 500 words.
1513
+
1514
+ Debate rounds:
1515
+ ${this.formatRounds(rounds)}`;
1516
+ }
1517
+
1518
+ private static formatRounds(rounds: DebateRound[]): string {
1519
+ return rounds
1520
+ .map((round, idx) => {
1521
+ const contributions = round.contributions
1522
+ .map(c => `[${c.agentRole}] ${c.type}: ${c.content}`)
1523
+ .join('\n');
1524
+ return `Round ${idx + 1}:\n${contributions}`;
1525
+ })
1526
+ .join('\n\n');
1527
+ }
1528
+ }
1529
+ ```
1530
+
1531
+ ### Logger
1532
+
1533
+ ```typescript
1534
+ class Logger {
1535
+ private verbose: boolean;
1536
+
1537
+ constructor(verbose: boolean = false) {
1538
+ this.verbose = verbose;
1539
+ }
1540
+
1541
+ info(message: string): void {
1542
+ console.log(`ℹ️ ${message}`);
1543
+ }
1544
+
1545
+ success(message: string): void {
1546
+ console.log(`✅ ${message}`);
1547
+ }
1548
+
1549
+ error(message: string): void {
1550
+ console.error(`❌ ${message}`);
1551
+ }
1552
+
1553
+ warn(message: string): void {
1554
+ console.warn(`⚠️ ${message}`);
1555
+ }
1556
+
1557
+ debug(message: string): void {
1558
+ if (this.verbose) {
1559
+ console.log(`🔍 ${message}`);
1560
+ }
1561
+ }
1562
+
1563
+ agentAction(agentName: string, action: string): void {
1564
+ console.log(` [${agentName}] ${action}`);
1565
+ }
1566
+
1567
+ progress(message: string, current: number, total: number): void {
1568
+ const percent = Math.round((current / total) * 100);
1569
+ console.log(` ${message} [${current}/${total}] ${percent}%`);
1570
+ }
1571
+
1572
+ separator(): void {
1573
+ console.log('━'.repeat(60));
1574
+ }
1575
+ }
1576
+ ```
1577
+
1578
+ ---
1579
+
1580
+ ## Export Functionality
1581
+
1582
+ ### Markdown Exporter
1583
+
1584
+ ```typescript
1585
+ class MarkdownExporter {
1586
+ async export(
1587
+ debate: DebateState,
1588
+ options: ExportOptions
1589
+ ): Promise<string> {
1590
+ let markdown = '';
1591
+
1592
+ // Header
1593
+ markdown += `# Debate Report\n\n`;
1594
+ markdown += `**Problem**: ${debate.problem}\n\n`;
1595
+ markdown += `**Date**: ${debate.createdAt.toLocaleString()}\n`;
1596
+ markdown += `**Status**: ${debate.status}\n`;
1597
+ markdown += `**Rounds**: ${debate.currentRound}\n\n`;
1598
+
1599
+ markdown += `---\n\n`;
1600
+
1601
+ // Debate rounds
1602
+ markdown += `## Debate History\n\n`;
1603
+
1604
+ for (const round of debate.rounds) {
1605
+ markdown += `### Round ${round.roundNumber} - ${round.phase}\n\n`;
1606
+
1607
+ for (const contrib of round.contributions) {
1608
+ markdown += `#### ${contrib.agentRole} (${contrib.type})\n\n`;
1609
+ markdown += `${contrib.content}\n\n`;
1610
+
1611
+ if (options.includeMetadata) {
1612
+ markdown += `*Tokens: ${contrib.metadata.tokensUsed}, `;
1613
+ markdown += `Latency: ${contrib.metadata.latencyMs}ms*\n\n`;
1614
+ }
1615
+ }
1616
+ }
1617
+
1618
+ // Final solution
1619
+ if (debate.finalSolution) {
1620
+ markdown += `---\n\n`;
1621
+ markdown += `## Final Solution\n\n`;
1622
+ markdown += `${debate.finalSolution.description}\n\n`;
1623
+
1624
+ if (debate.finalSolution.tradeoffs.length > 0) {
1625
+ markdown += `### Trade-offs\n\n`;
1626
+ debate.finalSolution.tradeoffs.forEach(tradeoff => {
1627
+ markdown += `- ${tradeoff}\n`;
1628
+ });
1629
+ markdown += `\n`;
1630
+ }
1631
+
1632
+ if (debate.finalSolution.recommendations.length > 0) {
1633
+ markdown += `### Recommendations\n\n`;
1634
+ debate.finalSolution.recommendations.forEach(rec => {
1635
+ markdown += `- ${rec}\n`;
1636
+ });
1637
+ markdown += `\n`;
1638
+ }
1639
+
1640
+ markdown += `**Confidence**: ${debate.finalSolution.confidence}/100\n\n`;
1641
+ }
1642
+
1643
+ return markdown;
1644
+ }
1645
+ }
1646
+ ```
1647
+
1648
+ ### JSON Exporter
1649
+
1650
+ ```typescript
1651
+ class JSONExporter {
1652
+ async export(
1653
+ debate: DebateState,
1654
+ options: ExportOptions
1655
+ ): Promise<string> {
1656
+ const exportData: any = {
1657
+ id: debate.id,
1658
+ problem: debate.problem,
1659
+ context: debate.context,
1660
+ status: debate.status,
1661
+ createdAt: debate.createdAt,
1662
+ updatedAt: debate.updatedAt,
1663
+ rounds: debate.rounds,
1664
+ finalSolution: debate.finalSolution,
1665
+ };
1666
+
1667
+ if (!options.includeMetadata) {
1668
+ // Remove metadata from contributions
1669
+ exportData.rounds = debate.rounds.map(round => ({
1670
+ ...round,
1671
+ contributions: round.contributions.map(({ metadata, ...rest }) => rest),
1672
+ }));
1673
+ }
1674
+
1675
+ return JSON.stringify(exportData, null, 2);
1676
+ }
1677
+ }
1678
+ ```
1679
+
1680
+ ---
1681
+
1682
+ ## Web Interface Extension (Future)
1683
+
1684
+ ### Architecture for Web Extension
1685
+
1686
+ ```
1687
+ Web Frontend (React/Vue)
1688
+
1689
+ ├── WebSocket Connection (real-time updates)
1690
+
1691
+
1692
+ ┌─────────────────────────────────────┐
1693
+ │ API Server (Express) │
1694
+ │ │
1695
+ │ Routes: │
1696
+ │ - POST /api/debates │
1697
+ │ - GET /api/debates/:id │
1698
+ │ - GET /api/debates │
1699
+ │ - WS /api/debates/:id/stream │
1700
+ │ - GET /api/config │
1701
+ │ - PUT /api/config │
1702
+ └─────────┬───────────────────────────┘
1703
+
1704
+
1705
+ ┌─────────────────────────────────────┐
1706
+ │ Debate Orchestrator (Core Logic) │
1707
+ └─────────────────────────────────────┘
1708
+ ```
1709
+
1710
+ ### API Endpoints
1711
+
1712
+ ```typescript
1713
+ // Express routes
1714
+ app.post('/api/debates', async (req, res) => {
1715
+ const { problem, context, config } = req.body;
1716
+
1717
+ const debateId = await orchestrator.startDebate(problem, context, config);
1718
+
1719
+ res.json({ debateId });
1720
+ });
1721
+
1722
+ app.get('/api/debates/:id', async (req, res) => {
1723
+ const debate = await stateManager.getDebate(req.params.id);
1724
+ res.json(debate);
1725
+ });
1726
+
1727
+ app.get('/api/debates/:id/stream', (req, res) => {
1728
+ // Setup Server-Sent Events for real-time updates
1729
+ res.setHeader('Content-Type', 'text/event-stream');
1730
+ res.setHeader('Cache-Control', 'no-cache');
1731
+ res.setHeader('Connection', 'keep-alive');
1732
+
1733
+ const listener = (update) => {
1734
+ res.write(`data: ${JSON.stringify(update)}\n\n`);
1735
+ };
1736
+
1737
+ orchestrator.on('update', listener);
1738
+
1739
+ req.on('close', () => {
1740
+ orchestrator.off('update', listener);
1741
+ });
1742
+ });
1743
+ ```
1744
+
1745
+ ### UI Components
1746
+
1747
+ **Dashboard**:
1748
+ - List of recent debates
1749
+ - Quick start debate button
1750
+ - Configuration settings
1751
+
1752
+ **Debate View**:
1753
+ - Real-time progress indicator
1754
+ - Current round/phase display
1755
+ - Agent activity log
1756
+ - Collapsible proposal/critique cards
1757
+ - Final solution display
1758
+
1759
+ **Configuration Panel**:
1760
+ - Agent enable/disable toggles
1761
+ - Model selection dropdowns
1762
+ - Temperature sliders
1763
+ - Round count input
1764
+
1765
+ ---
1766
+
1767
+ ## Error Handling
1768
+
1769
+ ### Error Types
1770
+
1771
+ ```typescript
1772
+ class DebateError extends Error {
1773
+ constructor(message: string, public code: string) {
1774
+ super(message);
1775
+ this.name = 'DebateError';
1776
+ }
1777
+ }
1778
+
1779
+ class AgentError extends DebateError {
1780
+ constructor(
1781
+ message: string,
1782
+ public agentId: string,
1783
+ public phase: string
1784
+ ) {
1785
+ super(message, 'AGENT_ERROR');
1786
+ }
1787
+ }
1788
+
1789
+ class ProviderError extends DebateError {
1790
+ constructor(
1791
+ message: string,
1792
+ public provider: string,
1793
+ public originalError?: Error
1794
+ ) {
1795
+ super(message, 'PROVIDER_ERROR');
1796
+ }
1797
+ }
1798
+
1799
+ class ConfigurationError extends DebateError {
1800
+ constructor(message: string) {
1801
+ super(message, 'CONFIG_ERROR');
1802
+ }
1803
+ }
1804
+ ```
1805
+
1806
+ ### Error Handling Strategy
1807
+
1808
+ ```typescript
1809
+ class ErrorHandler {
1810
+ async handleAgentError(
1811
+ error: AgentError,
1812
+ state: DebateState
1813
+ ): Promise<void> {
1814
+ // Log error
1815
+ logger.error(`Agent ${error.agentId} failed in ${error.phase}: ${error.message}`);
1816
+
1817
+ // Try to continue with other agents
1818
+ const remainingAgents = this.getRemainingAgents(error.agentId);
1819
+
1820
+ if (remainingAgents.length < 2) {
1821
+ throw new DebateError(
1822
+ 'Insufficient agents to continue debate',
1823
+ 'INSUFFICIENT_AGENTS'
1824
+ );
1825
+ }
1826
+
1827
+ // Mark agent as failed in this round
1828
+ await stateManager.markAgentFailed(state.id, error.agentId);
1829
+ }
1830
+
1831
+ async handleProviderError(
1832
+ error: ProviderError,
1833
+ retryCount: number = 0
1834
+ ): Promise<any> {
1835
+ const maxRetries = 3;
1836
+
1837
+ if (retryCount >= maxRetries) {
1838
+ throw error;
1839
+ }
1840
+
1841
+ // Exponential backoff
1842
+ const delay = Math.pow(2, retryCount) * 1000;
1843
+ await this.sleep(delay);
1844
+
1845
+ // Retry the operation
1846
+ logger.warn(`Retrying after provider error (attempt ${retryCount + 1}/${maxRetries})`);
1847
+ }
1848
+
1849
+ private sleep(ms: number): Promise<void> {
1850
+ return new Promise(resolve => setTimeout(resolve, ms));
1851
+ }
1852
+ }
1853
+ ```
1854
+
1855
+ ---
1856
+
1857
+ ## Testing Strategy
1858
+
1859
+ ### Unit Tests
1860
+
1861
+ ```typescript
1862
+ describe('DebateOrchestrator', () => {
1863
+ let orchestrator: DebateOrchestrator;
1864
+ let mockAgents: Agent[];
1865
+ let mockJudge: JudgeAgent;
1866
+ let mockStateManager: StateManager;
1867
+
1868
+ beforeEach(() => {
1869
+ mockAgents = [
1870
+ createMockAgent('architect'),
1871
+ createMockAgent('security'),
1872
+ ];
1873
+ mockJudge = createMockJudge();
1874
+ mockStateManager = createMockStateManager();
1875
+
1876
+ orchestrator = new DebateOrchestrator(
1877
+ mockAgents,
1878
+ mockJudge,
1879
+ mockStateManager,
1880
+ defaultConfig
1881
+ );
1882
+ });
1883
+
1884
+ it('should run complete debate flow', async () => {
1885
+ const result = await orchestrator.runDebate(
1886
+ 'Design a caching system'
1887
+ );
1888
+
1889
+ expect(result.debateId).toBeDefined();
1890
+ expect(result.solution).toBeDefined();
1891
+ expect(result.rounds.length).toBe(3);
1892
+ });
1893
+
1894
+ it('should handle agent failures gracefully', async () => {
1895
+ mockAgents[0].propose = jest.fn().mockRejectedValue(
1896
+ new Error('Agent failed')
1897
+ );
1898
+
1899
+ const result = await orchestrator.runDebate('Test problem');
1900
+
1901
+ // Should continue with remaining agent
1902
+ expect(result.solution).toBeDefined();
1903
+ });
1904
+ });
1905
+ ```
1906
+
1907
+ ### Integration Tests
1908
+
1909
+ ```typescript
1910
+ describe('End-to-End Debate', () => {
1911
+ it('should complete debate with real LLM providers', async () => {
1912
+ const config = loadTestConfig();
1913
+ const orchestrator = createOrchestrator(config);
1914
+
1915
+ const result = await orchestrator.runDebate(
1916
+ 'Design a simple rate limiting system for an API'
1917
+ );
1918
+
1919
+ expect(result.solution.description).toContain('rate limit');
1920
+ expect(result.solution.confidence).toBeGreaterThan(50);
1921
+ }, 120000); // 2 minute timeout for LLM calls
1922
+ });
1923
+ ```
1924
+
1925
+ ---
1926
+
1927
+ ## Performance Considerations
1928
+
1929
+ ### Parallel Execution
1930
+
1931
+ ```typescript
1932
+ // Execute agent proposals in parallel
1933
+ const proposals = await Promise.all(
1934
+ this.agents.map(agent => agent.propose(problem, context))
1935
+ );
1936
+
1937
+ // With timeout and error handling
1938
+ const proposals = await Promise.allSettled(
1939
+ this.agents.map(agent =>
1940
+ this.withTimeout(
1941
+ agent.propose(problem, context),
1942
+ this.config.timeoutPerRound
1943
+ )
1944
+ )
1945
+ );
1946
+ ```
1947
+
1948
+ ### Caching
1949
+
1950
+ ```typescript
1951
+ class CachedLLMProvider implements LLMProvider {
1952
+ private cache: Map<string, string> = new Map();
1953
+
1954
+ async complete(request: CompletionRequest): Promise<string> {
1955
+ const cacheKey = this.getCacheKey(request);
1956
+
1957
+ if (this.cache.has(cacheKey)) {
1958
+ return this.cache.get(cacheKey)!;
1959
+ }
1960
+
1961
+ const response = await this.provider.complete(request);
1962
+ this.cache.set(cacheKey, response);
1963
+
1964
+ return response;
1965
+ }
1966
+
1967
+ private getCacheKey(request: CompletionRequest): string {
1968
+ return JSON.stringify({
1969
+ model: request.model,
1970
+ system: request.systemPrompt,
1971
+ user: request.userPrompt,
1972
+ temp: request.temperature,
1973
+ });
1974
+ }
1975
+ }
1976
+ ```
1977
+
1978
+ ### Token Management
1979
+
1980
+ ```typescript
1981
+ class TokenTracker {
1982
+ private totalTokens: number = 0;
1983
+ private costEstimate: number = 0;
1984
+
1985
+ trackUsage(model: string, tokens: number): void {
1986
+ this.totalTokens += tokens;
1987
+ this.costEstimate += this.calculateCost(model, tokens);
1988
+ }
1989
+
1990
+ private calculateCost(model: string, tokens: number): number {
1991
+ const rates = {
1992
+ 'gpt-4': 0.03 / 1000, // $0.03 per 1K tokens
1993
+ 'gpt-3.5-turbo': 0.002 / 1000,
1994
+ 'claude-3-opus': 0.015 / 1000,
1995
+ };
1996
+
1997
+ return (rates[model] || 0) * tokens;
1998
+ }
1999
+
2000
+ getReport(): TokenReport {
2001
+ return {
2002
+ totalTokens: this.totalTokens,
2003
+ estimatedCost: this.costEstimate,
2004
+ };
2005
+ }
2006
+ }
2007
+ ```
2008
+
2009
+ ---
2010
+
2011
+ ## Deployment
2012
+
2013
+ ### Environment Variables
2014
+
2015
+ ```bash
2016
+ # .env file
2017
+ OPENAI_API_KEY=sk-...
2018
+ ANTHROPIC_API_KEY=sk-ant-...
2019
+
2020
+ # Optional
2021
+ DEBATE_STORAGE_PATH=./debates
2022
+ DEBATE_CONFIG_PATH=./config/custom-config.json
2023
+ LOG_LEVEL=info
2024
+ ```
2025
+
2026
+ ### Docker Support
2027
+
2028
+ ```dockerfile
2029
+ FROM node:18-alpine
2030
+
2031
+ WORKDIR /app
2032
+
2033
+ COPY package*.json ./
2034
+ RUN npm ci --only=production
2035
+
2036
+ COPY dist ./dist
2037
+ COPY config ./config
2038
+
2039
+ ENV NODE_ENV=production
2040
+
2041
+ ENTRYPOINT ["node", "dist/cli/index.js"]
2042
+ CMD ["--help"]
2043
+ ```
2044
+
2045
+ ### NPM Package
2046
+
2047
+ ```json
2048
+ {
2049
+ "name": "multi-agent-debate",
2050
+ "version": "1.0.0",
2051
+ "bin": {
2052
+ "debate": "./dist/cli/index.js"
2053
+ },
2054
+ "scripts": {
2055
+ "build": "tsc",
2056
+ "dev": "ts-node src/cli/index.ts",
2057
+ "test": "jest",
2058
+ "lint": "eslint src/**/*.ts"
2059
+ }
2060
+ }
2061
+ ```
2062
+
2063
+ ---
2064
+
2065
+ ## Example Usage Scenarios
2066
+
2067
+ ### Scenario 1: Software Architecture Design
2068
+
2069
+ ```bash
2070
+ $ debate "Design a microservices architecture for an e-commerce platform" \
2071
+ --agents architect,security,performance \
2072
+ --rounds 3 \
2073
+ --output ecommerce-architecture.md
2074
+ ```
2075
+
2076
+ Expected outcome:
2077
+ - Architect proposes service boundaries
2078
+ - Security evaluates auth/authorization
2079
+ - Performance analyzes scalability
2080
+ - Final solution: Balanced architecture with security and performance considerations
2081
+
2082
+ ### Scenario 2: API Design
2083
+
2084
+ ```bash
2085
+ $ debate "Design a RESTful API for a social media platform" \
2086
+ --context api-requirements.txt \
2087
+ --agents architect,security \
2088
+ --rounds 2
2089
+ ```
2090
+
2091
+ ### Scenario 3: Database Schema
2092
+
2093
+ ```bash
2094
+ $ debate "Design a database schema for a multi-tenant SaaS application" \
2095
+ --agents architect,performance,security \
2096
+ --rounds 4
2097
+ ```
2098
+
2099
+ ---
2100
+
2101
+ ## Future Enhancements
2102
+
2103
+ ### Phase 2 Features
2104
+
2105
+ 1. **Code Generation**: Generate actual code implementations
2106
+ 2. **Diagram Generation**: Auto-generate architecture diagrams
2107
+ 3. **Cost Optimization**: Smart agent selection based on budget
2108
+ 4. **Template Library**: Pre-built problem templates
2109
+ 5. **Agent Personalities**: Customizable agent behaviors
2110
+ 6. **Multi-language Support**: Internationalization
2111
+ 7. **Collaboration**: Multiple users can influence debate
2112
+ 8. **Learning**: Agents learn from past debates
2113
+
2114
+ ### Phase 3 Features
2115
+
2116
+ 1. **Visual Debate Flow**: Interactive visualization
2117
+ 2. **Voice Integration**: Speak problems, hear solutions
2118
+ 3. **Integration**: Jira, GitHub, Slack integrations
2119
+ 4. **Advanced Analytics**: Debate quality metrics
2120
+ 5. **Agent Marketplace**: Community-contributed agents
2121
+ 6. **Hybrid Debates**: Mix AI and human participants
2122
+
2123
+ ---
2124
+
2125
+ ## Conclusion
2126
+
2127
+ This specification provides a complete blueprint for building a multi-agent debate system. The architecture is:
2128
+
2129
+ - **Modular**: Easy to add new agents, providers, or storage backends
2130
+ - **Extensible**: CLI can extend to web interface with minimal changes
2131
+ - **Testable**: Clear separation of concerns enables comprehensive testing
2132
+ - **Production-ready**: Includes error handling, logging, and performance considerations
2133
+
2134
+ ---
2135
+
2136
+ ## Implementation Roadmap
2137
+
2138
+ ### Phase 1: Core CLI (Weeks 1-3)
2139
+
2140
+ **Week 1: Foundation**
2141
+ - Set up TypeScript project structure
2142
+ - Implement core data models and types
2143
+ - Create LLM provider abstractions
2144
+ - Implement OpenAI and Anthropic providers
2145
+ - Basic configuration system
2146
+
2147
+ **Week 2: Core Logic**
2148
+ - Implement Agent base class
2149
+ - Create specialized agents (Architect, Security, Performance)
2150
+ - Implement DebateOrchestrator
2151
+ - Implement JudgeAgent
2152
+ - Create StateManager with file storage
2153
+
2154
+ **Week 3: CLI & Polish**
2155
+ - Implement CLI commands (debate, configure, history, export)
2156
+ - Add logging and progress indicators
2157
+ - Implement export functionality (Markdown, JSON)
2158
+ - Error handling and validation
2159
+ - Documentation and examples
2160
+
2161
+ ### Phase 2: Advanced Features (Weeks 4-6)
2162
+
2163
+ **Week 4: Debate Enhancements**
2164
+ - Convergence detection
2165
+ - Tournament-style debates
2166
+ - Context summarization
2167
+ - Performance optimization (parallel execution, caching)
2168
+
2169
+ **Week 5: Usability**
2170
+ - Interactive mode
2171
+ - Configuration UI (CLI-based)
2172
+ - Better output formatting
2173
+ - Template system for common problems
2174
+
2175
+ **Week 6: Testing & Reliability**
2176
+ - Comprehensive unit tests
2177
+ - Integration tests with real LLMs
2178
+ - Error recovery mechanisms
2179
+ - Performance benchmarks
2180
+
2181
+ ### Phase 3: Web Interface (Weeks 7-10)
2182
+
2183
+ **Week 7: API Server**
2184
+ - Express.js server setup
2185
+ - REST API endpoints
2186
+ - WebSocket/SSE for real-time updates
2187
+ - Authentication (if needed)
2188
+
2189
+ **Week 8-9: Frontend**
2190
+ - React/Vue application
2191
+ - Dashboard with debate list
2192
+ - Real-time debate viewer
2193
+ - Configuration management UI
2194
+ - Export and sharing features
2195
+
2196
+ **Week 10: Deployment**
2197
+ - Docker containerization
2198
+ - CI/CD pipeline
2199
+ - Documentation
2200
+ - Demo videos and tutorials
2201
+
2202
+ ---
2203
+
2204
+ ## Sample Implementation Files
2205
+
2206
+ ### package.json
2207
+
2208
+ ```json
2209
+ {
2210
+ "name": "multi-agent-debate",
2211
+ "version": "1.0.0",
2212
+ "description": "Multi-agent debate system for software design problems",
2213
+ "main": "dist/index.js",
2214
+ "bin": {
2215
+ "debate": "./dist/cli/index.js"
2216
+ },
2217
+ "scripts": {
2218
+ "build": "tsc",
2219
+ "dev": "ts-node src/cli/index.ts",
2220
+ "test": "jest",
2221
+ "test:watch": "jest --watch",
2222
+ "lint": "eslint src/**/*.ts",
2223
+ "format": "prettier --write \"src/**/*.ts\"",
2224
+ "prepare": "npm run build"
2225
+ },
2226
+ "keywords": [
2227
+ "ai",
2228
+ "multi-agent",
2229
+ "debate",
2230
+ "llm",
2231
+ "software-design"
2232
+ ],
2233
+ "author": "Your Name",
2234
+ "license": "MIT",
2235
+ "dependencies": {
2236
+ "commander": "^11.0.0",
2237
+ "openai": "^4.20.0",
2238
+ "@anthropic-ai/sdk": "^0.9.0",
2239
+ "chalk": "^5.3.0",
2240
+ "inquirer": "^9.2.0",
2241
+ "ora": "^7.0.0",
2242
+ "dotenv": "^16.3.0",
2243
+ "uuid": "^9.0.0"
2244
+ },
2245
+ "devDependencies": {
2246
+ "@types/node": "^20.0.0",
2247
+ "@types/jest": "^29.5.0",
2248
+ "@types/inquirer": "^9.0.0",
2249
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
2250
+ "@typescript-eslint/parser": "^6.0.0",
2251
+ "eslint": "^8.50.0",
2252
+ "jest": "^29.7.0",
2253
+ "prettier": "^3.0.0",
2254
+ "ts-jest": "^29.1.0",
2255
+ "ts-node": "^10.9.0",
2256
+ "typescript": "^5.2.0"
2257
+ }
2258
+ }
2259
+ ```
2260
+
2261
+ ### tsconfig.json
2262
+
2263
+ ```json
2264
+ {
2265
+ "compilerOptions": {
2266
+ "target": "ES2020",
2267
+ "module": "commonjs",
2268
+ "lib": ["ES2020"],
2269
+ "outDir": "./dist",
2270
+ "rootDir": "./src",
2271
+ "strict": true,
2272
+ "esModuleInterop": true,
2273
+ "skipLibCheck": true,
2274
+ "forceConsistentCasingInFileNames": true,
2275
+ "resolveJsonModule": true,
2276
+ "declaration": true,
2277
+ "declarationMap": true,
2278
+ "sourceMap": true,
2279
+ "moduleResolution": "node"
2280
+ },
2281
+ "include": ["src/**/*"],
2282
+ "exclude": ["node_modules", "dist", "tests"]
2283
+ }
2284
+ ```
2285
+
2286
+ ### CLI Entry Point (src/cli/index.ts)
2287
+
2288
+ ```typescript
2289
+ #!/usr/bin/env node
2290
+ import { Command } from 'commander';
2291
+ import chalk from 'chalk';
2292
+ import { debateCommand } from './commands/debate';
2293
+ import { configureCommand } from './commands/configure';
2294
+ import { historyCommand } from './commands/history';
2295
+ import { exportCommand } from './commands/export';
2296
+ import { loadEnvironment } from '../utils/environment';
2297
+
2298
+ // Load environment variables
2299
+ loadEnvironment();
2300
+
2301
+ const program = new Command();
2302
+
2303
+ program
2304
+ .name('debate')
2305
+ .description('Multi-agent debate system for software design problems')
2306
+ .version('1.0.0');
2307
+
2308
+ // ASCII art banner
2309
+ const banner = `
2310
+ ╔═══════════════════════════════════════════════════╗
2311
+ ║ ║
2312
+ ║ Multi-Agent Debate System ║
2313
+ ║ Collaborative AI Problem Solving ║
2314
+ ║ ║
2315
+ ╚═══════════════════════════════════════════════════╝
2316
+ `;
2317
+
2318
+ console.log(chalk.cyan(banner));
2319
+
2320
+ // Register commands
2321
+ debateCommand(program);
2322
+ configureCommand(program);
2323
+ historyCommand(program);
2324
+ exportCommand(program);
2325
+
2326
+ // Parse arguments
2327
+ program.parse(process.argv);
2328
+
2329
+ // Show help if no command provided
2330
+ if (!process.argv.slice(2).length) {
2331
+ program.outputHelp();
2332
+ }
2333
+ ```
2334
+
2335
+ ### Main Debate Command (src/cli/commands/debate.ts)
2336
+
2337
+ ```typescript
2338
+ import { Command } from 'commander';
2339
+ import chalk from 'chalk';
2340
+ import ora from 'ora';
2341
+ import inquirer from 'inquirer';
2342
+ import { DebateOrchestrator } from '../../core/orchestrator';
2343
+ import { ConfigurationManager } from '../../core/config-manager';
2344
+ import { StateManager } from '../../core/state-manager';
2345
+ import { FileStorage } from '../../utils/storage';
2346
+ import { createProviders, createAgents, createJudge } from '../../core/factory';
2347
+ import { Logger } from '../../utils/logger';
2348
+
2349
+ export function debateCommand(program: Command): void {
2350
+ program
2351
+ .command('debate')
2352
+ .argument('[problem]', 'Problem statement to debate')
2353
+ .option('-a, --agents <agents>', 'Comma-separated list of agent roles')
2354
+ .option('-r, --rounds <number>', 'Number of debate rounds', '3')
2355
+ .option('-c, --config <path>', 'Path to configuration file')
2356
+ .option('-o, --output <path>', 'Output file for results')
2357
+ .option('-i, --interactive', 'Interactive mode')
2358
+ .option('-v, --verbose', 'Verbose logging')
2359
+ .option('--context <path>', 'Path to context file')
2360
+ .description('Start a new debate')
2361
+ .action(async (problem, options) => {
2362
+ const logger = new Logger(options.verbose);
2363
+
2364
+ try {
2365
+ // Interactive mode
2366
+ if (options.interactive || !problem) {
2367
+ const answers = await inquirer.prompt([
2368
+ {
2369
+ type: 'input',
2370
+ name: 'problem',
2371
+ message: 'Enter the problem to debate:',
2372
+ default: problem,
2373
+ validate: (input) => input.length > 0 || 'Problem cannot be empty',
2374
+ },
2375
+ {
2376
+ type: 'checkbox',
2377
+ name: 'agents',
2378
+ message: 'Select agents to participate:',
2379
+ choices: [
2380
+ { name: 'System Architect', value: 'architect', checked: true },
2381
+ { name: 'Security Expert', value: 'security', checked: true },
2382
+ { name: 'Performance Engineer', value: 'performance', checked: true },
2383
+ { name: 'Quality Engineer', value: 'testing', checked: false },
2384
+ ],
2385
+ },
2386
+ {
2387
+ type: 'number',
2388
+ name: 'rounds',
2389
+ message: 'Number of debate rounds:',
2390
+ default: parseInt(options.rounds),
2391
+ validate: (input) => input > 0 || 'Must be at least 1 round',
2392
+ },
2393
+ ]);
2394
+
2395
+ problem = answers.problem;
2396
+ options.agents = answers.agents.join(',');
2397
+ options.rounds = answers.rounds.toString();
2398
+ }
2399
+
2400
+ logger.separator();
2401
+ logger.info(chalk.bold('Starting Multi-Agent Debate'));
2402
+ logger.separator();
2403
+ logger.info(`Problem: ${chalk.yellow(problem)}`);
2404
+
2405
+ // Load configuration
2406
+ const configManager = new ConfigurationManager(options.config);
2407
+ const debateConfig = configManager.getDebateConfig();
2408
+ debateConfig.rounds = parseInt(options.rounds);
2409
+
2410
+ // Filter agents if specified
2411
+ let agentConfigs = configManager.getAgentConfigs();
2412
+ if (options.agents) {
2413
+ const requestedRoles = options.agents.split(',');
2414
+ agentConfigs = agentConfigs.filter(a =>
2415
+ requestedRoles.includes(a.role)
2416
+ );
2417
+ }
2418
+
2419
+ logger.info(`\nActive Agents:`);
2420
+ agentConfigs.forEach(agent => {
2421
+ logger.info(` ✓ ${agent.name} (${agent.model})`);
2422
+ });
2423
+
2424
+ // Load context if provided
2425
+ let context: string | undefined;
2426
+ if (options.context) {
2427
+ const fs = require('fs');
2428
+ context = fs.readFileSync(options.context, 'utf-8');
2429
+ logger.info(`\nContext loaded from: ${options.context}`);
2430
+ }
2431
+
2432
+ logger.separator();
2433
+
2434
+ // Initialize system
2435
+ const storage = new FileStorage();
2436
+ const stateManager = new StateManager(storage);
2437
+ const providers = createProviders(configManager);
2438
+ const agents = createAgents(agentConfigs, providers);
2439
+ const judge = createJudge(configManager.getJudgeConfig(), providers);
2440
+
2441
+ const orchestrator = new DebateOrchestrator(
2442
+ agents,
2443
+ judge,
2444
+ stateManager,
2445
+ debateConfig
2446
+ );
2447
+
2448
+ // Run debate with progress indicators
2449
+ const spinner = ora('Initializing debate...').start();
2450
+
2451
+ orchestrator.on('round-start', (round) => {
2452
+ spinner.stop();
2453
+ logger.info(`\n${chalk.bold(`Round ${round.number}/${debateConfig.rounds}`)}: ${round.phase}`);
2454
+ });
2455
+
2456
+ orchestrator.on('agent-start', ({ agent, action }) => {
2457
+ spinner.text = `[${agent.name}] ${action}...`;
2458
+ spinner.start();
2459
+ });
2460
+
2461
+ orchestrator.on('agent-complete', ({ agent, duration }) => {
2462
+ spinner.succeed(`[${agent.name}] Complete (${(duration / 1000).toFixed(1)}s)`);
2463
+ });
2464
+
2465
+ orchestrator.on('synthesis-start', () => {
2466
+ spinner.text = 'Synthesizing final solution...';
2467
+ spinner.start();
2468
+ });
2469
+
2470
+ const result = await orchestrator.runDebate(problem, context);
2471
+
2472
+ spinner.succeed('Debate complete!');
2473
+
2474
+ // Display results
2475
+ logger.separator();
2476
+ logger.success(chalk.bold.green('FINAL SOLUTION'));
2477
+ logger.separator();
2478
+
2479
+ console.log('\n' + result.solution.description + '\n');
2480
+
2481
+ if (result.solution.tradeoffs.length > 0) {
2482
+ logger.info(chalk.bold('Trade-offs:'));
2483
+ result.solution.tradeoffs.forEach(tradeoff => {
2484
+ logger.info(` • ${tradeoff}`);
2485
+ });
2486
+ console.log();
2487
+ }
2488
+
2489
+ if (result.solution.recommendations.length > 0) {
2490
+ logger.info(chalk.bold('Recommendations:'));
2491
+ result.solution.recommendations.forEach(rec => {
2492
+ logger.info(` • ${rec}`);
2493
+ });
2494
+ console.log();
2495
+ }
2496
+
2497
+ logger.info(`${chalk.bold('Confidence Score:')} ${result.solution.confidence}/100`);
2498
+ logger.info(`${chalk.bold('Total Rounds:')} ${result.metadata.totalRounds}`);
2499
+ logger.info(`${chalk.bold('Duration:')} ${(result.metadata.duration / 1000).toFixed(1)}s`);
2500
+ logger.info(`${chalk.bold('Total Tokens:')} ${result.metadata.totalTokens.toLocaleString()}`);
2501
+
2502
+ logger.separator();
2503
+
2504
+ // Save or export results
2505
+ if (options.output) {
2506
+ const fs = require('fs');
2507
+ const path = require('path');
2508
+ const ext = path.extname(options.output);
2509
+
2510
+ if (ext === '.json') {
2511
+ const debate = await stateManager.getDebate(result.debateId);
2512
+ fs.writeFileSync(options.output, JSON.stringify(debate, null, 2));
2513
+ } else {
2514
+ // Default to markdown
2515
+ const { MarkdownExporter } = require('../../utils/exporters');
2516
+ const exporter = new MarkdownExporter();
2517
+ const debate = await stateManager.getDebate(result.debateId);
2518
+ const markdown = await exporter.export(debate, { includeMetadata: true });
2519
+ fs.writeFileSync(options.output, markdown);
2520
+ }
2521
+
2522
+ logger.success(`Results saved to: ${options.output}`);
2523
+ } else {
2524
+ logger.info(`💾 Debate saved with ID: ${chalk.cyan(result.debateId)}`);
2525
+ logger.info(`📊 View details: ${chalk.cyan(`debate history show ${result.debateId}`)}`);
2526
+ }
2527
+
2528
+ } catch (error) {
2529
+ logger.error(`Debate failed: ${error.message}`);
2530
+ if (options.verbose) {
2531
+ console.error(error);
2532
+ }
2533
+ process.exit(1);
2534
+ }
2535
+ });
2536
+ }
2537
+ ```
2538
+
2539
+ ### Factory Pattern for Creating Components
2540
+
2541
+ ```typescript
2542
+ // src/core/factory.ts
2543
+ import { AgentConfig } from '../types/agent.types';
2544
+ import { LLMProvider } from '../providers/llm-provider';
2545
+ import { OpenAIProvider } from '../providers/openai-provider';
2546
+ import { AnthropicProvider } from '../providers/anthropic-provider';
2547
+ import { ArchitectAgent } from '../agents/architect-agent';
2548
+ import { SecurityAgent } from '../agents/security-agent';
2549
+ import { PerformanceAgent } from '../agents/performance-agent';
2550
+ import { TestingAgent } from '../agents/testing-agent';
2551
+ import { JudgeAgent } from '../core/judge';
2552
+ import { Agent } from '../core/agent';
2553
+ import { ConfigurationManager } from './config-manager';
2554
+
2555
+ export function createProviders(
2556
+ configManager: ConfigurationManager
2557
+ ): Map<string, LLMProvider> {
2558
+ const providers = new Map<string, LLMProvider>();
2559
+
2560
+ const providerConfigs = configManager.getProviderConfigs();
2561
+
2562
+ for (const [name, config] of Object.entries(providerConfigs)) {
2563
+ const apiKey = process.env[config.apiKeyEnv];
2564
+
2565
+ if (!apiKey) {
2566
+ console.warn(`Warning: API key not found for ${name} (${config.apiKeyEnv})`);
2567
+ continue;
2568
+ }
2569
+
2570
+ switch (name) {
2571
+ case 'openai':
2572
+ providers.set('openai', new OpenAIProvider(apiKey));
2573
+ break;
2574
+ case 'anthropic':
2575
+ providers.set('anthropic', new AnthropicProvider(apiKey));
2576
+ break;
2577
+ }
2578
+ }
2579
+
2580
+ return providers;
2581
+ }
2582
+
2583
+ export function createAgents(
2584
+ agentConfigs: AgentConfig[],
2585
+ providers: Map<string, LLMProvider>
2586
+ ): Agent[] {
2587
+ const agents: Agent[] = [];
2588
+
2589
+ for (const config of agentConfigs) {
2590
+ const provider = providers.get(config.provider);
2591
+
2592
+ if (!provider) {
2593
+ console.warn(`Provider ${config.provider} not available for agent ${config.name}`);
2594
+ continue;
2595
+ }
2596
+
2597
+ let agent: Agent;
2598
+
2599
+ switch (config.role) {
2600
+ case 'architect':
2601
+ agent = new ArchitectAgent(config, provider);
2602
+ break;
2603
+ case 'security':
2604
+ agent = new SecurityAgent(config, provider);
2605
+ break;
2606
+ case 'performance':
2607
+ agent = new PerformanceAgent(config, provider);
2608
+ break;
2609
+ case 'testing':
2610
+ agent = new TestingAgent(config, provider);
2611
+ break;
2612
+ default:
2613
+ // Fallback to base agent
2614
+ agent = new ArchitectAgent(config, provider);
2615
+ }
2616
+
2617
+ agents.push(agent);
2618
+ }
2619
+
2620
+ return agents;
2621
+ }
2622
+
2623
+ export function createJudge(
2624
+ judgeConfig: AgentConfig,
2625
+ providers: Map<string, LLMProvider>
2626
+ ): JudgeAgent {
2627
+ const provider = providers.get(judgeConfig.provider);
2628
+
2629
+ if (!provider) {
2630
+ throw new Error(`Provider ${judgeConfig.provider} not available for judge`);
2631
+ }
2632
+
2633
+ return new JudgeAgent(judgeConfig, provider);
2634
+ }
2635
+ ```
2636
+
2637
+ ---
2638
+
2639
+ ## Advanced Examples
2640
+
2641
+ ### Example 1: Custom Agent with Specific Expertise
2642
+
2643
+ ```typescript
2644
+ // src/agents/database-agent.ts
2645
+ import { Agent } from '../core/agent';
2646
+ import { AgentConfig } from '../types/agent.types';
2647
+ import { LLMProvider } from '../providers/llm-provider';
2648
+
2649
+ export class DatabaseAgent extends Agent {
2650
+ protected getSystemPrompt(): string {
2651
+ return `
2652
+ You are a database expert specializing in database design, optimization,
2653
+ and data modeling. Your expertise includes:
2654
+
2655
+ - Relational and NoSQL databases
2656
+ - Indexing strategies
2657
+ - Query optimization
2658
+ - Normalization and denormalization
2659
+ - Sharding and partitioning
2660
+ - Replication and consistency
2661
+ - Transaction management
2662
+
2663
+ When analyzing problems:
2664
+ 1. Consider data modeling and relationships
2665
+ 2. Evaluate query patterns and access patterns
2666
+ 3. Think about scalability and data volume
2667
+ 4. Consider data integrity and consistency
2668
+ 5. Evaluate backup and recovery strategies
2669
+
2670
+ When proposing solutions:
2671
+ - Design appropriate schema
2672
+ - Suggest indexing strategy
2673
+ - Consider partitioning if needed
2674
+ - Evaluate consistency requirements
2675
+ - Think about migration strategies
2676
+
2677
+ When critiquing:
2678
+ - Look for inefficient data models
2679
+ - Identify missing indexes or over-indexing
2680
+ - Evaluate scalability bottlenecks
2681
+ - Consider data integrity issues
2682
+ `;
2683
+ }
2684
+
2685
+ async propose(problem: string, context: any): Promise<any> {
2686
+ const prompt = `
2687
+ Problem: ${problem}
2688
+
2689
+ As a database expert, propose a comprehensive database solution that addresses:
2690
+ 1. Data model and schema design
2691
+ 2. Database technology choice (SQL vs NoSQL)
2692
+ 3. Indexing strategy
2693
+ 4. Scalability considerations
2694
+ 5. Consistency and availability trade-offs
2695
+
2696
+ Provide a detailed proposal.
2697
+ `;
2698
+
2699
+ const response = await this.callLLM(prompt);
2700
+
2701
+ return {
2702
+ content: response,
2703
+ metadata: {
2704
+ tokensUsed: this.estimateTokens(response),
2705
+ latencyMs: Date.now(),
2706
+ model: this.config.model,
2707
+ },
2708
+ };
2709
+ }
2710
+ }
2711
+ ```
2712
+
2713
+ ### Example 2: Problem Templates
2714
+
2715
+ ```typescript
2716
+ // src/templates/problem-templates.ts
2717
+ export const problemTemplates = {
2718
+ 'rate-limiting': {
2719
+ name: 'Rate Limiting System',
2720
+ template: `Design a rate limiting system for a {service_type} with the following requirements:
2721
+ - Support {rate} requests per {time_period}
2722
+ - Handle {concurrent_users} concurrent users
2723
+ - Distributed across {num_instances} instances
2724
+ - Requirements: {requirements}`,
2725
+ variables: ['service_type', 'rate', 'time_period', 'concurrent_users', 'num_instances', 'requirements'],
2726
+ suggestedAgents: ['architect', 'performance', 'security'],
2727
+ },
2728
+
2729
+ 'caching-layer': {
2730
+ name: 'Caching Layer',
2731
+ template: `Design a caching layer for {application_type} that:
2732
+ - Caches {data_types}
2733
+ - Supports {cache_size} of data
2734
+ - Has {ttl} TTL requirements
2735
+ - Needs to handle {consistency_level} consistency
2736
+ - Additional requirements: {requirements}`,
2737
+ variables: ['application_type', 'data_types', 'cache_size', 'ttl', 'consistency_level', 'requirements'],
2738
+ suggestedAgents: ['architect', 'performance'],
2739
+ },
2740
+
2741
+ 'authentication-service': {
2742
+ name: 'Authentication Service',
2743
+ template: `Design an authentication service for {application_type} that:
2744
+ - Supports {auth_methods}
2745
+ - Handles {user_count} users
2746
+ - Requires {security_level} security level
2747
+ - Needs {compliance} compliance
2748
+ - Additional requirements: {requirements}`,
2749
+ variables: ['application_type', 'auth_methods', 'user_count', 'security_level', 'compliance', 'requirements'],
2750
+ suggestedAgents: ['architect', 'security'],
2751
+ },
2752
+
2753
+ 'microservices-architecture': {
2754
+ name: 'Microservices Architecture',
2755
+ template: `Design a microservices architecture for {application_domain} that:
2756
+ - Includes {services_list} services
2757
+ - Handles {traffic_volume} traffic
2758
+ - Requires {availability} availability
2759
+ - Communication pattern: {communication_pattern}
2760
+ - Additional requirements: {requirements}`,
2761
+ variables: ['application_domain', 'services_list', 'traffic_volume', 'availability', 'communication_pattern', 'requirements'],
2762
+ suggestedAgents: ['architect', 'performance', 'security'],
2763
+ },
2764
+ };
2765
+
2766
+ // Usage in CLI
2767
+ export function getTemplate(templateName: string): any {
2768
+ return problemTemplates[templateName];
2769
+ }
2770
+
2771
+ export function fillTemplate(templateName: string, variables: Record<string, string>): string {
2772
+ const template = problemTemplates[templateName];
2773
+ if (!template) throw new Error(`Template ${templateName} not found`);
2774
+
2775
+ let problem = template.template;
2776
+ for (const [key, value] of Object.entries(variables)) {
2777
+ problem = problem.replace(`{${key}}`, value);
2778
+ }
2779
+
2780
+ return problem;
2781
+ }
2782
+ ```
2783
+
2784
+ ### Example 3: Debate Visualization (for web interface)
2785
+
2786
+ ```typescript
2787
+ // Component for visualizing debate flow
2788
+ interface DebateVisualizationProps {
2789
+ debate: DebateState;
2790
+ }
2791
+
2792
+ export const DebateVisualization: React.FC<DebateVisualizationProps> = ({ debate }) => {
2793
+ return (
2794
+ <div className="debate-visualization">
2795
+ <div className="timeline">
2796
+ {debate.rounds.map((round, idx) => (
2797
+ <div key={idx} className="round-section">
2798
+ <div className="round-header">
2799
+ <h3>Round {round.roundNumber}</h3>
2800
+ <span className="phase-badge">{round.phase}</span>
2801
+ </div>
2802
+
2803
+ <div className="contributions-grid">
2804
+ {round.contributions.map((contrib, cidx) => (
2805
+ <div
2806
+ key={cidx}
2807
+ className={`contribution-card ${contrib.type}`}
2808
+ data-agent={contrib.agentRole}
2809
+ >
2810
+ <div className="contribution-header">
2811
+ <span className="agent-name">{contrib.agentRole}</span>
2812
+ <span className="contribution-type">{contrib.type}</span>
2813
+ </div>
2814
+
2815
+ <div className="contribution-content">
2816
+ {contrib.content}
2817
+ </div>
2818
+
2819
+ <div className="contribution-metadata">
2820
+ <span>{contrib.metadata.tokensUsed} tokens</span>
2821
+ <span>{contrib.metadata.latencyMs}ms</span>
2822
+ </div>
2823
+ </div>
2824
+ ))}
2825
+ </div>
2826
+ </div>
2827
+ ))}
2828
+ </div>
2829
+
2830
+ {debate.finalSolution && (
2831
+ <div className="final-solution-section">
2832
+ <h2>Final Solution</h2>
2833
+ <div className="solution-content">
2834
+ {debate.finalSolution.description}
2835
+ </div>
2836
+ <div className="solution-metadata">
2837
+ <span>Confidence: {debate.finalSolution.confidence}/100</span>
2838
+ </div>
2839
+ </div>
2840
+ )}
2841
+ </div>
2842
+ );
2843
+ };
2844
+ ```
2845
+
2846
+ ---
2847
+
2848
+ ## Best Practices
2849
+
2850
+ ### 1. Prompt Engineering
2851
+
2852
+ **Do:**
2853
+ - Be specific and detailed in system prompts
2854
+ - Provide clear role definitions
2855
+ - Include examples when helpful
2856
+ - Structure prompts with numbered lists
2857
+ - Request specific output formats
2858
+
2859
+ **Don't:**
2860
+ - Use vague or ambiguous language
2861
+ - Overload prompts with too many instructions
2862
+ - Assume agents understand implicit context
2863
+ - Use overly complex nested instructions
2864
+
2865
+ ### 2. Error Handling
2866
+
2867
+ **Do:**
2868
+ - Handle LLM API errors gracefully
2869
+ - Implement retries with exponential backoff
2870
+ - Provide meaningful error messages
2871
+ - Log errors for debugging
2872
+ - Allow debates to continue with fewer agents if one fails
2873
+
2874
+ **Don't:**
2875
+ - Fail entire debate on single agent error
2876
+ - Retry indefinitely
2877
+ - Hide error details from users
2878
+ - Ignore rate limits
2879
+
2880
+ ### 3. Performance Optimization
2881
+
2882
+ **Do:**
2883
+ - Execute agent calls in parallel when possible
2884
+ - Cache similar requests
2885
+ - Use streaming for better UX
2886
+ - Monitor token usage
2887
+ - Set reasonable timeouts
2888
+
2889
+ **Don't:**
2890
+ - Make unnecessary API calls
2891
+ - Ignore rate limits
2892
+ - Block on sequential operations unnecessarily
2893
+ - Store excessive history in memory
2894
+
2895
+ ### 4. Configuration Management
2896
+
2897
+ **Do:**
2898
+ - Use environment variables for secrets
2899
+ - Provide sensible defaults
2900
+ - Validate configuration on load
2901
+ - Document all options
2902
+ - Support multiple configuration formats
2903
+
2904
+ **Don't:**
2905
+ - Hardcode API keys
2906
+ - Require configuration for everything
2907
+ - Ignore invalid configuration silently
2908
+ - Mix configuration concerns
2909
+
2910
+ ---
2911
+
2912
+ ## Glossary
2913
+
2914
+ **Agent**: An AI entity with a specific role and expertise that participates in debates
2915
+
2916
+ **Debate**: A structured conversation where multiple agents analyze and solve a problem
2917
+
2918
+ **Round**: One iteration of the debate process (proposal, critique, or refinement)
2919
+
2920
+ **Orchestrator**: The component that manages the debate flow and coordinates agents
2921
+
2922
+ **Judge**: A specialized agent that synthesizes final solutions from debate rounds
2923
+
2924
+ **Provider**: An abstraction layer for different LLM APIs (OpenAI, Anthropic, etc.)
2925
+
2926
+ **Contribution**: A single piece of input from an agent (proposal, critique, or refinement)
2927
+
2928
+ **Synthesis**: The process of combining multiple agent perspectives into a unified solution
2929
+
2930
+ **Convergence**: When agents' proposals become sufficiently similar, indicating consensus
2931
+
2932
+ ---
2933
+
2934
+ ## References and Resources
2935
+
2936
+ ### Documentation
2937
+ - OpenAI API: https://platform.openai.com/docs
2938
+ - Anthropic API: https://docs.anthropic.com
2939
+ - Commander.js: https://github.com/tj/commander.js
2940
+ - Inquirer.js: https://github.com/SBoudrias/Inquirer.js
2941
+
2942
+ ### Research Papers
2943
+ - "Improving Factuality and Reasoning in Language Models through Multiagent Debate" (Du et al., 2023)
2944
+ - "Multi-Agent Collaboration: Harnessing the Power of Intelligent LLM Agents" (Zhang et al., 2023)
2945
+ - "AutoGen: Enabling Next-Gen LLM Applications via Multi-Agent Conversation" (Wu et al., 2023)
2946
+
2947
+ ### Similar Projects
2948
+ - Microsoft AutoGen: https://github.com/microsoft/autogen
2949
+ - LangGraph: https://github.com/langchain-ai/langgraph
2950
+ - CrewAI: https://github.com/joaomdmoura/crewAI
2951
+ - ChatDev: https://github.com/OpenBMB/ChatDev
2952
+
2953
+ ---
2954
+
2955
+ ## Support and Contribution
2956
+
2957
+ ### Getting Help
2958
+ - Check documentation and examples
2959
+ - Search existing issues on GitHub
2960
+ - Ask questions in discussions
2961
+ - Review troubleshooting guide
2962
+
2963
+ ### Contributing
2964
+ - Fork the repository
2965
+ - Create a feature branch
2966
+ - Write tests for new features
2967
+ - Submit pull request with clear description
2968
+ - Follow code style guidelines
2969
+
2970
+ ### Reporting Issues
2971
+ - Use issue templates
2972
+ - Provide minimal reproduction steps
2973
+ - Include environment details
2974
+ - Attach relevant logs (without API keys!)
2975
+
2976
+ ---
2977
+
2978
+ **End of Specification**
2979
+
2980
+ This comprehensive specification provides everything needed to build a production-ready multi-agent debate system. The design emphasizes modularity, extensibility, and real-world usability while maintaining clean architecture principles.