Skip to content

Commit 2759421

Browse files
Update llm registering
2 parents 86d9ec0 + 83846af commit 2759421

25 files changed

Lines changed: 210 additions & 250 deletions

src/cli/codeAgent.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { Slack } from '#modules/slack/slack';
1818
import { logger } from '#o11y/logger';
1919
import { CodeEditingAgent } from '#swe/codeEditingAgent';
2020
import { CodeFunctions } from '#swe/codeFunctions';
21+
import { MorphEditor } from '#swe/morph/morphEditor';
2122
import { registerErrorHandlers } from '../errorHandlers';
2223
import { parseProcessArgs, saveAgentId } from './cli';
2324
import { loadCliEnvironment } from './envLoader';
@@ -61,19 +62,20 @@ export async function main(): Promise<void> {
6162
}
6263

6364
const functions = [
64-
AgentFeedback,
65-
PublicWeb,
65+
// AgentFeedback,
66+
// PublicWeb,
6667
CodeFunctions,
6768
FileSystemList,
6869
FileSystemTree,
6970
LiveFiles,
7071
Perplexity,
71-
CodeEditingAgent,
72+
MorphEditor,
73+
// CodeEditingAgent,
7274
// Git,
7375
// GitLab,
74-
DeepThink,
76+
// DeepThink,
7577
// Jira,
76-
Slack,
78+
// Slack,
7779
];
7880
// Add any additional functions provided from CLI args
7981
let additionalFunctions: Array<new () => any> = [];

src/llm/llmFactory.ts

Lines changed: 60 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,66 @@ import { logger } from '#o11y/logger';
2424
import type { AgentLLMs } from '#shared/agent/agent.model';
2525
import type { LLM } from '#shared/llm/llm.model';
2626

27-
export const LLM_FACTORY: Record<string, () => LLM> = {
28-
...anthropicVertexLLMRegistry(),
29-
...anthropicLLMRegistry(),
30-
...fireworksLLMRegistry(),
31-
...groqLLMRegistry(),
32-
...openAiLLMRegistry(),
33-
...togetherLLMRegistry(),
34-
...vertexLLMRegistry(),
35-
...geminiLLMRegistry(),
36-
...deepseekLLMRegistry(),
37-
...deepinfraLLMRegistry(),
38-
...cerebrasLLMRegistry(),
39-
...perplexityLLMRegistry(),
40-
// ...xaiLLMRegistry(),
41-
...nebiusLLMRegistry(),
42-
...sambanovaLLMRegistry(),
43-
...ollamaLLMRegistry(),
44-
...deepSeekFallbackRegistry(),
45-
...MoA_reasoningLLMRegistry(),
46-
...multiAgentLLMRegistry(),
47-
...openrouterLLMRegistry(),
48-
...mockLLMRegistry(),
49-
};
27+
/**
28+
* Builds a Record<string, () => LLM> from arrays of LLM factory functions.
29+
* The key for each factory is obtained by calling factory().getId() on a temporary instance.
30+
*
31+
* @param registries - Arrays of LLM factory functions from each service/multi-agent registry
32+
* @returns Record mapping LLM IDs to their factory functions
33+
*/
34+
function buildLlmFactory(...registries: Array<() => LLM>[]): Record<string, () => LLM> {
35+
const factory: Record<string, () => LLM> = {};
36+
37+
for (const registry of registries) {
38+
for (const llmFactory of registry) {
39+
// Create a temporary instance to get the ID
40+
const tempInstance = llmFactory();
41+
const id = tempInstance.getId();
42+
factory[id] = llmFactory;
43+
}
44+
}
45+
46+
return factory;
47+
}
48+
49+
// Lazy initialization to avoid calling factory functions during module initialization
50+
let _LLM_FACTORY: Record<string, () => LLM> | null = null;
51+
52+
function ensureLLMFactory(): Record<string, () => LLM> {
53+
if (!_LLM_FACTORY) {
54+
_LLM_FACTORY = buildLlmFactory(
55+
anthropicVertexLLMRegistry(),
56+
anthropicLLMRegistry(),
57+
fireworksLLMRegistry(),
58+
groqLLMRegistry(),
59+
openAiLLMRegistry(),
60+
togetherLLMRegistry(),
61+
vertexLLMRegistry(),
62+
geminiLLMRegistry(),
63+
deepseekLLMRegistry(),
64+
deepinfraLLMRegistry(),
65+
cerebrasLLMRegistry(),
66+
perplexityLLMRegistry(),
67+
// xaiLLMRegistry(),
68+
nebiusLLMRegistry(),
69+
sambanovaLLMRegistry(),
70+
ollamaLLMRegistry(),
71+
deepSeekFallbackRegistry(),
72+
MoA_reasoningLLMRegistry(),
73+
multiAgentLLMRegistry(),
74+
openrouterLLMRegistry(),
75+
mockLLMRegistry(),
76+
);
77+
}
78+
return _LLM_FACTORY;
79+
}
5080

