@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.
Files changed (199) hide show
  1. package/.eslintrc.json +27 -0
  2. package/README.md +516 -0
  3. package/dist/core/errors.d.ts +21 -0
  4. package/dist/core/errors.d.ts.map +1 -0
  5. package/dist/core/errors.js +38 -0
  6. package/dist/core/errors.js.map +1 -0
  7. package/dist/core/interfaces.d.ts +87 -0
  8. package/dist/core/interfaces.d.ts.map +1 -0
  9. package/dist/core/interfaces.js +5 -0
  10. package/dist/core/interfaces.js.map +1 -0
  11. package/dist/core/orchestrator.d.ts +55 -0
  12. package/dist/core/orchestrator.d.ts.map +1 -0
  13. package/dist/core/orchestrator.js +147 -0
  14. package/dist/core/orchestrator.js.map +1 -0
  15. package/dist/core/types.d.ts +72 -0
  16. package/dist/core/types.d.ts.map +1 -0
  17. package/dist/core/types.js +5 -0
  18. package/dist/core/types.js.map +1 -0
  19. package/dist/factory/index.d.ts +14 -0
  20. package/dist/factory/index.d.ts.map +1 -0
  21. package/dist/factory/index.js +184 -0
  22. package/dist/factory/index.js.map +1 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +15 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/providers/base.d.ts +30 -0
  28. package/dist/providers/base.d.ts.map +1 -0
  29. package/dist/providers/base.js +31 -0
  30. package/dist/providers/base.js.map +1 -0
  31. package/dist/providers/cerebras.d.ts +26 -0
  32. package/dist/providers/cerebras.d.ts.map +1 -0
  33. package/dist/providers/cerebras.js +190 -0
  34. package/dist/providers/cerebras.js.map +1 -0
  35. package/dist/providers/gemini.d.ts +26 -0
  36. package/dist/providers/gemini.d.ts.map +1 -0
  37. package/dist/providers/gemini.js +181 -0
  38. package/dist/providers/gemini.js.map +1 -0
  39. package/dist/providers/groq.d.ts +26 -0
  40. package/dist/providers/groq.d.ts.map +1 -0
  41. package/dist/providers/groq.js +225 -0
  42. package/dist/providers/groq.js.map +1 -0
  43. package/dist/providers/index.d.ts +15 -0
  44. package/dist/providers/index.d.ts.map +1 -0
  45. package/dist/providers/index.js +10 -0
  46. package/dist/providers/index.js.map +1 -0
  47. package/dist/providers/local.d.ts +27 -0
  48. package/dist/providers/local.d.ts.map +1 -0
  49. package/dist/providers/local.js +198 -0
  50. package/dist/providers/local.js.map +1 -0
  51. package/dist/providers/openrouter.d.ts +26 -0
  52. package/dist/providers/openrouter.d.ts.map +1 -0
  53. package/dist/providers/openrouter.js +172 -0
  54. package/dist/providers/openrouter.js.map +1 -0
  55. package/dist/strategies/base.d.ts +16 -0
  56. package/dist/strategies/base.d.ts.map +1 -0
  57. package/dist/strategies/base.js +21 -0
  58. package/dist/strategies/base.js.map +1 -0
  59. package/dist/strategies/fallback.d.ts +14 -0
  60. package/dist/strategies/fallback.d.ts.map +1 -0
  61. package/dist/strategies/fallback.js +29 -0
  62. package/dist/strategies/fallback.js.map +1 -0
  63. package/dist/strategies/health-aware.d.ts +20 -0
  64. package/dist/strategies/health-aware.d.ts.map +1 -0
  65. package/dist/strategies/health-aware.js +106 -0
  66. package/dist/strategies/health-aware.js.map +1 -0
  67. package/dist/strategies/index.d.ts +14 -0
  68. package/dist/strategies/index.d.ts.map +1 -0
  69. package/dist/strategies/index.js +10 -0
  70. package/dist/strategies/index.js.map +1 -0
  71. package/dist/strategies/priority.d.ts +18 -0
  72. package/dist/strategies/priority.d.ts.map +1 -0
  73. package/dist/strategies/priority.js +35 -0
  74. package/dist/strategies/priority.js.map +1 -0
  75. package/dist/strategies/round-robin.d.ts +10 -0
  76. package/dist/strategies/round-robin.d.ts.map +1 -0
  77. package/dist/strategies/round-robin.js +21 -0
  78. package/dist/strategies/round-robin.js.map +1 -0
  79. package/dist/strategies/weighted.d.ts +20 -0
  80. package/dist/strategies/weighted.d.ts.map +1 -0
  81. package/dist/strategies/weighted.js +58 -0
  82. package/dist/strategies/weighted.js.map +1 -0
  83. package/docs/ARCHITECTURE.md +126 -0
  84. package/docs/CHANGELOG.md +30 -0
  85. package/docs/CONTRIBUTING.md +198 -0
  86. package/examples/basic.ts +58 -0
  87. package/examples/chat-app/README.md +146 -0
  88. package/examples/chat-app/config.json +34 -0
  89. package/examples/chat-app/index.ts +330 -0
  90. package/examples/chat-app/package-lock.json +570 -0
  91. package/examples/chat-app/package.json +20 -0
  92. package/examples/config.example.json +42 -0
  93. package/examples/strategies.ts +112 -0
  94. package/examples/test-local.ts +150 -0
  95. package/examples/test-mock.ts +172 -0
  96. package/package/.eslintrc.json +27 -0
  97. package/package/CHANGELOG.md +31 -0
  98. package/package/CONTRIBUTING.md +156 -0
  99. package/package/PUBLISHING.md +213 -0
  100. package/package/README.md +515 -0
  101. package/package/dist/core/errors.d.ts +21 -0
  102. package/package/dist/core/errors.d.ts.map +1 -0
  103. package/package/dist/core/errors.js +38 -0
  104. package/package/dist/core/errors.js.map +1 -0
  105. package/package/dist/core/interfaces.d.ts +87 -0
  106. package/package/dist/core/interfaces.d.ts.map +1 -0
  107. package/package/dist/core/interfaces.js +5 -0
  108. package/package/dist/core/interfaces.js.map +1 -0
  109. package/package/dist/core/orchestrator.d.ts +55 -0
  110. package/package/dist/core/orchestrator.d.ts.map +1 -0
  111. package/package/dist/core/orchestrator.js +147 -0
  112. package/package/dist/core/orchestrator.js.map +1 -0
  113. package/package/dist/core/types.d.ts +72 -0
  114. package/package/dist/core/types.d.ts.map +1 -0
  115. package/package/dist/core/types.js +5 -0
  116. package/package/dist/core/types.js.map +1 -0
  117. package/package/dist/factory/index.d.ts +14 -0
  118. package/package/dist/factory/index.d.ts.map +1 -0
  119. package/package/dist/factory/index.js +184 -0
  120. package/package/dist/factory/index.js.map +1 -0
  121. package/package/dist/index.d.ts +14 -0
  122. package/package/dist/index.d.ts.map +1 -0
  123. package/package/dist/index.js +15 -0
  124. package/package/dist/index.js.map +1 -0
  125. package/package/dist/providers/base.d.ts +30 -0
  126. package/package/dist/providers/base.d.ts.map +1 -0
  127. package/package/dist/providers/base.js +31 -0
  128. package/package/dist/providers/base.js.map +1 -0
  129. package/package/dist/providers/cerebras.d.ts +26 -0
  130. package/package/dist/providers/cerebras.d.ts.map +1 -0
  131. package/package/dist/providers/cerebras.js +190 -0
  132. package/package/dist/providers/cerebras.js.map +1 -0
  133. package/package/dist/providers/gemini.d.ts +26 -0
  134. package/package/dist/providers/gemini.d.ts.map +1 -0
  135. package/package/dist/providers/gemini.js +181 -0
  136. package/package/dist/providers/gemini.js.map +1 -0
  137. package/package/dist/providers/groq.d.ts +26 -0
  138. package/package/dist/providers/groq.d.ts.map +1 -0
  139. package/package/dist/providers/groq.js +225 -0
  140. package/package/dist/providers/groq.js.map +1 -0
  141. package/package/dist/providers/index.d.ts +15 -0
  142. package/package/dist/providers/index.d.ts.map +1 -0
  143. package/package/dist/providers/index.js +10 -0
  144. package/package/dist/providers/index.js.map +1 -0
  145. package/package/dist/providers/local.d.ts +27 -0
  146. package/package/dist/providers/local.d.ts.map +1 -0
  147. package/package/dist/providers/local.js +198 -0
  148. package/package/dist/providers/local.js.map +1 -0
  149. package/package/dist/providers/openrouter.d.ts +26 -0
  150. package/package/dist/providers/openrouter.d.ts.map +1 -0
  151. package/package/dist/providers/openrouter.js +172 -0
  152. package/package/dist/providers/openrouter.js.map +1 -0
  153. package/package/dist/strategies/base.d.ts +16 -0
  154. package/package/dist/strategies/base.d.ts.map +1 -0
  155. package/package/dist/strategies/base.js +21 -0
  156. package/package/dist/strategies/base.js.map +1 -0
  157. package/package/dist/strategies/fallback.d.ts +14 -0
  158. package/package/dist/strategies/fallback.d.ts.map +1 -0
  159. package/package/dist/strategies/fallback.js +29 -0
  160. package/package/dist/strategies/fallback.js.map +1 -0
  161. package/package/dist/strategies/health-aware.d.ts +20 -0
  162. package/package/dist/strategies/health-aware.d.ts.map +1 -0
  163. package/package/dist/strategies/health-aware.js +106 -0
  164. package/package/dist/strategies/health-aware.js.map +1 -0
  165. package/package/dist/strategies/index.d.ts +14 -0
  166. package/package/dist/strategies/index.d.ts.map +1 -0
  167. package/package/dist/strategies/index.js +10 -0
  168. package/package/dist/strategies/index.js.map +1 -0
  169. package/package/dist/strategies/priority.d.ts +18 -0
  170. package/package/dist/strategies/priority.d.ts.map +1 -0
  171. package/package/dist/strategies/priority.js +35 -0
  172. package/package/dist/strategies/priority.js.map +1 -0
  173. package/package/dist/strategies/round-robin.d.ts +10 -0
  174. package/package/dist/strategies/round-robin.d.ts.map +1 -0
  175. package/package/dist/strategies/round-robin.js +21 -0
  176. package/package/dist/strategies/round-robin.js.map +1 -0
  177. package/package/dist/strategies/weighted.d.ts +20 -0
  178. package/package/dist/strategies/weighted.d.ts.map +1 -0
  179. package/package/dist/strategies/weighted.js +58 -0
  180. package/package/dist/strategies/weighted.js.map +1 -0
  181. package/package/docs/ARCHITECTURE.md +127 -0
  182. package/package/examples/basic.ts +58 -0
  183. package/package/examples/chat-app/README.md +146 -0
  184. package/package/examples/chat-app/config.json +34 -0
  185. package/package/examples/chat-app/index.ts +330 -0
  186. package/package/examples/chat-app/package-lock.json +570 -0
  187. package/package/examples/chat-app/package.json +20 -0
  188. package/package/examples/config.example.json +42 -0
  189. package/package/examples/strategies.ts +112 -0
  190. package/package/examples/test-local.ts +150 -0
  191. package/package/examples/test-mock.ts +172 -0
  192. package/package/package.json +62 -0
  193. package/package/scripts/check-types.ts +15 -0
  194. package/package/scripts/link.sh +30 -0
  195. package/package/scripts/pack.sh +36 -0
  196. package/package.json +62 -0
  197. package/scripts/check-types.ts +15 -0
  198. package/scripts/link.sh +30 -0
  199. package/scripts/pack.sh +36 -0
