@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
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Weighted strategy: selects providers based on weights (for load balancing or cost-aware selection)
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ export class WeightedStrategy extends BaseStrategy {
6
+ weights = new Map();
7
+ costAware;
8
+ constructor(config) {
9
+ super();
10
+ this.costAware = config?.costAware ?? false;
11
+ if (config?.weights) {
12
+ Object.entries(config.weights).forEach(([id, weight]) => {
13
+ this.weights.set(id, weight);
14
+ });
15
+ }
16
+ }
17
+ async select(providers, context) {
18
+ const available = this.filterAttempted(providers, context);
19
+ if (available.length === 0) {
20
+ return null;
21
+ }
22
+ // Calculate effective weights
23
+ const weightedProviders = available.map((provider) => {
24
+ let weight = this.weights.get(provider.id) ?? 1.0;
25
+ // Adjust weight based on cost if cost-aware
26
+ if (this.costAware && provider.metadata.costPerToken) {
27
+ const avgCost = (provider.metadata.costPerToken.prompt +
28
+ provider.metadata.costPerToken.completion) /
29
+ 2;
30
+ // Lower cost = higher weight (inverse relationship)
31
+ weight = weight / (avgCost + 0.0001); // Add small epsilon to avoid division by zero
32
+ }
33
+ return { provider, weight };
34
+ });
35
+ // Calculate total weight
36
+ const totalWeight = weightedProviders.reduce((sum, wp) => sum + wp.weight, 0);
37
+ if (totalWeight === 0) {
38
+ return available[0]; // Fallback to first available
39
+ }
40
+ // Select using weighted random
41
+ let random = Math.random() * totalWeight;
42
+ for (const { provider, weight } of weightedProviders) {
43
+ random -= weight;
44
+ if (random <= 0) {
45
+ return provider;
46
+ }
47
+ }
48
+ // Fallback (shouldn't reach here)
49
+ return available[0];
50
+ }
51
+ /**
52
+ * Set weight for a provider
53
+ */
54
+ setWeight(providerId, weight) {
55
+ this.weights.set(providerId, weight);
56
+ }
57
+ }
58
+ //# sourceMappingURL=weighted.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weighted.js","sourceRoot":"","sources":["../../src/strategies/weighted.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAQzC,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IACxC,OAAO,GAAwB,IAAI,GAAG,EAAE,CAAC;IACzC,SAAS,CAAU;IAE3B,YAAY,MAA+B;QACzC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,GAAG,MAAM,EAAE,SAAS,IAAI,KAAK,CAAC;QAE5C,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACpB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;gBACtD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YAC/B,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CACV,SAAsB,EACtB,OAA0B;QAE1B,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,8BAA8B;QAC9B,MAAM,iBAAiB,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;YACnD,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC;YAElD,4CAA4C;YAC5C,IAAI,IAAI,CAAC,SAAS,IAAI,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACrD,MAAM,OAAO,GACX,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,MAAM;oBACpC,QAAQ,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC;oBAC5C,CAAC,CAAC;gBACJ,oDAAoD;gBACpD,MAAM,GAAG,MAAM,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,8CAA8C;YACtF,CAAC;YAED,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,yBAAyB;QACzB,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,CAC1C,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,MAAM,EAC5B,CAAC,CACF,CAAC;QAEF,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,8BAA8B;QACrD,CAAC;QAED,+BAA+B;QAC/B,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,WAAW,CAAC;QACzC,KAAK,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,iBAAiB,EAAE,CAAC;YACrD,MAAM,IAAI,MAAM,CAAC;YACjB,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;gBAChB,OAAO,QAAQ,CAAC;YAClB,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,UAAkB,EAAE,MAAc;QAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;CACF"}
@@ -0,0 +1,126 @@
1
+ # Framework Architecture
2
+
3
+ ## Overview
4
+
5
+ The framework is designed following SOLID principles and plugin-based architecture, allowing extensibility without modifying core code.
6
+
7
+ ## Main Components
8
+
9
+ ### Core (`src/core/`)
10
+
11
+ #### `interfaces.ts`
12
+ Defines fundamental interfaces:
13
+ - `AIService`: Contract that all providers must implement
14
+ - `SelectionStrategy`: Contract for selection strategies
15
+ - `OrchestratorConfig`: Orchestrator configuration
16
+ - Configuration types for providers and strategies
17
+
18
+ #### `types.ts`
19
+ Shared types:
20
+ - `ChatMessage`: Message in a conversation
21
+ - `ChatOptions`: Options for chat completion
22
+ - `ChatResponse`: Non-streaming response
23
+ - `ChatChunk`: Streaming chunk
24
+ - `ProviderHealth`: Provider health status
25
+ - `ProviderMetadata`: Provider metadata
26
+
27
+ #### `orchestrator.ts`
28
+ Framework core:
29
+ - `Orchestrator`: Main class that manages providers and strategies
30
+ - Provider registration and management
31
+ - Automatic provider selection
32
+ - Automatic fallback on error
33
+ - Periodic health checks
34
+
35
+ ### Providers (`src/providers/`)
36
+
37
+ Each provider extends `BaseProvider` and implements:
38
+ - `checkHealth()`: Health verification
39
+ - `chat()`: Chat completion (non-streaming)
40
+ - `chatStream()`: Chat completion (streaming)
41
+ - `formatMessages()`: Conversion from standard format to provider format
42
+ - `parseResponse()`: Conversion from provider response to standard format
43
+ - `parseStream()`: Conversion from provider stream to standard format
44
+
45
+ **Implemented providers:**
46
+ - `GroqProvider`: Groq API integration
47
+ - `OpenRouterProvider`: OpenRouter integration
48
+ - `GeminiProvider`: Google Gemini integration
49
+ - `CerebrasProvider`: Cerebras Inference API integration
50
+ - `LocalProvider`: For local models (OpenAI-compatible API)
51
+
52
+ ### Strategies (`src/strategies/`)
53
+
54
+ Each strategy extends `BaseStrategy` and implements:
55
+ - `select()`: Provider selection logic
56
+ - `update()` (optional): Internal state update
57
+
58
+ **Implemented strategies:**
59
+ - `RoundRobinStrategy`: Cycles through providers
60
+ - `PriorityStrategy`: Selects by priority
61
+ - `FallbackStrategy`: Tries in order until success
62
+ - `WeightedStrategy`: Selection based on weights (load balancing)
63
+ - `HealthAwareStrategy`: Selection based on health metrics
64
+
65
+ ### Factory (`src/factory/`)
66
+
67
+ - `createOrchestrator()`: Creates an orchestrator from declarative configuration
68
+ - `createProvider()`: Creates provider instances from configuration
69
+ - `createStrategy()`: Creates strategy instances from configuration
70
+ - `isValidOrchestratorConfig()`: Validates configuration
71
+
72
+ ## Data Flow
73
+
74
+ ```
75
+ User
76
+ ↓
77
+ Orchestrator.chat() / chatStream()
78
+ ↓
79
+ Strategy.select() → Selects provider
80
+ ↓
81
+ Provider.chat() / chatStream()
82
+ ↓
83
+ Provider formats messages → formatMessages()
84
+ ↓
85
+ Provider API call
86
+ ↓
87
+ Provider parses response → parseResponse() / parseStream()
88
+ ↓
89
+ Standard response to user
90
+ ```
91
+
92
+ ## Extensibility
93
+
94
+ ### Adding a New Provider
95
+
96
+ 1. Create class extending `BaseProvider`
97
+ 2. Implement required methods
98
+ 3. Register in `factory/index.ts` (`createProvider` method)
99
+
100
+ ### Adding a New Strategy
101
+
102
+ 1. Create class extending `BaseStrategy`
103
+ 2. Implement `select()` method
104
+ 3. Optionally implement `update()`
105
+ 4. Register in `factory/index.ts` (`createStrategy` method)
106
+
107
+ ## Applied Design Principles
108
+
109
+ 1. **Single Responsibility**: Each class has a single responsibility
110
+ 2. **Open/Closed**: Open for extension, closed for modification
111
+ 3. **Liskov Substitution**: Providers and strategies are interchangeable
112
+ 4. **Interface Segregation**: Specific and cohesive interfaces
113
+ 5. **Dependency Inversion**: Dependencies on abstractions, not implementations
114
+
115
+ ## Compatibility
116
+
117
+ - **Node.js**: >= 18.0.0 (uses native ReadableStream)
118
+ - **TypeScript**: 5.3+
119
+ - **ES Modules**: Required
120
+
121
+ ## Performance Considerations
122
+
123
+ - Health checks can run in parallel
124
+ - Automatic fallback avoids unnecessary waits
125
+ - Native streaming for long responses
126
+ - Strategies can cache metrics for better performance
@@ -0,0 +1,30 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] - 2025-12-05
9
+
10
+ ### Added
11
+ - Complete AI orchestration framework
12
+ - Support for multiple providers: Groq, OpenRouter, Gemini, Cerebras, Local
13
+ - 5 selection strategies: Round-Robin, Priority, Fallback, Weighted, Health-Aware
14
+ - Native streaming with ReadableStream
15
+ - Automatic health checks with latency metrics
16
+ - Factory for declarative creation
17
+ - Custom error handling
18
+ - Configuration validation
19
+ - Complete documentation (README, ARCHITECTURE, CONTRIBUTING)
20
+ - Usage examples
21
+ - Basic tests
22
+ - Node.js compatibility
23
+
24
+ ### Main Features
25
+ - Plugin-based architecture (extensible without modifying core)
26
+ - Declarative and programmatic API
27
+ - Type-safe with TypeScript
28
+ - Automatic fallback between providers
29
+ - Support for cost-aware selection
30
+ - Health-aware selection with real-time metrics
@@ -0,0 +1,198 @@
1
+ # Contributing Guide
2
+
3
+ ## Project Structure
4
+
5
+ ```
6
+ src/
7
+ ├── core/ # Framework core (interfaces, types, orchestrator)
8
+ ├── providers/ # Provider implementations
9
+ ├── strategies/ # Selection strategies
10
+ ├── factory/ # Factory for declarative creation
11
+ └── index.ts # Main entry point
12
+ ```
13
+
14
+ ## Adding a New Provider
15
+
16
+ 1. **Create the provider file** in `src/providers/`:
17
+
18
+ ```typescript
19
+ import { BaseProvider } from './base.js';
20
+ import type {
21
+ ChatMessage,
22
+ ChatOptions,
23
+ ChatResponse,
24
+ ChatChunk,
25
+ ProviderHealth,
26
+ ProviderMetadata,
27
+ } from '../core/types.js';
28
+
29
+ export interface CustomProviderConfig {
30
+ id: string;
31
+ apiKey: string;
32
+ // ... other provider-specific fields
33
+ }
34
+
35
+ export class CustomProvider extends BaseProvider {
36
+ readonly id: string;
37
+ readonly metadata: ProviderMetadata;
38
+
39
+ constructor(config: CustomProviderConfig) {
40
+ super();
41
+ // Initialization
42
+ }
43
+
44
+ async checkHealth(): Promise<ProviderHealth> {
45
+ // Implement health check
46
+ }
47
+
48
+ async chat(messages: ChatMessage[], options?: ChatOptions): Promise<ChatResponse> {
49
+ // Implement chat
50
+ }
51
+
52
+ async chatStream(messages: ChatMessage[], options?: ChatOptions): Promise<ReadableStream<ChatChunk>> {
53
+ // Implement streaming
54
+ }
55
+
56
+ protected formatMessages(messages: ChatMessage[]): unknown {
57
+ // Convert standard format to provider format
58
+ }
59
+
60
+ protected parseResponse(response: unknown): ChatResponse {
61
+ // Convert response to standard format
62
+ }
63
+
64
+ protected parseStream(stream: ReadableStream<unknown>): ReadableStream<ChatChunk> {
65
+ // Convert stream to standard format
66
+ }
67
+ }
68
+ ```
69
+
70
+ 2. **Export in `src/providers/index.ts`**:
71
+
72
+ ```typescript
73
+ export { CustomProvider } from './custom.js';
74
+ export type { CustomProviderConfig } from './custom.js';
75
+ ```
76
+
77
+ 3. **Register in `src/factory/index.ts`**:
78
+
79
+ ```typescript
80
+ import { CustomProvider, type CustomProviderConfig } from '../providers/index.js';
81
+
82
+ // In the createProvider function:
83
+ case 'custom':
84
+ return new CustomProvider({
85
+ id,
86
+ ...(rest as CustomProviderConfig),
87
+ } as CustomProviderConfig);
88
+ ```
89
+
90
+ ## Adding a New Strategy
91
+
92
+ 1. **Create the strategy file** in `src/strategies/`:
93
+
94
+ ```typescript
95
+ import { BaseStrategy } from './base.js';
96
+ import type { AIService, SelectionContext } from '../core/interfaces.js';
97
+
98
+ export interface CustomStrategyConfig {
99
+ // Strategy-specific configuration
100
+ }
101
+
102
+ export class CustomStrategy extends BaseStrategy {
103
+ constructor(config?: CustomStrategyConfig) {
104
+ super();
105
+ // Initialization
106
+ }
107
+
108
+ async select(
109
+ providers: AIService[],
110
+ context?: SelectionContext
111
+ ): Promise<AIService | null> {
112
+ // Implement selection logic
113
+ }
114
+
115
+ update?(provider: AIService, success: boolean, metadata?: unknown): void {
116
+ // Optional: update internal state
117
+ }
118
+ }
119
+ ```
120
+
121
+ 2. **Export in `src/strategies/index.ts`**
122
+
123
+ 3. **Register in `src/factory/index.ts`**
124
+
125
+ ## Code Conventions
126
+
127
+ - **Strict TypeScript**: Use explicit types
128
+ - **Descriptive names**: Variables and functions with clear names
129
+ - **Documentation**: JSDoc for public functions
130
+ - **Error handling**: Use custom error classes
131
+ - **Tests**: Add tests for new functionality
132
+
133
+ ## Testing
134
+
135
+ Tests are in `tests/`. Use Node.js test runner:
136
+
137
+ ```bash
138
+ npm test
139
+ ```
140
+
141
+ For local testing with mock providers:
142
+
143
+ ```bash
144
+ npm run test:mock
145
+ ```
146
+
147
+ For testing with real providers:
148
+
149
+ ```bash
150
+ npm run test:local
151
+ ```
152
+
153
+ ## Versioning
154
+
155
+ Follow [Semantic Versioning](https://semver.org/):
156
+ - **MAJOR**: Incompatible API changes
157
+ - **MINOR**: New backward-compatible functionality
158
+ - **PATCH**: Backward-compatible bug fixes
159
+
160
+ ## Pull Requests
161
+
162
+ 1. Create a branch from `main`
163
+ 2. Implement changes
164
+ 3. Add tests
165
+ 4. Update documentation if necessary
166
+ 5. Ensure all tests pass
167
+ 6. Create PR with clear description
168
+
169
+ ## Development Setup
170
+
171
+ 1. **Clone the repository**
172
+ 2. **Install dependencies**:
173
+ ```bash
174
+ npm install
175
+ ```
176
+ 3. **Build the project**:
177
+ ```bash
178
+ npm run build
179
+ ```
180
+ 4. **Run tests**:
181
+ ```bash
182
+ npm test
183
+ ```
184
+
185
+ ## Code Style
186
+
187
+ - Use TypeScript strict mode
188
+ - Follow existing code style
189
+ - Use meaningful variable and function names
190
+ - Add comments for complex logic
191
+ - Keep functions focused and small
192
+
193
+ ## Commit Messages
194
+
195
+ Use clear, descriptive commit messages:
196
+ - Use imperative mood ("Add feature" not "Added feature")
197
+ - Reference issues when applicable
198
+ - Keep messages concise but informative
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Basic usage example
3
+ */
4
+
5
+ import { createOrchestrator } from '../src/index.js';
6
+
7
+ async function main() {
8
+ // Create orchestrator with declarative config
9
+ const orchestrator = createOrchestrator({
10
+ providers: [
11
+ {
12
+ id: 'groq-1',
13
+ type: 'groq',
14
+ apiKey: process.env.GROQ_API_KEY || '',
15
+ model: 'llama-3.3-70b-versatile', // Updated: llama-3.1-70b-versatile was decommissioned
16
+ },
17
+ {
18
+ id: 'openrouter-1',
19
+ type: 'openrouter',
20
+ apiKey: process.env.OPENROUTER_API_KEY || '',
21
+ model: 'openai/gpt-3.5-turbo',
22
+ },
23
+ ],
24
+ strategy: {
25
+ type: 'round-robin',
26
+ },
27
+ enableHealthChecks: true,
28
+ healthCheckInterval: 60000, // 60 seconds
29
+ });
30
+
31
+ // Simple chat
32
+ console.log('=== Simple Chat ===');
33
+ const response = await orchestrator.chat([
34
+ { role: 'user', content: 'Say hello in one sentence' },
35
+ ]);
36
+ console.log('Response:', response.content);
37
+ console.log('Usage:', response.usage);
38
+
39
+ // Streaming chat
40
+ console.log('\n=== Streaming Chat ===');
41
+ const stream = await orchestrator.chatStream([
42
+ { role: 'user', content: 'Count from 1 to 5' },
43
+ ]);
44
+
45
+ const reader = stream.getReader();
46
+ while (true) {
47
+ const { done, value } = await reader.read();
48
+ if (done) break;
49
+ process.stdout.write(value.content);
50
+ }
51
+ console.log('\n');
52
+
53
+ // Cleanup
54
+ orchestrator.dispose();
55
+ }
56
+
57
+ main().catch(console.error);
58
+
@@ -0,0 +1,146 @@
1
+ # Chat App Example
2
+
3
+ A simple chat application to test `@ai-orchestration/core` using npm link.
4
+
5
+ ## Quick Setup
6
+
7
+ ### 1. Link the Package
8
+
9
+ ```bash
10
+ # In the ia-orchestration directory (from project root)
11
+ cd /path/to/ia-orchestration
12
+ npm run link
13
+ ```
14
+
15
+ ### 2. Setup This Project
16
+
17
+ ```bash
18
+ # In this directory
19
+ cd examples/chat-app
20
+ npm install
21
+ npm link @ai-orchestration/core
22
+ ```
23
+
24
+ ### 3. Configure Environment Variables
25
+
26
+ Create a `.env` file from the example:
27
+
28
+ ```bash
29
+ # Copy the example file
30
+ cp .env.example .env
31
+
32
+ # Edit .env with your real API keys
33
+ # GROQ_API_KEY=your-real-key-here
34
+ # OPENROUTER_API_KEY=your-real-key-here
35
+ # GEMINI_API_KEY=your-real-key-here
36
+ # CEREBRAS_API_KEY=your-real-key-here
37
+ ```
38
+
39
+ **Important**: The `.env` file is in `.gitignore` and will not be committed to the repository.
40
+
41
+ **Note**: You only need to configure at least ONE API key for it to work.
42
+
43
+ ### 4. (Optional) Customize Configuration
44
+
45
+ You can edit `config.json` to:
46
+ - Change default models
47
+ - Change initial strategy
48
+ - Adjust chat options (temperature, maxTokens)
49
+ - Add or remove providers
50
+
51
+ ### 5. Run
52
+
53
+ ```bash
54
+ npm start
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ The application allows you to:
60
+ - Chat with multiple AI providers
61
+ - Change strategy at runtime
62
+ - See which provider is being used
63
+ - View usage statistics
64
+
65
+ ## Available Commands
66
+
67
+ - `/help` - Show help
68
+ - `/strategy <type>` - Change strategy (round-robin, priority, fallback)
69
+ - `/providers` - List available providers
70
+ - `/health` - Check provider health
71
+ - `/clear` - Clear conversation history
72
+ - `/exit` or `/quit` - Exit the application
73
+
74
+ ## Example Session
75
+
76
+ ```
77
+ 🚀 Chat App - Example with @ai-orchestration/core
78
+
79
+ 💡 Type /help to see available commands
80
+
81
+ 🔧 Creating orchestrator...
82
+ ✅ Orchestrator created with 2 provider(s)
83
+
84
+ 💬 You: Hello!
85
+ 🤔 Thinking...
86
+ ✅ Response (1234ms):
87
+
88
+ Hello! How can I help you today?
89
+
90
+ 💬 You: /providers
91
+ 📋 Available providers:
92
+ 1. groq-1 (Groq)
93
+ 2. openrouter-1 (OpenRouter)
94
+
95
+ 💬 You: /exit
96
+ 👋 Goodbye!
97
+ ```
98
+
99
+ ## Verification
100
+
101
+ To verify everything is configured correctly:
102
+
103
+ ```bash
104
+ # Verify that the link works
105
+ npm list @ai-orchestration/core
106
+
107
+ # Should show:
108
+ # chat-app-example@1.0.0
109
+ # └── @ai-orchestration/core@0.1.0 -> /path/to/ia-orchestration
110
+ ```
111
+
112
+ ## Troubleshooting
113
+
114
+ ### Error: "Cannot find module '@ai-orchestration/core'"
115
+
116
+ ```bash
117
+ # Verify link exists
118
+ npm list @ai-orchestration/core
119
+
120
+ # If it doesn't exist, re-link
121
+ npm link @ai-orchestration/core
122
+ ```
123
+
124
+ ### Error: "No providers configured"
125
+
126
+ - Verify that `.env` exists in `examples/chat-app/`
127
+ - Verify it has at least one API key configured
128
+ - Verify there are no spaces around `=` in `.env`
129
+ - Verify values are not the example ones (`your-*-api-key-here`)
130
+
131
+ ### Error: "Module not found" or TypeScript errors
132
+
133
+ ```bash
134
+ # Reinstall dependencies
135
+ rm -rf node_modules package-lock.json
136
+ npm install
137
+ ```
138
+
139
+ ### Changes in package not reflected
140
+
141
+ ```bash
142
+ # In the ia-orchestration directory (root)
143
+ npm run build
144
+
145
+ # Changes should be reflected automatically
146
+ ```
@@ -0,0 +1,34 @@
1
+ {
2
+ "providers": [
3
+ {
4
+ "id": "groq-1",
5
+ "type": "groq",
6
+ "envKey": "GROQ_API_KEY",
7
+ "model": "llama-3.3-70b-versatile"
8
+ },
9
+ {
10
+ "id": "openrouter-1",
11
+ "type": "openrouter",
12
+ "envKey": "OPENROUTER_API_KEY",
13
+ "model": "openai/gpt-3.5-turbo"
14
+ },
15
+ {
16
+ "id": "gemini-1",
17
+ "type": "gemini",
18
+ "envKey": "GEMINI_API_KEY",
19
+ "model": "gemini-pro"
20
+ },
21
+ {
22
+ "id": "cerebras-1",
23
+ "type": "cerebras",
24
+ "envKey": "CEREBRAS_API_KEY",
25
+ "model": "llama-3.3-70b"
26
+ }
27
+ ],
28
+ "defaultStrategy": "round-robin",
29
+ "chatOptions": {
30
+ "temperature": 0.7,
31
+ "maxTokens": 1000
32
+ }
33
+ }
34
+