5181
const modelMigrations: Record<string, string> = {};
5282

5383
let _llmTypes: Array<{ id: string; name: string }> | null = null;
5484

5585
export function llmTypes(): Array<{ id: string; name: string }> {
56-
_llmTypes ??= Object.values(LLM_FACTORY)
86+
_llmTypes ??= Object.values(ensureLLMFactory())
5787
.map((factory) => factory())
5888
.map((llm) => {
5989
for (const model of llm.getOldModels()) {
@@ -67,22 +97,23 @@ export function llmTypes(): Array<{ id: string; name: string }> {
6797
let _llmRegistryKeys: string[];
6898

6999
function llmRegistryKeys(): string[] {
70-
_llmRegistryKeys ??= Object.keys(LLM_FACTORY);
100+
_llmRegistryKeys ??= Object.keys(ensureLLMFactory());
71101
return _llmRegistryKeys;
72102
}
73103

74104
/**
75105
* @param llmId LLM identifier in the format service:model
76106
*/
77107
export function getLLM(llmId: string): LLM {
108+
const factory = ensureLLMFactory();
78109
// Check matching id first
79-
if (LLM_FACTORY[llmId]) {
80-
return LLM_FACTORY[llmId]();
110+
if (factory[llmId]) {
111+
return factory[llmId]();
81112
}
82113
// Check substring matching
83-
for (const key of Object.keys(LLM_FACTORY)) {
114+
for (const key of Object.keys(factory)) {
84115
if (llmId.startsWith(key)) {
85-
return LLM_FACTORY[key]!();
116+
return factory[key]!();
86117
}
87118
}
88119
if (llmId === 'multi:multi') {

src/llm/multi-agent/blueberry.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ import type { GenerateTextOptions, LLM } from '#shared/llm/llm.model';
99
// self-refine https://arxiv.org/pdf/2303.17651
1010
// https://www.academia.edu/123745078/Mind_over_Data_Elevating_LLMs_from_Memorization_to_Cognition
1111

12-
export function blueberryLLMRegistry(): Record<string, () => LLM> {
13-
return {
14-
'MoA:blueberry': () => new Blueberry(),
15-
};
12+
export function blueberryLLMRegistry(): Array<() => LLM> {
13+
return [() => new Blueberry()];
1614
}
1715

1816
const MIND_OVER_DATA_SYS_PROMPT = `When addressing a problem, employ "Comparative Problem Analysis and Direct Reasoning" as follows:

src/llm/multi-agent/deepSeek_Fallbacks.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,6 @@ import type { GenerateTextOptions, LLM, LlmMessage } from '#shared/llm/llm.model
66
import { BaseLLM } from '../base-llm';
77
import { fireworksDeepSeekR1_Fast } from '../services/fireworks';
88

9-
export function deepSeekFallbackRegistry(): Record<string, () => LLM> {
10-
return {
11-
DeepSeekFallback: DeepSeek_Together_Fireworks_Nebius_SambaNova,
12-
};
13-
}
14-
15-
export function DeepSeek_Together_Fireworks_Nebius_SambaNova(): LLM {
16-
return new DeepSeek_Fallbacks();
17-
}
18-
199
/**
2010
* LLM implementation for DeepSeek which uses Together.ai and Fireworks.ai for more privacy.
2111
* Tries Together.ai first as is slightly cheaper, then falls back to Fireworks
@@ -58,3 +48,11 @@ export class DeepSeek_Fallbacks extends BaseLLM {
5848
throw new Error('All DeepSeek providers failed.');
5949
}
6050
}
51+
52+
export function deepSeekFallbackRegistry(): Array<() => LLM> {
53+
return [DeepSeek_Together_Fireworks_Nebius_SambaNova];
54+
}
55+
56+
export function DeepSeek_Together_Fireworks_Nebius_SambaNova(): LLM {
57+
return new DeepSeek_Fallbacks();
58+
}

src/llm/multi-agent/multiRegistry.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ import { FastEasyLLM } from '#llm/multi-agent/fastEasy';
22
import { FastMediumLLM } from '#llm/multi-agent/fastMedium';
33
import type { LLM } from '#shared/llm/llm.model';
44

5-
export function multiAgentLLMRegistry(): Record<string, () => LLM> {
6-
const registry = {};
7-
registry['multi:fast-medium'] = () => new FastMediumLLM();
8-
registry['multi:fast-easy'] = () => new FastEasyLLM();
9-
return registry;
5+
export function multiAgentLLMRegistry(): Array<() => LLM> {
6+
return [() => new FastMediumLLM(), () => new FastEasyLLM()];
107
}

src/llm/multi-agent/reasoning-debate.ts

Lines changed: 83 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -48,96 +48,6 @@ function accumulateStats(accumulator: GenerationStats, newStats?: GenerationStat
4848

4949
// sparse multi-agent debate https://arxiv.org/abs/2406.11776
5050

51-
export function MoA_reasoningLLMRegistry(): Record<string, () => LLM> {
52-
return {
53-
'MAD:Cost': MAD_Cost,
54-
'MAD:Fast': MAD_Fast,
55-
'MAD:SOTA': MAD_SOTA,
56-
'MAD:Vertex': MAD_Vertex,
57-
'MAD:Balanced': MAD_Balanced,
58-
'MAD:Balanced4': MAD_Balanced4,
59-
};
60-
}
61-
62-
export function MAD_Cost(): LLM {
63-
return new ReasonerDebateLLM(
64-
'Cost',
65-
deepinfraDeepSeekR1,
66-
[deepinfraDeepSeekR1, deepinfraDeepSeekR1, deepinfraDeepSeekR1],
67-
'MAD:Cost multi-agent debate (DeepSeek R1x3)',
68-
);
69-
}
70-
71-
export function MAD_Fast(): LLM {
72-
const fastMedium = new FastMediumLLM();
73-
const fastMediumFactory = () => fastMedium;
74-
return new ReasonerDebateLLM(
75-
'Fast',
76-
fastMediumFactory,
77-
[fastMediumFactory, fastMediumFactory, fastMediumFactory],
78-
'MAD:Fast multi-agent debate (Cerebras Qwen3 32b, Flash 2.5 fallback)',
79-
);
80-
}
81-
82-
export function MAD_Balanced(): LLM {
83-
return new ReasonerDebateLLM(
84-
'Balanced',
85-
vertexGemini_2_5_Pro,
86-
[vertexGemini_2_5_Pro, xai_Grok4, openaiGPT5],
87-
'MAD:Balanced multi-agent debate (Gemini 2.5 Pro, Grok 4, o3)',
88-
);
89-
}
90-
91-
export function MAD_Balanced4(): LLM {
92-
return new ReasonerDebateLLM(
93-
'Balanced4',
94-
vertexGemini_2_5_Pro,
95-
[vertexGemini_2_5_Pro, xai_Grok4, openaiGPT5, Claude4_5_Sonnet_Vertex],
96-
'MAD:Balanced multi-agent debate (Gemini 2.5 Pro, Grok 4, o3, Sonnet 4)',
97-
);
98-
}
99-
100-
export function MAD_Vertex(): LLM {
101-
return new ReasonerDebateLLM(
102-
'Vertex',
103-
vertexGemini_2_5_Pro,
104-
[vertexGemini_2_5_Pro, vertexGemini_2_5_Pro, Claude4_5_Sonnet_Vertex],
105-
'MAD:Vertex multi-agent debate (Gemini 2.5 Pro x2, Sonnet 4)',
106-
);
107-
}
108-
109-
export function MAD_Anthropic(): LLM {
110-
return new ReasonerDebateLLM(
111-
'Anthropic',
112-
anthropicClaude4_5_Sonnet,
113-
[anthropicClaude4_5_Sonnet, anthropicClaude4_5_Sonnet, anthropicClaude4_5_Sonnet],
114-
'MAD:Anthropic multi-agent debate (Sonnet 4 x3)',
115-
);
116-
}
117-
118-
export function MAD_OpenAI(): LLM {
119-
return new ReasonerDebateLLM('OpenAI', openaiGPT5, [openaiGPT5, openaiGPT5, openaiGPT5], 'MAD:OpenAI multi-agent debate (GPT5 x3)');
120-
}
121-
122-
export function MAD_Grok(): LLM {
123-
return new ReasonerDebateLLM('Grok', xai_Grok4, [xai_Grok4, xai_Grok4, xai_Grok4], 'MAD:Grok multi-agent debate (Grok 4 x3)');
124-
}
125-
126-
export function MAD_SOTA(): LLM {
127-
return new ReasonerDebateLLM(
128-
'SOTA',
129-
openaiGPT5,
130-
[openaiGPT5, Claude4_1_Opus_Vertex, vertexGemini_2_5_Pro, xai_Grok4],
131-
'MAD:SOTA multi-agent debate (Opus 4, GPT5, Gemini 2.5 Pro, Grok 4)',
132-
);
133-
}
134-
135-
// export function MAD_Hard(): LLM {
136-
// const hardLLM = llms().hard; // cant have a dependancy to agentContextLocalStorage
137-
// const hardFactory = () => hardLLM;
138-
// return new ReasonerDebateLLM('Hard', hardFactory, [hardFactory, hardFactory, hardFactory], `MAD:Hard multi-agent debate (${hardLLM.getDisplayName} x3)`);
139-
// }
140-
14151
const INITIAL_TEMP = 0.7;
14252
const DEBATE_TEMP = 0.5;
14353
const FINAL_TEMP = 0.3;
@@ -297,3 +207,86 @@ Answer directly to the original user message and ensure any relevant response fo
297207
return this.mediator.generateMessage(mergedMessages, { ...opts, id: `${opts.id} - final`, temperature: FINAL_TEMP });
298208
}
299209
}
210+
211+
export function MoA_reasoningLLMRegistry(): Array<() => LLM> {
212+
return [MAD_Cost, MAD_Fast, MAD_SOTA, MAD_Vertex, MAD_Balanced, MAD_Balanced4];
213+
}
214+
215+
export function MAD_Cost(): LLM {
216+
return new ReasonerDebateLLM(
217+
'Cost',
218+
deepinfraDeepSeekR1,
219+
[deepinfraDeepSeekR1, deepinfraDeepSeekR1, deepinfraDeepSeekR1],
220+
'MAD:Cost multi-agent debate (DeepSeek R1x3)',
221+
);
222+
}
223+
224+
export function MAD_Fast(): LLM {
225+
const fastMedium = new FastMediumLLM();
226+
const fastMediumFactory = () => fastMedium;
227+
return new ReasonerDebateLLM(
228+
'Fast',
229+
fastMediumFactory,
230+
[fastMediumFactory, fastMediumFactory, fastMediumFactory],
231+
'MAD:Fast multi-agent debate (Cerebras Qwen3 32b, Flash 2.5 fallback)',
232+
);
233+
}
234+
235+
export function MAD_Balanced(): LLM {
236+
return new ReasonerDebateLLM(
237+
'Balanced',
238+
vertexGemini_2_5_Pro,
239+
[vertexGemini_2_5_Pro, xai_Grok4, openaiGPT5],
240+
'MAD:Balanced multi-agent debate (Gemini 2.5 Pro, Grok 4, o3)',
241+
);
242+
}
243+
244+
export function MAD_Balanced4(): LLM {
245+
return new ReasonerDebateLLM(
246+
'Balanced4',
247+
vertexGemini_2_5_Pro,
248+
[vertexGemini_2_5_Pro, xai_Grok4, openaiGPT5, Claude4_5_Sonnet_Vertex],
249+
'MAD:Balanced multi-agent debate (Gemini 2.5 Pro, Grok 4, o3, Sonnet 4)',
250+
);
251+
}
252+
253+
export function MAD_Vertex(): LLM {
254+
return new ReasonerDebateLLM(
255+
'Vertex',
256+
vertexGemini_2_5_Pro,
257+
[vertexGemini_2_5_Pro, vertexGemini_2_5_Pro, Claude4_5_Sonnet_Vertex],
258+
'MAD:Vertex multi-agent debate (Gemini 2.5 Pro x2, Sonnet 4)',
259+
);
260+
}
261+
262+
export function MAD_Anthropic(): LLM {
263+
return new ReasonerDebateLLM(
264+
'Anthropic',
265+
anthropicClaude4_5_Sonnet,
266+
[anthropicClaude4_5_Sonnet, anthropicClaude4_5_Sonnet, anthropicClaude4_5_Sonnet],
267+
'MAD:Anthropic multi-agent debate (Sonnet 4 x3)',
268+
);
269+
}
270+
271+
export function MAD_OpenAI(): LLM {
272+
return new ReasonerDebateLLM('OpenAI', openaiGPT5, [openaiGPT5, openaiGPT5, openaiGPT5], 'MAD:OpenAI multi-agent debate (GPT5 x3)');
273+
}
274+
275+
export function MAD_Grok(): LLM {
276+
return new ReasonerDebateLLM('Grok', xai_Grok4, [xai_Grok4, xai_Grok4, xai_Grok4], 'MAD:Grok multi-agent debate (Grok 4 x3)');
277+
}
278+
279+
export function MAD_SOTA(): LLM {
280+
return new ReasonerDebateLLM(
281+
'SOTA',
282+
openaiGPT5,
283+
[openaiGPT5, Claude4_1_Opus_Vertex, vertexGemini_2_5_Pro, xai_Grok4],
284+
'MAD:SOTA multi-agent debate (Opus 4, GPT5, Gemini 2.5 Pro, Grok 4)',
285+
);
286+
}
287+
288+
// export function MAD_Hard(): LLM {
289+
// const hardLLM = llms().hard; // cant have a dependancy to agentContextLocalStorage
290+
// const hardFactory = () => hardLLM;
291+
// return new ReasonerDebateLLM('Hard', hardFactory, [hardFactory, hardFactory, hardFactory], `MAD:Hard multi-agent debate (${hardLLM.getDisplayName} x3)`);
292+
// }

0 commit comments

Comments
 (0)