package/.eslintrc.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "parser": "@typescript-eslint/parser",
3
+ "extends": [
4
+ "eslint:recommended",
5
+ "plugin:@typescript-eslint/recommended"
6
+ ],
7
+ "parserOptions": {
8
+ "ecmaVersion": 2022,
9
+ "sourceType": "module"
10
+ },
11
+ "env": {
12
+ "node": true,
13
+ "es2022": true
14
+ },
15
+ "rules": {
16
+ "@typescript-eslint/no-unused-vars": [
17
+ "error",
18
+ {
19
+ "argsIgnorePattern": "^_",
20
+ "varsIgnorePattern": "^_"
21
+ }
22
+ ],
23
+ "@typescript-eslint/explicit-module-boundary-types": "off",
24
+ "@typescript-eslint/no-explicit-any": "warn"
25
+ }
26
+ }
27
+
package/README.md ADDED
@@ -0,0 +1,516 @@
1
+ # AI Orchestration Framework
2
+
3
+ A modular and extensible framework for orchestrating multiple AI/LLM providers consistently and configurable.
4
+
5
+ **📦 This is an npm package**: API keys must be configured in the project that uses this package (using environment variables or `.env` files in that project), not in the package itself.
6
+
7
+ ## Features
8
+
9
+ - 🔌 **Plugin-based architecture**: Add new providers or strategies without modifying the core
10
+ - 🎯 **Multiple selection strategies**: Round-robin, priority, fallback, weighted, health-aware
11
+ - 🌊 **Native streaming**: Full support for streaming responses using ReadableStream
12
+ - 🔄 **Automatic fallback**: Automatically tries multiple providers if one fails
13
+ - 💚 **Health checks**: Provider health monitoring with latency metrics
14
+ - 📦 **Runtime agnostic**: Compatible with Node.js and Bun
15
+ - 🎨 **Declarative API**: Simple configuration via JSON/JS objects
16
+ - 🔒 **Type-safe**: Fully typed with TypeScript
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @ai-orchestration/core
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### Basic Usage
27
+
28
+ ```typescript
29
+ import { createOrchestrator } from '@ai-orchestration/core';
30
+
31
+ // API keys should come from environment variables configured in YOUR project
32
+ // Example: export GROQ_API_KEY="your-key" or using dotenv in your project
33
+ const orchestrator = createOrchestrator({
34
+ providers: [
35
+ {
36
+ id: 'groq-1',
37
+ type: 'groq',
38
+ apiKey: process.env.GROQ_API_KEY!, // Configure this variable in your project
39
+ model: 'llama-3.3-70b-versatile',
40
+ },
41
+ {
42
+ id: 'openrouter-1',
43
+ type: 'openrouter',
44
+ apiKey: process.env.OPENROUTER_API_KEY!,
45
+ model: 'openai/gpt-3.5-turbo',
46
+ },
47
+ ],
48
+ strategy: {
49
+ type: 'round-robin',
50
+ },
51
+ });
52
+
53
+ // Simple chat
54
+ const response = await orchestrator.chat([
55
+ { role: 'user', content: 'Hello, world!' },
56
+ ]);
57
+
58
+ console.log(response.content);
59
+
60
+ // Streaming chat
61
+ const stream = await orchestrator.chatStream([
62
+ { role: 'user', content: 'Tell me a story' },
63
+ ]);
64
+
65
+ const reader = stream.getReader();
66
+ while (true) {
67
+ const { done, value } = await reader.read();
68
+ if (done) break;
69
+ process.stdout.write(value.content);
70
+ }
71
+ ```
72
+
73
+ ### Programmatic Usage
74
+
75
+ ```typescript
76
+ import {
77
+ Orchestrator,
78
+ RoundRobinStrategy,
79
+ GroqProvider,
80
+ OpenRouterProvider,
81
+ } from '@ai-orchestration/core';
82
+
83
+ // Create strategy
84
+ const strategy = new RoundRobinStrategy();
85
+
86
+ // Create orchestrator
87
+ const orchestrator = new Orchestrator(strategy);
88
+
89
+ // Register providers
90
+ // API keys should come from environment variables configured in YOUR project
91
+ orchestrator.registerProvider(
92
+ new GroqProvider({
93
+ id: 'groq-1',
94
+ apiKey: process.env.GROQ_API_KEY!,
95
+ })
96
+ );
97
+
98
+ orchestrator.registerProvider(
99
+ new OpenRouterProvider({
100
+ id: 'openrouter-1',
101
+ apiKey: process.env.OPENROUTER_API_KEY!,
102
+ })
103
+ );
104
+
105
+ // Use
106
+ const response = await orchestrator.chat([
107
+ { role: 'user', content: 'Hello!' },
108
+ ]);
109
+ ```
110
+
111
+ ## Selection Strategies
112
+
113
+ ### Round-Robin
114
+
115
+ Cycles through providers in order:
116
+
117
+ ```typescript
118
+ {
119
+ strategy: {
120
+ type: 'round-robin',
121
+ },
122
+ }
123
+ ```
124
+
125
+ ### Priority
126
+
127
+ Selects providers based on priority (lower number = higher priority):
128
+
129
+ ```typescript
130
+ {
131
+ strategy: {
132
+ type: 'priority',
133
+ priorities: {
134
+ 'groq-1': 1,
135
+ 'openrouter-1': 2,
136
+ 'gemini-1': 3,
137
+ },
138
+ },
139
+ }
140
+ ```
141
+
142
+ ### Fallback
143
+
144
+ Tries providers in order until one works:
145
+
146
+ ```typescript
147
+ {
148
+ strategy: {
149
+ type: 'fallback',
150
+ order: ['groq-1', 'openrouter-1', 'gemini-1'],
151
+ },
152
+ }
153
+ ```
154
+
155
+ ### Weighted
156
+
157
+ Selection based on weights (useful for load balancing):
158
+
159
+ ```typescript
160
+ {
161
+ strategy: {
162
+ type: 'weighted',
163
+ weights: {
164
+ 'groq-1': 0.7,
165
+ 'openrouter-1': 0.3,
166
+ },
167
+ },
168
+ }
169
+ ```
170
+
171
+ ### Weighted Cost-Aware
172
+
173
+ Considers cost per token:
174
+
175
+ ```typescript
176
+ {
177
+ strategy: {
178
+ type: 'weighted',
179
+ costAware: true,
180
+ weights: {
181
+ 'groq-1': 1.0,
182
+ 'openrouter-1': 1.0,
183
+ },
184
+ },
185
+ }
186
+ ```
187
+
188
+ ### Health-Aware
189
+
190
+ Selects based on health metrics (latency, success rate):
191
+
192
+ ```typescript
193
+ {
194
+ strategy: {
195
+ type: 'health-aware',
196
+ preferLowLatency: true,
197
+ minHealthScore: 0.5,
198
+ },
199
+ }
200
+ ```
201
+
202
+ ## Supported Providers
203
+
204
+ ### Groq
205
+
206
+ ```typescript
207
+ {
208
+ id: 'groq-1',
209
+ type: 'groq',
210
+ apiKey: 'your-api-key',
211
+ model: 'llama-3.3-70b-versatile', // optional, default
212
+ baseURL: 'https://api.groq.com/openai/v1', // optional
213
+ }
214
+ ```
215
+
216
+ ### OpenRouter
217
+
218
+ ```typescript
219
+ {
220
+ id: 'openrouter-1',
221
+ type: 'openrouter',
222
+ apiKey: 'your-api-key',
223
+ model: 'openai/gpt-3.5-turbo', // optional
224
+ baseURL: 'https://openrouter.ai/api/v1', // optional
225
+ }
226
+ ```
227
+
228
+ ### Google Gemini
229
+
230
+ ```typescript
231
+ {
232
+ id: 'gemini-1',
233
+ type: 'gemini',
234
+ apiKey: 'your-api-key',
235
+ model: 'gemini-pro', // optional
236
+ baseURL: 'https://generativelanguage.googleapis.com/v1beta', // optional
237
+ }
238
+ ```
239
+
240
+ ### Cerebras
241
+
242
+ Cerebras Inference API - OpenAI compatible. Documentation: [inference-docs.cerebras.ai](https://inference-docs.cerebras.ai/quickstart)
243
+
244
+ ```typescript
245
+ {
246
+ id: 'cerebras-1',
247
+ type: 'cerebras',
248
+ apiKey: 'your-api-key', // Get at: https://inference-docs.cerebras.ai
249
+ model: 'llama-3.3-70b', // optional, default
250
+ baseURL: 'https://api.cerebras.ai/v1', // optional
251
+ }
252
+ ```
253
+
254
+ **Note**: Cerebras API requires the `User-Agent` header to avoid CloudFront blocking. This is included automatically.
255
+
256
+ ### Local (Local Models)
257
+
258
+ For local models that expose an OpenAI-compatible API:
259
+
260
+ ```typescript
261
+ {
262
+ id: 'local-1',
263
+ type: 'local',
264
+ baseURL: 'http://localhost:8000',
265
+ model: 'local-model', // optional
266
+ apiKey: 'optional-key', // optional
267
+ }
268
+ ```
269
+
270
+ ## Health Checks
271
+
272
+ Enable periodic health monitoring:
273
+
274
+ ```typescript
275
+ const orchestrator = createOrchestrator({
276
+ providers: [...],
277
+ strategy: {...},
278
+ enableHealthChecks: true,
279
+ healthCheckInterval: 60000, // every 60 seconds
280
+ });
281
+ ```
282
+
283
+ Or manually:
284
+
285
+ ```typescript
286
+ const health = await provider.checkHealth();
287
+ console.log(health.healthy, health.latency);
288
+ ```
289
+
290
+ ## Chat Options
291
+
292
+ ```typescript
293
+ const response = await orchestrator.chat(messages, {
294
+ temperature: 0.7,
295
+ maxTokens: 1000,
296
+ topP: 0.9,
297
+ topK: 40,
298
+ stopSequences: ['\n\n'],
299
+ });
300
+ ```
301
+
302
+ ## Extensibility
303
+
304
+ ### Adding a New Provider
305
+
306
+ ```typescript
307
+ import { BaseProvider } from '@ai-orchestration/core';
308
+ import type {
309
+ ChatMessage,
310
+ ChatOptions,
311
+ ChatResponse,
312
+ ChatChunk,
313
+ ProviderHealth,
314
+ ProviderMetadata,
315
+ } from '@ai-orchestration/core';
316
+
317
+ export class CustomProvider extends BaseProvider {
318
+ readonly id: string;
319
+ readonly metadata: ProviderMetadata;
320
+
321
+ constructor(config: CustomConfig) {
322
+ super();
323
+ this.id = config.id;
324
+ this.metadata = {
325
+ id: this.id,
326
+ name: 'Custom Provider',
327
+ };
328
+ }
329
+
330
+ async checkHealth(): Promise<ProviderHealth> {
331
+ // Implement health check
332
+ }
333
+
334
+ async chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse> {
335
+ // Implement chat
336
+ }
337
+
338
+ async chatStream(messages: ChatMessage[], options?: ChatOptions): Promise<ReadableStream<ChatChunk>> {
339
+ // Implement streaming
340
+ }
341
+
342
+ protected formatMessages(messages: ChatMessage[]): unknown {
343
+ // Convert standard format to provider format
344
+ }
345
+
346
+ protected parseResponse(response: unknown): ChatResponse {
347
+ // Convert provider response to standard format
348
+ }
349
+
350
+ protected parseStream(stream: ReadableStream<unknown>): ReadableStream<ChatChunk> {
351
+ // Convert provider stream to standard format
352
+ }
353
+ }
354
+ ```
355
+
356
+ ### Adding a New Strategy
357
+
358
+ ```typescript
359
+ import { BaseStrategy } from '@ai-orchestration/core';
360
+ import type { AIService, SelectionContext } from '@ai-orchestration/core';
361
+
362
+ export class CustomStrategy extends BaseStrategy {
363
+ async select(
364
+ providers: AIService[],
365
+ context?: SelectionContext
366
+ ): Promise<AIService | null> {
367
+ // Implement selection logic
368
+ return providers[0];
369
+ }
370
+
371
+ update?(provider: AIService, success: boolean, metadata?: unknown): void {
372
+ // Optional: update internal state
373
+ }
374
+ }
375
+ ```
376
+
377
+ ## Architecture
378
+
379
+ ```
380
+ src/
381
+ ├── core/
382
+ │ ├── interfaces.ts # Main interfaces
383
+ │ ├── types.ts # Shared types
384
+ │ ├── orchestrator.ts # Orchestrator core
385
+ │ └── errors.ts # Custom error classes
386
+ ├── providers/
387
+ │ ├── base.ts # Base class for providers
388
+ │ ├── groq.ts
389
+ │ ├── openrouter.ts
390
+ │ ├── gemini.ts
391
+ │ ├── cerebras.ts
392
+ │ └── local.ts
393
+ ├── strategies/
394
+ │ ├── base.ts # Base class for strategies
395
+ │ ├── round-robin.ts
396
+ │ ├── priority.ts
397
+ │ ├── fallback.ts
398
+ │ ├── weighted.ts
399
+ │ └── health-aware.ts
400
+ ├── factory/
401
+ │ └── index.ts # Factory for declarative creation
402
+ └── index.ts # Main entry point
403
+ ```
404
+
405
+ ## Design Principles
406
+
407
+ - **Single Responsibility**: Each class has a single responsibility
408
+ - **Open/Closed Principle**: Extensible without modifying the core
409
+ - **Plugin-based Architecture**: Providers and strategies are plugins
410
+ - **Composition over Inheritance**: Preference for composition
411
+ - **Configuration over Hard-coding**: Declarative configuration
412
+ - **Declarative APIs**: Simple and expressive APIs
413
+
414
+ ## Development
415
+
416
+ ### Setup
417
+
418
+ ```bash
419
+ # Install dependencies
420
+ npm install
421
+
422
+ # Build
423
+ npm run build
424
+
425
+ # Development with watch
426
+ npm run dev
427
+
428
+ # Type checking
429
+ npm run typecheck
430
+
431
+ # Tests
432
+ npm test
433
+ ```
434
+
435
+ ### Testing
436
+
437
+ #### Quick Test (No API Keys Required)
438
+
439
+ Test the framework with mock providers without needing API keys:
440
+
441
+ ```bash
442
+ npm run test:mock
443
+ ```
444
+
445
+ #### Test with Real Providers
446
+
447
+ **Note**: The `@ai-orchestration/core` package does not include `.env` files. Environment variables must be configured in your project or in the examples.
448
+
449
+ 1. **Set environment variables:**
450
+
451
+ ```bash
452
+ export GROQ_API_KEY="your-key"
453
+ export OPENROUTER_API_KEY="your-key"
454
+ export GEMINI_API_KEY="your-key"
455
+ export CEREBRAS_API_KEY="your-key"
456
+ ```
457
+
458
+ 2. **Run tests:**
459
+
460
+ ```bash
461
+ npm run test:local
462
+ ```
463
+
464
+ ### Local Development in Other Projects
465
+
466
+ #### Method 1: npm link (Recommended)
467
+
468
+ ```bash
469
+ # In this directory (ai-orchestration)
470
+ npm run link
471
+
472
+ # In your other project
473
+ npm link @ai-orchestration/core
474
+ ```
475
+
476
+ Now you can import normally:
477
+ ```typescript
478
+ import { createOrchestrator } from '@ai-orchestration/core';
479
+ ```
480
+
481
+ #### Method 2: npm pack
482
+
483
+ ```bash
484
+ # In this directory
485
+ npm run pack:local
486
+
487
+ # In your other project
488
+ npm install ./@ai-orchestration-core-0.1.0.tgz
489
+ ```
490
+
491
+ ## Requirements
492
+
493
+ - **Node.js**: >= 18.0.0 (for native ReadableStream and test runner)
494
+ - **TypeScript**: 5.3+ (already included in devDependencies)
495
+
496
+ ## Examples
497
+
498
+ See the `examples/` directory for more code examples:
499
+ - `basic.ts` - Basic usage example
500
+ - `strategies.ts` - Strategy examples
501
+ - `test-local.ts` - Testing with real providers
502
+ - `test-mock.ts` - Testing with mock providers
503
+ - `chat-app/` - Full chat application example
504
+
505
+ ## License
506
+
507
+ MIT
508
+
509
+ ## Contributing
510
+
511
+ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md) for guidelines on contributing to this project.
512
+
513
+ ## Related Documentation
514
+
515
+ - [ARCHITECTURE.md](./docs/ARCHITECTURE.md) - Detailed architecture documentation
516
+ - [CHANGELOG.md](./docs/CHANGELOG.md) - Version history and changes
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Custom error classes for the framework
3
+ */
4
+ export declare class ProviderError extends Error {
5
+ readonly providerId: string;
6
+ readonly cause?: Error | undefined;
7
+ constructor(message: string, providerId: string, cause?: Error | undefined);
8
+ }
9
+ export declare class StrategyError extends Error {
10
+ readonly cause?: Error | undefined;
11
+ constructor(message: string, cause?: Error | undefined);
12
+ }
13
+ export declare class OrchestratorError extends Error {
14
+ readonly cause?: Error | undefined;
15
+ constructor(message: string, cause?: Error | undefined);
16
+ }
17
+ export declare class ConfigurationError extends Error {
18
+ readonly cause?: Error | undefined;
19
+ constructor(message: string, cause?: Error | undefined);
20
+ }
21
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;aAGpB,UAAU,EAAE,MAAM;aAClB,KAAK,CAAC,EAAE,KAAK;gBAF7B,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,KAAK,YAAA;CAKhC;AAED,qBAAa,aAAc,SAAQ,KAAK;aACO,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D;AAED,qBAAa,iBAAkB,SAAQ,KAAK;aACG,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aACE,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Custom error classes for the framework
3
+ */
4
+ export class ProviderError extends Error {
5
+ providerId;
6
+ cause;
7
+ constructor(message, providerId, cause) {
8
+ super(message);
9
+ this.providerId = providerId;
10
+ this.cause = cause;
11
+ this.name = 'ProviderError';
12
+ }
13
+ }
14
+ export class StrategyError extends Error {
15
+ cause;
16
+ constructor(message, cause) {
17
+ super(message);
18
+ this.cause = cause;
19
+ this.name = 'StrategyError';
20
+ }
21
+ }
22
+ export class OrchestratorError extends Error {
23
+ cause;
24
+ constructor(message, cause) {
25
+ super(message);
26
+ this.cause = cause;
27
+ this.name = 'OrchestratorError';
28
+ }
29
+ }
30
+ export class ConfigurationError extends Error {
31
+ cause;
32
+ constructor(message, cause) {
33
+ super(message);
34
+ this.cause = cause;
35
+ this.name = 'ConfigurationError';
36
+ }
37
+ }
38
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAGpB;IACA;IAHlB,YACE,OAAe,EACC,UAAkB,EAClB,KAAa;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHC,eAAU,GAAV,UAAU,CAAQ;QAClB,UAAK,GAAL,KAAK,CAAQ;QAG7B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,KAAK;IACO;IAA7C,YAAY,OAAe,EAAkB,KAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAQ;QAExD,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACG;IAA7C,YAAY,OAAe,EAAkB,KAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAQ;QAExD,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IACE;IAA7C,YAAY,OAAe,EAAkB,KAAa;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QAD4B,UAAK,GAAL,KAAK,CAAQ;QAExD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Core interfaces for AI providers and strategies
3
+ */
4
+ import type { ChatMessage, ChatOptions, ChatResponse, ChatChunk, ProviderHealth, ProviderMetadata } from './types.js';
5
+ export type { ChatMessage, ChatOptions, ChatResponse, ChatChunk, ProviderHealth, ProviderMetadata, };
6
+ /**
7
+ * Main interface that all AI providers must implement
8
+ */
9
+ export interface AIService {
10
+ /**
11
+ * Unique identifier for this provider instance
12
+ */
13
+ readonly id: string;
14
+ /**
15
+ * Provider metadata
16
+ */
17
+ readonly metadata: ProviderMetadata;
18
+ /**
19
+ * Check the health status of this provider
20
+ */
21
+ checkHealth(): Promise<ProviderHealth>;
22
+ /**
23
+ * Perform a chat completion (non-streaming)
24
+ */
25
+ chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse>;
26
+ /**
27
+ * Perform a chat completion with streaming
28
+ */
29
+ chatStream(messages: ChatMessage[], options?: ChatOptions): Promise<ReadableStream<ChatChunk>>;
30
+ }
31
+ /**
32
+ * Strategy interface for selecting providers
33
+ */
34
+ export interface SelectionStrategy {
35
+ /**
36
+ * Select a provider from the available list
37
+ * @param providers List of available providers
38
+ * @param context Optional context for selection (e.g., request metadata)
39
+ */
40
+ select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
41
+ /**
42
+ * Update strategy state (e.g., after a successful/failed request)
43
+ */
44
+ update?(provider: AIService, success: boolean, metadata?: unknown): void;
45
+ }
46
+ /**
47
+ * Context passed to selection strategies
48
+ */
49
+ export interface SelectionContext {
50
+ messages?: ChatMessage[];
51
+ options?: ChatOptions;
52
+ previousAttempts?: string[];
53
+ [key: string]: unknown;
54
+ }
55
+ /**
56
+ * Configuration for a provider instance
57
+ */
58
+ export interface ProviderConfig {
59
+ id: string;
60
+ type: string;
61
+ apiKey?: string;
62
+ baseURL?: string;
63
+ model?: string;
64
+ enabled?: boolean;
65
+ priority?: number;
66
+ weight?: number;
67
+ metadata?: Record<string, unknown>;
68
+ [key: string]: unknown;
69
+ }
70
+ /**
71
+ * Configuration for a selection strategy
72
+ */
73
+ export interface StrategyConfig {
74
+ type: string;
75
+ [key: string]: unknown;
76
+ }
77
+ /**
78
+ * Main orchestrator configuration
79
+ */
80
+ export interface OrchestratorConfig {
81
+ providers: ProviderConfig[];
82
+ strategy: StrategyConfig;
83
+ defaultOptions?: ChatOptions;
84
+ healthCheckInterval?: number;
85
+ enableHealthChecks?: boolean;
86
+ }
87
+ //# sourceMappingURL=interfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,cAAc,EACd,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAGpB,YAAY,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,SAAS,EACT,cAAc,EACd,gBAAgB,GACjB,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;IAEpC;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAEvC;;OAEG;IACH,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAE5E;;OAEG;IACH,UAAU,CACR,QAAQ,EAAE,WAAW,EAAE,EACvB,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,MAAM,CACJ,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAE7B;;OAEG;IACH,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1E;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Core interfaces for AI providers and strategies
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=interfaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA;;GAEG"}