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.
- package/LICENSE +21 -0
- package/README.md +302 -0
- package/dist/index.d.mts +1028 -0
- package/dist/index.d.ts +1028 -0
- package/dist/index.js +4 -0
- package/dist/index.mjs +4 -0
- package/package.json +87 -0
package/dist/index.d.mts
ADDED
|
@@ -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 };
|