@sparkleideas/providers 3.5.2-patch.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +574 -0
- package/package.json +70 -0
- package/src/__tests__/provider-integration.test.ts +446 -0
- package/src/__tests__/quick-test.ts +356 -0
- package/src/anthropic-provider.ts +435 -0
- package/src/base-provider.ts +596 -0
- package/src/cohere-provider.ts +423 -0
- package/src/google-provider.ts +429 -0
- package/src/index.ts +40 -0
- package/src/ollama-provider.ts +408 -0
- package/src/openai-provider.ts +490 -0
- package/src/provider-manager.ts +538 -0
- package/src/ruvector-provider.ts +721 -0
- package/src/types.ts +435 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* V3 LLM Provider Types
|
|
3
|
+
*
|
|
4
|
+
* Unified type system for all LLM providers with enhanced
|
|
5
|
+
* cost tracking, model capabilities, and error handling.
|
|
6
|
+
*
|
|
7
|
+
* @module @sparkleideas/providers/types
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { EventEmitter } from 'events';
|
|
11
|
+
|
|
12
|
+
// ===== PROVIDER TYPES =====
|
|
13
|
+
|
|
14
|
+
export type LLMProvider =
|
|
15
|
+
| 'anthropic'
|
|
16
|
+
| 'openai'
|
|
17
|
+
| 'google'
|
|
18
|
+
| 'cohere'
|
|
19
|
+
| 'ollama'
|
|
20
|
+
| 'ruvector'
|
|
21
|
+
| 'openrouter'
|
|
22
|
+
| 'litellm'
|
|
23
|
+
| 'custom';
|
|
24
|
+
|
|
25
|
+
export type LLMModel =
|
|
26
|
+
// Anthropic Models (2024-2025)
|
|
27
|
+
| 'claude-3-5-sonnet-20241022'
|
|
28
|
+
| 'claude-3-5-sonnet-latest'
|
|
29
|
+
| 'claude-3-opus-20240229'
|
|
30
|
+
| 'claude-3-sonnet-20240229'
|
|
31
|
+
| 'claude-3-haiku-20240307'
|
|
32
|
+
// OpenAI Models (2024-2025)
|
|
33
|
+
| 'gpt-4o'
|
|
34
|
+
| 'gpt-4o-mini'
|
|
35
|
+
| 'gpt-4-turbo'
|
|
36
|
+
| 'gpt-4'
|
|
37
|
+
| 'gpt-3.5-turbo'
|
|
38
|
+
| 'o1-preview'
|
|
39
|
+
| 'o1-mini'
|
|
40
|
+
| 'o3-mini'
|
|
41
|
+
// Google Models
|
|
42
|
+
| 'gemini-2.0-flash'
|
|
43
|
+
| 'gemini-1.5-pro'
|
|
44
|
+
| 'gemini-1.5-flash'
|
|
45
|
+
| 'gemini-pro'
|
|
46
|
+
// Cohere Models
|
|
47
|
+
| 'command-r-plus'
|
|
48
|
+
| 'command-r'
|
|
49
|
+
| 'command-light'
|
|
50
|
+
| 'command'
|
|
51
|
+
// Ollama (Local) Models
|
|
52
|
+
| 'llama3.2'
|
|
53
|
+
| 'llama3.1'
|
|
54
|
+
| 'mistral'
|
|
55
|
+
| 'mixtral'
|
|
56
|
+
| 'codellama'
|
|
57
|
+
| 'phi-4'
|
|
58
|
+
| 'deepseek-coder'
|
|
59
|
+
// Generic
|
|
60
|
+
| 'custom-model'
|
|
61
|
+
| string;
|
|
62
|
+
|
|
63
|
+
// ===== MESSAGE TYPES =====
|
|
64
|
+
|
|
65
|
+
export interface LLMMessage {
|
|
66
|
+
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
67
|
+
content: string | LLMContentPart[];
|
|
68
|
+
name?: string;
|
|
69
|
+
toolCallId?: string;
|
|
70
|
+
toolCalls?: LLMToolCall[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface LLMContentPart {
|
|
74
|
+
type: 'text' | 'image' | 'audio';
|
|
75
|
+
text?: string;
|
|
76
|
+
imageUrl?: string;
|
|
77
|
+
imageBase64?: string;
|
|
78
|
+
audioUrl?: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface LLMToolCall {
|
|
82
|
+
id: string;
|
|
83
|
+
type: 'function';
|
|
84
|
+
function: {
|
|
85
|
+
name: string;
|
|
86
|
+
arguments: string;
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface LLMTool {
|
|
91
|
+
type: 'function';
|
|
92
|
+
function: {
|
|
93
|
+
name: string;
|
|
94
|
+
description: string;
|
|
95
|
+
parameters: {
|
|
96
|
+
type: 'object';
|
|
97
|
+
properties: Record<string, unknown>;
|
|
98
|
+
required?: string[];
|
|
99
|
+
};
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ===== REQUEST/RESPONSE =====
|
|
104
|
+
|
|
105
|
+
export interface LLMProviderConfig {
|
|
106
|
+
provider: LLMProvider;
|
|
107
|
+
apiKey?: string;
|
|
108
|
+
apiUrl?: string;
|
|
109
|
+
model: LLMModel;
|
|
110
|
+
|
|
111
|
+
// Generation parameters
|
|
112
|
+
temperature?: number;
|
|
113
|
+
maxTokens?: number;
|
|
114
|
+
topP?: number;
|
|
115
|
+
topK?: number;
|
|
116
|
+
frequencyPenalty?: number;
|
|
117
|
+
presencePenalty?: number;
|
|
118
|
+
stopSequences?: string[];
|
|
119
|
+
|
|
120
|
+
// Provider-specific options
|
|
121
|
+
providerOptions?: Record<string, unknown>;
|
|
122
|
+
|
|
123
|
+
// Performance settings
|
|
124
|
+
timeout?: number;
|
|
125
|
+
retryAttempts?: number;
|
|
126
|
+
retryDelay?: number;
|
|
127
|
+
|
|
128
|
+
// Features
|
|
129
|
+
enableStreaming?: boolean;
|
|
130
|
+
enableCaching?: boolean;
|
|
131
|
+
cacheTimeout?: number;
|
|
132
|
+
|
|
133
|
+
// Cost optimization
|
|
134
|
+
enableCostOptimization?: boolean;
|
|
135
|
+
maxCostPerRequest?: number;
|
|
136
|
+
fallbackModels?: LLMModel[];
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface LLMRequest {
|
|
140
|
+
messages: LLMMessage[];
|
|
141
|
+
model?: LLMModel;
|
|
142
|
+
temperature?: number;
|
|
143
|
+
maxTokens?: number;
|
|
144
|
+
topP?: number;
|
|
145
|
+
topK?: number;
|
|
146
|
+
frequencyPenalty?: number;
|
|
147
|
+
presencePenalty?: number;
|
|
148
|
+
stopSequences?: string[];
|
|
149
|
+
stream?: boolean;
|
|
150
|
+
|
|
151
|
+
// Tool calling
|
|
152
|
+
tools?: LLMTool[];
|
|
153
|
+
toolChoice?: 'auto' | 'none' | 'required' | { type: 'function'; function: { name: string } };
|
|
154
|
+
|
|
155
|
+
// Provider-specific options
|
|
156
|
+
providerOptions?: Record<string, unknown>;
|
|
157
|
+
|
|
158
|
+
// Cost constraints
|
|
159
|
+
costConstraints?: {
|
|
160
|
+
maxCost?: number;
|
|
161
|
+
preferredModels?: LLMModel[];
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Request metadata
|
|
165
|
+
requestId?: string;
|
|
166
|
+
metadata?: Record<string, unknown>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export interface LLMResponse {
|
|
170
|
+
id: string;
|
|
171
|
+
model: LLMModel;
|
|
172
|
+
provider: LLMProvider;
|
|
173
|
+
|
|
174
|
+
// Content
|
|
175
|
+
content: string;
|
|
176
|
+
toolCalls?: LLMToolCall[];
|
|
177
|
+
|
|
178
|
+
// Usage
|
|
179
|
+
usage: {
|
|
180
|
+
promptTokens: number;
|
|
181
|
+
completionTokens: number;
|
|
182
|
+
totalTokens: number;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// Cost tracking
|
|
186
|
+
cost?: {
|
|
187
|
+
promptCost: number;
|
|
188
|
+
completionCost: number;
|
|
189
|
+
totalCost: number;
|
|
190
|
+
currency: string;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Performance
|
|
194
|
+
latency?: number;
|
|
195
|
+
|
|
196
|
+
// Metadata
|
|
197
|
+
finishReason?: 'stop' | 'length' | 'tool_calls' | 'content_filter';
|
|
198
|
+
metadata?: Record<string, unknown>;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface LLMStreamEvent {
|
|
202
|
+
type: 'content' | 'tool_call' | 'error' | 'done';
|
|
203
|
+
delta?: {
|
|
204
|
+
content?: string;
|
|
205
|
+
toolCall?: Partial<LLMToolCall>;
|
|
206
|
+
};
|
|
207
|
+
error?: Error;
|
|
208
|
+
usage?: LLMResponse['usage'];
|
|
209
|
+
cost?: LLMResponse['cost'];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// ===== PROVIDER CAPABILITIES =====
|
|
213
|
+
|
|
214
|
+
export interface ProviderCapabilities {
|
|
215
|
+
supportedModels: LLMModel[];
|
|
216
|
+
maxContextLength: Record<string, number>;
|
|
217
|
+
maxOutputTokens: Record<string, number>;
|
|
218
|
+
|
|
219
|
+
// Feature support
|
|
220
|
+
supportsStreaming: boolean;
|
|
221
|
+
supportsToolCalling: boolean;
|
|
222
|
+
supportsSystemMessages: boolean;
|
|
223
|
+
supportsVision: boolean;
|
|
224
|
+
supportsAudio: boolean;
|
|
225
|
+
|
|
226
|
+
// Advanced features
|
|
227
|
+
supportsFineTuning: boolean;
|
|
228
|
+
supportsEmbeddings: boolean;
|
|
229
|
+
supportsBatching: boolean;
|
|
230
|
+
|
|
231
|
+
// Rate limits
|
|
232
|
+
rateLimit?: {
|
|
233
|
+
requestsPerMinute: number;
|
|
234
|
+
tokensPerMinute: number;
|
|
235
|
+
concurrentRequests: number;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
// Pricing (per 1K tokens)
|
|
239
|
+
pricing: Record<string, {
|
|
240
|
+
promptCostPer1k: number;
|
|
241
|
+
completionCostPer1k: number;
|
|
242
|
+
currency: string;
|
|
243
|
+
}>;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// ===== ERROR TYPES =====
|
|
247
|
+
|
|
248
|
+
export class LLMProviderError extends Error {
|
|
249
|
+
constructor(
|
|
250
|
+
message: string,
|
|
251
|
+
public code: string,
|
|
252
|
+
public provider: LLMProvider,
|
|
253
|
+
public statusCode?: number,
|
|
254
|
+
public retryable: boolean = true,
|
|
255
|
+
public details?: unknown
|
|
256
|
+
) {
|
|
257
|
+
super(message);
|
|
258
|
+
this.name = 'LLMProviderError';
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export class RateLimitError extends LLMProviderError {
|
|
263
|
+
constructor(
|
|
264
|
+
message: string,
|
|
265
|
+
provider: LLMProvider,
|
|
266
|
+
public retryAfter?: number,
|
|
267
|
+
details?: unknown
|
|
268
|
+
) {
|
|
269
|
+
super(message, 'RATE_LIMIT', provider, 429, true, details);
|
|
270
|
+
this.name = 'RateLimitError';
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export class AuthenticationError extends LLMProviderError {
|
|
275
|
+
constructor(message: string, provider: LLMProvider, details?: unknown) {
|
|
276
|
+
super(message, 'AUTHENTICATION', provider, 401, false, details);
|
|
277
|
+
this.name = 'AuthenticationError';
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export class ModelNotFoundError extends LLMProviderError {
|
|
282
|
+
constructor(model: string, provider: LLMProvider, details?: unknown) {
|
|
283
|
+
super(`Model ${model} not found`, 'MODEL_NOT_FOUND', provider, 404, false, details);
|
|
284
|
+
this.name = 'ModelNotFoundError';
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
export class ProviderUnavailableError extends LLMProviderError {
|
|
289
|
+
constructor(provider: LLMProvider, details?: unknown) {
|
|
290
|
+
super(`Provider ${provider} is unavailable`, 'PROVIDER_UNAVAILABLE', provider, 503, true, details);
|
|
291
|
+
this.name = 'ProviderUnavailableError';
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// ===== PROVIDER INTERFACE =====
|
|
296
|
+
|
|
297
|
+
export interface ILLMProvider extends EventEmitter {
|
|
298
|
+
readonly name: LLMProvider;
|
|
299
|
+
readonly capabilities: ProviderCapabilities;
|
|
300
|
+
config: LLMProviderConfig;
|
|
301
|
+
|
|
302
|
+
// Core methods
|
|
303
|
+
initialize(): Promise<void>;
|
|
304
|
+
complete(request: LLMRequest): Promise<LLMResponse>;
|
|
305
|
+
streamComplete(request: LLMRequest): AsyncIterable<LLMStreamEvent>;
|
|
306
|
+
|
|
307
|
+
// Model management
|
|
308
|
+
listModels(): Promise<LLMModel[]>;
|
|
309
|
+
getModelInfo(model: LLMModel): Promise<ModelInfo>;
|
|
310
|
+
validateModel(model: LLMModel): boolean;
|
|
311
|
+
|
|
312
|
+
// Health and status
|
|
313
|
+
healthCheck(): Promise<HealthCheckResult>;
|
|
314
|
+
getStatus(): ProviderStatus;
|
|
315
|
+
|
|
316
|
+
// Cost management
|
|
317
|
+
estimateCost(request: LLMRequest): Promise<CostEstimate>;
|
|
318
|
+
getUsage(period?: UsagePeriod): Promise<UsageStats>;
|
|
319
|
+
|
|
320
|
+
// Cleanup
|
|
321
|
+
destroy(): void;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export interface ModelInfo {
|
|
325
|
+
model: LLMModel;
|
|
326
|
+
name: string;
|
|
327
|
+
description: string;
|
|
328
|
+
contextLength: number;
|
|
329
|
+
maxOutputTokens: number;
|
|
330
|
+
supportedFeatures: string[];
|
|
331
|
+
pricing?: {
|
|
332
|
+
promptCostPer1k: number;
|
|
333
|
+
completionCostPer1k: number;
|
|
334
|
+
currency: string;
|
|
335
|
+
};
|
|
336
|
+
deprecated?: boolean;
|
|
337
|
+
recommendedReplacement?: LLMModel;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export interface HealthCheckResult {
|
|
341
|
+
healthy: boolean;
|
|
342
|
+
latency?: number;
|
|
343
|
+
error?: string;
|
|
344
|
+
timestamp: Date;
|
|
345
|
+
details?: Record<string, unknown>;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
export interface ProviderStatus {
|
|
349
|
+
available: boolean;
|
|
350
|
+
currentLoad: number;
|
|
351
|
+
queueLength: number;
|
|
352
|
+
activeRequests: number;
|
|
353
|
+
rateLimitRemaining?: number;
|
|
354
|
+
rateLimitReset?: Date;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export interface CostEstimate {
|
|
358
|
+
estimatedPromptTokens: number;
|
|
359
|
+
estimatedCompletionTokens: number;
|
|
360
|
+
estimatedTotalTokens: number;
|
|
361
|
+
estimatedCost: {
|
|
362
|
+
prompt: number;
|
|
363
|
+
completion: number;
|
|
364
|
+
total: number;
|
|
365
|
+
currency: string;
|
|
366
|
+
};
|
|
367
|
+
confidence: number;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export interface UsageStats {
|
|
371
|
+
period: { start: Date; end: Date };
|
|
372
|
+
requests: number;
|
|
373
|
+
tokens: { prompt: number; completion: number; total: number };
|
|
374
|
+
cost: { prompt: number; completion: number; total: number; currency: string };
|
|
375
|
+
errors: number;
|
|
376
|
+
averageLatency: number;
|
|
377
|
+
modelBreakdown: Record<string, { requests: number; tokens: number; cost: number }>;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export type UsagePeriod = 'hour' | 'day' | 'week' | 'month' | 'all';
|
|
381
|
+
|
|
382
|
+
// ===== MANAGER TYPES =====
|
|
383
|
+
|
|
384
|
+
export type LoadBalancingStrategy = 'round-robin' | 'least-loaded' | 'latency-based' | 'cost-based';
|
|
385
|
+
|
|
386
|
+
export interface ProviderManagerConfig {
|
|
387
|
+
providers: LLMProviderConfig[];
|
|
388
|
+
defaultProvider?: LLMProvider;
|
|
389
|
+
loadBalancing?: {
|
|
390
|
+
enabled: boolean;
|
|
391
|
+
strategy: LoadBalancingStrategy;
|
|
392
|
+
};
|
|
393
|
+
fallback?: {
|
|
394
|
+
enabled: boolean;
|
|
395
|
+
maxAttempts: number;
|
|
396
|
+
};
|
|
397
|
+
cache?: {
|
|
398
|
+
enabled: boolean;
|
|
399
|
+
ttl: number;
|
|
400
|
+
maxSize: number;
|
|
401
|
+
};
|
|
402
|
+
costOptimization?: {
|
|
403
|
+
enabled: boolean;
|
|
404
|
+
maxCostPerRequest?: number;
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// ===== TYPE GUARDS =====
|
|
409
|
+
|
|
410
|
+
export function isLLMResponse(obj: unknown): obj is LLMResponse {
|
|
411
|
+
return (
|
|
412
|
+
typeof obj === 'object' &&
|
|
413
|
+
obj !== null &&
|
|
414
|
+
'id' in obj &&
|
|
415
|
+
'content' in obj &&
|
|
416
|
+
'provider' in obj
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
export function isLLMStreamEvent(obj: unknown): obj is LLMStreamEvent {
|
|
421
|
+
return (
|
|
422
|
+
typeof obj === 'object' &&
|
|
423
|
+
obj !== null &&
|
|
424
|
+
'type' in obj &&
|
|
425
|
+
['content', 'tool_call', 'error', 'done'].includes((obj as LLMStreamEvent).type)
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export function isLLMProviderError(error: unknown): error is LLMProviderError {
|
|
430
|
+
return error instanceof LLMProviderError;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export function isRateLimitError(error: unknown): error is RateLimitError {
|
|
434
|
+
return error instanceof RateLimitError;
|
|
435
|
+
}
|