adaptive-memory-multi-model-router 1.2.2

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 (95) hide show
  1. package/README.md +114 -0
  2. package/demo/research-demo.js +266 -0
  3. package/dist/cache/prefixCache.d.ts +114 -0
  4. package/dist/cache/prefixCache.d.ts.map +1 -0
  5. package/dist/cache/prefixCache.js +285 -0
  6. package/dist/cache/prefixCache.js.map +1 -0
  7. package/dist/cache/responseCache.d.ts +58 -0
  8. package/dist/cache/responseCache.d.ts.map +1 -0
  9. package/dist/cache/responseCache.js +153 -0
  10. package/dist/cache/responseCache.js.map +1 -0
  11. package/dist/cli.js +59 -0
  12. package/dist/cost/costTracker.d.ts +95 -0
  13. package/dist/cost/costTracker.d.ts.map +1 -0
  14. package/dist/cost/costTracker.js +240 -0
  15. package/dist/cost/costTracker.js.map +1 -0
  16. package/dist/index.d.ts +723 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/index.js +239 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/memory/episodicMemory.d.ts +82 -0
  21. package/dist/memory/episodicMemory.d.ts.map +1 -0
  22. package/dist/memory/episodicMemory.js +145 -0
  23. package/dist/memory/episodicMemory.js.map +1 -0
  24. package/dist/orchestration/haloOrchestrator.d.ts +102 -0
  25. package/dist/orchestration/haloOrchestrator.d.ts.map +1 -0
  26. package/dist/orchestration/haloOrchestrator.js +207 -0
  27. package/dist/orchestration/haloOrchestrator.js.map +1 -0
  28. package/dist/orchestration/mctsWorkflow.d.ts +85 -0
  29. package/dist/orchestration/mctsWorkflow.d.ts.map +1 -0
  30. package/dist/orchestration/mctsWorkflow.js +210 -0
  31. package/dist/orchestration/mctsWorkflow.js.map +1 -0
  32. package/dist/providers/localProvider.d.ts +102 -0
  33. package/dist/providers/localProvider.d.ts.map +1 -0
  34. package/dist/providers/localProvider.js +338 -0
  35. package/dist/providers/localProvider.js.map +1 -0
  36. package/dist/providers/registry.d.ts +55 -0
  37. package/dist/providers/registry.d.ts.map +1 -0
  38. package/dist/providers/registry.js +138 -0
  39. package/dist/providers/registry.js.map +1 -0
  40. package/dist/routing/advancedRouter.d.ts +68 -0
  41. package/dist/routing/advancedRouter.d.ts.map +1 -0
  42. package/dist/routing/advancedRouter.js +332 -0
  43. package/dist/routing/advancedRouter.js.map +1 -0
  44. package/dist/tools/tmlpdTools.d.ts +101 -0
  45. package/dist/tools/tmlpdTools.d.ts.map +1 -0
  46. package/dist/tools/tmlpdTools.js +368 -0
  47. package/dist/tools/tmlpdTools.js.map +1 -0
  48. package/dist/utils/batchProcessor.d.ts +96 -0
  49. package/dist/utils/batchProcessor.d.ts.map +1 -0
  50. package/dist/utils/batchProcessor.js +170 -0
  51. package/dist/utils/batchProcessor.js.map +1 -0
  52. package/dist/utils/compression.d.ts +61 -0
  53. package/dist/utils/compression.d.ts.map +1 -0
  54. package/dist/utils/compression.js +281 -0
  55. package/dist/utils/compression.js.map +1 -0
  56. package/dist/utils/reliability.d.ts +74 -0
  57. package/dist/utils/reliability.d.ts.map +1 -0
  58. package/dist/utils/reliability.js +177 -0
  59. package/dist/utils/reliability.js.map +1 -0
  60. package/dist/utils/speculativeDecoding.d.ts +117 -0
  61. package/dist/utils/speculativeDecoding.d.ts.map +1 -0
  62. package/dist/utils/speculativeDecoding.js +246 -0
  63. package/dist/utils/speculativeDecoding.js.map +1 -0
  64. package/dist/utils/tokenUtils.d.ts +50 -0
  65. package/dist/utils/tokenUtils.d.ts.map +1 -0
  66. package/dist/utils/tokenUtils.js +124 -0
  67. package/dist/utils/tokenUtils.js.map +1 -0
  68. package/examples/QUICKSTART.md +183 -0
  69. package/notebooks/quickstart.ipynb +157 -0
  70. package/package.json +83 -0
  71. package/python/examples.py +53 -0
  72. package/python/integrations.py +330 -0
  73. package/python/setup.py +28 -0
  74. package/python/tmlpd.py +369 -0
  75. package/qna/REDDIT_GAP_ANALYSIS.md +299 -0
  76. package/qna/TMLPD_QNA.md +751 -0
  77. package/rust/tmlpd.h +268 -0
  78. package/skill/SKILL.md +238 -0
  79. package/src/cache/prefixCache.ts +365 -0
  80. package/src/cache/responseCache.ts +147 -0
  81. package/src/cost/costTracker.ts +302 -0
  82. package/src/index.ts +224 -0
  83. package/src/memory/episodicMemory.ts +185 -0
  84. package/src/orchestration/haloOrchestrator.ts +266 -0
  85. package/src/orchestration/mctsWorkflow.ts +262 -0
  86. package/src/providers/localProvider.ts +406 -0
  87. package/src/providers/registry.ts +164 -0
  88. package/src/routing/advancedRouter.ts +406 -0
  89. package/src/tools/tmlpdTools.ts +433 -0
  90. package/src/utils/batchProcessor.ts +232 -0
  91. package/src/utils/compression.ts +325 -0
  92. package/src/utils/reliability.ts +221 -0
  93. package/src/utils/speculativeDecoding.ts +344 -0
  94. package/src/utils/tokenUtils.ts +145 -0
  95. package/tsconfig.json +18 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * TMLPD Episodic Memory Store
