@amux.ai/llm-bridge 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +909 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1328 -0
- package/dist/index.d.ts +1328 -0
- package/dist/index.js +886 -0
- package/dist/index.js.map +1 -0
- package/package.json +53 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,1328 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message role types
|
|
3
|
+
*/
|
|
4
|
+
type Role = 'system' | 'user' | 'assistant' | 'tool';
|
|
5
|
+
/**
|
|
6
|
+
* Text content part
|
|
7
|
+
*/
|
|
8
|
+
interface TextContent {
|
|
9
|
+
type: 'text';
|
|
10
|
+
text: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Image source types
|
|
14
|
+
*/
|
|
15
|
+
type ImageSource = {
|
|
16
|
+
type: 'url';
|
|
17
|
+
url: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'base64';
|
|
20
|
+
mediaType: string;
|
|
21
|
+
data: string;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Image content part
|
|
25
|
+
*/
|
|
26
|
+
interface ImageContent {
|
|
27
|
+
type: 'image';
|
|
28
|
+
source: ImageSource;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Content part union type
|
|
32
|
+
* Note: Tool calls use OpenAI-style toolCalls field on Message, not content parts
|
|
33
|
+
*/
|
|
34
|
+
type ContentPart = TextContent | ImageContent;
|
|
35
|
+
/**
|
|
36
|
+
* Message content can be a string or an array of content parts
|
|
37
|
+
*/
|
|
38
|
+
type MessageContent = string | ContentPart[];
|
|
39
|
+
/**
|
|
40
|
+
* Tool call (OpenAI-style)
|
|
41
|
+
* This is the unified format for tool calls in IR
|
|
42
|
+
*/
|
|
43
|
+
interface ToolCall {
|
|
44
|
+
id: string;
|
|
45
|
+
type: 'function';
|
|
46
|
+
function: {
|
|
47
|
+
name: string;
|
|
48
|
+
arguments: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Message structure supporting multimodal content
|
|
53
|
+
*/
|
|
54
|
+
interface Message {
|
|
55
|
+
role: Role;
|
|
56
|
+
content: MessageContent;
|
|
57
|
+
name?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Tool call ID (for tool role messages - tool results)
|
|
60
|
+
* When role is 'tool', this identifies which tool call this is a response to
|
|
61
|
+
*/
|
|
62
|
+
toolCallId?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Tool calls made by the assistant (OpenAI-style)
|
|
65
|
+
* When role is 'assistant' and the model wants to call tools
|
|
66
|
+
*/
|
|
67
|
+
toolCalls?: ToolCall[];
|
|
68
|
+
/**
|
|
69
|
+
* Reasoning/thinking content (DeepSeek, Qwen QwQ, Anthropic extended thinking)
|
|
70
|
+
* Contains the model's chain-of-thought reasoning process
|
|
71
|
+
*/
|
|
72
|
+
reasoningContent?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* JSON Schema definition
|
|
77
|
+
*/
|
|
78
|
+
interface JSONSchema {
|
|
79
|
+
type: string;
|
|
80
|
+
properties?: Record<string, unknown>;
|
|
81
|
+
required?: string[];
|
|
82
|
+
additionalProperties?: boolean;
|
|
83
|
+
description?: string;
|
|
84
|
+
[key: string]: unknown;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Function definition
|
|
88
|
+
*/
|
|
89
|
+
interface FunctionDefinition {
|
|
90
|
+
name: string;
|
|
91
|
+
description?: string;
|
|
92
|
+
parameters?: JSONSchema;
|
|
93
|
+
strict?: boolean;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Tool definition
|
|
97
|
+
*/
|
|
98
|
+
interface Tool {
|
|
99
|
+
type: 'function';
|
|
100
|
+
function: FunctionDefinition;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Tool choice options
|
|
104
|
+
*/
|
|
105
|
+
type ToolChoice = 'auto' | 'none' | 'required' | {
|
|
106
|
+
type: 'function';
|
|
107
|
+
function: {
|
|
108
|
+
name: string;
|
|
109
|
+
};
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Response format configuration
|
|
114
|
+
*/
|
|
115
|
+
interface ResponseFormat {
|
|
116
|
+
/**
|
|
117
|
+
* Response type: 'text' | 'json_object' | 'json_schema'
|
|
118
|
+
*/
|
|
119
|
+
type: 'text' | 'json_object' | 'json_schema';
|
|
120
|
+
/**
|
|
121
|
+
* JSON schema for structured output (when type is 'json_schema')
|
|
122
|
+
*/
|
|
123
|
+
jsonSchema?: {
|
|
124
|
+
name: string;
|
|
125
|
+
description?: string;
|
|
126
|
+
schema: Record<string, unknown>;
|
|
127
|
+
strict?: boolean;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Thinking/reasoning configuration
|
|
132
|
+
* Supported by: DeepSeek, Qwen, Anthropic (extended thinking)
|
|
133
|
+
*/
|
|
134
|
+
interface ThinkingConfig {
|
|
135
|
+
/**
|
|
136
|
+
* Enable thinking/reasoning mode
|
|
137
|
+
*/
|
|
138
|
+
enabled: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Budget tokens for thinking (Anthropic)
|
|
141
|
+
*/
|
|
142
|
+
budgetTokens?: number;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Generation configuration parameters
|
|
146
|
+
*/
|
|
147
|
+
interface GenerationConfig {
|
|
148
|
+
/**
|
|
149
|
+
* Temperature (0-2, typically 0-1)
|
|
150
|
+
* Higher values make output more random
|
|
151
|
+
*/
|
|
152
|
+
temperature?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Top-p sampling (nucleus sampling)
|
|
155
|
+
* Alternative to temperature
|
|
156
|
+
*/
|
|
157
|
+
topP?: number;
|
|
158
|
+
/**
|
|
159
|
+
* Top-k sampling
|
|
160
|
+
* Only consider top k tokens
|
|
161
|
+
*/
|
|
162
|
+
topK?: number;
|
|
163
|
+
/**
|
|
164
|
+
* Maximum tokens to generate
|
|
165
|
+
*/
|
|
166
|
+
maxTokens?: number;
|
|
167
|
+
/**
|
|
168
|
+
* Stop sequences
|
|
169
|
+
* Generation stops when any of these sequences is encountered
|
|
170
|
+
*/
|
|
171
|
+
stopSequences?: string[];
|
|
172
|
+
/**
|
|
173
|
+
* Presence penalty (-2.0 to 2.0)
|
|
174
|
+
* Positive values penalize new tokens based on whether they appear in the text so far
|
|
175
|
+
*/
|
|
176
|
+
presencePenalty?: number;
|
|
177
|
+
/**
|
|
178
|
+
* Frequency penalty (-2.0 to 2.0)
|
|
179
|
+
* Positive values penalize new tokens based on their frequency in the text so far
|
|
180
|
+
*/
|
|
181
|
+
frequencyPenalty?: number;
|
|
182
|
+
/**
|
|
183
|
+
* Number of completions to generate
|
|
184
|
+
*/
|
|
185
|
+
n?: number;
|
|
186
|
+
/**
|
|
187
|
+
* Seed for deterministic generation
|
|
188
|
+
*/
|
|
189
|
+
seed?: number;
|
|
190
|
+
/**
|
|
191
|
+
* Response format configuration
|
|
192
|
+
*/
|
|
193
|
+
responseFormat?: ResponseFormat;
|
|
194
|
+
/**
|
|
195
|
+
* Thinking/reasoning configuration
|
|
196
|
+
* Supported by: DeepSeek (deepseek-reasoner), Qwen (QwQ), Anthropic (extended thinking)
|
|
197
|
+
*/
|
|
198
|
+
thinking?: ThinkingConfig;
|
|
199
|
+
/**
|
|
200
|
+
* Enable web search (Qwen specific)
|
|
201
|
+
*/
|
|
202
|
+
enableSearch?: boolean;
|
|
203
|
+
/**
|
|
204
|
+
* Log probabilities configuration
|
|
205
|
+
*/
|
|
206
|
+
logprobs?: boolean;
|
|
207
|
+
/**
|
|
208
|
+
* Number of top log probabilities to return
|
|
209
|
+
*/
|
|
210
|
+
topLogprobs?: number;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Unified Intermediate Representation for LLM Requests
|
|
215
|
+
* This is the core data structure that all adapters convert to/from
|
|
216
|
+
*/
|
|
217
|
+
interface LLMRequestIR {
|
|
218
|
+
/**
|
|
219
|
+
* Conversation messages
|
|
220
|
+
* Supports multi-turn dialogue with role-based messages
|
|
221
|
+
*/
|
|
222
|
+
messages: Message[];
|
|
223
|
+
/**
|
|
224
|
+
* Model identifier (optional in IR, may be determined by router)
|
|
225
|
+
*/
|
|
226
|
+
model?: string;
|
|
227
|
+
/**
|
|
228
|
+
* Tools/Functions available for the model to call
|
|
229
|
+
*/
|
|
230
|
+
tools?: Tool[];
|
|
231
|
+
/**
|
|
232
|
+
* Tool choice strategy
|
|
233
|
+
*/
|
|
234
|
+
toolChoice?: ToolChoice;
|
|
235
|
+
/**
|
|
236
|
+
* Streaming configuration
|
|
237
|
+
*/
|
|
238
|
+
stream?: boolean;
|
|
239
|
+
/**
|
|
240
|
+
* Generation parameters
|
|
241
|
+
*/
|
|
242
|
+
generation?: GenerationConfig;
|
|
243
|
+
/**
|
|
244
|
+
* System prompt (some providers use separate field)
|
|
245
|
+
*/
|
|
246
|
+
system?: string;
|
|
247
|
+
/**
|
|
248
|
+
* Metadata for tracking and routing
|
|
249
|
+
*/
|
|
250
|
+
metadata?: {
|
|
251
|
+
requestId?: string;
|
|
252
|
+
userId?: string;
|
|
253
|
+
sessionId?: string;
|
|
254
|
+
tags?: string[];
|
|
255
|
+
[key: string]: unknown;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* Provider-specific extensions
|
|
259
|
+
* Allows passthrough of vendor-specific features
|
|
260
|
+
*/
|
|
261
|
+
extensions?: {
|
|
262
|
+
[provider: string]: unknown;
|
|
263
|
+
};
|
|
264
|
+
/**
|
|
265
|
+
* Raw original request (for debugging/logging)
|
|
266
|
+
*/
|
|
267
|
+
raw?: unknown;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Finish reason types
|
|
272
|
+
*/
|
|
273
|
+
type FinishReason = 'stop' | 'length' | 'tool_calls' | 'content_filter' | 'error';
|
|
274
|
+
/**
|
|
275
|
+
* Token usage statistics
|
|
276
|
+
*/
|
|
277
|
+
interface Usage {
|
|
278
|
+
promptTokens: number;
|
|
279
|
+
completionTokens: number;
|
|
280
|
+
totalTokens: number;
|
|
281
|
+
/**
|
|
282
|
+
* Detailed token breakdown (provider-specific)
|
|
283
|
+
*/
|
|
284
|
+
details?: {
|
|
285
|
+
/**
|
|
286
|
+
* Reasoning/thinking tokens (DeepSeek, Qwen)
|
|
287
|
+
*/
|
|
288
|
+
reasoningTokens?: number;
|
|
289
|
+
/**
|
|
290
|
+
* Cached prompt tokens (DeepSeek, Anthropic)
|
|
291
|
+
*/
|
|
292
|
+
cachedTokens?: number;
|
|
293
|
+
/**
|
|
294
|
+
* Cache creation tokens (Anthropic)
|
|
295
|
+
*/
|
|
296
|
+
cacheCreationTokens?: number;
|
|
297
|
+
/**
|
|
298
|
+
* Cache read tokens (Anthropic)
|
|
299
|
+
*/
|
|
300
|
+
cacheReadTokens?: number;
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Response choice
|
|
305
|
+
*/
|
|
306
|
+
interface Choice {
|
|
307
|
+
index: number;
|
|
308
|
+
message: Message;
|
|
309
|
+
finishReason?: FinishReason;
|
|
310
|
+
/**
|
|
311
|
+
* Log probabilities (if requested)
|
|
312
|
+
*/
|
|
313
|
+
logprobs?: {
|
|
314
|
+
content?: Array<{
|
|
315
|
+
token: string;
|
|
316
|
+
logprob: number;
|
|
317
|
+
topLogprobs?: Array<{
|
|
318
|
+
token: string;
|
|
319
|
+
logprob: number;
|
|
320
|
+
}>;
|
|
321
|
+
}>;
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Unified response structure
|
|
326
|
+
*/
|
|
327
|
+
interface LLMResponseIR {
|
|
328
|
+
/**
|
|
329
|
+
* Response ID
|
|
330
|
+
*/
|
|
331
|
+
id: string;
|
|
332
|
+
/**
|
|
333
|
+
* Model used
|
|
334
|
+
*/
|
|
335
|
+
model: string;
|
|
336
|
+
/**
|
|
337
|
+
* Generated message(s)
|
|
338
|
+
*/
|
|
339
|
+
choices: Choice[];
|
|
340
|
+
/**
|
|
341
|
+
* Token usage statistics
|
|
342
|
+
*/
|
|
343
|
+
usage?: Usage;
|
|
344
|
+
/**
|
|
345
|
+
* Response creation timestamp
|
|
346
|
+
*/
|
|
347
|
+
created?: number;
|
|
348
|
+
/**
|
|
349
|
+
* System fingerprint (for reproducibility)
|
|
350
|
+
*/
|
|
351
|
+
systemFingerprint?: string;
|
|
352
|
+
/**
|
|
353
|
+
* Metadata
|
|
354
|
+
*/
|
|
355
|
+
metadata?: {
|
|
356
|
+
requestId?: string;
|
|
357
|
+
[key: string]: unknown;
|
|
358
|
+
};
|
|
359
|
+
/**
|
|
360
|
+
* Provider-specific extensions
|
|
361
|
+
*/
|
|
362
|
+
extensions?: {
|
|
363
|
+
[provider: string]: unknown;
|
|
364
|
+
};
|
|
365
|
+
/**
|
|
366
|
+
* Raw original response (for debugging/logging)
|
|
367
|
+
*/
|
|
368
|
+
raw?: unknown;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Stream event types
|
|
373
|
+
*/
|
|
374
|
+
type StreamEventType = 'start' | 'content' | 'reasoning' | 'tool_call' | 'end' | 'error';
|
|
375
|
+
/**
|
|
376
|
+
* Content delta
|
|
377
|
+
*/
|
|
378
|
+
interface ContentDelta {
|
|
379
|
+
type: 'content';
|
|
380
|
+
delta: string;
|
|
381
|
+
index?: number;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Reasoning content delta (DeepSeek, Qwen, Anthropic)
|
|
385
|
+
*/
|
|
386
|
+
interface ReasoningDelta {
|
|
387
|
+
type: 'reasoning';
|
|
388
|
+
delta: string;
|
|
389
|
+
index?: number;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Tool call delta
|
|
393
|
+
*/
|
|
394
|
+
interface ToolCallDelta {
|
|
395
|
+
type: 'tool_call';
|
|
396
|
+
id?: string;
|
|
397
|
+
name?: string;
|
|
398
|
+
arguments?: string;
|
|
399
|
+
index?: number;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Stream event
|
|
403
|
+
*/
|
|
404
|
+
interface LLMStreamEvent {
|
|
405
|
+
/**
|
|
406
|
+
* Event type
|
|
407
|
+
*/
|
|
408
|
+
type: StreamEventType;
|
|
409
|
+
/**
|
|
410
|
+
* Event ID
|
|
411
|
+
*/
|
|
412
|
+
id?: string;
|
|
413
|
+
/**
|
|
414
|
+
* Model used
|
|
415
|
+
*/
|
|
416
|
+
model?: string;
|
|
417
|
+
/**
|
|
418
|
+
* Content delta
|
|
419
|
+
*/
|
|
420
|
+
content?: ContentDelta;
|
|
421
|
+
/**
|
|
422
|
+
* Reasoning/thinking content delta
|
|
423
|
+
*/
|
|
424
|
+
reasoning?: ReasoningDelta;
|
|
425
|
+
/**
|
|
426
|
+
* Tool call delta
|
|
427
|
+
*/
|
|
428
|
+
toolCall?: ToolCallDelta;
|
|
429
|
+
/**
|
|
430
|
+
* Finish reason (for end event)
|
|
431
|
+
*/
|
|
432
|
+
finishReason?: FinishReason;
|
|
433
|
+
/**
|
|
434
|
+
* Complete message (for end event)
|
|
435
|
+
*/
|
|
436
|
+
message?: Message;
|
|
437
|
+
/**
|
|
438
|
+
* Usage statistics (for end event, if stream_options.include_usage is true)
|
|
439
|
+
*/
|
|
440
|
+
usage?: Usage;
|
|
441
|
+
/**
|
|
442
|
+
* Error (for error event)
|
|
443
|
+
*/
|
|
444
|
+
error?: {
|
|
445
|
+
message: string;
|
|
446
|
+
code?: string;
|
|
447
|
+
[key: string]: unknown;
|
|
448
|
+
};
|
|
449
|
+
/**
|
|
450
|
+
* Raw original event (for debugging)
|
|
451
|
+
*/
|
|
452
|
+
raw?: unknown;
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* SSE (Server-Sent Events) event for streaming responses
|
|
456
|
+
* This is the formatted event that can be directly written to HTTP response
|
|
457
|
+
*/
|
|
458
|
+
interface SSEEvent {
|
|
459
|
+
/**
|
|
460
|
+
* Event type (e.g., 'message_start', 'content_block_delta', 'data')
|
|
461
|
+
*/
|
|
462
|
+
event: string;
|
|
463
|
+
/**
|
|
464
|
+
* Event data payload
|
|
465
|
+
*/
|
|
466
|
+
data: unknown;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Error types
|
|
471
|
+
*/
|
|
472
|
+
type ErrorType = 'network' | 'api' | 'validation' | 'rate_limit' | 'authentication' | 'permission' | 'not_found' | 'server' | 'unknown';
|
|
473
|
+
/**
|
|
474
|
+
* Unified error structure
|
|
475
|
+
*/
|
|
476
|
+
interface LLMErrorIR {
|
|
477
|
+
/**
|
|
478
|
+
* Error type
|
|
479
|
+
*/
|
|
480
|
+
type: ErrorType;
|
|
481
|
+
/**
|
|
482
|
+
* Error message
|
|
483
|
+
*/
|
|
484
|
+
message: string;
|
|
485
|
+
/**
|
|
486
|
+
* Error code (provider-specific)
|
|
487
|
+
*/
|
|
488
|
+
code?: string;
|
|
489
|
+
/**
|
|
490
|
+
* HTTP status code
|
|
491
|
+
*/
|
|
492
|
+
status?: number;
|
|
493
|
+
/**
|
|
494
|
+
* Whether the error is retryable
|
|
495
|
+
*/
|
|
496
|
+
retryable?: boolean;
|
|
497
|
+
/**
|
|
498
|
+
* Additional error details
|
|
499
|
+
*/
|
|
500
|
+
details?: {
|
|
501
|
+
[key: string]: unknown;
|
|
502
|
+
};
|
|
503
|
+
/**
|
|
504
|
+
* Original error (for debugging)
|
|
505
|
+
*/
|
|
506
|
+
raw?: unknown;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Provider endpoint configuration
|
|
511
|
+
*/
|
|
512
|
+
interface ProviderEndpoint {
|
|
513
|
+
/**
|
|
514
|
+
* Base URL for the API
|
|
515
|
+
*/
|
|
516
|
+
baseUrl: string;
|
|
517
|
+
/**
|
|
518
|
+
* Chat completions path (default: '/v1/chat/completions')
|
|
519
|
+
*/
|
|
520
|
+
chatPath?: string;
|
|
521
|
+
/**
|
|
522
|
+
* Models list path (default: '/v1/models')
|
|
523
|
+
*/
|
|
524
|
+
modelsPath?: string;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Adapter capabilities
|
|
528
|
+
*/
|
|
529
|
+
interface AdapterCapabilities {
|
|
530
|
+
/**
|
|
531
|
+
* Supports streaming
|
|
532
|
+
*/
|
|
533
|
+
streaming: boolean;
|
|
534
|
+
/**
|
|
535
|
+
* Supports tool/function calling
|
|
536
|
+
*/
|
|
537
|
+
tools: boolean;
|
|
538
|
+
/**
|
|
539
|
+
* Supports vision (image input)
|
|
540
|
+
*/
|
|
541
|
+
vision: boolean;
|
|
542
|
+
/**
|
|
543
|
+
* Supports multimodal content (images, audio, video, documents)
|
|
544
|
+
*/
|
|
545
|
+
multimodal: boolean;
|
|
546
|
+
/**
|
|
547
|
+
* Supports system prompt
|
|
548
|
+
*/
|
|
549
|
+
systemPrompt: boolean;
|
|
550
|
+
/**
|
|
551
|
+
* Supports tool choice
|
|
552
|
+
*/
|
|
553
|
+
toolChoice: boolean;
|
|
554
|
+
/**
|
|
555
|
+
* Supports reasoning/thinking mode (DeepSeek, Qwen QwQ, Anthropic)
|
|
556
|
+
*/
|
|
557
|
+
reasoning?: boolean;
|
|
558
|
+
/**
|
|
559
|
+
* Supports web search (Qwen)
|
|
560
|
+
*/
|
|
561
|
+
webSearch?: boolean;
|
|
562
|
+
/**
|
|
563
|
+
* Supports JSON mode / structured output
|
|
564
|
+
*/
|
|
565
|
+
jsonMode?: boolean;
|
|
566
|
+
/**
|
|
567
|
+
* Supports log probabilities
|
|
568
|
+
*/
|
|
569
|
+
logprobs?: boolean;
|
|
570
|
+
/**
|
|
571
|
+
* Supports seed for reproducibility
|
|
572
|
+
*/
|
|
573
|
+
seed?: boolean;
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Validation result
|
|
577
|
+
*/
|
|
578
|
+
interface ValidationResult {
|
|
579
|
+
valid: boolean;
|
|
580
|
+
errors?: string[];
|
|
581
|
+
warnings?: string[];
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Adapter information
|
|
585
|
+
*/
|
|
586
|
+
interface AdapterInfo {
|
|
587
|
+
name: string;
|
|
588
|
+
version: string;
|
|
589
|
+
capabilities: AdapterCapabilities;
|
|
590
|
+
/**
|
|
591
|
+
* Default endpoint configuration
|
|
592
|
+
*/
|
|
593
|
+
endpoint?: ProviderEndpoint;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Stream handler function
|
|
598
|
+
*/
|
|
599
|
+
type StreamHandler = (chunk: unknown) => LLMStreamEvent | LLMStreamEvent[] | null;
|
|
600
|
+
/**
|
|
601
|
+
* Error handler function
|
|
602
|
+
*/
|
|
603
|
+
type ErrorHandler = (error: unknown) => LLMErrorIR;
|
|
604
|
+
/**
|
|
605
|
+
* Stream event builder interface
|
|
606
|
+
* Handles stateful conversion of IR stream events to provider-specific SSE events
|
|
607
|
+
*/
|
|
608
|
+
interface StreamEventBuilder {
|
|
609
|
+
/**
|
|
610
|
+
* Process an IR stream event and return SSE events
|
|
611
|
+
* May return multiple events (e.g., message_start + content_block_start)
|
|
612
|
+
* May return empty array if no events should be emitted
|
|
613
|
+
*/
|
|
614
|
+
process(event: LLMStreamEvent): SSEEvent[];
|
|
615
|
+
/**
|
|
616
|
+
* Get any final events that should be emitted when the stream ends
|
|
617
|
+
* Called after all events have been processed
|
|
618
|
+
*/
|
|
619
|
+
finalize?(): SSEEvent[];
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* LLM Adapter interface
|
|
623
|
+
* Defines the contract for bidirectional conversion between provider formats and IR
|
|
624
|
+
*/
|
|
625
|
+
interface LLMAdapter {
|
|
626
|
+
/**
|
|
627
|
+
* Adapter name (e.g., 'openai', 'anthropic')
|
|
628
|
+
*/
|
|
629
|
+
readonly name: string;
|
|
630
|
+
/**
|
|
631
|
+
* Adapter version
|
|
632
|
+
*/
|
|
633
|
+
readonly version: string;
|
|
634
|
+
/**
|
|
635
|
+
* Adapter capabilities
|
|
636
|
+
*/
|
|
637
|
+
readonly capabilities: AdapterCapabilities;
|
|
638
|
+
/**
|
|
639
|
+
* Inbound conversion (Provider format → IR)
|
|
640
|
+
*/
|
|
641
|
+
inbound: {
|
|
642
|
+
/**
|
|
643
|
+
* Parse provider request to IR
|
|
644
|
+
*/
|
|
645
|
+
parseRequest(request: unknown): LLMRequestIR;
|
|
646
|
+
/**
|
|
647
|
+
* Parse provider response to IR
|
|
648
|
+
*/
|
|
649
|
+
parseResponse?(response: unknown): LLMResponseIR;
|
|
650
|
+
/**
|
|
651
|
+
* Parse provider stream chunk to IR stream event
|
|
652
|
+
*/
|
|
653
|
+
parseStream?(chunk: unknown): LLMStreamEvent | LLMStreamEvent[] | null;
|
|
654
|
+
/**
|
|
655
|
+
* Parse provider error to IR error
|
|
656
|
+
*/
|
|
657
|
+
parseError?(error: unknown): LLMErrorIR;
|
|
658
|
+
};
|
|
659
|
+
/**
|
|
660
|
+
* Outbound conversion (IR → Provider format)
|
|
661
|
+
*/
|
|
662
|
+
outbound: {
|
|
663
|
+
/**
|
|
664
|
+
* Build provider request from IR
|
|
665
|
+
*/
|
|
666
|
+
buildRequest(ir: LLMRequestIR): unknown;
|
|
667
|
+
/**
|
|
668
|
+
* Build provider response from IR
|
|
669
|
+
*/
|
|
670
|
+
buildResponse?(ir: LLMResponseIR): unknown;
|
|
671
|
+
/**
|
|
672
|
+
* Build provider stream event from IR stream event
|
|
673
|
+
*/
|
|
674
|
+
buildStreamEvent?(ir: LLMStreamEvent): unknown;
|
|
675
|
+
/**
|
|
676
|
+
* Get stream handler for provider
|
|
677
|
+
*/
|
|
678
|
+
buildStreamHandler?(): StreamHandler;
|
|
679
|
+
/**
|
|
680
|
+
* Get error handler for provider
|
|
681
|
+
*/
|
|
682
|
+
buildErrorHandler?(): ErrorHandler;
|
|
683
|
+
/**
|
|
684
|
+
* Create a stream event builder for converting IR events to provider SSE format
|
|
685
|
+
* The builder maintains state for proper event sequencing (e.g., tracking content blocks)
|
|
686
|
+
*/
|
|
687
|
+
createStreamBuilder?(): StreamEventBuilder;
|
|
688
|
+
};
|
|
689
|
+
/**
|
|
690
|
+
* Validate IR request for this adapter
|
|
691
|
+
*/
|
|
692
|
+
validateRequest?(ir: LLMRequestIR): ValidationResult;
|
|
693
|
+
/**
|
|
694
|
+
* Check if adapter supports a specific capability
|
|
695
|
+
*/
|
|
696
|
+
supportsCapability?(capability: keyof AdapterCapabilities): boolean;
|
|
697
|
+
/**
|
|
698
|
+
* Get adapter information
|
|
699
|
+
*/
|
|
700
|
+
getInfo(): AdapterInfo;
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* Adapter registry for managing adapters
|
|
705
|
+
*/
|
|
706
|
+
declare class AdapterRegistry {
|
|
707
|
+
private adapters;
|
|
708
|
+
/**
|
|
709
|
+
* Register an adapter
|
|
710
|
+
*/
|
|
711
|
+
register(adapter: LLMAdapter): void;
|
|
712
|
+
/**
|
|
713
|
+
* Unregister an adapter
|
|
714
|
+
*/
|
|
715
|
+
unregister(name: string): boolean;
|
|
716
|
+
/**
|
|
717
|
+
* Get an adapter by name
|
|
718
|
+
*/
|
|
719
|
+
get(name: string): LLMAdapter | undefined;
|
|
720
|
+
/**
|
|
721
|
+
* Check if an adapter is registered
|
|
722
|
+
*/
|
|
723
|
+
has(name: string): boolean;
|
|
724
|
+
/**
|
|
725
|
+
* List all registered adapters
|
|
726
|
+
*/
|
|
727
|
+
list(): AdapterInfo[];
|
|
728
|
+
/**
|
|
729
|
+
* Clear all adapters
|
|
730
|
+
*/
|
|
731
|
+
clear(): void;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Global adapter registry instance
|
|
735
|
+
*/
|
|
736
|
+
declare const globalRegistry: AdapterRegistry;
|
|
737
|
+
|
|
738
|
+
/**
|
|
739
|
+
* Bridge configuration
|
|
740
|
+
*/
|
|
741
|
+
interface BridgeConfig {
|
|
742
|
+
/**
|
|
743
|
+
* API key for the target provider
|
|
744
|
+
*/
|
|
745
|
+
apiKey: string;
|
|
746
|
+
/**
|
|
747
|
+
* Base URL for the target provider API
|
|
748
|
+
* Overrides adapter's default baseUrl
|
|
749
|
+
*/
|
|
750
|
+
baseURL?: string;
|
|
751
|
+
/**
|
|
752
|
+
* Custom chat endpoint path
|
|
753
|
+
* Overrides adapter's default chatPath
|
|
754
|
+
* Example: '/v1/chat/completions', '/responses'
|
|
755
|
+
*/
|
|
756
|
+
chatPath?: string;
|
|
757
|
+
/**
|
|
758
|
+
* Custom models endpoint path
|
|
759
|
+
* Overrides adapter's default modelsPath
|
|
760
|
+
* Example: '/v1/models', '/models'
|
|
761
|
+
*/
|
|
762
|
+
modelsPath?: string;
|
|
763
|
+
/**
|
|
764
|
+
* Request timeout in milliseconds
|
|
765
|
+
*/
|
|
766
|
+
timeout?: number;
|
|
767
|
+
/**
|
|
768
|
+
* Maximum number of retries for failed requests
|
|
769
|
+
*/
|
|
770
|
+
maxRetries?: number;
|
|
771
|
+
/**
|
|
772
|
+
* Custom headers
|
|
773
|
+
*/
|
|
774
|
+
headers?: Record<string, string>;
|
|
775
|
+
/**
|
|
776
|
+
* Authentication header name (default: 'Authorization')
|
|
777
|
+
*/
|
|
778
|
+
authHeaderName?: string;
|
|
779
|
+
/**
|
|
780
|
+
* Authentication header prefix (default: 'Bearer')
|
|
781
|
+
* Set to empty string if no prefix is needed
|
|
782
|
+
*/
|
|
783
|
+
authHeaderPrefix?: string;
|
|
784
|
+
/**
|
|
785
|
+
* Additional provider-specific options
|
|
786
|
+
*/
|
|
787
|
+
[key: string]: unknown;
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Bridge lifecycle hooks
|
|
791
|
+
*
|
|
792
|
+
* Hooks allow external code to intercept and observe the Bridge's request/response flow
|
|
793
|
+
* at the IR (Intermediate Representation) layer, where all data is in a unified format.
|
|
794
|
+
*
|
|
795
|
+
* Use cases:
|
|
796
|
+
* - Logging and monitoring (track token usage, latency, errors)
|
|
797
|
+
* - Cost tracking (calculate costs based on token usage)
|
|
798
|
+
* - Debugging and tracing (inspect IR transformations)
|
|
799
|
+
* - Rate limiting and alerting (implement usage-based limits)
|
|
800
|
+
* - Audit logging (record all LLM API calls)
|
|
801
|
+
*/
|
|
802
|
+
interface BridgeHooks {
|
|
803
|
+
/**
|
|
804
|
+
* Called after parsing the inbound request into IR, before building the outbound request
|
|
805
|
+
*
|
|
806
|
+
* @param ir - The unified request IR
|
|
807
|
+
* @returns void or Promise<void>
|
|
808
|
+
*
|
|
809
|
+
* @example
|
|
810
|
+
* ```typescript
|
|
811
|
+
* onRequest: async (ir) => {
|
|
812
|
+
* console.log(`Request to model: ${ir.model}`)
|
|
813
|
+
* console.log(`Message count: ${ir.messages.length}`)
|
|
814
|
+
* }
|
|
815
|
+
* ```
|
|
816
|
+
*/
|
|
817
|
+
onRequest?: (ir: LLMRequestIR) => void | Promise<void>;
|
|
818
|
+
/**
|
|
819
|
+
* Called after parsing the provider response into IR, before building the final response
|
|
820
|
+
*
|
|
821
|
+
* This is the ideal place to extract metadata like token usage, as all providers'
|
|
822
|
+
* responses have been normalized to the same IR format.
|
|
823
|
+
*
|
|
824
|
+
* @param ir - The unified response IR
|
|
825
|
+
* @returns void or Promise<void>
|
|
826
|
+
*
|
|
827
|
+
* @example
|
|
828
|
+
* ```typescript
|
|
829
|
+
* onResponse: async (ir) => {
|
|
830
|
+
* if (ir.usage) {
|
|
831
|
+
* console.log(`Input tokens: ${ir.usage.promptTokens}`)
|
|
832
|
+
* console.log(`Output tokens: ${ir.usage.completionTokens}`)
|
|
833
|
+
* await recordTokenUsage(ir.usage)
|
|
834
|
+
* }
|
|
835
|
+
* }
|
|
836
|
+
* ```
|
|
837
|
+
*/
|
|
838
|
+
onResponse?: (ir: LLMResponseIR) => void | Promise<void>;
|
|
839
|
+
/**
|
|
840
|
+
* Called for each streaming event after parsing into IR, before building the SSE event
|
|
841
|
+
*
|
|
842
|
+
* @param event - The unified stream event IR
|
|
843
|
+
* @returns void or Promise<void>
|
|
844
|
+
*
|
|
845
|
+
* @example
|
|
846
|
+
* ```typescript
|
|
847
|
+
* onStreamEvent: async (event) => {
|
|
848
|
+
* if (event.type === 'end' && event.usage) {
|
|
849
|
+
* await recordTokenUsage(event.usage)
|
|
850
|
+
* }
|
|
851
|
+
* }
|
|
852
|
+
* ```
|
|
853
|
+
*/
|
|
854
|
+
onStreamEvent?: (event: LLMStreamEvent) => void | Promise<void>;
|
|
855
|
+
/**
|
|
856
|
+
* Called when an error occurs during the request/response flow
|
|
857
|
+
*
|
|
858
|
+
* @param error - The unified error IR
|
|
859
|
+
* @returns void or Promise<void>
|
|
860
|
+
*
|
|
861
|
+
* @example
|
|
862
|
+
* ```typescript
|
|
863
|
+
* onError: async (error) => {
|
|
864
|
+
* console.error(`Bridge error: ${error.message}`)
|
|
865
|
+
* await logError(error)
|
|
866
|
+
* }
|
|
867
|
+
* ```
|
|
868
|
+
*/
|
|
869
|
+
onError?: (error: LLMErrorIR) => void | Promise<void>;
|
|
870
|
+
}
|
|
871
|
+
/**
|
|
872
|
+
* Bridge options
|
|
873
|
+
*/
|
|
874
|
+
interface BridgeOptions {
|
|
875
|
+
/**
|
|
876
|
+
* Inbound adapter (parses incoming requests)
|
|
877
|
+
*/
|
|
878
|
+
inbound: LLMAdapter;
|
|
879
|
+
/**
|
|
880
|
+
* Outbound adapter (builds outgoing requests)
|
|
881
|
+
*/
|
|
882
|
+
outbound: LLMAdapter;
|
|
883
|
+
/**
|
|
884
|
+
* Configuration for the target provider
|
|
885
|
+
*/
|
|
886
|
+
config: BridgeConfig;
|
|
887
|
+
/**
|
|
888
|
+
* Lifecycle hooks for intercepting IR-level events
|
|
889
|
+
*
|
|
890
|
+
* Hooks are called at key points in the request/response flow, allowing
|
|
891
|
+
* external code to observe and react to events at the IR layer where all
|
|
892
|
+
* data is in a unified format.
|
|
893
|
+
*
|
|
894
|
+
* @example
|
|
895
|
+
* ```typescript
|
|
896
|
+
* const bridge = createBridge({
|
|
897
|
+
* inbound: openaiAdapter,
|
|
898
|
+
* outbound: anthropicAdapter,
|
|
899
|
+
* config: { apiKey: '...' },
|
|
900
|
+
* hooks: {
|
|
901
|
+
* onResponse: async (ir) => {
|
|
902
|
+
* // Track token usage in unified format
|
|
903
|
+
* await recordTokens({
|
|
904
|
+
* input: ir.usage?.promptTokens ?? 0,
|
|
905
|
+
* output: ir.usage?.completionTokens ?? 0
|
|
906
|
+
* })
|
|
907
|
+
* }
|
|
908
|
+
* }
|
|
909
|
+
* })
|
|
910
|
+
* ```
|
|
911
|
+
*/
|
|
912
|
+
hooks?: BridgeHooks;
|
|
913
|
+
/**
|
|
914
|
+
* Fixed target model (highest priority)
|
|
915
|
+
* If set, ignores the inbound model and always uses this model
|
|
916
|
+
*/
|
|
917
|
+
targetModel?: string;
|
|
918
|
+
/**
|
|
919
|
+
* Model mapping function (second priority)
|
|
920
|
+
* Receives the inbound model name and returns the outbound model name
|
|
921
|
+
*/
|
|
922
|
+
modelMapper?: (inboundModel: string) => string;
|
|
923
|
+
/**
|
|
924
|
+
* Model mapping table (third priority)
|
|
925
|
+
* Maps inbound model names to outbound model names
|
|
926
|
+
*/
|
|
927
|
+
modelMapping?: {
|
|
928
|
+
[inboundModel: string]: string;
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Compatibility report
|
|
933
|
+
*/
|
|
934
|
+
interface CompatibilityReport {
|
|
935
|
+
compatible: boolean;
|
|
936
|
+
issues?: string[];
|
|
937
|
+
warnings?: string[];
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Amux Bridge interface
|
|
941
|
+
*/
|
|
942
|
+
interface LLMBridge {
|
|
943
|
+
/**
|
|
944
|
+
* Send a chat request
|
|
945
|
+
* Returns response in inbound adapter's format
|
|
946
|
+
*/
|
|
947
|
+
chat(request: unknown): Promise<unknown>;
|
|
948
|
+
/**
|
|
949
|
+
* Send a chat request (raw IR response)
|
|
950
|
+
* Returns raw IR response for custom processing
|
|
951
|
+
* Use this when you need to access the IR directly
|
|
952
|
+
*/
|
|
953
|
+
chatRaw(request: unknown): Promise<LLMResponseIR>;
|
|
954
|
+
/**
|
|
955
|
+
* Send a streaming chat request
|
|
956
|
+
* Returns SSE events in inbound adapter's format
|
|
957
|
+
* This is the recommended method for streaming - events can be directly written to HTTP response
|
|
958
|
+
*/
|
|
959
|
+
chatStream(request: unknown): AsyncIterable<SSEEvent>;
|
|
960
|
+
/**
|
|
961
|
+
* Send a streaming chat request (raw IR events)
|
|
962
|
+
* Returns raw IR stream events for custom processing
|
|
963
|
+
* Use this when you need to customize the stream handling
|
|
964
|
+
*/
|
|
965
|
+
chatStreamRaw(request: unknown): AsyncIterable<LLMStreamEvent>;
|
|
966
|
+
/**
|
|
967
|
+
* List available models from the provider
|
|
968
|
+
* Returns the raw model list response from the provider
|
|
969
|
+
*/
|
|
970
|
+
listModels(): Promise<unknown>;
|
|
971
|
+
/**
|
|
972
|
+
* Check compatibility between inbound and outbound adapters
|
|
973
|
+
*/
|
|
974
|
+
checkCompatibility(): CompatibilityReport;
|
|
975
|
+
/**
|
|
976
|
+
* Get adapter information
|
|
977
|
+
*/
|
|
978
|
+
getAdapters(): {
|
|
979
|
+
inbound: {
|
|
980
|
+
name: string;
|
|
981
|
+
version: string;
|
|
982
|
+
};
|
|
983
|
+
outbound: {
|
|
984
|
+
name: string;
|
|
985
|
+
version: string;
|
|
986
|
+
};
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* HTTP request options
|
|
991
|
+
*/
|
|
992
|
+
interface HTTPRequestOptions {
|
|
993
|
+
method: string;
|
|
994
|
+
url: string;
|
|
995
|
+
headers?: Record<string, string>;
|
|
996
|
+
body?: unknown;
|
|
997
|
+
timeout?: number;
|
|
998
|
+
signal?: AbortSignal;
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* HTTP response
|
|
1002
|
+
*/
|
|
1003
|
+
interface HTTPResponse<T = unknown> {
|
|
1004
|
+
status: number;
|
|
1005
|
+
statusText: string;
|
|
1006
|
+
headers: Record<string, string>;
|
|
1007
|
+
data: T;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
/**
|
|
1011
|
+
* Bridge implementation
|
|
1012
|
+
*/
|
|
1013
|
+
declare class Bridge implements LLMBridge {
|
|
1014
|
+
private inboundAdapter;
|
|
1015
|
+
private outboundAdapter;
|
|
1016
|
+
private config;
|
|
1017
|
+
private httpClient;
|
|
1018
|
+
private hooks?;
|
|
1019
|
+
private targetModel?;
|
|
1020
|
+
private modelMapper?;
|
|
1021
|
+
private modelMapping?;
|
|
1022
|
+
constructor(options: BridgeOptions);
|
|
1023
|
+
/**
|
|
1024
|
+
* Map model name from inbound to outbound
|
|
1025
|
+
* Priority: targetModel > modelMapper > modelMapping > original model
|
|
1026
|
+
*/
|
|
1027
|
+
private mapModel;
|
|
1028
|
+
/**
|
|
1029
|
+
* Validate that the IR request features are supported by outbound adapter
|
|
1030
|
+
* @private
|
|
1031
|
+
*/
|
|
1032
|
+
private validateCapabilities;
|
|
1033
|
+
/**
|
|
1034
|
+
* Send a chat request
|
|
1035
|
+
*/
|
|
1036
|
+
chat(request: unknown): Promise<unknown>;
|
|
1037
|
+
/**
|
|
1038
|
+
* Send a chat request (raw IR response)
|
|
1039
|
+
* Returns raw IR response for custom processing
|
|
1040
|
+
*/
|
|
1041
|
+
chatRaw(request: unknown): Promise<LLMResponseIR>;
|
|
1042
|
+
/**
|
|
1043
|
+
* Send a streaming chat request
|
|
1044
|
+
* Returns SSE events in inbound adapter's format
|
|
1045
|
+
*/
|
|
1046
|
+
chatStream(request: unknown): AsyncIterable<SSEEvent>;
|
|
1047
|
+
/**
|
|
1048
|
+
* Send a streaming chat request (raw IR events)
|
|
1049
|
+
* Returns raw IR stream events for custom processing
|
|
1050
|
+
*/
|
|
1051
|
+
chatStreamRaw(request: unknown): AsyncIterable<LLMStreamEvent>;
|
|
1052
|
+
/**
|
|
1053
|
+
* Process SSE lines and yield stream events
|
|
1054
|
+
* @private
|
|
1055
|
+
*/
|
|
1056
|
+
private processSSELines;
|
|
1057
|
+
/**
|
|
1058
|
+
* List available models from the provider
|
|
1059
|
+
*/
|
|
1060
|
+
listModels(): Promise<unknown>;
|
|
1061
|
+
/**
|
|
1062
|
+
* Check compatibility between adapters
|
|
1063
|
+
*/
|
|
1064
|
+
checkCompatibility(): CompatibilityReport;
|
|
1065
|
+
/**
|
|
1066
|
+
* Get adapter information
|
|
1067
|
+
*/
|
|
1068
|
+
getAdapters(): {
|
|
1069
|
+
inbound: {
|
|
1070
|
+
name: string;
|
|
1071
|
+
version: string;
|
|
1072
|
+
};
|
|
1073
|
+
outbound: {
|
|
1074
|
+
name: string;
|
|
1075
|
+
version: string;
|
|
1076
|
+
};
|
|
1077
|
+
};
|
|
1078
|
+
/**
|
|
1079
|
+
* Get default base URL from outbound adapter
|
|
1080
|
+
* Note: config.baseURL is checked before calling this method
|
|
1081
|
+
*/
|
|
1082
|
+
private getDefaultBaseURL;
|
|
1083
|
+
/**
|
|
1084
|
+
* Get chat endpoint path
|
|
1085
|
+
* Supports dynamic model replacement for endpoints like /v1beta/models/{model}:generateContent
|
|
1086
|
+
* Priority: config.chatPath > adapter.endpoint.chatPath
|
|
1087
|
+
*/
|
|
1088
|
+
private getEndpoint;
|
|
1089
|
+
/**
|
|
1090
|
+
* Get models endpoint path
|
|
1091
|
+
* Priority: config.modelsPath > adapter.endpoint.modelsPath
|
|
1092
|
+
*/
|
|
1093
|
+
private getModelsPath;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
/**
|
|
1097
|
+
* Create a new Amux Bridge instance
|
|
1098
|
+
*
|
|
1099
|
+
* @example
|
|
1100
|
+
* ```typescript
|
|
1101
|
+
* import { createBridge } from '@amux.ai/llm-bridge'
|
|
1102
|
+
* import { openaiAdapter } from '@amux.ai/adapter-openai'
|
|
1103
|
+
* import { anthropicAdapter } from '@amux.ai/adapter-anthropic'
|
|
1104
|
+
*
|
|
1105
|
+
* const bridge = createBridge({
|
|
1106
|
+
* inbound: openaiAdapter,
|
|
1107
|
+
* outbound: anthropicAdapter,
|
|
1108
|
+
* config: {
|
|
1109
|
+
* apiKey: process.env.ANTHROPIC_API_KEY,
|
|
1110
|
+
* }
|
|
1111
|
+
* })
|
|
1112
|
+
*
|
|
1113
|
+
* const response = await bridge.chat({
|
|
1114
|
+
* model: 'gpt-4',
|
|
1115
|
+
* messages: [{ role: 'user', content: 'Hello!' }]
|
|
1116
|
+
* })
|
|
1117
|
+
* ```
|
|
1118
|
+
*/
|
|
1119
|
+
declare function createBridge(options: BridgeOptions): LLMBridge;
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* Simple HTTP client for making requests to LLM APIs
|
|
1123
|
+
*/
|
|
1124
|
+
declare class HTTPClient {
|
|
1125
|
+
private defaultHeaders;
|
|
1126
|
+
private defaultTimeout;
|
|
1127
|
+
private maxRetries;
|
|
1128
|
+
private provider;
|
|
1129
|
+
private maxResponseSize;
|
|
1130
|
+
constructor(options?: {
|
|
1131
|
+
headers?: Record<string, string>;
|
|
1132
|
+
timeout?: number;
|
|
1133
|
+
maxRetries?: number;
|
|
1134
|
+
provider?: string;
|
|
1135
|
+
maxResponseSize?: number;
|
|
1136
|
+
});
|
|
1137
|
+
/**
|
|
1138
|
+
* Determine if a status code should be retried
|
|
1139
|
+
* @private
|
|
1140
|
+
*/
|
|
1141
|
+
private shouldRetry;
|
|
1142
|
+
/**
|
|
1143
|
+
* Calculate backoff delay with jitter
|
|
1144
|
+
* @private
|
|
1145
|
+
*/
|
|
1146
|
+
private getBackoffDelay;
|
|
1147
|
+
/**
|
|
1148
|
+
* Make an HTTP request with retry logic
|
|
1149
|
+
*/
|
|
1150
|
+
request<T = unknown>(options: HTTPRequestOptions, retries?: number): Promise<HTTPResponse<T>>;
|
|
1151
|
+
/**
|
|
1152
|
+
* Make a streaming HTTP request
|
|
1153
|
+
*/
|
|
1154
|
+
requestStream(options: HTTPRequestOptions): AsyncIterable<string>;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* Base error class for all Amux errors
|
|
1159
|
+
*/
|
|
1160
|
+
declare class LLMBridgeError extends Error {
|
|
1161
|
+
code: string;
|
|
1162
|
+
retryable: boolean;
|
|
1163
|
+
details?: unknown;
|
|
1164
|
+
constructor(message: string, code: string, retryable?: boolean, details?: unknown);
|
|
1165
|
+
}
|
|
1166
|
+
/**
|
|
1167
|
+
* Error from provider API calls
|
|
1168
|
+
*/
|
|
1169
|
+
declare class APIError extends LLMBridgeError {
|
|
1170
|
+
status: number;
|
|
1171
|
+
provider: string;
|
|
1172
|
+
data?: unknown;
|
|
1173
|
+
response?: {
|
|
1174
|
+
headers?: Record<string, string>;
|
|
1175
|
+
};
|
|
1176
|
+
constructor(message: string, status: number, provider: string, data?: unknown, response?: {
|
|
1177
|
+
headers?: Record<string, string>;
|
|
1178
|
+
});
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Network-related errors (connection failures, timeouts, etc.)
|
|
1182
|
+
*/
|
|
1183
|
+
declare class NetworkError extends LLMBridgeError {
|
|
1184
|
+
cause?: unknown;
|
|
1185
|
+
constructor(message: string, cause?: unknown);
|
|
1186
|
+
}
|
|
1187
|
+
/**
|
|
1188
|
+
* Request timeout errors
|
|
1189
|
+
*/
|
|
1190
|
+
declare class TimeoutError extends LLMBridgeError {
|
|
1191
|
+
timeout: number;
|
|
1192
|
+
constructor(message: string, timeout: number);
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Validation errors (invalid request format, missing required fields, etc.)
|
|
1196
|
+
*/
|
|
1197
|
+
declare class ValidationError extends LLMBridgeError {
|
|
1198
|
+
errors: string[];
|
|
1199
|
+
constructor(message: string, errors: string[]);
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Adapter-related errors (conversion failures, unsupported features, etc.)
|
|
1203
|
+
*/
|
|
1204
|
+
declare class AdapterError extends LLMBridgeError {
|
|
1205
|
+
adapterName: string;
|
|
1206
|
+
constructor(message: string, adapterName: string, details?: unknown);
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Bridge orchestration errors
|
|
1210
|
+
*/
|
|
1211
|
+
declare class BridgeError extends LLMBridgeError {
|
|
1212
|
+
constructor(message: string, details?: unknown);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
/**
|
|
1216
|
+
* Efficient SSE (Server-Sent Events) line parser
|
|
1217
|
+
* Handles incomplete chunks and extracts complete lines efficiently
|
|
1218
|
+
*/
|
|
1219
|
+
declare class SSELineParser {
|
|
1220
|
+
private buffer;
|
|
1221
|
+
/**
|
|
1222
|
+
* Process a chunk of SSE data and extract complete lines
|
|
1223
|
+
* @param chunk - The data chunk to process
|
|
1224
|
+
* @returns Array of complete lines
|
|
1225
|
+
*/
|
|
1226
|
+
processChunk(chunk: string): string[];
|
|
1227
|
+
/**
|
|
1228
|
+
* Extract all complete lines from the buffer
|
|
1229
|
+
* Incomplete lines remain in the buffer
|
|
1230
|
+
* @private
|
|
1231
|
+
*/
|
|
1232
|
+
private extractLines;
|
|
1233
|
+
/**
|
|
1234
|
+
* Get any remaining data in the buffer and clear it
|
|
1235
|
+
* Call this when the stream ends to get the last incomplete line
|
|
1236
|
+
*/
|
|
1237
|
+
flush(): string[];
|
|
1238
|
+
/**
|
|
1239
|
+
* Check if buffer has any remaining data
|
|
1240
|
+
*/
|
|
1241
|
+
hasRemaining(): boolean;
|
|
1242
|
+
/**
|
|
1243
|
+
* Clear the buffer
|
|
1244
|
+
*/
|
|
1245
|
+
clear(): void;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
/**
|
|
1249
|
+
* Map finish reason string to IR finish reason
|
|
1250
|
+
* @param reason - The finish reason string from the provider
|
|
1251
|
+
* @param customMappings - Optional custom mappings to extend/override standard mappings
|
|
1252
|
+
* @param defaultReason - Default reason if not found (default: 'stop')
|
|
1253
|
+
*/
|
|
1254
|
+
declare function mapFinishReason(reason?: string, customMappings?: Record<string, FinishReason>, defaultReason?: FinishReason): FinishReason;
|
|
1255
|
+
/**
|
|
1256
|
+
* Map error type or code string to IR error type
|
|
1257
|
+
* @param type - The error type string from the provider
|
|
1258
|
+
* @param code - The error code string from the provider (optional)
|
|
1259
|
+
* @param customTypeMappings - Optional custom type mappings to extend/override standard mappings
|
|
1260
|
+
* @param customCodeMappings - Optional custom code mappings to extend/override standard mappings
|
|
1261
|
+
*/
|
|
1262
|
+
declare function mapErrorType(type?: string, code?: string, customTypeMappings?: Record<string, ErrorType>, customCodeMappings?: Record<string, ErrorType>): ErrorType;
|
|
1263
|
+
/**
|
|
1264
|
+
* Parse OpenAI-compatible error response to IR
|
|
1265
|
+
* Works for OpenAI, DeepSeek, Moonshot, Qwen, Zhipu, and other compatible APIs
|
|
1266
|
+
*
|
|
1267
|
+
* @param error - The error object from the provider
|
|
1268
|
+
* @param customTypeMappings - Optional custom error type mappings
|
|
1269
|
+
* @param customCodeMappings - Optional custom error code mappings
|
|
1270
|
+
*/
|
|
1271
|
+
declare function parseOpenAICompatibleError(error: unknown, customTypeMappings?: Record<string, ErrorType>, customCodeMappings?: Record<string, ErrorType>): LLMErrorIR;
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* Convert message content to string
|
|
1275
|
+
* Used by response builders to convert IR content to provider format
|
|
1276
|
+
*
|
|
1277
|
+
* @param content - Message content (string or ContentPart array)
|
|
1278
|
+
* @returns String content or null if empty
|
|
1279
|
+
*/
|
|
1280
|
+
declare function contentToString(content: MessageContent): string | null;
|
|
1281
|
+
/**
|
|
1282
|
+
* Check if content contains only text
|
|
1283
|
+
* @param content - Message content
|
|
1284
|
+
* @returns True if content is string or contains only text parts
|
|
1285
|
+
*/
|
|
1286
|
+
declare function isTextOnlyContent(content: MessageContent): boolean;
|
|
1287
|
+
/**
|
|
1288
|
+
* Extract text from content
|
|
1289
|
+
* @param content - Message content
|
|
1290
|
+
* @returns Array of text strings
|
|
1291
|
+
*/
|
|
1292
|
+
declare function extractTextFromContent(content: MessageContent): string[];
|
|
1293
|
+
/**
|
|
1294
|
+
* Check if content has images
|
|
1295
|
+
* @param content - Message content
|
|
1296
|
+
* @returns True if content contains image parts
|
|
1297
|
+
*/
|
|
1298
|
+
declare function hasImageContent(content: MessageContent): boolean;
|
|
1299
|
+
|
|
1300
|
+
/**
|
|
1301
|
+
* Standard OpenAI-compatible usage object structure
|
|
1302
|
+
*/
|
|
1303
|
+
interface StandardUsage {
|
|
1304
|
+
prompt_tokens: number;
|
|
1305
|
+
completion_tokens: number;
|
|
1306
|
+
total_tokens: number;
|
|
1307
|
+
completion_tokens_details?: {
|
|
1308
|
+
reasoning_tokens?: number;
|
|
1309
|
+
};
|
|
1310
|
+
prompt_cache_hit_tokens?: number;
|
|
1311
|
+
prompt_cache_miss_tokens?: number;
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Parse OpenAI-compatible usage to IR usage
|
|
1315
|
+
* @param usage - Usage object from provider response
|
|
1316
|
+
* @returns IR usage object or undefined
|
|
1317
|
+
*/
|
|
1318
|
+
declare function parseOpenAIUsage(usage?: StandardUsage): Usage | undefined;
|
|
1319
|
+
/**
|
|
1320
|
+
* Build OpenAI-compatible usage from IR usage
|
|
1321
|
+
* @param usage - IR usage object
|
|
1322
|
+
* @param includeReasoningTokens - Whether to include reasoning tokens (default: true)
|
|
1323
|
+
* @param includeCacheTokens - Whether to include cache tokens (default: false)
|
|
1324
|
+
* @returns OpenAI-compatible usage object or undefined
|
|
1325
|
+
*/
|
|
1326
|
+
declare function buildOpenAIUsage(usage?: Usage, includeReasoningTokens?: boolean, includeCacheTokens?: boolean): StandardUsage | undefined;
|
|
1327
|
+
|
|
1328
|
+
export { APIError, type AdapterCapabilities, AdapterError, type AdapterInfo, AdapterRegistry, Bridge, type BridgeConfig, BridgeError, type BridgeHooks, type BridgeOptions, type Choice, type CompatibilityReport, type ContentDelta, type ContentPart, type ErrorHandler, type ErrorType, type FinishReason, type FunctionDefinition, type GenerationConfig, HTTPClient, type HTTPRequestOptions, type HTTPResponse, type ImageContent, type ImageSource, type JSONSchema, type LLMAdapter, type LLMBridge, LLMBridgeError, type LLMErrorIR, type LLMRequestIR, type LLMResponseIR, type LLMStreamEvent, type Message, type MessageContent, NetworkError, type ProviderEndpoint, type ReasoningDelta, type ResponseFormat, type Role, type SSEEvent, SSELineParser, type StandardUsage, type StreamEventBuilder, type StreamEventType, type StreamHandler, type TextContent, type ThinkingConfig, TimeoutError, type Tool, type ToolCall, type ToolCallDelta, type ToolChoice, type Usage, ValidationError, type ValidationResult, buildOpenAIUsage, contentToString, createBridge, extractTextFromContent, globalRegistry, hasImageContent, isTextOnlyContent, mapErrorType, mapFinishReason, parseOpenAICompatibleError, parseOpenAIUsage };
|