@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,172 @@
1
+ /**
2
+ * OpenRouter provider implementation
3
+ */
4
+ import { BaseProvider } from './base.js';
5
+ export class OpenRouterProvider extends BaseProvider {
6
+ id;
7
+ metadata;
8
+ apiKey;
9
+ model;
10
+ baseURL;
11
+ constructor(config) {
12
+ super();
13
+ this.id = config.id;
14
+ this.apiKey = config.apiKey;
15
+ this.model = config.model || 'openai/gpt-3.5-turbo';
16
+ this.baseURL = config.baseURL || 'https://openrouter.ai/api/v1';
17
+ this.metadata = {
18
+ id: this.id,
19
+ name: 'OpenRouter',
20
+ model: this.model,
21
+ };
22
+ }
23
+ async checkHealth() {
24
+ return this.defaultHealthCheck();
25
+ }
26
+ async chat(messages, options) {
27
+ const response = await fetch(`${this.baseURL}/chat/completions`, {
28
+ method: 'POST',
29
+ headers: {
30
+ 'Content-Type': 'application/json',
31
+ Authorization: `Bearer ${this.apiKey}`,
32
+ 'HTTP-Referer': 'https://github.com/ia-orchestration/core',
33
+ 'X-Title': 'AI Orchestration Framework',
34
+ },
35
+ body: JSON.stringify({
36
+ model: this.model,
37
+ messages: this.formatMessages(messages),
38
+ temperature: options?.temperature,
39
+ max_tokens: options?.maxTokens,
40
+ top_p: options?.topP,
41
+ stop: options?.stopSequences,
42
+ ...options,
43
+ }),
44
+ });
45
+ if (!response.ok) {
46
+ const error = await response.text();
47
+ throw new Error(`OpenRouter API error: ${response.status} ${error}`);
48
+ }
49
+ const data = await response.json();
50
+ return this.parseResponse(data);
51
+ }
52
+ async chatStream(messages, options) {
53
+ const response = await fetch(`${this.baseURL}/chat/completions`, {
54
+ method: 'POST',
55
+ headers: {
56
+ 'Content-Type': 'application/json',
57
+ Authorization: `Bearer ${this.apiKey}`,
58
+ 'HTTP-Referer': 'https://github.com/ia-orchestration/core',
59
+ 'X-Title': 'AI Orchestration Framework',
60
+ },
61
+ body: JSON.stringify({
62
+ model: this.model,
63
+ messages: this.formatMessages(messages),
64
+ stream: true,
65
+ temperature: options?.temperature,
66
+ max_tokens: options?.maxTokens,
67
+ top_p: options?.topP,
68
+ stop: options?.stopSequences,
69
+ ...options,
70
+ }),
71
+ });
72
+ if (!response.ok) {
73
+ const error = await response.text();
74
+ throw new Error(`OpenRouter API error: ${response.status} ${error}`);
75
+ }
76
+ if (!response.body) {
77
+ throw new Error('No response body');
78
+ }
79
+ return this.parseStream(response.body);
80
+ }
81
+ formatMessages(messages) {
82
+ return messages.map((msg) => ({
83
+ role: msg.role,
84
+ content: msg.content,
85
+ }));
86
+ }
87
+ parseResponse(response) {
88
+ const data = response;
89
+ const choice = data.choices?.[0];
90
+ if (!choice?.message?.content) {
91
+ throw new Error('Invalid response format from OpenRouter');
92
+ }
93
+ return {
94
+ content: choice.message.content,
95
+ usage: data.usage
96
+ ? {
97
+ promptTokens: data.usage.prompt_tokens ?? 0,
98
+ completionTokens: data.usage.completion_tokens ?? 0,
99
+ totalTokens: data.usage.total_tokens ?? 0,
100
+ }
101
+ : undefined,
102
+ model: data.model,
103
+ finishReason: choice.finish_reason,
104
+ };
105
+ }
106
+ parseStream(stream) {
107
+ const reader = stream.getReader();
108
+ const decoder = new TextDecoder();
109
+ return new ReadableStream({
110
+ async start(controller) {
111
+ try {
112
+ while (true) {
113
+ const { done, value } = await reader.read();
114
+ if (done) {
115
+ controller.close();
116
+ break;
117
+ }
118
+ const chunk = decoder.decode(value);
119
+ const lines = chunk.split('\n').filter((line) => line.trim());
120
+ for (const line of lines) {
121
+ if (line.startsWith('data: ')) {
122
+ const data = line.slice(6);
123
+ if (data === '[DONE]') {
124
+ controller.close();
125
+ return;
126
+ }
127
+ try {
128
+ const parsed = JSON.parse(data);
129
+ const choice = parsed.choices?.[0];
130
+ const delta = choice?.delta;
131
+ if (delta?.content) {
132
+ controller.enqueue({
133
+ content: delta.content,
134
+ done: false,
135
+ finishReason: choice?.finish_reason,
136
+ });
137
+ }
138
+ if (choice?.finish_reason) {
139
+ controller.enqueue({
140
+ content: '',
141
+ done: true,
142
+ finishReason: choice.finish_reason,
143
+ usage: parsed.usage
144
+ ? {
145
+ promptTokens: parsed.usage.prompt_tokens,
146
+ completionTokens: parsed.usage.completion_tokens,
147
+ totalTokens: parsed.usage.total_tokens,
148
+ }
149
+ : undefined,
150
+ });
151
+ controller.close();
152
+ return;
153
+ }
154
+ }
155
+ catch {
156
+ // Skip invalid JSON
157
+ }
158
+ }
159
+ }
160
+ }
161
+ }
162
+ catch (error) {
163
+ controller.error(error);
164
+ }
165
+ finally {
166
+ reader.releaseLock();
167
+ }
168
+ },
169
+ });
170
+ }
171
+ }
172
+ //# sourceMappingURL=openrouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../src/providers/openrouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Base strategy implementations
3
+ */
4
+ import type { AIService, SelectionStrategy, SelectionContext } from '../core/interfaces.js';
5
+ /**
6
+ * Base class for strategies with common utilities
7
+ */
8
+ export declare abstract class BaseStrategy implements SelectionStrategy {
9
+ abstract select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
10
+ update?(_provider: AIService, _success: boolean, _metadata?: unknown): void;
11
+ /**
12
+ * Filter out providers that were already attempted
13
+ */
14
+ protected filterAttempted(providers: AIService[], context?: SelectionContext): AIService[];
15
+ }
16
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/strategies/base.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE5F;;GAEG;AACH,8BAAsB,YAAa,YAAW,iBAAiB;IAC7D,QAAQ,CAAC,MAAM,CACb,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAE5B,MAAM,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI;IAI3E;;OAEG;IACH,SAAS,CAAC,eAAe,CACvB,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,SAAS,EAAE;CASf"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Base strategy implementations
3
+ */
4
+ /**
5
+ * Base class for strategies with common utilities
6
+ */
7
+ export class BaseStrategy {
8
+ update(_provider, _success, _metadata) {
9
+ // Default: no-op
10
+ }
11
+ /**
12
+ * Filter out providers that were already attempted
13
+ */
14
+ filterAttempted(providers, context) {
15
+ if (!context?.previousAttempts || context.previousAttempts.length === 0) {
16
+ return providers;
17
+ }
18
+ return providers.filter((p) => !context.previousAttempts.includes(p.id));
19
+ }
20
+ }
21
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/strategies/base.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,OAAgB,YAAY;IAMhC,MAAM,CAAE,SAAoB,EAAE,QAAiB,EAAE,SAAmB;QAClE,iBAAiB;IACnB,CAAC;IAED;;OAEG;IACO,eAAe,CACvB,SAAsB,EACtB,OAA0B;QAE1B,IAAI,CAAC,OAAO,EAAE,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxE,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,OAAO,SAAS,CAAC,MAAM,CACrB,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,gBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CACjD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Fallback strategy: tries providers in order until one succeeds
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ import type { AIService, SelectionContext } from '../core/interfaces.js';
6
+ export interface FallbackStrategyConfig {
7
+ order?: string[];
8
+ }
9
+ export declare class FallbackStrategy extends BaseStrategy {
10
+ private order;
11
+ constructor(config?: FallbackStrategyConfig);
12
+ select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
13
+ }
14
+ //# sourceMappingURL=fallback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.d.ts","sourceRoot":"","sources":["../../src/strategies/fallback.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,KAAK,CAAW;gBAEZ,MAAM,CAAC,EAAE,sBAAsB;IAKrC,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAmB7B"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Fallback strategy: tries providers in order until one succeeds
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ export class FallbackStrategy extends BaseStrategy {
6
+ order;
7
+ constructor(config) {
8
+ super();
9
+ this.order = config?.order ?? [];
10
+ }
11
+ async select(providers, context) {
12
+ const available = this.filterAttempted(providers, context);
13
+ if (available.length === 0) {
14
+ return null;
15
+ }
16
+ // If order is specified, use it
17
+ if (this.order.length > 0) {
18
+ for (const id of this.order) {
19
+ const provider = available.find((p) => p.id === id);
20
+ if (provider) {
21
+ return provider;
22
+ }
23
+ }
24
+ }
25
+ // Otherwise, return first available
26
+ return available[0];
27
+ }
28
+ }
29
+ //# sourceMappingURL=fallback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback.js","sourceRoot":"","sources":["../../src/strategies/fallback.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAOzC,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IACxC,KAAK,CAAW;IAExB,YAAY,MAA+B;QACzC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;IACnC,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,gCAAgC;QAChC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;gBACpD,IAAI,QAAQ,EAAE,CAAC;oBACb,OAAO,QAAQ,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Health-aware strategy: selects providers based on health metrics (latency, success rate)
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ import type { AIService, SelectionContext } from '../core/interfaces.js';
6
+ export interface HealthAwareStrategyConfig {
7
+ preferLowLatency?: boolean;
8
+ minHealthScore?: number;
9
+ }
10
+ export declare class HealthAwareStrategy extends BaseStrategy {
11
+ private stats;
12
+ private preferLowLatency;
13
+ private minHealthScore;
14
+ constructor(config?: HealthAwareStrategyConfig);
15
+ select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
16
+ update(provider: AIService, success: boolean, metadata?: unknown): void;
17
+ private getOrCreateStats;
18
+ private calculateHealthScore;
19
+ }
20
+ //# sourceMappingURL=health-aware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-aware.d.ts","sourceRoot":"","sources":["../../src/strategies/health-aware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAG/B,MAAM,WAAW,yBAAyB;IACxC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAUD,qBAAa,mBAAoB,SAAQ,YAAY;IACnD,OAAO,CAAC,KAAK,CAAyC;IACtD,OAAO,CAAC,gBAAgB,CAAU;IAClC,OAAO,CAAC,cAAc,CAAS;gBAEnB,MAAM,CAAC,EAAE,yBAAyB;IAMxC,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAyD5B,MAAM,CAAC,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,IAAI;IAoBvE,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,oBAAoB;CAiB7B"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Health-aware strategy: selects providers based on health metrics (latency, success rate)
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ export class HealthAwareStrategy extends BaseStrategy {
6
+ stats = new Map();
7
+ preferLowLatency;
8
+ minHealthScore;
9
+ constructor(config) {
10
+ super();
11
+ this.preferLowLatency = config?.preferLowLatency ?? true;
12
+ this.minHealthScore = config?.minHealthScore ?? 0;
13
+ }
14
+ async select(providers, context) {
15
+ const available = this.filterAttempted(providers, context);
16
+ if (available.length === 0) {
17
+ return null;
18
+ }
19
+ // Fetch health for all providers
20
+ const healthChecks = await Promise.allSettled(available.map(async (p) => {
21
+ const health = await p.checkHealth();
22
+ return { provider: p, health };
23
+ }));
24
+ // Build stats with health information
25
+ const candidates = [];
26
+ for (const result of healthChecks) {
27
+ if (result.status === 'fulfilled') {
28
+ const { provider, health } = result.value;
29
+ if (!health.healthy)
30
+ continue;
31
+ const stats = this.getOrCreateStats(provider);
32
+ stats.health = health;
33
+ const healthScore = this.calculateHealthScore(stats);
34
+ if (healthScore >= this.minHealthScore) {
35
+ candidates.push(stats);
36
+ }
37
+ }
38
+ }
39
+ if (candidates.length === 0) {
40
+ return null;
41
+ }
42
+ // Sort by health score (and latency if preferred)
43
+ candidates.sort((a, b) => {
44
+ const scoreA = this.calculateHealthScore(a);
45
+ const scoreB = this.calculateHealthScore(b);
46
+ if (scoreA !== scoreB) {
47
+ return scoreB - scoreA; // Higher score first
48
+ }
49
+ // If scores are equal and prefer low latency, sort by latency
50
+ if (this.preferLowLatency) {
51
+ const latencyA = a.health.latency ?? Infinity;
52
+ const latencyB = b.health.latency ?? Infinity;
53
+ return latencyA - latencyB;
54
+ }
55
+ return 0;
56
+ });
57
+ return candidates[0].provider;
58
+ }
59
+ update(provider, success, metadata) {
60
+ const stats = this.getOrCreateStats(provider);
61
+ if (success) {
62
+ stats.successCount++;
63
+ // Update latency if available
64
+ if (metadata && typeof metadata === 'object' && 'latency' in metadata) {
65
+ const latency = Number(metadata.latency);
66
+ if (!isNaN(latency)) {
67
+ stats.avgLatency =
68
+ stats.avgLatency === undefined
69
+ ? latency
70
+ : (stats.avgLatency + latency) / 2;
71
+ }
72
+ }
73
+ }
74
+ else {
75
+ stats.failureCount++;
76
+ }
77
+ }
78
+ getOrCreateStats(provider) {
79
+ let stats = this.stats.get(provider.id);
80
+ if (!stats) {
81
+ stats = {
82
+ provider,
83
+ health: { healthy: true },
84
+ successCount: 0,
85
+ failureCount: 0,
86
+ };
87
+ this.stats.set(provider.id, stats);
88
+ }
89
+ return stats;
90
+ }
91
+ calculateHealthScore(stats) {
92
+ const total = stats.successCount + stats.failureCount;
93
+ if (total === 0) {
94
+ return 1.0; // No data, assume healthy
95
+ }
96
+ const successRate = stats.successCount / total;
97
+ // Factor in latency if available
98
+ let latencyFactor = 1.0;
99
+ if (stats.avgLatency !== undefined) {
100
+ // Normalize latency (assume < 1000ms is good, > 5000ms is bad)
101
+ latencyFactor = Math.max(0, 1 - (stats.avgLatency - 1000) / 4000);
102
+ }
103
+ return successRate * latencyFactor;
104
+ }
105
+ }
106
+ //# sourceMappingURL=health-aware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health-aware.js","sourceRoot":"","sources":["../../src/strategies/health-aware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Export all strategies
3
+ */
4
+ export { BaseStrategy } from './base.js';
5
+ export { RoundRobinStrategy } from './round-robin.js';
6
+ export { PriorityStrategy } from './priority.js';
7
+ export type { PriorityStrategyConfig } from './priority.js';
8
+ export { FallbackStrategy } from './fallback.js';
9
+ export type { FallbackStrategyConfig } from './fallback.js';
10
+ export { WeightedStrategy } from './weighted.js';
11
+ export type { WeightedStrategyConfig } from './weighted.js';
12
+ export { HealthAwareStrategy } from './health-aware.js';
13
+ export type { HealthAwareStrategyConfig } from './health-aware.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/strategies/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,YAAY,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Export all strategies
3
+ */
4
+ export { BaseStrategy } from './base.js';
5
+ export { RoundRobinStrategy } from './round-robin.js';
6
+ export { PriorityStrategy } from './priority.js';
7
+ export { FallbackStrategy } from './fallback.js';
8
+ export { WeightedStrategy } from './weighted.js';
9
+ export { HealthAwareStrategy } from './health-aware.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/strategies/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Priority strategy: selects providers based on priority order
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ import type { AIService, SelectionContext } from '../core/interfaces.js';
6
+ export interface PriorityStrategyConfig {
7
+ priorities?: Record<string, number>;
8
+ }
9
+ export declare class PriorityStrategy extends BaseStrategy {
10
+ private priorities;
11
+ constructor(config?: PriorityStrategyConfig);
12
+ select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
13
+ /**
14
+ * Set priority for a provider
15
+ */
16
+ setPriority(providerId: string, priority: number): void;
17
+ }
18
+ //# sourceMappingURL=priority.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority.d.ts","sourceRoot":"","sources":["../../src/strategies/priority.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,UAAU,CAAkC;gBAExC,MAAM,CAAC,EAAE,sBAAsB;IASrC,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAgB5B;;OAEG;IACH,WAAW,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;CAGxD"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Priority strategy: selects providers based on priority order
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ export class PriorityStrategy extends BaseStrategy {
6
+ priorities = new Map();
7
+ constructor(config) {
8
+ super();
9
+ if (config?.priorities) {
10
+ Object.entries(config.priorities).forEach(([id, priority]) => {
11
+ this.priorities.set(id, priority);
12
+ });
13
+ }
14
+ }
15
+ async select(providers, context) {
16
+ const available = this.filterAttempted(providers, context);
17
+ if (available.length === 0) {
18
+ return null;
19
+ }
20
+ // Sort by priority (lower number = higher priority)
21
+ const sorted = [...available].sort((a, b) => {
22
+ const priorityA = this.priorities.get(a.id) ?? 999;
23
+ const priorityB = this.priorities.get(b.id) ?? 999;
24
+ return priorityA - priorityB;
25
+ });
26
+ return sorted[0];
27
+ }
28
+ /**
29
+ * Set priority for a provider
30
+ */
31
+ setPriority(providerId, priority) {
32
+ this.priorities.set(providerId, priority);
33
+ }
34
+ }
35
+ //# sourceMappingURL=priority.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"priority.js","sourceRoot":"","sources":["../../src/strategies/priority.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAOzC,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IACxC,UAAU,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEpD,YAAY,MAA+B;QACzC,KAAK,EAAE,CAAC;QACR,IAAI,MAAM,EAAE,UAAU,EAAE,CAAC;YACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE;gBAC3D,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;YACpC,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,oDAAoD;QACpD,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC;YACnD,OAAO,SAAS,GAAG,SAAS,CAAC;QAC/B,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,UAAkB,EAAE,QAAgB;QAC9C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Round-robin strategy: cycles through providers in order
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ import type { AIService, SelectionContext } from '../core/interfaces.js';
6
+ export declare class RoundRobinStrategy extends BaseStrategy {
7
+ private currentIndex;
8
+ select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
9
+ }
10
+ //# sourceMappingURL=round-robin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round-robin.d.ts","sourceRoot":"","sources":["../../src/strategies/round-robin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,qBAAa,kBAAmB,SAAQ,YAAY;IAClD,OAAO,CAAC,YAAY,CAAK;IAEnB,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;CAgB7B"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Round-robin strategy: cycles through providers in order
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ export class RoundRobinStrategy extends BaseStrategy {
6
+ currentIndex = 0;
7
+ async select(providers, context) {
8
+ const available = this.filterAttempted(providers, context);
9
+ if (available.length === 0) {
10
+ return null;
11
+ }
12
+ // Reset index if it's out of bounds
13
+ if (this.currentIndex >= available.length) {
14
+ this.currentIndex = 0;
15
+ }
16
+ const selected = available[this.currentIndex];
17
+ this.currentIndex = (this.currentIndex + 1) % available.length;
18
+ return selected;
19
+ }
20
+ }
21
+ //# sourceMappingURL=round-robin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round-robin.js","sourceRoot":"","sources":["../../src/strategies/round-robin.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAGzC,MAAM,OAAO,kBAAmB,SAAQ,YAAY;IAC1C,YAAY,GAAG,CAAC,CAAC;IAEzB,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,oCAAoC;QACpC,IAAI,IAAI,CAAC,YAAY,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;QACxB,CAAC;QAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9C,IAAI,CAAC,YAAY,GAAG,CAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC;QAE/D,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Weighted strategy: selects providers based on weights (for load balancing or cost-aware selection)
3
+ */
4
+ import { BaseStrategy } from './base.js';
5
+ import type { AIService, SelectionContext } from '../core/interfaces.js';
6
+ export interface WeightedStrategyConfig {
7
+ weights?: Record<string, number>;
8
+ costAware?: boolean;
9
+ }
10
+ export declare class WeightedStrategy extends BaseStrategy {
11
+ private weights;
12
+ private costAware;
13
+ constructor(config?: WeightedStrategyConfig);
14
+ select(providers: AIService[], context?: SelectionContext): Promise<AIService | null>;
15
+ /**
16
+ * Set weight for a provider
17
+ */
18
+ setWeight(providerId: string, weight: number): void;
19
+ }
20
+ //# sourceMappingURL=weighted.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"weighted.d.ts","sourceRoot":"","sources":["../../src/strategies/weighted.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzE,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,OAAO,CAAC,OAAO,CAAkC;IACjD,OAAO,CAAC,SAAS,CAAU;gBAEf,MAAM,CAAC,EAAE,sBAAsB;IAWrC,MAAM,CACV,SAAS,EAAE,SAAS,EAAE,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA8C5B;;OAEG;IACH,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI;CAGpD"}