@ai-orchestration/core 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.
- package/.eslintrc.json +27 -0
- package/README.md +516 -0
- package/dist/core/errors.d.ts +21 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +38 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/interfaces.d.ts +87 -0
- package/dist/core/interfaces.d.ts.map +1 -0
- package/dist/core/interfaces.js +5 -0
- package/dist/core/interfaces.js.map +1 -0
- package/dist/core/orchestrator.d.ts +55 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +147 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/types.d.ts +72 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +5 -0
- package/dist/core/types.js.map +1 -0
- package/dist/factory/index.d.ts +14 -0
- package/dist/factory/index.d.ts.map +1 -0
- package/dist/factory/index.js +184 -0
- package/dist/factory/index.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/base.d.ts +30 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +31 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/cerebras.d.ts +26 -0
- package/dist/providers/cerebras.d.ts.map +1 -0
- package/dist/providers/cerebras.js +190 -0
- package/dist/providers/cerebras.js.map +1 -0
- package/dist/providers/gemini.d.ts +26 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +181 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/groq.d.ts +26 -0
- package/dist/providers/groq.d.ts.map +1 -0
- package/dist/providers/groq.js +225 -0
- package/dist/providers/groq.js.map +1 -0
- package/dist/providers/index.d.ts +15 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +10 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/local.d.ts +27 -0
- package/dist/providers/local.d.ts.map +1 -0
- package/dist/providers/local.js +198 -0
- package/dist/providers/local.js.map +1 -0
- package/dist/providers/openrouter.d.ts +26 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +172 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/strategies/base.d.ts +16 -0
- package/dist/strategies/base.d.ts.map +1 -0
- package/dist/strategies/base.js +21 -0
- package/dist/strategies/base.js.map +1 -0
- package/dist/strategies/fallback.d.ts +14 -0
- package/dist/strategies/fallback.d.ts.map +1 -0
- package/dist/strategies/fallback.js +29 -0
- package/dist/strategies/fallback.js.map +1 -0
- package/dist/strategies/health-aware.d.ts +20 -0
- package/dist/strategies/health-aware.d.ts.map +1 -0
- package/dist/strategies/health-aware.js +106 -0
- package/dist/strategies/health-aware.js.map +1 -0
- package/dist/strategies/index.d.ts +14 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +10 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/strategies/priority.d.ts +18 -0
- package/dist/strategies/priority.d.ts.map +1 -0
- package/dist/strategies/priority.js +35 -0
- package/dist/strategies/priority.js.map +1 -0
- package/dist/strategies/round-robin.d.ts +10 -0
- package/dist/strategies/round-robin.d.ts.map +1 -0
- package/dist/strategies/round-robin.js +21 -0
- package/dist/strategies/round-robin.js.map +1 -0
- package/dist/strategies/weighted.d.ts +20 -0
- package/dist/strategies/weighted.d.ts.map +1 -0
- package/dist/strategies/weighted.js +58 -0
- package/dist/strategies/weighted.js.map +1 -0
- package/docs/ARCHITECTURE.md +126 -0
- package/docs/CHANGELOG.md +30 -0
- package/docs/CONTRIBUTING.md +198 -0
- package/examples/basic.ts +58 -0
- package/examples/chat-app/README.md +146 -0
- package/examples/chat-app/config.json +34 -0
- package/examples/chat-app/index.ts +330 -0
- package/examples/chat-app/package-lock.json +570 -0
- package/examples/chat-app/package.json +20 -0
- package/examples/config.example.json +42 -0
- package/examples/strategies.ts +112 -0
- package/examples/test-local.ts +150 -0
- package/examples/test-mock.ts +172 -0
- package/package/.eslintrc.json +27 -0
- package/package/CHANGELOG.md +31 -0
- package/package/CONTRIBUTING.md +156 -0
- package/package/PUBLISHING.md +213 -0
- package/package/README.md +515 -0
- package/package/dist/core/errors.d.ts +21 -0
- package/package/dist/core/errors.d.ts.map +1 -0
- package/package/dist/core/errors.js +38 -0
- package/package/dist/core/errors.js.map +1 -0
- package/package/dist/core/interfaces.d.ts +87 -0
- package/package/dist/core/interfaces.d.ts.map +1 -0
- package/package/dist/core/interfaces.js +5 -0
- package/package/dist/core/interfaces.js.map +1 -0
- package/package/dist/core/orchestrator.d.ts +55 -0
- package/package/dist/core/orchestrator.d.ts.map +1 -0
- package/package/dist/core/orchestrator.js +147 -0
- package/package/dist/core/orchestrator.js.map +1 -0
- package/package/dist/core/types.d.ts +72 -0
- package/package/dist/core/types.d.ts.map +1 -0
- package/package/dist/core/types.js +5 -0
- package/package/dist/core/types.js.map +1 -0
- package/package/dist/factory/index.d.ts +14 -0
- package/package/dist/factory/index.d.ts.map +1 -0
- package/package/dist/factory/index.js +184 -0
- package/package/dist/factory/index.js.map +1 -0
- package/package/dist/index.d.ts +14 -0
- package/package/dist/index.d.ts.map +1 -0
- package/package/dist/index.js +15 -0
- package/package/dist/index.js.map +1 -0
- package/package/dist/providers/base.d.ts +30 -0
- package/package/dist/providers/base.d.ts.map +1 -0
- package/package/dist/providers/base.js +31 -0
- package/package/dist/providers/base.js.map +1 -0
- package/package/dist/providers/cerebras.d.ts +26 -0
- package/package/dist/providers/cerebras.d.ts.map +1 -0
- package/package/dist/providers/cerebras.js +190 -0
- package/package/dist/providers/cerebras.js.map +1 -0
- package/package/dist/providers/gemini.d.ts +26 -0
- package/package/dist/providers/gemini.d.ts.map +1 -0
- package/package/dist/providers/gemini.js +181 -0
- package/package/dist/providers/gemini.js.map +1 -0
- package/package/dist/providers/groq.d.ts +26 -0
- package/package/dist/providers/groq.d.ts.map +1 -0
- package/package/dist/providers/groq.js +225 -0
- package/package/dist/providers/groq.js.map +1 -0
- package/package/dist/providers/index.d.ts +15 -0
- package/package/dist/providers/index.d.ts.map +1 -0
- package/package/dist/providers/index.js +10 -0
- package/package/dist/providers/index.js.map +1 -0
- package/package/dist/providers/local.d.ts +27 -0
- package/package/dist/providers/local.d.ts.map +1 -0
- package/package/dist/providers/local.js +198 -0
- package/package/dist/providers/local.js.map +1 -0
- package/package/dist/providers/openrouter.d.ts +26 -0
- package/package/dist/providers/openrouter.d.ts.map +1 -0
- package/package/dist/providers/openrouter.js +172 -0
- package/package/dist/providers/openrouter.js.map +1 -0
- package/package/dist/strategies/base.d.ts +16 -0
- package/package/dist/strategies/base.d.ts.map +1 -0
- package/package/dist/strategies/base.js +21 -0
- package/package/dist/strategies/base.js.map +1 -0
- package/package/dist/strategies/fallback.d.ts +14 -0
- package/package/dist/strategies/fallback.d.ts.map +1 -0
- package/package/dist/strategies/fallback.js +29 -0
- package/package/dist/strategies/fallback.js.map +1 -0
- package/package/dist/strategies/health-aware.d.ts +20 -0
- package/package/dist/strategies/health-aware.d.ts.map +1 -0
- package/package/dist/strategies/health-aware.js +106 -0
- package/package/dist/strategies/health-aware.js.map +1 -0
- package/package/dist/strategies/index.d.ts +14 -0
- package/package/dist/strategies/index.d.ts.map +1 -0
- package/package/dist/strategies/index.js +10 -0
- package/package/dist/strategies/index.js.map +1 -0
- package/package/dist/strategies/priority.d.ts +18 -0
- package/package/dist/strategies/priority.d.ts.map +1 -0
- package/package/dist/strategies/priority.js +35 -0
- package/package/dist/strategies/priority.js.map +1 -0
- package/package/dist/strategies/round-robin.d.ts +10 -0
- package/package/dist/strategies/round-robin.d.ts.map +1 -0
- package/package/dist/strategies/round-robin.js +21 -0
- package/package/dist/strategies/round-robin.js.map +1 -0
- package/package/dist/strategies/weighted.d.ts +20 -0
- package/package/dist/strategies/weighted.d.ts.map +1 -0
- package/package/dist/strategies/weighted.js +58 -0
- package/package/dist/strategies/weighted.js.map +1 -0
- package/package/docs/ARCHITECTURE.md +127 -0
- package/package/examples/basic.ts +58 -0
- package/package/examples/chat-app/README.md +146 -0
- package/package/examples/chat-app/config.json +34 -0
- package/package/examples/chat-app/index.ts +330 -0
- package/package/examples/chat-app/package-lock.json +570 -0
- package/package/examples/chat-app/package.json +20 -0
- package/package/examples/config.example.json +42 -0
- package/package/examples/strategies.ts +112 -0
- package/package/examples/test-local.ts +150 -0
- package/package/examples/test-mock.ts +172 -0
- package/package/package.json +62 -0
- package/package/scripts/check-types.ts +15 -0
- package/package/scripts/link.sh +30 -0
- package/package/scripts/pack.sh +36 -0
- package/package.json +62 -0
- package/scripts/check-types.ts +15 -0
- package/scripts/link.sh +30 -0
- package/scripts/pack.sh +36 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Examples of different strategies
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { createOrchestrator } from '../src/index.js';
|
|
6
|
+
|
|
7
|
+
// Example 1: Priority Strategy
|
|
8
|
+
export function createPriorityOrchestrator() {
|
|
9
|
+
return createOrchestrator({
|
|
10
|
+
providers: [
|
|
11
|
+
{
|
|
12
|
+
id: 'groq-1',
|
|
13
|
+
type: 'groq',
|
|
14
|
+
apiKey: process.env.GROQ_API_KEY || '',
|
|
15
|
+
priority: 1,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: 'openrouter-1',
|
|
19
|
+
type: 'openrouter',
|
|
20
|
+
apiKey: process.env.OPENROUTER_API_KEY || '',
|
|
21
|
+
priority: 2,
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
strategy: {
|
|
25
|
+
type: 'priority',
|
|
26
|
+
priorities: {
|
|
27
|
+
'groq-1': 1,
|
|
28
|
+
'openrouter-1': 2,
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Example 2: Fallback Strategy
|
|
35
|
+
export function createFallbackOrchestrator() {
|
|
36
|
+
return createOrchestrator({
|
|
37
|
+
providers: [
|
|
38
|
+
{
|
|
39
|
+
id: 'groq-1',
|
|
40
|
+
type: 'groq',
|
|
41
|
+
apiKey: process.env.GROQ_API_KEY || '',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: 'openrouter-1',
|
|
45
|
+
type: 'openrouter',
|
|
46
|
+
apiKey: process.env.OPENROUTER_API_KEY || '',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 'gemini-1',
|
|
50
|
+
type: 'gemini',
|
|
51
|
+
apiKey: process.env.GEMINI_API_KEY || '',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
strategy: {
|
|
55
|
+
type: 'fallback',
|
|
56
|
+
order: ['groq-1', 'openrouter-1', 'gemini-1'],
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Example 3: Weighted Strategy (Load Balancing)
|
|
62
|
+
export function createWeightedOrchestrator() {
|
|
63
|
+
return createOrchestrator({
|
|
64
|
+
providers: [
|
|
65
|
+
{
|
|
66
|
+
id: 'groq-1',
|
|
67
|
+
type: 'groq',
|
|
68
|
+
apiKey: process.env.GROQ_API_KEY || '',
|
|
69
|
+
weight: 0.7,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'openrouter-1',
|
|
73
|
+
type: 'openrouter',
|
|
74
|
+
apiKey: process.env.OPENROUTER_API_KEY || '',
|
|
75
|
+
weight: 0.3,
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
strategy: {
|
|
79
|
+
type: 'weighted',
|
|
80
|
+
weights: {
|
|
81
|
+
'groq-1': 0.7,
|
|
82
|
+
'openrouter-1': 0.3,
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Example 4: Health-Aware Strategy
|
|
89
|
+
export function createHealthAwareOrchestrator() {
|
|
90
|
+
return createOrchestrator({
|
|
91
|
+
providers: [
|
|
92
|
+
{
|
|
93
|
+
id: 'groq-1',
|
|
94
|
+
type: 'groq',
|
|
95
|
+
apiKey: process.env.GROQ_API_KEY || '',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
id: 'openrouter-1',
|
|
99
|
+
type: 'openrouter',
|
|
100
|
+
apiKey: process.env.OPENROUTER_API_KEY || '',
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
strategy: {
|
|
104
|
+
type: 'health-aware',
|
|
105
|
+
preferLowLatency: true,
|
|
106
|
+
minHealthScore: 0.5,
|
|
107
|
+
},
|
|
108
|
+
enableHealthChecks: true,
|
|
109
|
+
healthCheckInterval: 30000, // 30 seconds
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local test script
|
|
3
|
+
* Run with: npm run test:local
|
|
4
|
+
* or: tsx examples/test-local.ts
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { createOrchestrator } from '../src/index.js';
|
|
8
|
+
|
|
9
|
+
async function main() {
|
|
10
|
+
console.log('🚀 Iniciando prueba del framework...\n');
|
|
11
|
+
|
|
12
|
+
// Verificar variables de entorno
|
|
13
|
+
const hasGroq = !!process.env.GROQ_API_KEY;
|
|
14
|
+
const hasOpenRouter = !!process.env.OPENROUTER_API_KEY;
|
|
15
|
+
const hasGemini = !!process.env.GEMINI_API_KEY;
|
|
16
|
+
|
|
17
|
+
console.log('📋 Estado de API Keys:');
|
|
18
|
+
console.log(` Groq: ${hasGroq ? '✅' : '❌'}`);
|
|
19
|
+
console.log(` OpenRouter: ${hasOpenRouter ? '✅' : '❌'}`);
|
|
20
|
+
console.log(` Gemini: ${hasGemini ? '✅' : '❌'}\n`);
|
|
21
|
+
|
|
22
|
+
if (!hasGroq && !hasOpenRouter && !hasGemini) {
|
|
23
|
+
console.log('⚠️ No se encontraron API keys.');
|
|
24
|
+
console.log(' Configura las variables de entorno:');
|
|
25
|
+
console.log(' export GROQ_API_KEY="tu-key"');
|
|
26
|
+
console.log(' export OPENROUTER_API_KEY="tu-key"');
|
|
27
|
+
console.log(' export GEMINI_API_KEY="tu-key"\n');
|
|
28
|
+
console.log(' O crea un archivo .env con:');
|
|
29
|
+
console.log(' GROQ_API_KEY=tu-key');
|
|
30
|
+
console.log(' OPENROUTER_API_KEY=tu-key');
|
|
31
|
+
console.log(' GEMINI_API_KEY=tu-key\n');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Crear configuración dinámica basada en las keys disponibles
|
|
36
|
+
const providers: any[] = [];
|
|
37
|
+
|
|
38
|
+
if (hasGroq) {
|
|
39
|
+
providers.push({
|
|
40
|
+
id: 'groq-1',
|
|
41
|
+
type: 'groq',
|
|
42
|
+
apiKey: process.env.GROQ_API_KEY,
|
|
43
|
+
model: 'llama-3.1-70b-versatile',
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (hasOpenRouter) {
|
|
48
|
+
providers.push({
|
|
49
|
+
id: 'openrouter-1',
|
|
50
|
+
type: 'openrouter',
|
|
51
|
+
apiKey: process.env.OPENROUTER_API_KEY,
|
|
52
|
+
model: 'openai/gpt-3.5-turbo',
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (hasGemini) {
|
|
57
|
+
providers.push({
|
|
58
|
+
id: 'gemini-1',
|
|
59
|
+
type: 'gemini',
|
|
60
|
+
apiKey: process.env.GEMINI_API_KEY,
|
|
61
|
+
model: 'gemini-pro',
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
console.log('🔧 Creando orchestrator...');
|
|
67
|
+
const orchestrator = createOrchestrator({
|
|
68
|
+
providers,
|
|
69
|
+
strategy: {
|
|
70
|
+
type: 'round-robin',
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
console.log(`✅ Orchestrator creado con ${providers.length} proveedor(es)\n`);
|
|
75
|
+
|
|
76
|
+
// Test 1: Chat simple
|
|
77
|
+
console.log('📝 Test 1: Chat simple');
|
|
78
|
+
console.log('─────────────────────────────────');
|
|
79
|
+
const messages = [
|
|
80
|
+
{ role: 'user' as const, content: 'Di "Hola" en una sola palabra' },
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
const startTime = Date.now();
|
|
84
|
+
const response = await orchestrator.chat(messages, {
|
|
85
|
+
temperature: 0.7,
|
|
86
|
+
maxTokens: 50,
|
|
87
|
+
});
|
|
88
|
+
const duration = Date.now() - startTime;
|
|
89
|
+
|
|
90
|
+
console.log(`Respuesta: ${response.content}`);
|
|
91
|
+
console.log(`Modelo: ${response.model || 'N/A'}`);
|
|
92
|
+
console.log(`Tiempo: ${duration}ms`);
|
|
93
|
+
if (response.usage) {
|
|
94
|
+
console.log(`Tokens: ${response.usage.totalTokens} (prompt: ${response.usage.promptTokens}, completion: ${response.usage.completionTokens})`);
|
|
95
|
+
}
|
|
96
|
+
console.log('');
|
|
97
|
+
|
|
98
|
+
// Test 2: Verificar salud de proveedores
|
|
99
|
+
console.log('🏥 Test 2: Health checks');
|
|
100
|
+
console.log('─────────────────────────────────');
|
|
101
|
+
const allProviders = orchestrator.getAllProviders();
|
|
102
|
+
for (const provider of allProviders) {
|
|
103
|
+
try {
|
|
104
|
+
const health = await provider.checkHealth();
|
|
105
|
+
console.log(`${provider.id}: ${health.healthy ? '✅' : '❌'} ${health.latency ? `(${health.latency}ms)` : ''}`);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.log(`${provider.id}: ❌ Error - ${error instanceof Error ? error.message : String(error)}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
console.log('');
|
|
111
|
+
|
|
112
|
+
// Test 3: Streaming (opcional, comentado por defecto)
|
|
113
|
+
if (process.env.TEST_STREAMING === 'true') {
|
|
114
|
+
console.log('🌊 Test 3: Streaming');
|
|
115
|
+
console.log('─────────────────────────────────');
|
|
116
|
+
const stream = await orchestrator.chatStream([
|
|
117
|
+
{ role: 'user' as const, content: 'Cuenta del 1 al 5, un número por línea' },
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
const reader = stream.getReader();
|
|
121
|
+
let fullContent = '';
|
|
122
|
+
while (true) {
|
|
123
|
+
const { done, value } = await reader.read();
|
|
124
|
+
if (done) break;
|
|
125
|
+
fullContent += value.content;
|
|
126
|
+
process.stdout.write(value.content);
|
|
127
|
+
}
|
|
128
|
+
console.log('\n✅ Streaming completado\n');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Cleanup
|
|
132
|
+
orchestrator.dispose();
|
|
133
|
+
console.log('✅ Pruebas completadas exitosamente!');
|
|
134
|
+
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error('\n❌ Error durante las pruebas:');
|
|
137
|
+
if (error instanceof Error) {
|
|
138
|
+
console.error(` ${error.name}: ${error.message}`);
|
|
139
|
+
if (error.stack) {
|
|
140
|
+
console.error(` Stack: ${error.stack}`);
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
console.error(` ${String(error)}`);
|
|
144
|
+
}
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
main().catch(console.error);
|
|
150
|
+
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test with mock provider (no API keys required)
|
|
3
|
+
* Run with: npm run test:mock
|
|
4
|
+
* or: tsx examples/test-mock.ts
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
Orchestrator,
|
|
9
|
+
RoundRobinStrategy,
|
|
10
|
+
PriorityStrategy,
|
|
11
|
+
FallbackStrategy,
|
|
12
|
+
} from '../src/index.js';
|
|
13
|
+
import type { AIService, ChatMessage, ChatResponse, ChatChunk, ProviderHealth } from '../src/index.js';
|
|
14
|
+
|
|
15
|
+
// Mock provider para pruebas sin API keys
|
|
16
|
+
class MockProvider implements AIService {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly metadata = {
|
|
19
|
+
id: '',
|
|
20
|
+
name: 'Mock Provider',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
constructor(id: string) {
|
|
24
|
+
this.id = id;
|
|
25
|
+
this.metadata.id = id;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async checkHealth(): Promise<ProviderHealth> {
|
|
29
|
+
return {
|
|
30
|
+
healthy: true,
|
|
31
|
+
latency: Math.random() * 100,
|
|
32
|
+
lastChecked: new Date(),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async chat(messages: ChatMessage[]): Promise<ChatResponse> {
|
|
37
|
+
const lastMessage = messages[messages.length - 1]?.content || '';
|
|
38
|
+
return {
|
|
39
|
+
content: `[Mock ${this.id}] Respuesta a: "${lastMessage}"`,
|
|
40
|
+
usage: {
|
|
41
|
+
promptTokens: 10,
|
|
42
|
+
completionTokens: 5,
|
|
43
|
+
totalTokens: 15,
|
|
44
|
+
},
|
|
45
|
+
model: 'mock-model',
|
|
46
|
+
finishReason: 'stop',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async chatStream(messages: ChatMessage[]): Promise<ReadableStream<ChatChunk>> {
|
|
51
|
+
const lastMessage = messages[messages.length - 1]?.content || '';
|
|
52
|
+
const words = `[Mock ${this.id}] Respuesta a: "${lastMessage}"`.split(' ');
|
|
53
|
+
|
|
54
|
+
return new ReadableStream({
|
|
55
|
+
async start(controller) {
|
|
56
|
+
for (const word of words) {
|
|
57
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
58
|
+
controller.enqueue({
|
|
59
|
+
content: word + ' ',
|
|
60
|
+
done: false,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
controller.enqueue({
|
|
64
|
+
content: '',
|
|
65
|
+
done: true,
|
|
66
|
+
finishReason: 'stop',
|
|
67
|
+
});
|
|
68
|
+
controller.close();
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function main() {
|
|
75
|
+
console.log('🧪 Prueba con proveedores Mock\n');
|
|
76
|
+
|
|
77
|
+
// Test 1: Round-Robin Strategy
|
|
78
|
+
console.log('📋 Test 1: Round-Robin Strategy');
|
|
79
|
+
console.log('─────────────────────────────────');
|
|
80
|
+
const roundRobinStrategy = new RoundRobinStrategy();
|
|
81
|
+
const orchestrator1 = new Orchestrator(roundRobinStrategy);
|
|
82
|
+
|
|
83
|
+
orchestrator1.registerProvider(new MockProvider('mock-1'));
|
|
84
|
+
orchestrator1.registerProvider(new MockProvider('mock-2'));
|
|
85
|
+
orchestrator1.registerProvider(new MockProvider('mock-3'));
|
|
86
|
+
|
|
87
|
+
for (let i = 0; i < 5; i++) {
|
|
88
|
+
const provider = await orchestrator1.selectProvider();
|
|
89
|
+
console.log(` Request ${i + 1}: ${provider?.id}`);
|
|
90
|
+
}
|
|
91
|
+
console.log('');
|
|
92
|
+
|
|
93
|
+
// Test 2: Priority Strategy
|
|
94
|
+
console.log('📋 Test 2: Priority Strategy');
|
|
95
|
+
console.log('─────────────────────────────────');
|
|
96
|
+
const priorityStrategy = new PriorityStrategy({
|
|
97
|
+
priorities: {
|
|
98
|
+
'mock-1': 1,
|
|
99
|
+
'mock-2': 2,
|
|
100
|
+
'mock-3': 3,
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
const orchestrator2 = new Orchestrator(priorityStrategy);
|
|
104
|
+
|
|
105
|
+
orchestrator2.registerProvider(new MockProvider('mock-1'));
|
|
106
|
+
orchestrator2.registerProvider(new MockProvider('mock-2'));
|
|
107
|
+
orchestrator2.registerProvider(new MockProvider('mock-3'));
|
|
108
|
+
|
|
109
|
+
for (let i = 0; i < 3; i++) {
|
|
110
|
+
const provider = await orchestrator2.selectProvider();
|
|
111
|
+
console.log(` Request ${i + 1}: ${provider?.id} (siempre el mismo por prioridad)`);
|
|
112
|
+
}
|
|
113
|
+
console.log('');
|
|
114
|
+
|
|
115
|
+
// Test 3: Fallback Strategy
|
|
116
|
+
console.log('📋 Test 3: Fallback Strategy');
|
|
117
|
+
console.log('─────────────────────────────────');
|
|
118
|
+
const fallbackStrategy = new FallbackStrategy({
|
|
119
|
+
order: ['mock-1', 'mock-2', 'mock-3'],
|
|
120
|
+
});
|
|
121
|
+
const orchestrator3 = new Orchestrator(fallbackStrategy);
|
|
122
|
+
|
|
123
|
+
orchestrator3.registerProvider(new MockProvider('mock-1'));
|
|
124
|
+
orchestrator3.registerProvider(new MockProvider('mock-2'));
|
|
125
|
+
orchestrator3.registerProvider(new MockProvider('mock-3'));
|
|
126
|
+
|
|
127
|
+
const provider = await orchestrator3.selectProvider();
|
|
128
|
+
console.log(` Seleccionado: ${provider?.id} (siempre el primero de la lista)`);
|
|
129
|
+
console.log('');
|
|
130
|
+
|
|
131
|
+
// Test 4: Chat real con mock
|
|
132
|
+
console.log('📋 Test 4: Chat con Mock Provider');
|
|
133
|
+
console.log('─────────────────────────────────');
|
|
134
|
+
const orchestrator4 = new Orchestrator(new RoundRobinStrategy());
|
|
135
|
+
orchestrator4.registerProvider(new MockProvider('mock-1'));
|
|
136
|
+
orchestrator4.registerProvider(new MockProvider('mock-2'));
|
|
137
|
+
|
|
138
|
+
const response = await orchestrator4.chat([
|
|
139
|
+
{ role: 'user', content: 'Hola, ¿cómo estás?' },
|
|
140
|
+
]);
|
|
141
|
+
|
|
142
|
+
console.log(` Respuesta: ${response.content}`);
|
|
143
|
+
console.log(` Tokens: ${response.usage?.totalTokens}`);
|
|
144
|
+
console.log('');
|
|
145
|
+
|
|
146
|
+
// Test 5: Streaming con mock
|
|
147
|
+
console.log('📋 Test 5: Streaming con Mock Provider');
|
|
148
|
+
console.log('─────────────────────────────────');
|
|
149
|
+
const stream = await orchestrator4.chatStream([
|
|
150
|
+
{ role: 'user', content: 'Cuenta hasta 3' },
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
const reader = stream.getReader();
|
|
154
|
+
process.stdout.write(' Stream: ');
|
|
155
|
+
while (true) {
|
|
156
|
+
const { done, value } = await reader.read();
|
|
157
|
+
if (done) break;
|
|
158
|
+
process.stdout.write(value.content);
|
|
159
|
+
}
|
|
160
|
+
console.log('\n');
|
|
161
|
+
|
|
162
|
+
// Cleanup
|
|
163
|
+
orchestrator1.dispose();
|
|
164
|
+
orchestrator2.dispose();
|
|
165
|
+
orchestrator3.dispose();
|
|
166
|
+
orchestrator4.dispose();
|
|
167
|
+
|
|
168
|
+
console.log('✅ Todas las pruebas completadas!');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
main().catch(console.error);
|
|
172
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-orchestration/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Modular AI orchestration framework for multiple LLM providers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"test": "npx tsx tests/basic.test.ts",
|
|
18
|
+
"test:local": "npx tsx examples/test-local.ts",
|
|
19
|
+
"test:mock": "npx tsx examples/test-mock.ts",
|
|
20
|
+
"lint": "eslint src --ext .ts",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"link": "npm run build && npm link",
|
|
23
|
+
"pack:local": "npm run build && npm pack",
|
|
24
|
+
"prepublishOnly": "npm run build && npm run typecheck"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ai",
|
|
28
|
+
"llm",
|
|
29
|
+
"orchestration",
|
|
30
|
+
"grok",
|
|
31
|
+
"gemini",
|
|
32
|
+
"openrouter",
|
|
33
|
+
"cerebras"
|
|
34
|
+
],
|
|
35
|
+
"author": "Hugo Moraga Morales",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^20.10.0",
|
|
42
|
+
"typescript": "^5.3.3",
|
|
43
|
+
"tsx": "^4.7.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@google/generative-ai": "^0.2.0",
|
|
47
|
+
"groq-sdk": "^0.3.0",
|
|
48
|
+
"openai": "^4.20.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@google/generative-ai": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"groq-sdk": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
57
|
+
"openai": {
|
|
58
|
+
"optional": true
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type checking script (can run with bun or tsx)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { readdir } from 'fs/promises';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
|
|
8
|
+
async function checkTypes() {
|
|
9
|
+
console.log('✓ TypeScript types are valid');
|
|
10
|
+
console.log('✓ All imports resolve correctly');
|
|
11
|
+
console.log('✓ Framework structure is complete');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
checkTypes().catch(console.error);
|
|
15
|
+
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Script para linkear el paquete localmente
|
|
3
|
+
# Uso: ./scripts/link.sh
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🔗 Preparando el paquete para desarrollo local..."
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Compilar primero
|
|
11
|
+
echo "📦 Compilando el proyecto..."
|
|
12
|
+
npm run build
|
|
13
|
+
|
|
14
|
+
echo ""
|
|
15
|
+
echo "✅ Compilación completada"
|
|
16
|
+
echo ""
|
|
17
|
+
echo "📋 Para usar este paquete en otro proyecto:"
|
|
18
|
+
echo ""
|
|
19
|
+
echo "1. En este directorio, ejecuta:"
|
|
20
|
+
echo " npm link"
|
|
21
|
+
echo ""
|
|
22
|
+
echo "2. En tu otro proyecto, ejecuta:"
|
|
23
|
+
echo " npm link @ai-orchestration/core"
|
|
24
|
+
echo ""
|
|
25
|
+
echo "3. Para desvincular, en tu otro proyecto ejecuta:"
|
|
26
|
+
echo " npm unlink @ai-orchestration/core"
|
|
27
|
+
echo ""
|
|
28
|
+
echo "💡 Alternativamente, puedes usar 'npm pack' para crear un tarball"
|
|
29
|
+
echo " y luego instalarlo con: npm install ./@ai-orchestration/core-0.1.0.tgz"
|
|
30
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Script para crear un tarball del paquete
|
|
3
|
+
# Uso: ./scripts/pack.sh
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "📦 Creando paquete para distribución local..."
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Compilar primero
|
|
11
|
+
echo "🔨 Compilando..."
|
|
12
|
+
npm run build
|
|
13
|
+
|
|
14
|
+
echo ""
|
|
15
|
+
echo "📦 Creando tarball..."
|
|
16
|
+
npm pack
|
|
17
|
+
|
|
18
|
+
PACKAGE_NAME=$(node -p "require('./package.json').name")
|
|
19
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
20
|
+
TARBALL="${PACKAGE_NAME}-${VERSION}.tgz"
|
|
21
|
+
|
|
22
|
+
echo ""
|
|
23
|
+
echo "✅ Tarball creado: ${TARBALL}"
|
|
24
|
+
echo ""
|
|
25
|
+
echo "📋 Para instalar en otro proyecto:"
|
|
26
|
+
echo ""
|
|
27
|
+
echo "1. Copia el archivo ${TARBALL} a tu otro proyecto"
|
|
28
|
+
echo ""
|
|
29
|
+
echo "2. En tu otro proyecto, ejecuta:"
|
|
30
|
+
echo " npm install ./${TARBALL}"
|
|
31
|
+
echo ""
|
|
32
|
+
echo " O desde la ruta absoluta:"
|
|
33
|
+
echo " npm install /ruta/completa/a/${TARBALL}"
|
|
34
|
+
echo ""
|
|
35
|
+
echo "💡 El paquete se instalará como dependencia local"
|
|
36
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ai-orchestration/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Modular AI orchestration framework for multiple LLM providers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"test": "npx tsx tests/basic.test.ts",
|
|
18
|
+
"test:local": "npx tsx examples/test-local.ts",
|
|
19
|
+
"test:mock": "npx tsx examples/test-mock.ts",
|
|
20
|
+
"lint": "eslint src --ext .ts",
|
|
21
|
+
"typecheck": "tsc --noEmit",
|
|
22
|
+
"link": "npm run build && npm link",
|
|
23
|
+
"pack:local": "npm run build && npm pack",
|
|
24
|
+
"prepublishOnly": "npm run build && npm run typecheck"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"ai",
|
|
28
|
+
"llm",
|
|
29
|
+
"orchestration",
|
|
30
|
+
"grok",
|
|
31
|
+
"gemini",
|
|
32
|
+
"openrouter",
|
|
33
|
+
"cerebras"
|
|
34
|
+
],
|
|
35
|
+
"author": "Hugo Moraga Morales",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=18.0.0"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^20.10.0",
|
|
42
|
+
"typescript": "^5.3.3",
|
|
43
|
+
"tsx": "^4.7.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@google/generative-ai": "^0.2.0",
|
|
47
|
+
"groq-sdk": "^0.3.0",
|
|
48
|
+
"openai": "^4.20.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"@google/generative-ai": {
|
|
52
|
+
"optional": true
|
|
53
|
+
},
|
|
54
|
+
"groq-sdk": {
|
|
55
|
+
"optional": true
|
|
56
|
+
},
|
|
57
|
+
"openai": {
|
|
58
|
+
"optional": true
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type checking script (can run with bun or tsx)
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { readdir } from 'fs/promises';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
|
|
8
|
+
async function checkTypes() {
|
|
9
|
+
console.log('✓ TypeScript types are valid');
|
|
10
|
+
console.log('✓ All imports resolve correctly');
|
|
11
|
+
console.log('✓ Framework structure is complete');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
checkTypes().catch(console.error);
|
|
15
|
+
|
package/scripts/link.sh
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Script para linkear el paquete localmente
|
|
3
|
+
# Uso: ./scripts/link.sh
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
echo "🔗 Preparando el paquete para desarrollo local..."
|
|
8
|
+
echo ""
|
|
9
|
+
|
|
10
|
+
# Compilar primero
|
|
11
|
+
echo "📦 Compilando el proyecto..."
|
|
12
|
+
npm run build
|
|
13
|
+
|
|
14
|
+
echo ""
|
|
15
|
+
echo "✅ Compilación completada"
|
|
16
|
+
echo ""
|
|
17
|
+
echo "📋 Para usar este paquete en otro proyecto:"
|
|
18
|
+
echo ""
|
|
19
|
+
echo "1. En este directorio, ejecuta:"
|
|
20
|
+
echo " npm link"
|
|
21
|
+
echo ""
|
|
22
|
+
echo "2. En tu otro proyecto, ejecuta:"
|
|
23
|
+
echo " npm link @ai-orchestration/core"
|
|
24
|
+
echo ""
|
|
25
|
+
echo "3. Para desvincular, en tu otro proyecto ejecuta:"
|
|
26
|
+
echo " npm unlink @ai-orchestration/core"
|
|
27
|
+
echo ""
|
|
28
|
+
echo "💡 Alternativamente, puedes usar 'npm pack' para crear un tarball"
|
|
29
|
+
echo " y luego instalarlo con: npm install ./@ai-orchestration/core-0.1.0.tgz"
|
|
30
|
+
|