3
+ *
4
+ * Stores specific task executions with full context.
5
+ * Reference implementation - for full features see TMLPD v2.x
6
+ *
7
+ * Full TMLPD includes:
8
+ * - JSON-based episodic storage with keyword indexing
9
+ * - Importance scoring and time-based decay
10
+ * - Episodic retrieval by task similarity
11
+ */
12
+
13
+ import { nanoid } from "nanoid";
14
+
15
+ export interface EpisodicEntry {
16
+ id: string;
17
+ timestamp: number;
18
+ task: {
19
+ description: string;
20
+ type: string;
21
+ complexity: number;
22
+ };
23
+ result: {
24
+ success: boolean;
25
+ output: string;
26
+ duration_ms: number;
27
+ };
28
+ agent: {
29
+ id: string;
30
+ model: string;
31
+ provider: string;
32
+ };
33
+ metadata: Record<string, any>;
34
+ importance: number;
35
+ }
36
+
37
+ export interface MemoryQuery {
38
+ task_type?: string;
39
+ keywords?: string[];
40
+ limit?: number;
41
+ }
42
+
43
+ export class EpisodicMemoryStore {
44
+ private entries: EpisodicEntry[] = [];
45
+ private maxEntries: number;
46
+ private keywordIndex: Map<string, string[]>;
47
+
48
+ constructor(maxEntries = 1000) {
49
+ this.maxEntries = maxEntries;
50
+ this.keywordIndex = new Map();
51
+ }
52
+
53
+ /**
54
+ * Store an episodic memory
55
+ */
56
+ store(entry: Omit<EpisodicEntry, "id" | "timestamp">): string {
57
+ const id = nanoid(12);
58
+ const fullEntry: EpisodicEntry = {
59
+ ...entry,
60
+ id,
61
+ timestamp: Date.now()
62
+ };
63
+
64
+ this.entries.push(fullEntry);
65
+
66
+ // Index keywords
67
+ if (entry.task.description) {
68
+ const words = entry.task.description.toLowerCase().split(/\s+/);
69
+ words.forEach(word => {
70
+ if (word.length > 3) {
71
+ const existing = this.keywordIndex.get(word) || [];
72
+ existing.push(id);
73
+ this.keywordIndex.set(word, existing);
74
+ }
75
+ });
76
+ }
77
+
78
+ // Evict oldest if at capacity
79
+ if (this.entries.length > this.maxEntries) {
80
+ const evicted = this.entries.shift();
81
+ if (evicted) {
82
+ // Clean up keyword index for evicted entry
83
+ for (const [word, ids] of this.keywordIndex.entries()) {
84
+ const filtered = ids.filter(existingId => existingId !== evicted.id);
85
+ if (filtered.length === 0) {
86
+ this.keywordIndex.delete(word);
87
+ } else {
88
+ this.keywordIndex.set(word, filtered);
89
+ }
90
+ }
91
+ }
92
+ }
93
+
94
+ return id;
95
+ }
96
+
97
+ /**
98
+ * Query episodic memories
99
+ */
100
+ query(query: MemoryQuery): EpisodicEntry[] {
101
+ let results = [...this.entries];
102
+
103
+ if (query.task_type) {
104
+ results = results.filter(e => e.task.type === query.task_type);
105
+ }
106
+
107
+ if (query.keywords && query.keywords.length > 0) {
108
+ const matchingIds = new Set<string>();
109
+ query.keywords.forEach(kw => {
110
+ const lower = kw.toLowerCase();
111
+ for (const [word, ids] of this.keywordIndex.entries()) {
112
+ if (word.includes(lower)) {
113
+ ids.forEach(id => matchingIds.add(id));
114
+ }
115
+ }
116
+ });
117
+ if (matchingIds.size > 0) {
118
+ results = results.filter(e => matchingIds.has(e.id));
119
+ }
120
+ }
121
+
122
+ return results.slice(-(query.limit || 10));
123
+ }
124
+
125
+ /**
126
+ * Get similar tasks (for learning)
127
+ */
128
+ getSimilarTasks(taskDescription: string, limit = 5): EpisodicEntry[] {
129
+ const words = taskDescription.toLowerCase().split(/\s+/);
130
+ const scores = new Map<string, number>();
131
+
132
+ this.entries.forEach(entry => {
133
+ let score = 0;
134
+ const entryWords = entry.task.description.toLowerCase().split(/\s+/);
135
+ words.forEach(w => {
136
+ if (entryWords.includes(w)) score++;
137
+ });
138
+ if (score > 0) {
139
+ scores.set(entry.id, score);
140
+ }
141
+ });
142
+
143
+ const sorted = Array.from(scores.entries())
144
+ .sort((a, b) => b[1] - a[1])
145
+ .slice(0, limit)
146
+ .map(([id]) => this.entries.find(e => e.id === id))
147
+ .filter(Boolean) as EpisodicEntry[];
148
+
149
+ return sorted;
150
+ }
151
+
152
+ /**
153
+ * Get statistics
154
+ */
155
+ getStats() {
156
+ return {
157
+ total_entries: this.entries.length,
158
+ indexed_keywords: this.keywordIndex.size,
159
+ success_rate: this.entries.filter(e => e.result.success).length / Math.max(1, this.entries.length),
160
+ avg_duration_ms: this.entries.reduce((sum, e) => sum + e.result.duration_ms, 0) / Math.max(1, this.entries.length)
161
+ };
162
+ }
163
+
164
+ /**
165
+ * Clear all memories
166
+ */
167
+ clear() {
168
+ this.entries = [];
169
+ this.keywordIndex.clear();
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Reference to Full TMLPD Memory System
175
+ *
176
+ * For production use with full features:
177
+ * - Install: npm install tmlpd-skill (Python)
178
+ * - Or integrate with tmlpd-clean/src/memory/
179
+ *
180
+ * Full features include:
181
+ * - Semantic memory with ChromaDB vector embeddings
182
+ * - Time-based importance decay (A-Mem pattern)
183
+ * - Cross-session learning
184
+ * - Episodic + Semantic + Working 3-tier architecture
185
+ */
@@ -0,0 +1,266 @@
1
+ /**
2
+ * TMLPD HALO Orchestrator Reference
3
+ *
4
+ * Hierarchical Autonomous Logic-Oriented Orchestration
5
+ *
6
+ * Reference implementation - for full features see TMLPD v2.x
7
+ *
8
+ * Full TMLPD includes:
9
+ * - 3-tier hierarchical planning
10
+ * - TaskPlanner: Decompose with dependencies
11
+ * - RoleAssigner: Specialized agent assignment
12
+ * - ExecutionEngine: Parallel with verification
13
+ * - 19.6% improvement on complex tasks
14
+ */
15
+
16
+ import { MCTSWorkflowOptimizer } from "./mctsWorkflow";
17
+ import { EpisodicMemoryStore } from "../memory/episodicMemory";
18
+
19
+ export interface SubTask {
20
+ id: string;
21
+ description: string;
22
+ dependencies: string[];
23
+ estimatedComplexity: number;
24
+ }
25
+
26
+ export interface AgentAssignment {
27
+ subtaskId: string;
28
+ agentId: string;
29
+ model: string;
30
+ estimatedDuration: number;
31
+ }
32
+
33
+ export interface ExecutionResult {
34
+ subtaskId: string;
35
+ success: boolean;
36
+ output: string;
37
+ duration_ms: number;
38
+ }
39
+
40
+ export interface HALOConfig {
41
+ maxConcurrent: number;
42
+ optimizationTarget: "quality" | "cost" | "balanced";
43
+ enableMCTS: boolean;
44
+ }
45
+
46
+ const DEFAULT_HALO_CONFIG: HALOConfig = {
47
+ maxConcurrent: 3,
48
+ optimizationTarget: "balanced",
49
+ enableMCTS: false
50
+ };
51
+
52
+ /**
53
+ * HALO Orchestrator
54
+ *
55
+ * Hierarchical orchestration with 3 tiers:
56
+ * 1. Plan: Decompose task into subtasks with dependencies
57
+ * 2. Assign: Match subtasks to optimal agents
58
+ * 3. Execute: Run in parallel with result verification
59
+ */
60
+ export class HALOOrchestrator {
61
+ private config: HALOConfig;
62
+ private memory: EpisodicMemoryStore;
63
+ private mcts: MCTSWorkflowOptimizer;
64
+
65
+ constructor(config: Partial<HALOConfig> = {}) {
66
+ this.config = { ...DEFAULT_HALO_CONFIG, ...config };
67
+ this.memory = new EpisodicMemoryStore();
68
+ this.mcts = new MCTSWorkflowOptimizer({ maxIterations: 30 });
69
+ }
70
+
71
+ /**
72
+ * Execute task with HALO orchestration
73
+ */
74
+ async execute(
75
+ taskDescription: string,
76
+ executeFn: (subtask: SubTask, agentId: string) => Promise<ExecutionResult>
77
+ ): Promise<{
78
+ success: boolean;
79
+ results: ExecutionResult[];
80
+ strategy: Record<string, string>;
81
+ metadata: any;
82
+ }> {
83
+ // Phase 1: Plan - decompose task
84
+ const subtasks = this.decomposeTask(taskDescription);
85
+
86
+ // Check memory for similar successful strategies
87
+ const similar = this.memory.getSimilarTasks(taskDescription, 3);
88
+
89
+ // Phase 2: Assign - determine optimal agent assignments
90
+ const strategy = this.config.enableMCTS
91
+ ? await this.optimizeWithMCTS(subtasks)
92
+ : this.quickAssign(subtasks);
93
+
94
+ // Phase 3: Execute - run with concurrency limit
95
+ const results = await this.executeParallel(subtasks, strategy, executeFn);
96
+
97
+ // Store in episodic memory
98
+ this.memory.store({
99
+ task: {
100
+ description: taskDescription,
101
+ type: this.classifyTask(taskDescription),
102
+ complexity: subtasks.length
103
+ },
104
+ result: {
105
+ success: results.every(r => r.success),
106
+ output: results.map(r => r.output).join("\n---\n"),
107
+ duration_ms: results.reduce((sum, r) => sum + r.duration_ms, 0)
108
+ },
109
+ agent: { id: "halo", model: "composite", provider: "multi" },
110
+ metadata: { strategy, subtaskCount: subtasks.length },
111
+ importance: subtasks.length > 5 ? 0.8 : 0.5
112
+ });
113
+
114
+ return {
115
+ success: results.every(r => r.success),
116
+ results,
117
+ strategy,
118
+ metadata: {
119
+ subtasks: subtasks.length,
120
+ optimizationTarget: this.config.optimizationTarget
121
+ }
122
+ };
123
+ }
124
+
125
+ /**
126
+ * Decompose task into subtasks
127
+ */
128
+ decomposeTask(taskDescription: string): SubTask[] {
129
+ // Simple decomposition - for full NLP-based decomposition see TMLPD
130
+ const words = taskDescription.toLowerCase().split(/\s+/);
131
+ const subtasks: SubTask[] = [];
132
+
133
+ // Detect complexity indicators
134
+ const hasMultipleSteps = /and|then|also|plus|additionally/.test(taskDescription);
135
+ const hasBranching = /if|when|either|option|choice/.test(taskDescription);
136
+ const hasSequential = /first|then|finally|step|last/.test(taskDescription);
137
+
138
+ if (hasMultipleSteps || taskDescription.length > 100) {
139
+ // Multi-subtask decomposition
140
+ const segments = taskDescription.split(/[.,]+/).filter(s => s.trim().length > 10);
141
+ segments.forEach((seg, idx) => {
142
+ subtasks.push({
143
+ id: `subtask-${idx}`,
144
+ description: seg.trim(),
145
+ dependencies: idx > 0 ? [`subtask-${idx - 1}`] : [],
146
+ estimatedComplexity: seg.split(/\s+/).length / 10
147
+ });
148
+ });
149
+ } else {
150
+ // Single task
151
+ subtasks.push({
152
+ id: "subtask-0",
153
+ description: taskDescription,
154
+ dependencies: [],
155
+ estimatedComplexity: words.length / 10
156
+ });
157
+ }
158
+
159
+ return subtasks;
160
+ }
161
+
162
+ /**
163
+ * Classify task type
164
+ */
165
+ classifyTask(description: string): string {
166
+ const lower = description.toLowerCase();
167
+ if (/coding|code|function|class|debug/.test(lower)) return "coding";
168
+ if (/explain|what is|how to|understand/.test(lower)) return "explanation";
169
+ if (/analyze|review|evaluate|assess/.test(lower)) return "analysis";
170
+ if (/create|build|design|implement/.test(lower)) return "creation";
171
+ if (/translate|convert|transform/.test(lower)) return "transformation";
172
+ return "general";
173
+ }
174
+
175
+ /**
176
+ * Quick agent assignment without MCTS
177
+ */
178
+ quickAssign(subtasks: SubTask[]): Record<string, string> {
179
+ const strategy: Record<string, string> = {};
180
+ const agents = ["claude", "codex", "claude-minimax", "gemini"];
181
+
182
+ subtasks.forEach((subtask, idx) => {
183
+ // Round-robin assignment based on complexity
184
+ if (subtask.estimatedComplexity > 1.5) {
185
+ strategy[subtask.id] = agents[idx % agents.length];
186
+ } else {
187
+ strategy[subtask.id] = "claude-minimax"; // Fast agent for simple tasks
188
+ }
189
+ });
190
+
191
+ return strategy;
192
+ }
193
+
194
+ /**
195
+ * Optimize assignment with MCTS
196
+ */
197
+ private async optimizeWithMCTS(
198
+ subtasks: SubTask[]
199
+ ): Promise<Record<string, string>> {
200
+ const subtaskIds = subtasks.map(s => s.id);
201
+
202
+ return await this.mcts.findBestStrategy(subtaskIds, async (assignments) => {
203
+ // Evaluate strategy quality
204
+ // For reference: higher reward for balanced load + successful execution
205
+ const agentLoad = Object.values(assignments).reduce((acc: Record<string, number>, agentId) => {
206
+ acc[agentId] = (acc[agentId] || 0) + 1;
207
+ return acc;
208
+ }, {});
209
+
210
+ const loadBalance = 1 / (1 + Object.values(agentLoad).reduce((max, v) => Math.max(max, v), 0) - 1);
211
+ return loadBalance * 100; // Reward for balanced assignment
212
+ });
213
+ }
214
+
215
+ /**
216
+ * Execute subtasks in parallel with concurrency limit
217
+ */
218
+ private async executeParallel(
219
+ subtasks: SubTask[],
220
+ strategy: Record<string, string>,
221
+ executeFn: (subtask: SubTask, agentId: string) => Promise<ExecutionResult>
222
+ ): Promise<ExecutionResult[]> {
223
+ const results: ExecutionResult[] = [];
224
+ const pending: Promise<void>[] = [];
225
+ let idx = 0;
226
+
227
+ for (const subtask of subtasks) {
228
+ const agentId = strategy[subtask.id] || "claude";
229
+
230
+ const promise = executeFn(subtask, agentId).then(result => {
231
+ results[idx] = result;
232
+ });
233
+
234
+ pending.push(promise);
235
+
236
+ if (pending.length >= this.config.maxConcurrent) {
237
+ await Promise.race(pending);
238
+ }
239
+
240
+ idx++;
241
+ }
242
+
243
+ await Promise.all(pending);
244
+ return results;
245
+ }
246
+
247
+ /**
248
+ * Get memory statistics
249
+ */
250
+ getMemoryStats() {
251
+ return this.memory.getStats();
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Reference to Full TMLPD HALO
257
+ *
258
+ * Full implementation in tmlpd-clean/src/orchestration/halo_orchestrator.py
259
+ *
260
+ * Features:
261
+ * - NLP-based task decomposition
262
+ * - Dependency graph resolution
263
+ * - Agent capability matching
264
+ * - Result verification and retry
265
+ * - Multi-round refinement for low confidence
266
+ */
@@ -0,0 +1,262 @@
1
+ /**
2
+ * TMLPD MCTS Workflow Search
3
+ *
4
+ * Monte Carlo Tree Search for workflow optimization.
5
+ * Reference implementation - for full features see TMLPD v2.x
6
+ *
7
+ * Full TMLPD includes:
8
+ * - UCB1 selection policy
9
+ * - Exploration vs exploitation balancing
10
+ * - Workflow state tree building
11
+ * - Strategy learning from execution outcomes
12
+ */
13
+
14
+ import { nanoid } from "nanoid";
15
+
16
+ export interface WorkflowState {
17
+ stateId: string;
18
+ subtasks: string[];
19
+ completed: string[];
20
+ assignments: Record<string, string>; // subtask -> agent
21
+ totalReward: number;
22
+ visits: number;
23
+ }
24
+
25
+ export interface WorkflowAction {
26
+ type: "assign" | "execute" | "parallelize";
27
+ subtaskId?: string;
28
+ agentId?: string;
29
+ }
30
+
31
+ export interface MCTSConfig {
32
+ maxIterations: number;
33
+ explorationConstant: number; // UCB1 exploration parameter
34
+ maxDepth: number;
35
+ }
36
+
37
+ const DEFAULT_MCTS_CONFIG: MCTSConfig = {
38
+ maxIterations: 50,
39
+ explorationConstant: 1.414, // sqrt(2) for UCB1
40
+ maxDepth: 5
41
+ };
42
+
43
+ export class WorkflowNode {
44
+ state: WorkflowState;
45
+ parent: WorkflowNode | null;
46
+ children: Map<string, WorkflowNode>;
47
+ untriedActions: WorkflowAction[];
48
+
49
+ constructor(state: WorkflowState, parent: WorkflowNode | null = null) {
50
+ this.state = state;
51
+ this.parent = parent;
52
+ this.children = new Map();
53
+ this.untriedActions = [];
54
+ }
55
+
56
+ get averageReward(): number {
57
+ return this.state.visits > 0 ? this.state.totalReward / this.state.visits : 0;
58
+ }
59
+
60
+ get isTerminal(): boolean {
61
+ return this.state.subtasks.length === this.state.completed.length;
62
+ }
63
+
64
+ get isFullyExpanded(): boolean {
65
+ return this.untriedActions.length === 0 && this.children.size > 0;
66
+ }
67
+ }
68
+
69
+ /**
70
+ * MCTS Workflow Optimizer
71
+ *
72
+ * Uses Monte Carlo Tree Search to find optimal workflow strategies.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const optimizer = new MCTSWorkflowOptimizer();
77
+ * const bestStrategy = optimizer.findBestStrategy(task);
78
+ * ```
79
+ */
80
+ export class MCTSWorkflowOptimizer {
81
+ private config: MCTSConfig;
82
+ private root: WorkflowNode | null = null;
83
+ private agents: string[];
84
+
85
+ constructor(config: Partial<MCTSConfig> = {}, agents: string[] = []) {
86
+ this.config = { ...DEFAULT_MCTS_CONFIG, ...config };
87
+ this.agents = agents;
88
+ }
89
+
90
+ /**
91
+ * Set available agents
92
+ */
93
+ setAgents(agents: string[]) {
94
+ this.agents = agents;
95
+ }
96
+
97
+ /**
98
+ * Find best workflow strategy using MCTS
99
+ */
100
+ async findBestStrategy(
101
+ subtasks: string[],
102
+ evaluateFn: (strategy: Record<string, string>) => Promise<number> // Returns reward
103
+ ): Promise<Record<string, string>> {
104
+ const initialState: WorkflowState = {
105
+ stateId: nanoid(8),
106
+ subtasks,
107
+ completed: [],
108
+ assignments: {},
109
+ totalReward: 0,
110
+ visits: 0
111
+ };
112
+
113
+ this.root = new WorkflowNode(initialState);
114
+
115
+ // Initialize untried actions
116
+ if (this.root) {
117
+ this.root.untriedActions = this.generateActions(subtasks);
118
+ }
119
+
120
+ // MCTS iterations
121
+ for (let i = 0; i < this.config.maxIterations; i++) {
122
+ await this.mctsIteration(evaluateFn);
123
+ }
124
+
125
+ // Return best strategy
126
+ if (this.root && this.root.children.size > 0) {
127
+ const bestChild = this.selectBestChild(this.root);
128
+ return bestChild?.state.assignments || {};
129
+ } else {
130
+ return {};
131
+ }
132
+ }
133
+
134
+ private async mctsIteration(
135
+ evaluateFn: (strategy: Record<string, string>) => Promise<number>
136
+ ) {
137
+ if (!this.root) return;
138
+
139
+ let node = this.selectNode(this.root);
140
+
141
+ if (!node) return;
142
+
143
+ // Expansion
144
+ if (node.untriedActions.length > 0) {
145
+ const action = node.untriedActions.pop()!;
146
+ node = this.expand(node, action);
147
+ }
148
+
149
+ // Simulation (simplified - evaluate async)
150
+ if (node) {
151
+ const reward = await evaluateFn(node.state.assignments);
152
+ this.backpropagate(node, reward);
153
+ }
154
+ }
155
+
156
+ private selectNode(node: WorkflowNode): WorkflowNode | null {
157
+ while (node && !node.isTerminal) {
158
+ if (node.isFullyExpanded) {
159
+ node = this.ucb1Select(node);
160
+ } else {
161
+ return node;
162
+ }
163
+ }
164
+ return node;
165
+ }
166
+
167
+ private ucb1Select(node: WorkflowNode): WorkflowNode {
168
+ let bestChild: WorkflowNode | null = null;
169
+ let bestUCB = -Infinity;
170
+
171
+ for (const child of node.children.values()) {
172
+ const ucb = this.ucb(child);
173
+ if (ucb > bestUCB) {
174
+ bestUCB = ucb;
175
+ bestChild = child;
176
+ }
177
+ }
178
+
179
+ return bestChild || node;
180
+ }
181
+
182
+ private ucb(node: WorkflowNode): number {
183
+ if (node.state.visits === 0) return Infinity;
184
+ const parentVisits = node.parent?.state.visits || 1;
185
+ return node.averageReward +
186
+ this.config.explorationConstant * Math.sqrt(Math.log(parentVisits) / node.state.visits);
187
+ }
188
+
189
+ private expand(node: WorkflowNode, action: WorkflowAction): WorkflowNode {
190
+ const newAssignments = { ...node.state.assignments };
191
+
192
+ if (action.type === "assign" && action.subtaskId && action.agentId) {
193
+ newAssignments[action.subtaskId] = action.agentId;
194
+ }
195
+
196
+ const newState: WorkflowState = {
197
+ stateId: nanoid(8),
198
+ subtasks: node.state.subtasks,
199
+ completed: [...node.state.completed],
200
+ assignments: newAssignments,
201
+ totalReward: 0,
202
+ visits: 0
203
+ };
204
+
205
+ const child = new WorkflowNode(newState, node);
206
+ node.children.set(newState.stateId, child);
207
+ child.untriedActions = this.generateActions(newState.subtasks);
208
+
209
+ return child;
210
+ }
211
+
212
+ private generateActions(subtasks: string[]): WorkflowAction[] {
213
+ const actions: WorkflowAction[] = [];
214
+ const availableAgents = this.agents.length > 0 ? this.agents : ["claude", "codex", "gemini"];
215
+
216
+ subtasks.forEach(subtask => {
217
+ availableAgents.forEach(agent => {
218
+ actions.push({
219
+ type: "assign",
220
+ subtaskId: subtask,
221
+ agentId: agent
222
+ });
223
+ });
224
+ });
225
+
226
+ return actions;
227
+ }
228
+
229
+ private selectBestChild(node: WorkflowNode): WorkflowNode | null {
230
+ let best: WorkflowNode | null = null;
231
+ let bestReward = -Infinity;
232
+
233
+ for (const child of node.children.values()) {
234
+ if (child.averageReward > bestReward) {
235
+ bestReward = child.averageReward;
236
+ best = child;
237
+ }
238
+ }
239
+
240
+ return best;
241
+ }
242
+
243
+ private backpropagate(node: WorkflowNode, reward: number) {
244
+ while (node) {
245
+ node.state.visits++;
246
+ node.state.totalReward += reward;
247
+ node = node.parent as WorkflowNode;
248
+ }
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Reference to Full TMLPD MCTS
254
+ *
255
+ * Full implementation in tmlpd-clean/src/orchestration/mcts_workflow.py
256
+ *
257
+ * Features:
258
+ * - Full UCB1 with proper exploration constant
259
+ * - Deterministic rollout simulation
260
+ * - Strategy caching with performance tracking
261
+ * - Adaptive depth based on task complexity
262
+ */