hydra-aidirector 1.3.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.
@@ -0,0 +1,1028 @@
1
+ /**
2
+ * Hydra Client Types
3
+ * Type definitions for the SDK
4
+ */
5
+ /**
6
+ * Configuration for Hydra client
7
+ */
8
+ interface HydraConfig {
9
+ /**
10
+ * Your Hydra secret key
11
+ * Get this from your dashboard at https://hydrai.dev/dashboard/keys
12
+ * Format: hyd_sk_<random>
13
+ */
14
+ secretKey: string;
15
+ /**
16
+ * API base URL
17
+ * @default 'http://localhost:3000' in development
18
+ * @example 'https://api.hydrai.dev'
19
+ */
20
+ baseUrl?: string;
21
+ /**
22
+ * Request timeout in milliseconds
23
+ * @default 600000 (10 minutes)
24
+ */
25
+ timeout?: number;
26
+ /**
27
+ * Maximum number of retries for failed requests
28
+ * Set to 0 to disable retries
29
+ * @default 3
30
+ */
31
+ maxRetries?: number;
32
+ /**
33
+ * Enable debug logging to console
34
+ * @default false
35
+ */
36
+ debug?: boolean;
37
+ }
38
+ /**
39
+ * Options for the generate method
40
+ */
41
+ interface GenerateOptions {
42
+ /**
43
+ * ID of the fallback chain to use
44
+ * Get chain IDs from your dashboard
45
+ */
46
+ chainId: string;
47
+ /**
48
+ * The prompt to send to the AI
49
+ */
50
+ prompt: string;
51
+ /**
52
+ * Optional JSON schema for response validation
53
+ * The AI will be instructed to return data matching this schema
54
+ * @example { name: 'string', age: 'number', tags: 'string[]' }
55
+ */
56
+ schema?: Record<string, unknown>;
57
+ /**
58
+ * Override the client timeout for this request
59
+ */
60
+ timeout?: number;
61
+ /**
62
+ * Skip the cache for this request.
63
+ * Useful for prompts that should always generate fresh responses.
64
+ * @default false
65
+ */
66
+ noCache?: boolean;
67
+ /**
68
+ * File attachments to include with the request.
69
+ * The server automatically handles:
70
+ * - File type detection (magic bytes)
71
+ * - Model compatibility checking
72
+ * - Automatic conversion (e.g., DOCX → PDF)
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * await client.generate({
77
+ * chainId: 'my-chain',
78
+ * prompt: 'Summarize this document',
79
+ * files: [{
80
+ * data: documentBuffer.toString('base64'),
81
+ * filename: 'report.pdf',
82
+ * mimeType: 'application/pdf',
83
+ * }],
84
+ * });
85
+ * ```
86
+ */
87
+ files?: FileAttachment[];
88
+ /**
89
+ * Use the optimized 3-step generation flow.
90
+ * This minimizes Vercel compute costs by calling the Cloudflare Worker directly.
91
+ * Set to false to force legacy single-call mode.
92
+ * @default true
93
+ */
94
+ useOptimized?: boolean;
95
+ /**
96
+ * Cache scope for this request.
97
+ * - 'global': Cache is shared across all users (default)
98
+ * - 'user': Cache is scoped to the authenticated user
99
+ * - 'skip': Do not cache this response
100
+ * @default 'global'
101
+ */
102
+ cacheScope?: 'global' | 'user' | 'skip';
103
+ /**
104
+ * AbortSignal for request cancellation.
105
+ * Pass a signal from an AbortController to cancel the request.
106
+ * @example
107
+ * ```typescript
108
+ * const controller = new AbortController();
109
+ * setTimeout(() => controller.abort(), 5000);
110
+ * await client.generate({ chainId: 'x', prompt: 'y', signal: controller.signal });
111
+ * ```
112
+ */
113
+ signal?: AbortSignal;
114
+ /**
115
+ * Override max retries for this specific request.
116
+ * Set to 0 to disable retries for idempotent-sensitive operations.
117
+ */
118
+ maxRetries?: number;
119
+ /**
120
+ * Client-generated request ID for tracing and debugging.
121
+ * If not provided, one will be generated automatically.
122
+ */
123
+ requestId?: string;
124
+ /**
125
+ * Generation parameters
126
+ */
127
+ options?: GenerationParameters;
128
+ }
129
+ /**
130
+ * File attachment for generate requests.
131
+ * Pass files and the server handles detection/conversion automatically.
132
+ */
133
+ interface FileAttachment {
134
+ /**
135
+ * File content as base64-encoded string
136
+ */
137
+ data: string;
138
+ /**
139
+ * Original filename (optional, helps with type detection)
140
+ */
141
+ filename?: string;
142
+ /**
143
+ * Claimed MIME type (optional, will be verified by server)
144
+ * If omitted, server will auto-detect from magic bytes
145
+ */
146
+ mimeType?: string;
147
+ }
148
+ /**
149
+ * AI generation parameters
150
+ */
151
+ interface GenerationParameters {
152
+ /**
153
+ * Controls randomness (0 = deterministic, 2 = very random)
154
+ * @default 0.7
155
+ */
156
+ temperature?: number;
157
+ /**
158
+ * Maximum tokens to generate
159
+ */
160
+ maxTokens?: number;
161
+ /**
162
+ * Nucleus sampling parameter
163
+ * @default 1.0
164
+ */
165
+ topP?: number;
166
+ /**
167
+ * Top-K sampling parameter
168
+ */
169
+ topK?: number;
170
+ /**
171
+ * System prompt to prepend
172
+ */
173
+ systemPrompt?: string;
174
+ /**
175
+ * Enable thinking/reasoning mode for supported models.
176
+ * When enabled, the model will show its reasoning process.
177
+ * Only works with models that support thinking (e.g., Gemini 2.0 Flash Thinking).
178
+ */
179
+ thinkingMode?: boolean;
180
+ }
181
+ /**
182
+ * Result from the generate method
183
+ */
184
+ interface GenerateResult {
185
+ /**
186
+ * Whether the request was successful
187
+ */
188
+ success: boolean;
189
+ /**
190
+ * The generated data
191
+ */
192
+ data: GenerateData;
193
+ /**
194
+ * Request metadata
195
+ */
196
+ meta: GenerateMeta;
197
+ /**
198
+ * Error information (only present if success is false)
199
+ */
200
+ error?: GenerateError;
201
+ }
202
+ /**
203
+ * Generated data
204
+ */
205
+ interface GenerateData {
206
+ /**
207
+ * Schema-compliant objects (or all parsed objects if no schema)
208
+ */
209
+ valid: unknown[];
210
+ /**
211
+ * Objects that failed schema validation but were successfully parsed
212
+ */
213
+ invalid: unknown[];
214
+ /**
215
+ * Raw AI response text (useful for debugging)
216
+ */
217
+ rawContent?: string;
218
+ /**
219
+ * Report of auto-healed validation errors
220
+ * detailed log of how the system fixed invalid AI output
221
+ */
222
+ healingReport?: Array<{
223
+ original: unknown;
224
+ healed: unknown;
225
+ fixes: string[];
226
+ }>;
227
+ }
228
+ /**
229
+ * Generation metadata
230
+ */
231
+ interface GenerateMeta {
232
+ /**
233
+ * Whether the response was served from cache
234
+ */
235
+ cached: boolean;
236
+ /**
237
+ * The model that generated the response
238
+ */
239
+ modelUsed: string;
240
+ /**
241
+ * Token usage
242
+ */
243
+ tokensUsed: TokenUsage;
244
+ /**
245
+ * Request latency in milliseconds
246
+ */
247
+ latencyMs: number;
248
+ /**
249
+ * Models attempted before success (includes failed models)
250
+ */
251
+ attemptedModels: string[];
252
+ /**
253
+ * Why the generation stopped
254
+ */
255
+ finishReason?: 'stop' | 'length' | 'content_filter' | 'error';
256
+ /**
257
+ * Whether JSON recovery was needed
258
+ */
259
+ recovered?: boolean;
260
+ }
261
+ /**
262
+ * Token usage information
263
+ */
264
+ interface TokenUsage {
265
+ input: number;
266
+ output: number;
267
+ total?: number;
268
+ }
269
+ /**
270
+ * Error information
271
+ */
272
+ interface GenerateError {
273
+ /**
274
+ * Error code for programmatic handling
275
+ */
276
+ code: string;
277
+ /**
278
+ * Human-readable error message
279
+ */
280
+ message: string;
281
+ /**
282
+ * Whether the error can be retried
283
+ */
284
+ retryable?: boolean;
285
+ /**
286
+ * Additional error details
287
+ */
288
+ details?: Record<string, unknown>;
289
+ }
290
+ /**
291
+ * Callbacks for streaming generation
292
+ */
293
+ interface StreamCallbacks {
294
+ /**
295
+ * Called for each text chunk received (legacy/backwards compatible)
296
+ */
297
+ onChunk?: (chunk: string) => void;
298
+ /**
299
+ * Called for each VALID JSON object parsed from stream
300
+ * This is the preferred callback for JSON streaming - each object is complete and parseable
301
+ */
302
+ onObject?: (object: unknown, index: number) => void;
303
+ /**
304
+ * Called when a JSON array starts in the stream
305
+ */
306
+ onArrayStart?: () => void;
307
+ /**
308
+ * Called when streaming is complete with full result
309
+ */
310
+ onComplete?: (result: StreamCompleteResult) => void;
311
+ /**
312
+ * Called if an error occurs
313
+ */
314
+ onError?: (error: Error) => void;
315
+ /**
316
+ * Called with progress updates
317
+ */
318
+ onProgress?: (progress: StreamProgress) => void;
319
+ }
320
+ /**
321
+ * Result passed to onComplete callback during streaming
322
+ */
323
+ interface StreamCompleteResult {
324
+ /**
325
+ * All collected objects from the stream
326
+ */
327
+ objects: unknown[];
328
+ /**
329
+ * Total number of objects parsed
330
+ */
331
+ objectCount: number;
332
+ /**
333
+ * Token usage for the request
334
+ */
335
+ tokensUsed?: {
336
+ input: number;
337
+ output: number;
338
+ };
339
+ /**
340
+ * Whether the response was cached at stream end
341
+ */
342
+ cached?: boolean;
343
+ }
344
+ /**
345
+ * Streaming progress information
346
+ */
347
+ interface StreamProgress {
348
+ /**
349
+ * Total characters received so far
350
+ */
351
+ charactersReceived: number;
352
+ /**
353
+ * Elapsed time in milliseconds
354
+ */
355
+ elapsedMs: number;
356
+ /**
357
+ * Current model being used
358
+ */
359
+ model: string;
360
+ }
361
+ /**
362
+ * Information about a fallback chain
363
+ */
364
+ interface ChainInfo {
365
+ /**
366
+ * Unique chain identifier
367
+ */
368
+ id: string;
369
+ /**
370
+ * Human-readable chain name
371
+ */
372
+ name: string;
373
+ /**
374
+ * Chain description
375
+ */
376
+ description?: string;
377
+ /**
378
+ * Whether this is the default chain
379
+ */
380
+ isDefault: boolean;
381
+ /**
382
+ * Chain steps (models to try in order)
383
+ */
384
+ steps: ChainStep[];
385
+ /**
386
+ * Number of requests using this chain
387
+ */
388
+ requestCount?: number;
389
+ /**
390
+ * Date chain was created
391
+ */
392
+ createdAt?: string;
393
+ }
394
+ /**
395
+ * A step in a fallback chain
396
+ */
397
+ interface ChainStep {
398
+ /**
399
+ * Model identifier
400
+ */
401
+ modelId: string;
402
+ /**
403
+ * Human-readable model name
404
+ */
405
+ modelName: string;
406
+ /**
407
+ * Provider (GEMINI, OPENROUTER)
408
+ */
409
+ provider: 'GEMINI' | 'OPENROUTER';
410
+ /**
411
+ * Step priority (lower = tried first)
412
+ */
413
+ priority: number;
414
+ /**
415
+ * Maximum retries for this step
416
+ */
417
+ maxRetries?: number;
418
+ /**
419
+ * Timeout for this step in milliseconds
420
+ */
421
+ timeoutMs?: number;
422
+ }
423
+ /**
424
+ * Information about an AI model
425
+ */
426
+ interface ModelInfo {
427
+ /**
428
+ * Model identifier (use this in chains)
429
+ */
430
+ id: string;
431
+ /**
432
+ * Provider name
433
+ */
434
+ provider: 'GEMINI' | 'OPENROUTER';
435
+ /**
436
+ * Human-readable model name
437
+ */
438
+ displayName: string;
439
+ /**
440
+ * Model description
441
+ */
442
+ description?: string;
443
+ /**
444
+ * Maximum input tokens
445
+ */
446
+ inputTokenLimit?: number;
447
+ /**
448
+ * Maximum output tokens
449
+ */
450
+ outputTokenLimit?: number;
451
+ /**
452
+ * Whether model supports JSON mode
453
+ */
454
+ supportsJsonMode: boolean;
455
+ /**
456
+ * Whether model supports streaming
457
+ */
458
+ supportsStreaming?: boolean;
459
+ /**
460
+ * Whether model supports thinking/reasoning
461
+ */
462
+ supportsThinking?: boolean;
463
+ /**
464
+ * Whether model is free to use
465
+ */
466
+ isFree: boolean;
467
+ /**
468
+ * Pricing per 1M tokens (if available)
469
+ */
470
+ pricing?: {
471
+ input: number;
472
+ output: number;
473
+ currency: string;
474
+ };
475
+ }
476
+ /**
477
+ * Usage statistics
478
+ */
479
+ interface UsageStats {
480
+ /**
481
+ * Total requests in period
482
+ */
483
+ totalRequests: number;
484
+ /**
485
+ * Successful requests
486
+ */
487
+ successfulRequests: number;
488
+ /**
489
+ * Failed requests
490
+ */
491
+ failedRequests: number;
492
+ /**
493
+ * Cached responses served
494
+ */
495
+ cachedResponses: number;
496
+ /**
497
+ * Total tokens used
498
+ */
499
+ totalTokens: TokenUsage;
500
+ /**
501
+ * Usage by model
502
+ */
503
+ byModel: Record<string, {
504
+ requests: number;
505
+ tokens: TokenUsage;
506
+ }>;
507
+ /**
508
+ * Average latency in milliseconds
509
+ */
510
+ avgLatencyMs: number;
511
+ /**
512
+ * Period start date
513
+ */
514
+ periodStart: string;
515
+ /**
516
+ * Period end date
517
+ */
518
+ periodEnd: string;
519
+ }
520
+ /**
521
+ * Health check result
522
+ */
523
+ interface HealthResult {
524
+ /**
525
+ * Whether the API is healthy
526
+ */
527
+ ok: boolean;
528
+ /**
529
+ * Response latency in milliseconds
530
+ */
531
+ latencyMs: number;
532
+ /**
533
+ * API version
534
+ */
535
+ version?: string;
536
+ /**
537
+ * Current time on server
538
+ */
539
+ timestamp?: string;
540
+ }
541
+ /**
542
+ * Detailed health check result with component status
543
+ */
544
+ interface DetailedHealthResult {
545
+ /**
546
+ * Overall status
547
+ */
548
+ status: 'healthy' | 'degraded' | 'unhealthy';
549
+ /**
550
+ * Server timestamp
551
+ */
552
+ timestamp: string;
553
+ /**
554
+ * Server uptime in seconds
555
+ */
556
+ uptime: number;
557
+ /**
558
+ * Component status
559
+ */
560
+ components: {
561
+ database: {
562
+ status: string;
563
+ latencyMs: number;
564
+ message?: string;
565
+ };
566
+ redis: {
567
+ status: string;
568
+ latencyMs: number;
569
+ message?: string;
570
+ };
571
+ gemini: {
572
+ status: string;
573
+ errorRate: number;
574
+ recentErrors: number;
575
+ };
576
+ openrouter: {
577
+ status: string;
578
+ errorRate: number;
579
+ recentErrors: number;
580
+ };
581
+ };
582
+ /**
583
+ * 24h metrics
584
+ */
585
+ metrics: {
586
+ last24h: {
587
+ totalRequests: number;
588
+ successRate: number;
589
+ cacheHitRate: number;
590
+ avgLatencyMs: number;
591
+ };
592
+ errorsByCode: Record<string, number>;
593
+ };
594
+ /**
595
+ * Cache status
596
+ */
597
+ cache: {
598
+ totalEntries: number;
599
+ redisAvailable: boolean;
600
+ };
601
+ }
602
+ /**
603
+ * Webhook configuration for async notifications
604
+ */
605
+ interface WebhookConfig {
606
+ /**
607
+ * Request ID to receive notifications for
608
+ */
609
+ requestId: string;
610
+ /**
611
+ * URL to call when request completes
612
+ */
613
+ url: string;
614
+ /**
615
+ * Optional secret for HMAC signing
616
+ */
617
+ secret?: string;
618
+ /**
619
+ * Number of retry attempts on failure
620
+ * @default 3
621
+ */
622
+ retryCount?: number;
623
+ }
624
+
625
+ /**
626
+ * Hydra Client SDK
627
+ *
628
+ * Production-grade client for the Hydra API gateway.
629
+ * Use in Next.js API routes, Server Actions, or any Node.js/Edge environment.
630
+ *
631
+ * Features:
632
+ * - 🔐 HMAC Authentication with browser support
633
+ * - ⚡ Configurable timeout (default 10 minutes)
634
+ * - 🔄 Automatic retries with exponential backoff
635
+ * - 📦 Structured error handling
636
+ * - 🎯 Full TypeScript support
637
+ *
638
+ * @example
639
+ * ```typescript
640
+ * import { Hydra } from 'hydra-aidirector';
641
+ *
642
+ * const client = new Hydra({
643
+ * secretKey: process.env.HYDRA_SECRET_KEY!,
644
+ * baseUrl: 'https://api.hydrai.dev',
645
+ * });
646
+ *
647
+ * const result = await client.generate({
648
+ * chainId: 'my-chain',
649
+ * prompt: 'Generate 5 user profiles',
650
+ * schema: { name: 'string', age: 'number' },
651
+ * });
652
+ *
653
+ * if (result.success) {
654
+ * console.log(result.data.valid);
655
+ * }
656
+ * ```
657
+ */
658
+ declare class Hydra {
659
+ private readonly secretKey;
660
+ private readonly baseUrl;
661
+ private readonly timeout;
662
+ private readonly maxRetries;
663
+ private readonly keyPrefix;
664
+ private readonly debug;
665
+ constructor(config: HydraConfig);
666
+ /**
667
+ * Generate content using your fallback chain
668
+ *
669
+ * @param options - Generation options
670
+ * @returns Promise resolving to GenerateResult
671
+ * @throws HydraError subclasses on failure
672
+ *
673
+ * @example
674
+ * ```typescript
675
+ * const result = await client.generate({
676
+ * chainId: 'production-chain',
677
+ * prompt: 'List 3 programming languages',
678
+ * options: { temperature: 0.7 },
679
+ * });
680
+ * ```
681
+ */
682
+ generate(options: GenerateOptions): Promise<GenerateResult>;
683
+ /**
684
+ * Optimized 3-step generation (minimizes Vercel compute costs)
685
+ *
686
+ * Step 1: Get token from Vercel (~50ms)
687
+ * Step 2: Call CF Worker directly (FREE)
688
+ * Step 3: Cache result in Vercel (~50ms)
689
+ *
690
+ * Total Vercel time: ~100ms vs 30-120s in legacy mode
691
+ */
692
+ private generateOptimized;
693
+ /**
694
+ * Cache completion from worker (Step 3 - async, non-blocking)
695
+ */
696
+ private cacheCompletionAsync;
697
+ /**
698
+ * Legacy single-call generation (higher Vercel compute cost)
699
+ */
700
+ private generateLegacy;
701
+ /**
702
+ * Generate content with streaming (for long responses)
703
+ *
704
+ * @param options - Generation options
705
+ * @param callbacks - Streaming callbacks
706
+ *
707
+ * @example
708
+ * ```typescript
709
+ * await client.generateStream(
710
+ * { chainId: 'my-chain', prompt: 'Write a long story' },
711
+ * {
712
+ * onChunk: (chunk) => process.stdout.write(chunk),
713
+ * onComplete: (result) => console.log('\nDone!', result.meta),
714
+ * onError: (error) => console.error('Error:', error),
715
+ * }
716
+ * );
717
+ * ```
718
+ */
719
+ generateStream(options: GenerateOptions, callbacks: StreamCallbacks): Promise<void>;
720
+ /**
721
+ * List available AI models
722
+ *
723
+ * @returns Array of available models
724
+ */
725
+ listModels(): Promise<ModelInfo[]>;
726
+ /**
727
+ * Get your fallback chains
728
+ * Note: Requires cookies/session from authenticated context
729
+ *
730
+ * @returns Array of chain configurations
731
+ */
732
+ listChains(): Promise<ChainInfo[]>;
733
+ /**
734
+ * Get usage statistics for your account
735
+ *
736
+ * @param options - Date range options
737
+ * @returns Usage statistics
738
+ */
739
+ getUsage(options?: {
740
+ startDate?: Date;
741
+ endDate?: Date;
742
+ }): Promise<UsageStats>;
743
+ /**
744
+ * Health check - verify API connection
745
+ *
746
+ * @returns Health status with latency
747
+ */
748
+ health(): Promise<{
749
+ ok: boolean;
750
+ latencyMs: number;
751
+ version?: string;
752
+ }>;
753
+ /**
754
+ * Create a new client with different configuration
755
+ * Useful for testing or switching environments
756
+ *
757
+ * @param overrides - Configuration overrides
758
+ * @returns New Hydra instance
759
+ */
760
+ withConfig(overrides: Partial<HydraConfig>): Hydra;
761
+ /**
762
+ * Register a webhook for async notifications
763
+ *
764
+ * @param config - Webhook configuration
765
+ * @returns Registration result
766
+ */
767
+ registerWebhook(config: {
768
+ requestId: string;
769
+ url: string;
770
+ secret?: string;
771
+ retryCount?: number;
772
+ }): Promise<{
773
+ registered: boolean;
774
+ message: string;
775
+ }>;
776
+ /**
777
+ * Unregister a webhook
778
+ *
779
+ * @param webhookId - ID of the webhook to unregister
780
+ * @returns Unregistration result
781
+ */
782
+ unregisterWebhook(webhookId: string): Promise<{
783
+ unregistered: boolean;
784
+ message: string;
785
+ }>;
786
+ /**
787
+ * List all registered webhooks
788
+ *
789
+ * @returns Array of webhook configurations
790
+ */
791
+ listWebhooks(): Promise<Array<{
792
+ id: string;
793
+ requestId: string;
794
+ url: string;
795
+ status: 'pending' | 'delivered' | 'failed';
796
+ retryCount: number;
797
+ createdAt: string;
798
+ }>>;
799
+ /**
800
+ * Update a webhook configuration
801
+ *
802
+ * @param webhookId - ID of the webhook to update
803
+ * @param updates - Fields to update
804
+ * @returns Updated webhook info
805
+ */
806
+ updateWebhook(webhookId: string, updates: {
807
+ url?: string;
808
+ retryCount?: number;
809
+ }): Promise<{
810
+ updated: boolean;
811
+ message: string;
812
+ }>;
813
+ /**
814
+ * Get detailed health information including component status
815
+ *
816
+ * @returns Detailed health status
817
+ */
818
+ healthDetailed(): Promise<{
819
+ status: 'healthy' | 'degraded' | 'unhealthy';
820
+ timestamp: string;
821
+ uptime: number;
822
+ components: Record<string, unknown>;
823
+ metrics: Record<string, unknown>;
824
+ }>;
825
+ /**
826
+ * Generate content for multiple prompts in a single request
827
+ *
828
+ * @param chainId - Chain to use for all items
829
+ * @param items - Array of prompts with IDs
830
+ * @param options - Batch options
831
+ * @returns Batch generation results
832
+ */
833
+ generateBatch(chainId: string, items: Array<{
834
+ id: string;
835
+ prompt: string;
836
+ systemPrompt?: string;
837
+ temperature?: number;
838
+ maxTokens?: number;
839
+ }>, options?: {
840
+ continueOnError?: boolean;
841
+ }): Promise<{
842
+ results: Array<{
843
+ id: string;
844
+ success: boolean;
845
+ data?: unknown[];
846
+ error?: string;
847
+ }>;
848
+ summary: {
849
+ total: number;
850
+ succeeded: number;
851
+ failed: number;
852
+ tokensUsed: {
853
+ input: number;
854
+ output: number;
855
+ total: number;
856
+ };
857
+ };
858
+ }>;
859
+ /**
860
+ * Make authenticated API request
861
+ */
862
+ private makeAuthenticatedRequest;
863
+ /**
864
+ * Fetch with timeout
865
+ */
866
+ private fetchWithTimeout;
867
+ /**
868
+ * Parse API error response
869
+ */
870
+ private parseError;
871
+ /**
872
+ * Check if error is retryable
873
+ */
874
+ private isRetryable;
875
+ /**
876
+ * Sleep utility
877
+ */
878
+ private sleep;
879
+ /**
880
+ * Debug logging
881
+ */
882
+ private log;
883
+ }
884
+
885
+ /**
886
+ * Hydra Error Classes
887
+ * Structured error types for better error handling
888
+ */
889
+ /**
890
+ * Base error class for Hydra errors
891
+ */
892
+ declare class HydraError extends Error {
893
+ readonly code: string;
894
+ readonly retryable: boolean;
895
+ readonly statusCode?: number;
896
+ readonly originalError?: Error;
897
+ constructor(message: string, code: string, options?: {
898
+ retryable?: boolean;
899
+ statusCode?: number;
900
+ cause?: Error;
901
+ });
902
+ }
903
+ /**
904
+ * Configuration error - invalid client setup
905
+ */
906
+ declare class ConfigurationError extends HydraError {
907
+ constructor(message: string);
908
+ }
909
+ /**
910
+ * Authentication error - invalid or expired credentials
911
+ */
912
+ declare class AuthenticationError extends HydraError {
913
+ constructor(message: string, statusCode?: number);
914
+ }
915
+ /**
916
+ * Rate limit error - too many requests
917
+ */
918
+ declare class RateLimitError extends HydraError {
919
+ readonly retryAfterMs: number;
920
+ constructor(message: string, retryAfterMs?: number);
921
+ }
922
+ /**
923
+ * Timeout error - request took too long
924
+ */
925
+ declare class TimeoutError extends HydraError {
926
+ readonly timeoutMs: number;
927
+ constructor(timeoutMs: number);
928
+ }
929
+ /**
930
+ * Network error - connection failed
931
+ */
932
+ declare class NetworkError extends HydraError {
933
+ constructor(message: string, cause?: Error);
934
+ }
935
+ /**
936
+ * Chain error - fallback chain execution failed
937
+ */
938
+ declare class ChainExecutionError extends HydraError {
939
+ readonly attemptedModels: string[];
940
+ constructor(message: string, attemptedModels?: string[]);
941
+ }
942
+ /**
943
+ * Validation error - schema validation failed
944
+ */
945
+ declare class ValidationError extends HydraError {
946
+ readonly validationErrors: unknown[];
947
+ constructor(message: string, validationErrors?: unknown[]);
948
+ }
949
+ /**
950
+ * Server error - internal server error
951
+ */
952
+ declare class ServerError extends HydraError {
953
+ constructor(message: string, statusCode?: number);
954
+ }
955
+ /**
956
+ * Quota exceeded error - monthly request limit reached
957
+ */
958
+ declare class QuotaExceededError extends HydraError {
959
+ readonly tier: string;
960
+ readonly limit: number;
961
+ readonly used: number;
962
+ constructor(message: string, options: {
963
+ tier: string;
964
+ limit: number;
965
+ used: number;
966
+ });
967
+ }
968
+ /**
969
+ * Worker error - Cloudflare Worker execution failed
970
+ */
971
+ declare class WorkerError extends HydraError {
972
+ readonly workerDurationMs?: number;
973
+ constructor(message: string, workerDurationMs?: number);
974
+ }
975
+ /**
976
+ * File processing error - attachment handling failed
977
+ */
978
+ declare class FileProcessingError extends HydraError {
979
+ readonly filename?: string;
980
+ readonly mimeType?: string;
981
+ readonly reason: 'unsupported_type' | 'conversion_failed' | 'too_large' | 'corrupted';
982
+ constructor(message: string, options: {
983
+ filename?: string;
984
+ mimeType?: string;
985
+ reason: 'unsupported_type' | 'conversion_failed' | 'too_large' | 'corrupted';
986
+ });
987
+ }
988
+ /**
989
+ * Invalid schema error - provided schema is malformed
990
+ */
991
+ declare class InvalidSchemaError extends HydraError {
992
+ readonly schemaPath?: string;
993
+ constructor(message: string, schemaPath?: string);
994
+ }
995
+ /**
996
+ * Check if error is an Hydra error
997
+ */
998
+ declare function isHydraError(error: unknown): error is HydraError;
999
+ /**
1000
+ * Check if error is retryable
1001
+ */
1002
+ declare function isRetryableError(error: unknown): boolean;
1003
+
1004
+ /**
1005
+ * HMAC Signature Generation
1006
+ *
1007
+ * Supports both Node.js (crypto) and browser (Web Crypto API) environments.
1008
+ * The signature algorithm matches the server-side verification.
1009
+ */
1010
+ /**
1011
+ * Generate HMAC signature for request authentication
1012
+ *
1013
+ * Automatically detects environment and uses appropriate implementation.
1014
+ *
1015
+ * IMPORTANT: We hash the secret key first, then use the hash as HMAC key.
1016
+ * This allows the server to verify using the stored hash (it never sees the full key).
1017
+ */
1018
+ declare function generateSignature(secretKey: string, method: string, path: string, body: string, timestamp: number): Promise<string>;
1019
+ /**
1020
+ * Get the key prefix for identification (sent in headers)
1021
+ */
1022
+ declare function getKeyPrefix(secretKey: string): string;
1023
+ /**
1024
+ * Validate secret key format
1025
+ */
1026
+ declare function isValidSecretKey(secretKey: string): boolean;
1027
+
1028
+ export { AuthenticationError, ChainExecutionError, type ChainInfo, type ChainStep, ConfigurationError, type DetailedHealthResult, type FileAttachment, FileProcessingError, type GenerateData, type GenerateError, type GenerateMeta, type GenerateOptions, type GenerateResult, type GenerationParameters, type HealthResult, Hydra, type HydraConfig, HydraError, InvalidSchemaError, type ModelInfo, NetworkError, QuotaExceededError, RateLimitError, ServerError, type StreamCallbacks, type StreamCompleteResult, type StreamProgress, TimeoutError, type TokenUsage, type UsageStats, ValidationError, type WebhookConfig, WorkerError, generateSignature, getKeyPrefix, isHydraError, isRetryableError, isValidSecretKey };