@doclo/providers-llm 0.1.5

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.
@@ -0,0 +1,1421 @@
1
+ import { JSONSchemaType } from 'ajv';
2
+ import { ObservabilityConfig, TraceContext } from '@doclo/core/observability';
3
+ import { LLMJsonProvider, VLMProvider } from '@doclo/core';
4
+
5
+ /** Unified internal schema (standard JSON Schema) */
6
+ type UnifiedSchema<T = any> = JSONSchemaType<T>;
7
+ /** Provider types - 'x-ai' is an alias for 'xai' */
8
+ type ProviderType = 'openai' | 'anthropic' | 'google' | 'xai' | 'x-ai';
9
+ /** Access method */
10
+ type AccessMethod = 'openrouter' | 'native';
11
+ /** Resource limit configuration (optional overrides for defaults) */
12
+ interface ResourceLimits {
13
+ /**
14
+ * Maximum file size in bytes (default: 100MB)
15
+ *
16
+ * SECURITY WARNING: Increasing this limit can expose your application
17
+ * to memory exhaustion attacks. Only increase if you control the input sources.
18
+ */
19
+ maxFileSize?: number;
20
+ /**
21
+ * Request timeout in milliseconds (default: 30000ms / 30 seconds)
22
+ *
23
+ * SECURITY WARNING: Increasing this timeout can cause hung requests.
24
+ * Only increase for known slow endpoints (e.g., processing large files).
25
+ */
26
+ requestTimeout?: number;
27
+ /**
28
+ * Maximum JSON nesting depth (default: 100)
29
+ *
30
+ * SECURITY WARNING: Deeply nested JSON can cause stack overflows.
31
+ * Only increase if you're processing complex nested structures.
32
+ */
33
+ maxJsonDepth?: number;
34
+ }
35
+ /** Provider configuration */
36
+ interface ProviderConfig {
37
+ provider: ProviderType;
38
+ model: string;
39
+ via?: AccessMethod;
40
+ apiKey: string;
41
+ baseUrl?: string;
42
+ limits?: ResourceLimits;
43
+ }
44
+ /** Fallback configuration */
45
+ interface FallbackConfig {
46
+ providers: ProviderConfig[];
47
+ maxRetries: number;
48
+ primaryMaxRetries?: number;
49
+ retryDelay: number;
50
+ useExponentialBackoff: boolean;
51
+ circuitBreakerThreshold?: number;
52
+ }
53
+ /** Image input */
54
+ interface ImageInput {
55
+ url?: string;
56
+ base64?: string;
57
+ mimeType: 'image/jpeg' | 'image/png' | 'image/webp' | 'image/gif';
58
+ }
59
+ /** PDF input */
60
+ interface PDFInput {
61
+ url?: string;
62
+ base64?: string;
63
+ fileId?: string;
64
+ }
65
+ /** Multimodal input (unified) */
66
+ interface MultimodalInput {
67
+ text?: string;
68
+ images?: ImageInput[];
69
+ pdfs?: PDFInput[];
70
+ }
71
+ /** Response metrics */
72
+ interface ResponseMetrics {
73
+ costUSD?: number;
74
+ inputTokens?: number;
75
+ outputTokens?: number;
76
+ latencyMs: number;
77
+ attemptNumber: number;
78
+ provider: string;
79
+ model: string;
80
+ cacheCreationInputTokens?: number;
81
+ cacheReadInputTokens?: number;
82
+ httpStatusCode?: number;
83
+ httpMethod?: string;
84
+ httpUrl?: string;
85
+ responseId?: string;
86
+ finishReason?: string;
87
+ modelUsed?: string;
88
+ }
89
+ /** LLM response */
90
+ interface LLMResponse<T = unknown> {
91
+ json: T;
92
+ rawText?: string;
93
+ metrics: ResponseMetrics;
94
+ reasoning?: string;
95
+ reasoning_details?: ReasoningDetail[];
96
+ }
97
+ /** Provider capability flags */
98
+ interface ProviderCapabilities {
99
+ supportsStructuredOutput: boolean;
100
+ supportsStreaming: boolean;
101
+ supportsImages: boolean;
102
+ supportsPDFs: boolean;
103
+ maxPDFPages?: number;
104
+ maxPDFSize?: number;
105
+ maxContextTokens?: number;
106
+ }
107
+ /** JSON output mode */
108
+ type JsonMode = 'strict' | 'relaxed';
109
+ /** Provider interface */
110
+ interface LLMProvider {
111
+ readonly name: string;
112
+ readonly capabilities: ProviderCapabilities;
113
+ completeJson<T>(params: {
114
+ input: MultimodalInput;
115
+ schema?: UnifiedSchema<T>;
116
+ mode?: JsonMode;
117
+ max_tokens?: number;
118
+ reasoning?: ReasoningConfig;
119
+ embedSchemaInPrompt?: boolean;
120
+ }): Promise<LLMResponse<T>>;
121
+ }
122
+ /** Reasoning configuration (normalized across providers) */
123
+ interface ReasoningConfig {
124
+ effort?: 'low' | 'medium' | 'high';
125
+ exclude?: boolean;
126
+ enabled?: boolean;
127
+ }
128
+ /** Reasoning detail types (from OpenRouter API) */
129
+ type ReasoningDetail = {
130
+ type: 'reasoning.summary';
131
+ summary: string;
132
+ id: string | null;
133
+ format: string;
134
+ index?: number;
135
+ } | {
136
+ type: 'reasoning.encrypted';
137
+ data: string;
138
+ id: string | null;
139
+ format: string;
140
+ index?: number;
141
+ } | {
142
+ type: 'reasoning.text';
143
+ text: string;
144
+ signature?: string | null;
145
+ id: string | null;
146
+ format: string;
147
+ index?: number;
148
+ };
149
+ /** Circuit breaker state */
150
+ interface CircuitBreakerState {
151
+ consecutiveFailures: number;
152
+ lastFailureTime?: number;
153
+ isOpen: boolean;
154
+ }
155
+
156
+ /**
157
+ * Internal JSON Schema representation for schema translation.
158
+ * This is more flexible than JSONSchemaNode to accommodate:
159
+ * - Zod schema markers (~standard, _def)
160
+ * - Provider-specific extensions (propertyOrdering)
161
+ * - Intermediate conversion states
162
+ */
163
+ interface FlexibleSchemaNode {
164
+ type?: string | string[];
165
+ properties?: Record<string, FlexibleSchemaNode>;
166
+ items?: FlexibleSchemaNode | FlexibleSchemaNode[];
167
+ required?: string[];
168
+ enum?: (string | number | boolean | null)[];
169
+ nullable?: boolean;
170
+ anyOf?: FlexibleSchemaNode[];
171
+ oneOf?: FlexibleSchemaNode[];
172
+ allOf?: FlexibleSchemaNode[];
173
+ additionalProperties?: boolean | FlexibleSchemaNode;
174
+ description?: string;
175
+ format?: string;
176
+ default?: unknown;
177
+ $schema?: string;
178
+ $defs?: Record<string, FlexibleSchemaNode>;
179
+ definitions?: Record<string, FlexibleSchemaNode>;
180
+ '~standard'?: {
181
+ vendor: string;
182
+ [key: string]: unknown;
183
+ };
184
+ _def?: unknown;
185
+ propertyOrdering?: string[];
186
+ [key: string]: unknown;
187
+ }
188
+ /**
189
+ * Translates unified JSON Schema to provider-specific formats
190
+ */
191
+ declare class SchemaTranslator {
192
+ /**
193
+ * Unified → OpenAI/Grok (standard JSON Schema)
194
+ * OpenAI strict mode doesn't support nullable: true
195
+ * Must convert to anyOf: [{ type: "string" }, { type: "null" }]
196
+ */
197
+ toOpenAISchema<T>(schema: UnifiedSchema<T>): object;
198
+ /**
199
+ * Detect if schema is a Zod schema and convert to JSON Schema
200
+ * Public method to allow embedding schemas in prompts
201
+ */
202
+ convertZodIfNeeded(schema: FlexibleSchemaNode | unknown): FlexibleSchemaNode;
203
+ /**
204
+ * Convert nullable fields to anyOf format for OpenAI strict mode
205
+ * nullable: true is not supported, must use anyOf with null type
206
+ */
207
+ private convertNullableToAnyOf;
208
+ /**
209
+ * Unified → Claude (Tool Input Schema format)
210
+ * Claude requires tool calling with input_schema
211
+ * Claude supports nullable: true directly
212
+ */
213
+ toClaudeToolSchema<T>(schema: UnifiedSchema<T>): object;
214
+ /**
215
+ * Unified → Claude for OpenRouter
216
+ * When using Claude via OpenRouter, use anyOf format like OpenAI
217
+ */
218
+ toClaudeOpenRouterSchema<T>(schema: UnifiedSchema<T>): object;
219
+ /**
220
+ * Unified → Gemini (OpenAPI 3.0 subset with propertyOrdering)
221
+ * Gemini uses a subset of OpenAPI 3.0 schema
222
+ */
223
+ toGeminiSchema<T>(schema: UnifiedSchema<T>): object;
224
+ /**
225
+ * Convert individual property to Gemini format
226
+ */
227
+ private convertPropertyToGemini;
228
+ }
229
+
230
+ /**
231
+ * Utility for converting JSON Schema to human-readable prompt text
232
+ * that emphasizes exact field name requirements for structured extraction.
233
+ */
234
+ /**
235
+ * JSON Schema type used for prompt formatting.
236
+ * Uses a recursive structure to support nested schemas.
237
+ */
238
+ interface JSONSchema {
239
+ type?: string | string[];
240
+ properties?: Record<string, JSONSchema>;
241
+ items?: JSONSchema | JSONSchema[];
242
+ description?: string;
243
+ required?: string[];
244
+ enum?: (string | number | boolean | null)[];
245
+ anyOf?: JSONSchema[];
246
+ oneOf?: JSONSchema[];
247
+ allOf?: JSONSchema[];
248
+ format?: string;
249
+ [key: string]: unknown;
250
+ }
251
+ /**
252
+ * Formats a JSON Schema into prompt text that emphasizes exact field names.
253
+ * This helps LLMs understand they must use the exact field names specified
254
+ * in the schema, not invent their own based on document content.
255
+ */
256
+ declare function formatSchemaForPrompt(schema: JSONSchema, indent?: number): string;
257
+ /**
258
+ * Generates a complete prompt section with schema information and
259
+ * strict field name instructions.
260
+ */
261
+ declare function buildSchemaPromptSection(schema: JSONSchema): string;
262
+ /**
263
+ * Combines schema prompt section with user's custom prompt
264
+ */
265
+ declare function combineSchemaAndUserPrompt(schema: JSONSchema, userPrompt: string): string;
266
+
267
+ /**
268
+ * Factory function type for creating provider instances
269
+ */
270
+ type ProviderFactory = (config: ProviderConfig) => LLMProvider;
271
+ /**
272
+ * Provider registry for dynamic provider loading
273
+ *
274
+ * This allows provider packages to register themselves when imported,
275
+ * avoiding hardcoded imports in the core package.
276
+ */
277
+ declare class ProviderRegistry {
278
+ private factories;
279
+ /**
280
+ * Register a provider factory
281
+ * Called by each provider package when it's imported
282
+ */
283
+ register(type: ProviderType, factory: ProviderFactory): void;
284
+ /**
285
+ * Check if a provider is registered
286
+ */
287
+ has(type: ProviderType): boolean;
288
+ /**
289
+ * Get a provider factory
290
+ */
291
+ get(type: ProviderType): ProviderFactory | undefined;
292
+ /**
293
+ * Create a provider instance
294
+ * @throws Error if provider is not registered
295
+ */
296
+ create(config: ProviderConfig): LLMProvider;
297
+ /**
298
+ * Get all registered provider types
299
+ */
300
+ getRegisteredTypes(): ProviderType[];
301
+ /**
302
+ * Clear all registrations (for testing)
303
+ */
304
+ clear(): void;
305
+ }
306
+ /**
307
+ * Global provider registry instance
308
+ */
309
+ declare const providerRegistry: ProviderRegistry;
310
+ /**
311
+ * Register a provider factory
312
+ * Convenience function for provider packages
313
+ */
314
+ declare function registerProvider(type: ProviderType, factory: ProviderFactory): void;
315
+ /**
316
+ * Create a provider instance from the registry
317
+ */
318
+ declare function createProviderFromRegistry(config: ProviderConfig): LLMProvider;
319
+
320
+ declare class OpenAIProvider implements LLMProvider {
321
+ readonly name: string;
322
+ readonly capabilities: ProviderCapabilities;
323
+ private config;
324
+ private translator;
325
+ private limits;
326
+ constructor(config: ProviderConfig);
327
+ completeJson<T>(params: {
328
+ input: MultimodalInput;
329
+ schema?: UnifiedSchema<T>;
330
+ mode?: JsonMode;
331
+ max_tokens?: number;
332
+ reasoning?: ReasoningConfig;
333
+ embedSchemaInPrompt?: boolean;
334
+ }): Promise<LLMResponse<T>>;
335
+ private buildReasoningConfig;
336
+ private buildMessages;
337
+ /**
338
+ * Extract base64 data from a data URL or return as-is if already raw base64
339
+ */
340
+ private extractBase64;
341
+ private calculateCost;
342
+ }
343
+
344
+ declare class AnthropicProvider implements LLMProvider {
345
+ readonly name: string;
346
+ readonly capabilities: ProviderCapabilities;
347
+ private config;
348
+ private translator;
349
+ private limits;
350
+ constructor(config: ProviderConfig);
351
+ completeJson<T>(params: {
352
+ input: MultimodalInput;
353
+ schema?: UnifiedSchema<T>;
354
+ mode?: JsonMode;
355
+ max_tokens?: number;
356
+ reasoning?: ReasoningConfig;
357
+ embedSchemaInPrompt?: boolean;
358
+ }): Promise<LLMResponse<T>>;
359
+ private buildNativeThinkingConfig;
360
+ private translateToOpenRouterFormat;
361
+ private buildReasoningConfig;
362
+ private supportsNewStructuredOutputs;
363
+ private fixSchemaForStrictMode;
364
+ private buildMessages;
365
+ private urlToBase64;
366
+ /**
367
+ * Extract base64 data from a data URL or return as-is if already raw base64
368
+ */
369
+ private extractBase64;
370
+ private calculateCost;
371
+ /**
372
+ * Detect if a parsed JSON object looks like unwrapped JSON Schema properties
373
+ * (e.g., missing the root "type": "object" and "properties": {...} wrapper)
374
+ */
375
+ private looksLikeUnwrappedProperties;
376
+ /**
377
+ * Wrap unwrapped properties into a proper JSON Schema structure
378
+ */
379
+ private wrapAsSchema;
380
+ }
381
+
382
+ declare class GoogleProvider implements LLMProvider {
383
+ readonly name: string;
384
+ readonly capabilities: ProviderCapabilities;
385
+ private config;
386
+ private translator;
387
+ private limits;
388
+ constructor(config: ProviderConfig);
389
+ completeJson<T>(params: {
390
+ input: MultimodalInput;
391
+ schema?: UnifiedSchema<T>;
392
+ mode?: JsonMode;
393
+ max_tokens?: number;
394
+ reasoning?: ReasoningConfig;
395
+ embedSchemaInPrompt?: boolean;
396
+ }): Promise<LLMResponse<T>>;
397
+ private buildNativeThinkingConfig;
398
+ private translateToOpenRouterFormat;
399
+ private buildReasoningConfig;
400
+ private buildContents;
401
+ private urlToBase64;
402
+ /**
403
+ * Extract base64 data from a data URL or return as-is if already raw base64
404
+ */
405
+ private extractBase64;
406
+ private calculateCost;
407
+ }
408
+
409
+ declare class XAIProvider implements LLMProvider {
410
+ readonly name: string;
411
+ readonly capabilities: ProviderCapabilities;
412
+ private config;
413
+ private translator;
414
+ private limits;
415
+ constructor(config: ProviderConfig);
416
+ completeJson<T>(params: {
417
+ input: MultimodalInput;
418
+ schema?: UnifiedSchema<T>;
419
+ mode?: JsonMode;
420
+ max_tokens?: number;
421
+ reasoning?: ReasoningConfig;
422
+ embedSchemaInPrompt?: boolean;
423
+ }): Promise<LLMResponse<T>>;
424
+ private buildReasoningConfig;
425
+ private buildMessages;
426
+ /**
427
+ * Extract base64 data from a data URL or return as-is if already raw base64
428
+ */
429
+ private extractBase64;
430
+ private calculateCost;
431
+ }
432
+
433
+ declare class FallbackManager {
434
+ private config;
435
+ private circuitBreakers;
436
+ constructor(config: FallbackConfig);
437
+ executeWithFallback<T>(input: MultimodalInput, schema: UnifiedSchema<T>, max_tokens?: number, reasoning?: ReasoningConfig, mode?: JsonMode, observability?: {
438
+ config?: ObservabilityConfig;
439
+ flowId?: string;
440
+ executionId?: string;
441
+ stepId?: string;
442
+ traceContext?: TraceContext;
443
+ metadata?: Record<string, unknown>;
444
+ }): Promise<LLMResponse<T>>;
445
+ private createProvider;
446
+ private validateResponse;
447
+ private isRetryable;
448
+ private calculateDelay;
449
+ private sleep;
450
+ private isCircuitOpen;
451
+ private recordSuccess;
452
+ private recordFailure;
453
+ }
454
+
455
+ /**
456
+ * Adapter to make new LLMProvider compatible with core LLMJsonProvider interface
457
+ */
458
+ declare function adaptToCoreLLMProvider(provider: LLMProvider): LLMJsonProvider;
459
+
460
+ /**
461
+ * LLM Provider Metadata
462
+ *
463
+ * Comprehensive metadata for all LLM/VLM providers including:
464
+ * - Supported file types (inline/base64 encoded)
465
+ * - Input/output formats
466
+ * - Pricing
467
+ * - Capabilities
468
+ * - Native API vs OpenRouter differences
469
+ */
470
+ declare const SUPPORTED_IMAGE_TYPES: {
471
+ readonly COMMON: readonly ["image/png", "image/jpeg", "image/webp", "image/gif"];
472
+ readonly EXTENDED: readonly ["image/png", "image/jpeg", "image/webp", "image/gif", "image/bmp", "image/tiff", "image/heif"];
473
+ };
474
+ /**
475
+ * Input type requirements for providers.
476
+ * - 'raw-document': Needs FlowInput with base64/url
477
+ * - 'parsed-text': Needs DocumentIR text output
478
+ * - 'any': Can work with either (LLM providers with vision)
479
+ */
480
+ type ProviderInputType = 'raw-document' | 'parsed-text' | 'any';
481
+ /**
482
+ * Model-level metadata for per-model capability overrides
483
+ */
484
+ type LLMModelMetadata = {
485
+ /** Model ID as used in API calls */
486
+ id: string;
487
+ /** Human-readable name */
488
+ name?: string;
489
+ /** OpenRouter model ID (e.g., 'openai/gpt-4.1') */
490
+ openRouterId: string;
491
+ /** Capability overrides (inherit from provider if unset) */
492
+ capabilities?: {
493
+ supportsReasoning?: boolean;
494
+ supportsImages?: boolean;
495
+ supportsPDFs?: boolean;
496
+ supportsStructuredOutput?: boolean;
497
+ };
498
+ /** Model-specific limits */
499
+ limits?: {
500
+ maxContextTokens?: number;
501
+ maxOutputTokens?: number;
502
+ };
503
+ /** Model-specific pricing (USD per 1k tokens) */
504
+ pricing?: {
505
+ inputPer1k?: number;
506
+ outputPer1k?: number;
507
+ };
508
+ };
509
+ type LLMProviderMetadata = {
510
+ id: string;
511
+ name: string;
512
+ vendor: 'openai' | 'anthropic' | 'google' | 'xai';
513
+ models: string[];
514
+ /**
515
+ * Detailed per-model metadata with capability overrides.
516
+ * Use this for model-specific reasoning, pricing, and limits.
517
+ */
518
+ detailedModels?: LLMModelMetadata[];
519
+ accessMethods: {
520
+ native: {
521
+ available: boolean;
522
+ endpoint: string;
523
+ requiresApiKey: boolean;
524
+ };
525
+ openrouter: {
526
+ available: boolean;
527
+ modelPrefix: string;
528
+ };
529
+ };
530
+ capabilities: {
531
+ supportsImages: boolean;
532
+ supportsPDFs: boolean;
533
+ supportsReasoning: boolean;
534
+ supportsStreaming: boolean;
535
+ supportsStructuredOutput: boolean;
536
+ };
537
+ /**
538
+ * Input requirements for this provider.
539
+ * LLM providers with vision can accept either raw documents OR parsed text.
540
+ */
541
+ inputRequirements?: {
542
+ inputType: ProviderInputType;
543
+ acceptedMethods?: readonly ('url' | 'base64')[];
544
+ };
545
+ compatibleNodes: {
546
+ parse: boolean;
547
+ extract: boolean;
548
+ categorize: boolean;
549
+ qualify: boolean;
550
+ split: boolean;
551
+ };
552
+ inputFormats: {
553
+ images: {
554
+ mimeTypes: readonly string[];
555
+ methods: ('url' | 'base64')[];
556
+ maxSize?: number;
557
+ maxDimensions?: {
558
+ width: number;
559
+ height: number;
560
+ };
561
+ notes?: string;
562
+ };
563
+ pdfs: {
564
+ supported: boolean;
565
+ methods: ('url' | 'base64' | 'fileId')[];
566
+ maxSize?: number;
567
+ maxPages?: number;
568
+ notes?: string;
569
+ };
570
+ };
571
+ outputFormat: {
572
+ supportsJSON: boolean;
573
+ supportsReasoning: boolean;
574
+ tokenTracking: boolean;
575
+ costTracking: boolean;
576
+ };
577
+ pricing: {
578
+ model: 'per-token';
579
+ inputPer1k: number;
580
+ outputPer1k: number;
581
+ currency: 'USD';
582
+ notes?: string;
583
+ };
584
+ limits: {
585
+ maxContextTokens: number;
586
+ maxOutputTokens?: number;
587
+ requestsPerMinute?: number;
588
+ };
589
+ nativeAPI: {
590
+ imageFormat: string;
591
+ pdfFormat: string;
592
+ reasoningConfig: string;
593
+ };
594
+ openRouterAPI: {
595
+ imageFormat: string;
596
+ pdfFormat: string;
597
+ reasoningConfig: string;
598
+ differences: string[];
599
+ };
600
+ };
601
+ declare const PROVIDER_METADATA: {
602
+ readonly openai: {
603
+ readonly id: "openai";
604
+ readonly name: "OpenAI";
605
+ readonly vendor: "openai";
606
+ readonly models: ["gpt-5.1", "gpt-4.1", "gpt-4.1-mini", "o3", "o3-mini", "o4-mini"];
607
+ readonly detailedModels: [{
608
+ readonly id: "gpt-4.1";
609
+ readonly name: "GPT-4.1";
610
+ readonly openRouterId: "openai/gpt-4.1";
611
+ readonly capabilities: {
612
+ readonly supportsReasoning: false;
613
+ };
614
+ readonly limits: {
615
+ readonly maxContextTokens: 128000;
616
+ readonly maxOutputTokens: 16384;
617
+ };
618
+ readonly pricing: {
619
+ readonly inputPer1k: 0.002;
620
+ readonly outputPer1k: 0.008;
621
+ };
622
+ }, {
623
+ readonly id: "gpt-4.1-mini";
624
+ readonly name: "GPT-4.1 Mini";
625
+ readonly openRouterId: "openai/gpt-4.1-mini";
626
+ readonly capabilities: {
627
+ readonly supportsReasoning: false;
628
+ };
629
+ readonly limits: {
630
+ readonly maxContextTokens: 128000;
631
+ readonly maxOutputTokens: 16384;
632
+ };
633
+ readonly pricing: {
634
+ readonly inputPer1k: 0.0004;
635
+ readonly outputPer1k: 0.0016;
636
+ };
637
+ }, {
638
+ readonly id: "o3";
639
+ readonly name: "o3";
640
+ readonly openRouterId: "openai/o3";
641
+ readonly capabilities: {
642
+ readonly supportsReasoning: true;
643
+ };
644
+ readonly limits: {
645
+ readonly maxContextTokens: 200000;
646
+ readonly maxOutputTokens: 100000;
647
+ };
648
+ readonly pricing: {
649
+ readonly inputPer1k: 0.01;
650
+ readonly outputPer1k: 0.04;
651
+ };
652
+ }, {
653
+ readonly id: "o3-mini";
654
+ readonly name: "o3-mini";
655
+ readonly openRouterId: "openai/o3-mini";
656
+ readonly capabilities: {
657
+ readonly supportsReasoning: true;
658
+ };
659
+ readonly limits: {
660
+ readonly maxContextTokens: 200000;
661
+ readonly maxOutputTokens: 100000;
662
+ };
663
+ readonly pricing: {
664
+ readonly inputPer1k: 0.0011;
665
+ readonly outputPer1k: 0.0044;
666
+ };
667
+ }, {
668
+ readonly id: "o4-mini";
669
+ readonly name: "o4-mini";
670
+ readonly openRouterId: "openai/o4-mini";
671
+ readonly capabilities: {
672
+ readonly supportsReasoning: true;
673
+ };
674
+ readonly limits: {
675
+ readonly maxContextTokens: 200000;
676
+ readonly maxOutputTokens: 100000;
677
+ };
678
+ readonly pricing: {
679
+ readonly inputPer1k: 0.0011;
680
+ readonly outputPer1k: 0.0044;
681
+ };
682
+ }, {
683
+ readonly id: "gpt-5.1";
684
+ readonly name: "GPT-5.1";
685
+ readonly openRouterId: "openai/gpt-5.1";
686
+ readonly capabilities: {
687
+ readonly supportsReasoning: true;
688
+ };
689
+ readonly limits: {
690
+ readonly maxContextTokens: 256000;
691
+ readonly maxOutputTokens: 32768;
692
+ };
693
+ readonly pricing: {
694
+ readonly inputPer1k: 0.005;
695
+ readonly outputPer1k: 0.015;
696
+ };
697
+ }];
698
+ readonly accessMethods: {
699
+ readonly native: {
700
+ readonly available: true;
701
+ readonly endpoint: "https://api.openai.com/v1";
702
+ readonly requiresApiKey: true;
703
+ };
704
+ readonly openrouter: {
705
+ readonly available: true;
706
+ readonly modelPrefix: "openai/";
707
+ };
708
+ };
709
+ readonly capabilities: {
710
+ readonly supportsImages: true;
711
+ readonly supportsPDFs: true;
712
+ readonly supportsReasoning: true;
713
+ readonly supportsStreaming: true;
714
+ readonly supportsStructuredOutput: true;
715
+ };
716
+ readonly inputRequirements: {
717
+ readonly inputType: "any";
718
+ readonly acceptedMethods: readonly ["url", "base64"];
719
+ };
720
+ readonly compatibleNodes: {
721
+ readonly parse: true;
722
+ readonly extract: true;
723
+ readonly categorize: true;
724
+ readonly qualify: true;
725
+ readonly split: true;
726
+ };
727
+ readonly inputFormats: {
728
+ readonly images: {
729
+ readonly mimeTypes: readonly ["image/png", "image/jpeg", "image/webp", "image/gif"];
730
+ readonly methods: ["url", "base64"];
731
+ readonly maxSize: 20;
732
+ readonly maxDimensions: undefined;
733
+ readonly notes: "Inline via image_url with data URL or HTTP URL. Large images auto-resized.";
734
+ };
735
+ readonly pdfs: {
736
+ readonly supported: true;
737
+ readonly methods: ["base64", "fileId"];
738
+ readonly maxSize: 50;
739
+ readonly maxPages: 100;
740
+ readonly notes: "Inline via type: file with base64, or via Files API. Extracts text + images of each page. File URLs NOT supported for chat completions.";
741
+ };
742
+ };
743
+ readonly outputFormat: {
744
+ readonly supportsJSON: true;
745
+ readonly supportsReasoning: true;
746
+ readonly tokenTracking: true;
747
+ readonly costTracking: true;
748
+ };
749
+ readonly pricing: {
750
+ readonly model: "per-token";
751
+ readonly inputPer1k: 0.005;
752
+ readonly outputPer1k: 0.015;
753
+ readonly currency: "USD";
754
+ readonly notes: "Cost calculated from tokens. OpenRouter may include cost in response. GPT-4.1 baseline.";
755
+ };
756
+ readonly limits: {
757
+ readonly maxContextTokens: 128000;
758
+ readonly maxOutputTokens: 16384;
759
+ readonly requestsPerMinute: undefined;
760
+ };
761
+ readonly nativeAPI: {
762
+ readonly imageFormat: "type: \"image_url\", image_url: { url: \"data:image/jpeg;base64,...\" }";
763
+ readonly pdfFormat: "type: \"file\", file: { file_id: \"...\" } OR file: { filename: \"...\", file_data: \"data:application/pdf;base64,...\" }";
764
+ readonly reasoningConfig: "reasoning: { effort: \"low\"|\"medium\"|\"high\", exclude?: boolean }";
765
+ };
766
+ readonly openRouterAPI: {
767
+ readonly imageFormat: "Same as native (OpenAI-compatible)";
768
+ readonly pdfFormat: "Same as native (OpenAI-compatible)";
769
+ readonly reasoningConfig: "Same as native (OpenAI-compatible)";
770
+ readonly differences: ["File URLs not supported (base64 only)", "Cost may be available via usage.total_cost or generation endpoint"];
771
+ };
772
+ };
773
+ readonly anthropic: {
774
+ readonly id: "anthropic";
775
+ readonly name: "Anthropic (Claude)";
776
+ readonly vendor: "anthropic";
777
+ readonly models: ["claude-opus-4.5", "claude-sonnet-4.5", "claude-haiku-4.5", "claude-opus-4", "claude-sonnet-4"];
778
+ readonly detailedModels: [{
779
+ readonly id: "claude-opus-4.5";
780
+ readonly name: "Claude Opus 4.5";
781
+ readonly openRouterId: "anthropic/claude-opus-4.5";
782
+ readonly capabilities: {
783
+ readonly supportsReasoning: true;
784
+ };
785
+ readonly limits: {
786
+ readonly maxContextTokens: 200000;
787
+ readonly maxOutputTokens: 32000;
788
+ };
789
+ readonly pricing: {
790
+ readonly inputPer1k: 0.015;
791
+ readonly outputPer1k: 0.075;
792
+ };
793
+ }, {
794
+ readonly id: "claude-sonnet-4.5";
795
+ readonly name: "Claude Sonnet 4.5";
796
+ readonly openRouterId: "anthropic/claude-sonnet-4.5";
797
+ readonly capabilities: {
798
+ readonly supportsReasoning: true;
799
+ };
800
+ readonly limits: {
801
+ readonly maxContextTokens: 200000;
802
+ readonly maxOutputTokens: 16000;
803
+ };
804
+ readonly pricing: {
805
+ readonly inputPer1k: 0.003;
806
+ readonly outputPer1k: 0.015;
807
+ };
808
+ }, {
809
+ readonly id: "claude-haiku-4.5";
810
+ readonly name: "Claude Haiku 4.5";
811
+ readonly openRouterId: "anthropic/claude-haiku-4.5";
812
+ readonly capabilities: {
813
+ readonly supportsReasoning: true;
814
+ };
815
+ readonly limits: {
816
+ readonly maxContextTokens: 200000;
817
+ readonly maxOutputTokens: 8192;
818
+ };
819
+ readonly pricing: {
820
+ readonly inputPer1k: 0.0008;
821
+ readonly outputPer1k: 0.004;
822
+ };
823
+ }, {
824
+ readonly id: "claude-opus-4";
825
+ readonly name: "Claude Opus 4";
826
+ readonly openRouterId: "anthropic/claude-opus-4";
827
+ readonly capabilities: {
828
+ readonly supportsReasoning: true;
829
+ };
830
+ readonly limits: {
831
+ readonly maxContextTokens: 200000;
832
+ readonly maxOutputTokens: 32000;
833
+ };
834
+ readonly pricing: {
835
+ readonly inputPer1k: 0.015;
836
+ readonly outputPer1k: 0.075;
837
+ };
838
+ }, {
839
+ readonly id: "claude-sonnet-4";
840
+ readonly name: "Claude Sonnet 4";
841
+ readonly openRouterId: "anthropic/claude-sonnet-4";
842
+ readonly capabilities: {
843
+ readonly supportsReasoning: true;
844
+ };
845
+ readonly limits: {
846
+ readonly maxContextTokens: 200000;
847
+ readonly maxOutputTokens: 16000;
848
+ };
849
+ readonly pricing: {
850
+ readonly inputPer1k: 0.003;
851
+ readonly outputPer1k: 0.015;
852
+ };
853
+ }];
854
+ readonly accessMethods: {
855
+ readonly native: {
856
+ readonly available: true;
857
+ readonly endpoint: "https://api.anthropic.com/v1";
858
+ readonly requiresApiKey: true;
859
+ };
860
+ readonly openrouter: {
861
+ readonly available: true;
862
+ readonly modelPrefix: "anthropic/";
863
+ };
864
+ };
865
+ readonly capabilities: {
866
+ readonly supportsImages: true;
867
+ readonly supportsPDFs: true;
868
+ readonly supportsReasoning: true;
869
+ readonly supportsStreaming: true;
870
+ readonly supportsStructuredOutput: true;
871
+ };
872
+ readonly inputRequirements: {
873
+ readonly inputType: "any";
874
+ readonly acceptedMethods: readonly ["base64"];
875
+ };
876
+ readonly compatibleNodes: {
877
+ readonly parse: true;
878
+ readonly extract: true;
879
+ readonly categorize: true;
880
+ readonly qualify: true;
881
+ readonly split: true;
882
+ };
883
+ readonly inputFormats: {
884
+ readonly images: {
885
+ readonly mimeTypes: readonly ["image/png", "image/jpeg", "image/webp", "image/gif"];
886
+ readonly methods: ["base64"];
887
+ readonly maxSize: 5;
888
+ readonly maxDimensions: {
889
+ readonly width: 8000;
890
+ readonly height: 8000;
891
+ };
892
+ readonly notes: "Native API requires base64. Max 100 images/request. Optimal at 1568px max dimension.";
893
+ };
894
+ readonly pdfs: {
895
+ readonly supported: true;
896
+ readonly methods: ["base64", "fileId"];
897
+ readonly maxSize: 32;
898
+ readonly maxPages: 100;
899
+ readonly notes: "Inline via type: document with base64, or via Files API (beta). PDFs over 100 pages: text-only processing.";
900
+ };
901
+ };
902
+ readonly outputFormat: {
903
+ readonly supportsJSON: true;
904
+ readonly supportsReasoning: true;
905
+ readonly tokenTracking: true;
906
+ readonly costTracking: true;
907
+ };
908
+ readonly pricing: {
909
+ readonly model: "per-token";
910
+ readonly inputPer1k: 0.003;
911
+ readonly outputPer1k: 0.015;
912
+ readonly currency: "USD";
913
+ readonly notes: "Cost calculated from tokens. OpenRouter may include cost in response. Claude 3.5 Sonnet baseline.";
914
+ };
915
+ readonly limits: {
916
+ readonly maxContextTokens: 200000;
917
+ readonly maxOutputTokens: 8192;
918
+ readonly requestsPerMinute: undefined;
919
+ };
920
+ readonly nativeAPI: {
921
+ readonly imageFormat: "type: \"image\", source: { type: \"base64\", media_type: \"image/jpeg\", data: \"...\" }";
922
+ readonly pdfFormat: "type: \"document\", source: { type: \"base64\"|\"file\", media_type: \"application/pdf\", data: \"...\" | file_id: \"...\" }";
923
+ readonly reasoningConfig: "thinking: { type: \"enabled\", budget_tokens: 1024-32000 }";
924
+ };
925
+ readonly openRouterAPI: {
926
+ readonly imageFormat: "type: \"image_url\", image_url: { url: \"data:image/jpeg;base64,...\" }";
927
+ readonly pdfFormat: "type: \"file\", file: { filename: \"...\", file_data: \"data:application/pdf;base64,...\" }";
928
+ readonly reasoningConfig: "reasoning: { max_tokens: number, exclude?: boolean }";
929
+ readonly differences: ["Uses OpenAI-compatible format (image_url, file types)", "Reasoning uses max_tokens instead of budget_tokens", "Response prefill trick ({ role: \"assistant\", content: \"{\" }) for strict JSON", "Tool calling instead of native structured output"];
930
+ };
931
+ };
932
+ readonly google: {
933
+ readonly id: "google";
934
+ readonly name: "Google (Gemini)";
935
+ readonly vendor: "google";
936
+ readonly models: ["gemini-3-pro", "gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.5-flash-lite"];
937
+ readonly detailedModels: [{
938
+ readonly id: "gemini-3-pro";
939
+ readonly name: "Gemini 3 Pro";
940
+ readonly openRouterId: "google/gemini-3-pro";
941
+ readonly capabilities: {
942
+ readonly supportsReasoning: true;
943
+ };
944
+ readonly limits: {
945
+ readonly maxContextTokens: 1000000;
946
+ readonly maxOutputTokens: 65536;
947
+ };
948
+ readonly pricing: {
949
+ readonly inputPer1k: 0.00125;
950
+ readonly outputPer1k: 0.005;
951
+ };
952
+ }, {
953
+ readonly id: "gemini-2.5-pro";
954
+ readonly name: "Gemini 2.5 Pro";
955
+ readonly openRouterId: "google/gemini-2.5-pro-preview-06-05";
956
+ readonly capabilities: {
957
+ readonly supportsReasoning: true;
958
+ };
959
+ readonly limits: {
960
+ readonly maxContextTokens: 1000000;
961
+ readonly maxOutputTokens: 65536;
962
+ };
963
+ readonly pricing: {
964
+ readonly inputPer1k: 0.00125;
965
+ readonly outputPer1k: 0.005;
966
+ };
967
+ }, {
968
+ readonly id: "gemini-2.5-flash";
969
+ readonly name: "Gemini 2.5 Flash";
970
+ readonly openRouterId: "google/gemini-2.5-flash-preview-09-2025";
971
+ readonly capabilities: {
972
+ readonly supportsReasoning: false;
973
+ };
974
+ readonly limits: {
975
+ readonly maxContextTokens: 1000000;
976
+ readonly maxOutputTokens: 8192;
977
+ };
978
+ readonly pricing: {
979
+ readonly inputPer1k: 0.00015;
980
+ readonly outputPer1k: 0.0006;
981
+ };
982
+ }, {
983
+ readonly id: "gemini-2.5-flash-lite";
984
+ readonly name: "Gemini 2.5 Flash Lite";
985
+ readonly openRouterId: "google/gemini-2.5-flash-lite";
986
+ readonly capabilities: {
987
+ readonly supportsReasoning: false;
988
+ };
989
+ readonly limits: {
990
+ readonly maxContextTokens: 1000000;
991
+ readonly maxOutputTokens: 8192;
992
+ };
993
+ readonly pricing: {
994
+ readonly inputPer1k: 0.000075;
995
+ readonly outputPer1k: 0.0003;
996
+ };
997
+ }];
998
+ readonly accessMethods: {
999
+ readonly native: {
1000
+ readonly available: true;
1001
+ readonly endpoint: "https://generativelanguage.googleapis.com/v1beta";
1002
+ readonly requiresApiKey: true;
1003
+ };
1004
+ readonly openrouter: {
1005
+ readonly available: true;
1006
+ readonly modelPrefix: "google/";
1007
+ };
1008
+ };
1009
+ readonly capabilities: {
1010
+ readonly supportsImages: true;
1011
+ readonly supportsPDFs: true;
1012
+ readonly supportsReasoning: true;
1013
+ readonly supportsStreaming: true;
1014
+ readonly supportsStructuredOutput: true;
1015
+ };
1016
+ readonly inputRequirements: {
1017
+ readonly inputType: "any";
1018
+ readonly acceptedMethods: readonly ["base64"];
1019
+ };
1020
+ readonly compatibleNodes: {
1021
+ readonly parse: true;
1022
+ readonly extract: true;
1023
+ readonly categorize: true;
1024
+ readonly qualify: true;
1025
+ readonly split: true;
1026
+ };
1027
+ readonly inputFormats: {
1028
+ readonly images: {
1029
+ readonly mimeTypes: readonly ["image/png", "image/jpeg", "image/webp", "image/gif", "image/bmp", "image/tiff", "image/heif"];
1030
+ readonly methods: ["base64"];
1031
+ readonly maxSize: 20;
1032
+ readonly maxDimensions: {
1033
+ readonly width: 3072;
1034
+ readonly height: 3072;
1035
+ };
1036
+ readonly notes: "Inline via inlineData. Max 3000 images/request. File API supports larger files (stored 48 hours).";
1037
+ };
1038
+ readonly pdfs: {
1039
+ readonly supported: true;
1040
+ readonly methods: ["base64", "fileId"];
1041
+ readonly maxSize: 50;
1042
+ readonly maxPages: 1000;
1043
+ readonly notes: "Inline via inlineData OR File API. Pages scaled to 3072x3072 max. Native text not charged.";
1044
+ };
1045
+ };
1046
+ readonly outputFormat: {
1047
+ readonly supportsJSON: true;
1048
+ readonly supportsReasoning: true;
1049
+ readonly tokenTracking: true;
1050
+ readonly costTracking: true;
1051
+ };
1052
+ readonly pricing: {
1053
+ readonly model: "per-token";
1054
+ readonly inputPer1k: 0.00025;
1055
+ readonly outputPer1k: 0.001;
1056
+ readonly currency: "USD";
1057
+ readonly notes: "Cost calculated from tokens. OpenRouter may include cost in response. Gemini 2.5 Flash baseline.";
1058
+ };
1059
+ readonly limits: {
1060
+ readonly maxContextTokens: 1000000;
1061
+ readonly maxOutputTokens: 8192;
1062
+ readonly requestsPerMinute: undefined;
1063
+ };
1064
+ readonly nativeAPI: {
1065
+ readonly imageFormat: "inlineData: { mimeType: \"image/jpeg\", data: \"...\" }";
1066
+ readonly pdfFormat: "inlineData: { mimeType: \"application/pdf\", data: \"...\" } OR fileData: { fileUri: \"...\", mimeType: \"application/pdf\" }";
1067
+ readonly reasoningConfig: "generationConfig.thinking_config: { thinking_budget: number } (max 24576)";
1068
+ };
1069
+ readonly openRouterAPI: {
1070
+ readonly imageFormat: "type: \"image_url\", image_url: { url: \"data:image/jpeg;base64,...\" }";
1071
+ readonly pdfFormat: "type: \"file\", file: { filename: \"...\", file_data: \"data:application/pdf;base64,...\" }";
1072
+ readonly reasoningConfig: "reasoning: { max_tokens: number, exclude?: boolean }";
1073
+ readonly differences: ["Uses OpenAI-compatible format instead of parts/inlineData", "Reasoning uses max_tokens instead of thinking_budget", "Different content structure (messages vs contents.parts)"];
1074
+ };
1075
+ };
1076
+ readonly xai: {
1077
+ readonly id: "xai";
1078
+ readonly name: "xAI (Grok)";
1079
+ readonly vendor: "xai";
1080
+ readonly models: ["grok-4.1", "grok-4.1-fast", "grok-4", "grok-4-fast"];
1081
+ readonly detailedModels: [{
1082
+ readonly id: "grok-4.1";
1083
+ readonly name: "Grok 4.1";
1084
+ readonly openRouterId: "x-ai/grok-4.1";
1085
+ readonly capabilities: {
1086
+ readonly supportsReasoning: true;
1087
+ };
1088
+ readonly limits: {
1089
+ readonly maxContextTokens: 256000;
1090
+ readonly maxOutputTokens: 32768;
1091
+ };
1092
+ readonly pricing: {
1093
+ readonly inputPer1k: 0.003;
1094
+ readonly outputPer1k: 0.015;
1095
+ };
1096
+ }, {
1097
+ readonly id: "grok-4.1-fast";
1098
+ readonly name: "Grok 4.1 Fast";
1099
+ readonly openRouterId: "x-ai/grok-4.1-fast";
1100
+ readonly capabilities: {
1101
+ readonly supportsReasoning: false;
1102
+ };
1103
+ readonly limits: {
1104
+ readonly maxContextTokens: 2000000;
1105
+ readonly maxOutputTokens: 32768;
1106
+ };
1107
+ readonly pricing: {
1108
+ readonly inputPer1k: 0.005;
1109
+ readonly outputPer1k: 0.025;
1110
+ };
1111
+ }, {
1112
+ readonly id: "grok-4";
1113
+ readonly name: "Grok 4";
1114
+ readonly openRouterId: "x-ai/grok-4";
1115
+ readonly capabilities: {
1116
+ readonly supportsReasoning: true;
1117
+ };
1118
+ readonly limits: {
1119
+ readonly maxContextTokens: 256000;
1120
+ readonly maxOutputTokens: 32768;
1121
+ };
1122
+ readonly pricing: {
1123
+ readonly inputPer1k: 0.003;
1124
+ readonly outputPer1k: 0.015;
1125
+ };
1126
+ }, {
1127
+ readonly id: "grok-4-fast";
1128
+ readonly name: "Grok 4 Fast";
1129
+ readonly openRouterId: "x-ai/grok-4-fast";
1130
+ readonly capabilities: {
1131
+ readonly supportsReasoning: false;
1132
+ };
1133
+ readonly limits: {
1134
+ readonly maxContextTokens: 2000000;
1135
+ readonly maxOutputTokens: 32768;
1136
+ };
1137
+ readonly pricing: {
1138
+ readonly inputPer1k: 0.005;
1139
+ readonly outputPer1k: 0.025;
1140
+ };
1141
+ }];
1142
+ readonly accessMethods: {
1143
+ readonly native: {
1144
+ readonly available: true;
1145
+ readonly endpoint: "https://api.x.ai/v1";
1146
+ readonly requiresApiKey: true;
1147
+ };
1148
+ readonly openrouter: {
1149
+ readonly available: true;
1150
+ readonly modelPrefix: "xai/";
1151
+ };
1152
+ };
1153
+ readonly capabilities: {
1154
+ readonly supportsImages: true;
1155
+ readonly supportsPDFs: true;
1156
+ readonly supportsReasoning: true;
1157
+ readonly supportsStreaming: false;
1158
+ readonly supportsStructuredOutput: true;
1159
+ };
1160
+ readonly inputRequirements: {
1161
+ readonly inputType: "any";
1162
+ readonly acceptedMethods: readonly ["url", "base64"];
1163
+ };
1164
+ readonly compatibleNodes: {
1165
+ readonly parse: true;
1166
+ readonly extract: true;
1167
+ readonly categorize: true;
1168
+ readonly qualify: true;
1169
+ readonly split: true;
1170
+ };
1171
+ readonly inputFormats: {
1172
+ readonly images: {
1173
+ readonly mimeTypes: readonly ["image/jpeg", "image/png"];
1174
+ readonly methods: ["url", "base64"];
1175
+ readonly maxSize: 30;
1176
+ readonly maxDimensions: undefined;
1177
+ readonly notes: "OpenAI-compatible format. Max 10 images via API. Only JPEG/PNG supported.";
1178
+ };
1179
+ readonly pdfs: {
1180
+ readonly supported: true;
1181
+ readonly methods: ["url", "base64"];
1182
+ readonly maxSize: 30;
1183
+ readonly maxPages: undefined;
1184
+ readonly notes: "OpenAI-compatible format. Inline via type: file. Also supports DOCX, TXT, MD, CSV.";
1185
+ };
1186
+ };
1187
+ readonly outputFormat: {
1188
+ readonly supportsJSON: true;
1189
+ readonly supportsReasoning: true;
1190
+ readonly tokenTracking: true;
1191
+ readonly costTracking: true;
1192
+ };
1193
+ readonly pricing: {
1194
+ readonly model: "per-token";
1195
+ readonly inputPer1k: 0.005;
1196
+ readonly outputPer1k: 0.015;
1197
+ readonly currency: "USD";
1198
+ readonly notes: "Cost calculated from tokens. OpenRouter may include cost in response. Grok-4 baseline.";
1199
+ };
1200
+ readonly limits: {
1201
+ readonly maxContextTokens: 131072;
1202
+ readonly maxOutputTokens: undefined;
1203
+ readonly requestsPerMinute: undefined;
1204
+ };
1205
+ readonly nativeAPI: {
1206
+ readonly imageFormat: "type: \"image_url\", image_url: { url: \"data:image/jpeg;base64,...\" }";
1207
+ readonly pdfFormat: "type: \"file\", file: { filename: \"...\", file_data: \"data:application/pdf;base64,...\" }";
1208
+ readonly reasoningConfig: "reasoning: { effort: \"low\"|\"medium\"|\"high\", exclude?: boolean }";
1209
+ };
1210
+ readonly openRouterAPI: {
1211
+ readonly imageFormat: "Same as native (OpenAI-compatible)";
1212
+ readonly pdfFormat: "Same as native (OpenAI-compatible)";
1213
+ readonly reasoningConfig: "Same as native (OpenAI-compatible)";
1214
+ readonly differences: ["Minimal differences - xAI uses OpenAI-compatible format", "Cost tracking via usage.total_cost field in OpenRouter"];
1215
+ };
1216
+ };
1217
+ };
1218
+ /**
1219
+ * Check if an image MIME type is supported by a provider
1220
+ *
1221
+ * @param providerId - Provider ID
1222
+ * @param mimeType - MIME type to check
1223
+ * @returns True if supported
1224
+ *
1225
+ * @example
1226
+ * ```typescript
1227
+ * isImageTypeSupported('openai', 'image/png') // true
1228
+ * isImageTypeSupported('openai', 'image/bmp') // false
1229
+ * isImageTypeSupported('google', 'image/bmp') // true
1230
+ * ```
1231
+ */
1232
+ declare function isImageTypeSupported(providerId: keyof typeof PROVIDER_METADATA, mimeType: string): boolean;
1233
+ /**
1234
+ * Check if a provider supports PDFs inline (base64)
1235
+ *
1236
+ * @param providerId - Provider ID
1237
+ * @returns True if inline PDFs are supported
1238
+ *
1239
+ * @example
1240
+ * ```typescript
1241
+ * supportsPDFsInline('openai') // true
1242
+ * supportsPDFsInline('anthropic') // true
1243
+ * supportsPDFsInline('google') // true
1244
+ * ```
1245
+ */
1246
+ declare function supportsPDFsInline(providerId: keyof typeof PROVIDER_METADATA): boolean;
1247
+ /**
1248
+ * Get providers compatible with a specific node type
1249
+ *
1250
+ * @param nodeType - Node type to check
1251
+ * @returns Array of compatible provider metadata
1252
+ *
1253
+ * @example
1254
+ * ```typescript
1255
+ * // Get providers that work with parse()
1256
+ * const parseProviders = getProvidersForNode('parse');
1257
+ * // Returns: [openai, anthropic, google, xai] (all VLM providers)
1258
+ *
1259
+ * // Get providers that work with extract()
1260
+ * const extractProviders = getProvidersForNode('extract');
1261
+ * // Returns: [openai, anthropic, google, xai] (all VLM providers)
1262
+ * ```
1263
+ */
1264
+ declare function getProvidersForNode(nodeType: 'parse' | 'extract' | 'categorize' | 'qualify' | 'split'): LLMProviderMetadata[];
1265
+ /**
1266
+ * Check if a provider is compatible with a node type
1267
+ *
1268
+ * @param providerId - Provider ID
1269
+ * @param nodeType - Node type to check
1270
+ * @returns True if compatible
1271
+ *
1272
+ * @example
1273
+ * ```typescript
1274
+ * isProviderCompatibleWithNode('openai', 'parse'); // true
1275
+ * isProviderCompatibleWithNode('openai', 'extract'); // true
1276
+ * isProviderCompatibleWithNode('anthropic', 'qualify'); // true
1277
+ * ```
1278
+ */
1279
+ declare function isProviderCompatibleWithNode(providerId: keyof typeof PROVIDER_METADATA, nodeType: 'parse' | 'extract' | 'categorize' | 'qualify' | 'split'): boolean;
1280
+ /**
1281
+ * Estimate cost for a request
1282
+ *
1283
+ * @param providerId - Provider ID
1284
+ * @param inputTokens - Number of input tokens
1285
+ * @param outputTokens - Number of output tokens
1286
+ * @returns Estimated cost in USD
1287
+ *
1288
+ * @example
1289
+ * ```typescript
1290
+ * const cost = estimateCost('openai', 1000, 500);
1291
+ * console.log(`$${cost.toFixed(4)}`); // "$0.0125"
1292
+ *
1293
+ * const cost = estimateCost('google', 10000, 1000);
1294
+ * console.log(`$${cost.toFixed(4)}`); // "$0.0035"
1295
+ * ```
1296
+ */
1297
+ declare function estimateCost(providerId: keyof typeof PROVIDER_METADATA, inputTokens: number, outputTokens: number): number;
1298
+ /**
1299
+ * Get the cheapest provider for a given workload
1300
+ *
1301
+ * @param inputTokens - Number of input tokens
1302
+ * @param outputTokens - Number of output tokens
1303
+ * @returns Cheapest provider metadata
1304
+ *
1305
+ * @example
1306
+ * ```typescript
1307
+ * const cheapest = getCheapestProvider(10000, 1000);
1308
+ * console.log(cheapest.name); // "Google (Gemini)"
1309
+ * ```
1310
+ */
1311
+ declare function getCheapestProvider(inputTokens: number, outputTokens: number): LLMProviderMetadata;
1312
+ /**
1313
+ * Compare native vs OpenRouter for a provider
1314
+ *
1315
+ * @param providerId - Provider ID
1316
+ * @returns Comparison object with key differences
1317
+ *
1318
+ * @example
1319
+ * ```typescript
1320
+ * const comparison = compareNativeVsOpenRouter('anthropic');
1321
+ * console.log(comparison.differences);
1322
+ * // ['Uses OpenAI-compatible format...', 'Response prefill trick...']
1323
+ * ```
1324
+ */
1325
+ declare function compareNativeVsOpenRouter(providerId: keyof typeof PROVIDER_METADATA): {
1326
+ provider: string;
1327
+ nativeAvailable: boolean;
1328
+ openRouterAvailable: boolean;
1329
+ differences: string[];
1330
+ };
1331
+ type LLMProviderType = keyof typeof PROVIDER_METADATA;
1332
+ type SupportedImageMimeType = typeof SUPPORTED_IMAGE_TYPES.COMMON[number];
1333
+ type NodeType = 'parse' | 'extract' | 'categorize' | 'qualify' | 'split';
1334
+
1335
+ /**
1336
+ * Create a single VLM provider with direct instantiation (no retry/fallback logic).
1337
+ *
1338
+ * Use this for:
1339
+ * - Simple scripts and quick prototypes
1340
+ * - Testing individual provider behavior
1341
+ * - Benchmarking (no retry overhead)
1342
+ * - Cases where you want immediate failures without retry logic
1343
+ *
1344
+ * For production applications requiring resilience, use `buildLLMProvider()` instead.
1345
+ *
1346
+ * @example
1347
+ * ```typescript
1348
+ * const provider = createVLMProvider({
1349
+ * provider: 'google',
1350
+ * model: 'gemini-2.5-flash-preview-09-2025',
1351
+ * apiKey: process.env.OPENROUTER_API_KEY,
1352
+ * via: 'openrouter'
1353
+ * });
1354
+ * ```
1355
+ *
1356
+ * @param config - Provider configuration
1357
+ * @returns CoreVLMProvider instance (no retry/fallback wrapper)
1358
+ */
1359
+ declare function createVLMProvider(config: {
1360
+ provider: 'openai' | 'anthropic' | 'google' | 'xai' | 'x-ai';
1361
+ model: string;
1362
+ apiKey: string;
1363
+ via?: 'openrouter';
1364
+ baseUrl?: string;
1365
+ }): VLMProvider;
1366
+ /**
1367
+ * Build a production-ready LLM provider with retry logic, fallback support, and circuit breakers.
1368
+ *
1369
+ * Features:
1370
+ * - **Retry Logic**: Configurable retries with exponential backoff for transient failures
1371
+ * - **Fallback Chain**: Automatically tries next provider if current one fails
1372
+ * - **Circuit Breaker**: Temporarily skips providers with repeated failures
1373
+ * - **Observability**: Full integration with observability hooks for monitoring
1374
+ * - **Mode Support**: Supports both strict and relaxed JSON modes
1375
+ *
1376
+ * Works with single OR multiple providers:
1377
+ * - Single provider: Gets retry logic and circuit breaker protection
1378
+ * - Multiple providers: Adds fallback to alternative providers
1379
+ *
1380
+ * Use this for:
1381
+ * - Production applications requiring high availability
1382
+ * - Cases where you need retry logic even with a single provider
1383
+ * - Multi-provider fallback chains
1384
+ * - Advanced error handling and monitoring
1385
+ *
1386
+ * @example Single provider with retry
1387
+ * ```typescript
1388
+ * const provider = buildLLMProvider({
1389
+ * providers: [{
1390
+ * provider: 'google',
1391
+ * model: 'gemini-2.5-flash-preview-09-2025',
1392
+ * apiKey: process.env.OPENROUTER_API_KEY,
1393
+ * via: 'openrouter'
1394
+ * }],
1395
+ * maxRetries: 2,
1396
+ * retryDelay: 1000,
1397
+ * useExponentialBackoff: true,
1398
+ * circuitBreakerThreshold: 3
1399
+ * });
1400
+ * ```
1401
+ *
1402
+ * @example Multi-provider fallback
1403
+ * ```typescript
1404
+ * const provider = buildLLMProvider({
1405
+ * providers: [
1406
+ * { provider: 'google', model: 'gemini-2.5-flash', apiKey: key1 },
1407
+ * { provider: 'openai', model: 'gpt-4.1', apiKey: key2 },
1408
+ * { provider: 'anthropic', model: 'claude-haiku-4.5', apiKey: key3 }
1409
+ * ],
1410
+ * maxRetries: 2,
1411
+ * retryDelay: 1000,
1412
+ * useExponentialBackoff: true
1413
+ * });
1414
+ * ```
1415
+ *
1416
+ * @param config - Fallback configuration with providers array and retry settings
1417
+ * @returns CoreVLMProvider with retry/fallback capabilities (compatible with flow interface)
1418
+ */
1419
+ declare function buildLLMProvider(config: FallbackConfig): VLMProvider;
1420
+
1421
+ export { type AccessMethod, AnthropicProvider, type CircuitBreakerState, type FallbackConfig, FallbackManager, GoogleProvider, type ImageInput, type JsonMode, type LLMModelMetadata, type LLMProvider, type LLMProviderMetadata, type LLMProviderType, type LLMResponse, type MultimodalInput, type NodeType, OpenAIProvider, type PDFInput, PROVIDER_METADATA, type ProviderCapabilities, type ProviderConfig, type ProviderFactory, type ProviderInputType, type ProviderType, type ReasoningConfig, type ReasoningDetail, type ResourceLimits, type ResponseMetrics, SUPPORTED_IMAGE_TYPES, SchemaTranslator, type SupportedImageMimeType, type UnifiedSchema, XAIProvider, adaptToCoreLLMProvider, buildLLMProvider, buildSchemaPromptSection, combineSchemaAndUserPrompt, compareNativeVsOpenRouter, createProviderFromRegistry, createVLMProvider, estimateCost, formatSchemaForPrompt, getCheapestProvider, getProvidersForNode, isImageTypeSupported, isProviderCompatibleWithNode, providerRegistry, registerProvider, supportsPDFsInline };