@kb-labs/core-resource-broker 1.0.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,1217 @@
1
+ import { StateBroker } from '@kb-labs/core-state-broker';
2
+ import { ILLM, LLMOptions, LLMResponse, LLMProtocolCapabilities, LLMMessage, LLMToolCallOptions, LLMToolCallResponse, IEmbeddings, IVectorStore, VectorFilter, VectorSearchResult, VectorRecord } from '@kb-labs/core-platform';
3
+
4
+ /**
5
+ * @module @kb-labs/core-resource-broker/types
6
+ * Type definitions for the Resource Broker system.
7
+ *
8
+ * The Resource Broker provides centralized queue management, rate limiting,
9
+ * and retry logic for heavy platform resources (LLM, Embeddings, VectorStore).
10
+ */
11
+ /**
12
+ * Rate limiting configuration for a resource.
13
+ * Supports multiple rate limiting strategies (TPM, RPM, RPS, concurrent).
14
+ */
15
+ interface RateLimitConfig {
16
+ /**
17
+ * Tokens per minute limit (e.g., OpenAI TPM)
18
+ * If undefined, no token-based rate limiting is applied
19
+ */
20
+ tokensPerMinute?: number;
21
+ /**
22
+ * Requests per minute limit (e.g., OpenAI RPM)
23
+ * If undefined, no request-per-minute rate limiting is applied
24
+ */
25
+ requestsPerMinute?: number;
26
+ /**
27
+ * Requests per second limit
28
+ * Some APIs (like Sber) use RPS instead of RPM
29
+ */
30
+ requestsPerSecond?: number;
31
+ /**
32
+ * Maximum tokens per single request
33
+ * Provider-specific limit
34
+ */
35
+ maxTokensPerRequest?: number;
36
+ /**
37
+ * Maximum concurrent requests
38
+ * For local models - GPU/CPU concurrency limit
39
+ */
40
+ maxConcurrentRequests?: number;
41
+ /**
42
+ * Safety margin (0-1, default 0.9)
43
+ * Use only X% of the limit to avoid hitting exact boundaries
44
+ */
45
+ safetyMargin?: number;
46
+ }
47
+ /**
48
+ * Result of attempting to acquire rate limit capacity.
49
+ */
50
+ interface AcquireResult {
51
+ /** Whether the request is allowed to proceed */
52
+ allowed: boolean;
53
+ /** Milliseconds to wait if not allowed */
54
+ waitTimeMs?: number;
55
+ /** Remaining tokens in current window */
56
+ tokensRemaining?: number;
57
+ /** Remaining requests in current window */
58
+ requestsRemaining?: number;
59
+ /** Current active concurrent requests */
60
+ activeRequests?: number;
61
+ }
62
+ /**
63
+ * Statistics for a rate-limited resource.
64
+ */
65
+ interface RateLimitStats {
66
+ /** Resource identifier */
67
+ resource: string;
68
+ /** Tokens used in current minute window */
69
+ tokensThisMinute: number;
70
+ /** Requests made in current minute window */
71
+ requestsThisMinute: number;
72
+ /** Requests made in current second window */
73
+ requestsThisSecond: number;
74
+ /** Currently active requests */
75
+ activeRequests: number;
76
+ /** Total requests made since start */
77
+ totalRequests: number;
78
+ /** Total tokens used since start */
79
+ totalTokens: number;
80
+ /** Number of times capacity was unavailable */
81
+ waitCount: number;
82
+ /** Total time spent waiting (ms) */
83
+ totalWaitTime: number;
84
+ }
85
+ /**
86
+ * Backend abstraction for rate limit state storage.
87
+ * Allows swapping between in-memory and distributed storage.
88
+ */
89
+ interface RateLimitBackend {
90
+ /**
91
+ * Atomically check limit and reserve capacity.
92
+ *
93
+ * @param resource - Resource identifier (e.g., 'llm', 'embeddings')
94
+ * @param tokens - Estimated tokens for this request
95
+ * @param config - Rate limit configuration
96
+ * @returns Acquire result with allowed/waitTime
97
+ */
98
+ acquire(resource: string, tokens: number, config: RateLimitConfig): Promise<AcquireResult>;
99
+ /**
100
+ * Release a concurrent request slot.
101
+ *
102
+ * @param resource - Resource identifier
103
+ */
104
+ release(resource: string): Promise<void>;
105
+ /**
106
+ * Get current statistics for a resource.
107
+ *
108
+ * @param resource - Resource identifier
109
+ */
110
+ getStats(resource: string): Promise<RateLimitStats>;
111
+ /**
112
+ * Reset statistics for a resource.
113
+ *
114
+ * @param resource - Resource identifier
115
+ */
116
+ reset(resource: string): Promise<void>;
117
+ }
118
+ /**
119
+ * Priority levels for resource requests.
120
+ * - high: User-facing operations (commit, interactive queries)
121
+ * - normal: Background operations with reasonable latency expectations
122
+ * - low: Analytics, batch processing, non-urgent tasks
123
+ */
124
+ type ResourcePriority = 'high' | 'normal' | 'low';
125
+ /**
126
+ * Request to execute a resource operation.
127
+ */
128
+ interface ResourceRequest {
129
+ /** Unique request identifier */
130
+ id: string;
131
+ /** Resource type ('llm', 'embeddings', 'vectorStore') */
132
+ resource: string;
133
+ /** Operation name ('complete', 'embed', 'search') */
134
+ operation: string;
135
+ /** Arguments to pass to the operation */
136
+ args: unknown[];
137
+ /** Request priority */
138
+ priority: ResourcePriority;
139
+ /** Estimated tokens for rate limiting (optional) */
140
+ estimatedTokens?: number;
141
+ /** Request timeout in ms (optional, default: 60000) */
142
+ timeout?: number;
143
+ /** Max retry attempts (optional, default: 3) */
144
+ maxRetries?: number;
145
+ /** Timestamp when request was created */
146
+ createdAt: number;
147
+ }
148
+ /**
149
+ * Response from a resource operation.
150
+ */
151
+ interface ResourceResponse<T = unknown> {
152
+ /** Whether the operation succeeded */
153
+ success: boolean;
154
+ /** Result data if successful */
155
+ data?: T;
156
+ /** Error if failed */
157
+ error?: Error;
158
+ /** Number of retry attempts made */
159
+ retries: number;
160
+ /** Time spent waiting in queue (ms) */
161
+ waitTime: number;
162
+ /** Time spent executing the operation (ms) */
163
+ processingTime: number;
164
+ /** Total time from request to response (ms) */
165
+ totalTime: number;
166
+ }
167
+ /**
168
+ * Queue item wrapping a request with execution context.
169
+ */
170
+ interface QueueItem {
171
+ /** The resource request */
172
+ request: ResourceRequest;
173
+ /** Resolve function to complete the promise */
174
+ resolve: (response: ResourceResponse) => void;
175
+ /** Reject function to fail the promise */
176
+ reject: (error: Error) => void;
177
+ /** Timestamp when added to queue */
178
+ enqueuedAt: number;
179
+ }
180
+ /**
181
+ * Configuration for a registered resource.
182
+ */
183
+ interface ResourceConfig {
184
+ /** Rate limit configuration or preset name */
185
+ rateLimits?: RateLimitConfig | string;
186
+ /** Maximum retry attempts */
187
+ maxRetries?: number;
188
+ /** Base delay for exponential backoff (ms) */
189
+ baseDelay?: number;
190
+ /** Maximum delay between retries (ms) */
191
+ maxDelay?: number;
192
+ /** Request timeout (ms) */
193
+ timeout?: number;
194
+ /** The actual executor function */
195
+ executor: ResourceExecutor;
196
+ }
197
+ /**
198
+ * Function that executes a resource operation.
199
+ */
200
+ type ResourceExecutor = (operation: string, args: unknown[]) => Promise<unknown>;
201
+ /**
202
+ * Statistics for the resource broker.
203
+ */
204
+ interface ResourceBrokerStats {
205
+ /** Stats per resource */
206
+ resources: Record<string, ResourceStats>;
207
+ /** Total requests processed */
208
+ totalRequests: number;
209
+ /** Total successful requests */
210
+ totalSuccess: number;
211
+ /** Total failed requests */
212
+ totalErrors: number;
213
+ /** Current queue size */
214
+ queueSize: number;
215
+ /** Uptime in milliseconds */
216
+ uptime: number;
217
+ }
218
+ /**
219
+ * Statistics for a single resource.
220
+ */
221
+ interface ResourceStats {
222
+ /** Rate limit stats */
223
+ rateLimits: RateLimitStats;
224
+ /** Queue size for this resource */
225
+ queueSize: number;
226
+ /** Requests by priority */
227
+ queueByPriority: {
228
+ high: number;
229
+ normal: number;
230
+ low: number;
231
+ };
232
+ /** Total requests processed */
233
+ totalRequests: number;
234
+ /** Total successful requests */
235
+ totalSuccess: number;
236
+ /** Total failed requests */
237
+ totalErrors: number;
238
+ /** Average wait time (ms) */
239
+ avgWaitTime: number;
240
+ /** Average processing time (ms) */
241
+ avgProcessingTime: number;
242
+ }
243
+ /**
244
+ * Main resource broker interface.
245
+ * Coordinates queues, rate limiting, and execution for all resources.
246
+ */
247
+ interface IResourceBroker {
248
+ /**
249
+ * Register a resource with its configuration.
250
+ *
251
+ * @param resource - Resource identifier
252
+ * @param config - Resource configuration
253
+ */
254
+ register(resource: string, config: ResourceConfig): void;
255
+ /**
256
+ * Enqueue a request for execution.
257
+ * Returns a promise that resolves when the request completes.
258
+ *
259
+ * @param request - Resource request (without id and createdAt)
260
+ * @returns Response with result or error
261
+ */
262
+ enqueue<T>(request: Omit<ResourceRequest, 'id' | 'createdAt'>): Promise<ResourceResponse<T>>;
263
+ /**
264
+ * Get broker statistics.
265
+ */
266
+ getStats(): ResourceBrokerStats;
267
+ /**
268
+ * Graceful shutdown - drain queues and stop processing.
269
+ */
270
+ shutdown(): Promise<void>;
271
+ /**
272
+ * Check if broker is shutting down.
273
+ */
274
+ isShuttingDown(): boolean;
275
+ }
276
+ /**
277
+ * Error classification for retry logic.
278
+ */
279
+ type ErrorType = 'rate_limit' | 'server_error' | 'timeout' | 'client_error' | 'network' | 'unknown';
280
+ /**
281
+ * Configuration for retry strategy.
282
+ */
283
+ interface RetryConfig {
284
+ /** Maximum number of retry attempts */
285
+ maxRetries: number;
286
+ /** Base delay in ms (default: 1000) */
287
+ baseDelay: number;
288
+ /** Maximum delay in ms (default: 30000) */
289
+ maxDelay: number;
290
+ /** Jitter factor (0-1, default: 0.1) */
291
+ jitter: number;
292
+ /** Which error types to retry */
293
+ retryableErrors: ErrorType[];
294
+ }
295
+ /**
296
+ * Default retry configuration.
297
+ */
298
+ declare const DEFAULT_RETRY_CONFIG: RetryConfig;
299
+ /**
300
+ * Default rate limit config (no limits).
301
+ */
302
+ declare const DEFAULT_RATE_LIMIT_CONFIG: RateLimitConfig;
303
+
304
+ /**
305
+ * @module @kb-labs/core-resource-broker/broker/resource-broker
306
+ * Main ResourceBroker implementation - coordinates queues, rate limiting, and execution.
307
+ */
308
+
309
+ /**
310
+ * ResourceBroker - Centralized coordinator for heavy platform resources.
311
+ *
312
+ * Features:
313
+ * - Priority queue (high/normal/low)
314
+ * - Rate limiting with configurable backend (in-memory or distributed)
315
+ * - Automatic retry with exponential backoff
316
+ * - Graceful shutdown
317
+ * - Per-resource statistics
318
+ *
319
+ * The platform doesn't know about plugins - only manages resources.
320
+ * Any caller can enqueue requests with appropriate priority.
321
+ *
322
+ * @example
323
+ * ```typescript
324
+ * const backend = new InMemoryRateLimitBackend();
325
+ * const broker = new ResourceBroker(backend);
326
+ *
327
+ * // Register resources
328
+ * broker.register('llm', {
329
+ * rateLimits: 'openai-tier-2',
330
+ * executor: (op, args) => llmAdapter[op](...args),
331
+ * });
332
+ *
333
+ * // Enqueue request
334
+ * const response = await broker.enqueue({
335
+ * resource: 'llm',
336
+ * operation: 'complete',
337
+ * args: [prompt, options],
338
+ * priority: 'high',
339
+ * estimatedTokens: 1000,
340
+ * });
341
+ * ```
342
+ */
343
+ declare class ResourceBroker implements IResourceBroker {
344
+ private rateLimitBackend;
345
+ private resources;
346
+ private queue;
347
+ private processing;
348
+ private shuttingDown;
349
+ private startTime;
350
+ /**
351
+ * Active processing count per resource (for concurrent limit tracking).
352
+ */
353
+ private activeProcessing;
354
+ constructor(rateLimitBackend: RateLimitBackend);
355
+ /**
356
+ * Register a resource with its configuration.
357
+ *
358
+ * @param resource - Resource identifier ('llm', 'embeddings', 'vectorStore')
359
+ * @param config - Resource configuration including executor
360
+ */
361
+ register(resource: string, config: ResourceConfig): void;
362
+ /**
363
+ * Enqueue a request for execution.
364
+ *
365
+ * @param request - Resource request (without id and createdAt)
366
+ * @returns Promise that resolves with response when execution completes
367
+ */
368
+ enqueue<T>(request: Omit<ResourceRequest, 'id' | 'createdAt'>): Promise<ResourceResponse<T>>;
369
+ /**
370
+ * Process queue items continuously.
371
+ */
372
+ private processQueue;
373
+ /**
374
+ * Execute a single queue item with retry logic.
375
+ */
376
+ private executeItem;
377
+ /**
378
+ * Get broker statistics.
379
+ */
380
+ getStats(): ResourceBrokerStats;
381
+ /**
382
+ * Graceful shutdown - drain queues and stop processing.
383
+ *
384
+ * @param timeoutMs - Maximum time to wait for drain (default: 30000)
385
+ */
386
+ shutdown(timeoutMs?: number): Promise<void>;
387
+ /**
388
+ * Check if broker is shutting down.
389
+ */
390
+ isShuttingDown(): boolean;
391
+ /**
392
+ * Get registered resource names.
393
+ */
394
+ getRegisteredResources(): string[];
395
+ /**
396
+ * Check if a resource is registered.
397
+ */
398
+ hasResource(resource: string): boolean;
399
+ /**
400
+ * Unregister a resource.
401
+ * Note: Pending requests for this resource will fail.
402
+ */
403
+ unregister(resource: string): void;
404
+ }
405
+
406
+ /**
407
+ * @module @kb-labs/core-resource-broker/queue/priority-queue
408
+ * Priority queue implementation with three levels: high, normal, low.
409
+ */
410
+
411
+ /**
412
+ * Priority queue with three priority levels.
413
+ *
414
+ * - High priority items are always dequeued first
415
+ * - Within the same priority, items are dequeued FIFO
416
+ * - Supports peeking without removing
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * const queue = new PriorityQueue();
421
+ *
422
+ * queue.enqueue(item1); // normal priority
423
+ * queue.enqueue(item2); // high priority
424
+ *
425
+ * const next = queue.dequeue(); // returns item2 (high priority)
426
+ * ```
427
+ */
428
+ declare class PriorityQueue {
429
+ private high;
430
+ private normal;
431
+ private low;
432
+ /**
433
+ * Add an item to the queue.
434
+ *
435
+ * @param item - Queue item to add
436
+ */
437
+ enqueue(item: QueueItem): void;
438
+ /**
439
+ * Remove and return the highest priority item.
440
+ *
441
+ * @returns The next item or undefined if queue is empty
442
+ */
443
+ dequeue(): QueueItem | undefined;
444
+ /**
445
+ * Peek at the highest priority item without removing it.
446
+ *
447
+ * @returns The next item or undefined if queue is empty
448
+ */
449
+ peek(): QueueItem | undefined;
450
+ /**
451
+ * Get total queue size.
452
+ */
453
+ size(): number;
454
+ /**
455
+ * Get queue size by priority.
456
+ */
457
+ sizeByPriority(): {
458
+ high: number;
459
+ normal: number;
460
+ low: number;
461
+ };
462
+ /**
463
+ * Check if queue is empty.
464
+ */
465
+ isEmpty(): boolean;
466
+ /**
467
+ * Clear all items from the queue.
468
+ *
469
+ * @returns All removed items (for cleanup/rejection)
470
+ */
471
+ clear(): QueueItem[];
472
+ /**
473
+ * Remove a specific item by request ID.
474
+ *
475
+ * @param requestId - ID of the request to remove
476
+ * @returns The removed item or undefined if not found
477
+ */
478
+ remove(requestId: string): QueueItem | undefined;
479
+ /**
480
+ * Get all items for a specific resource.
481
+ *
482
+ * @param resource - Resource identifier
483
+ * @returns Items matching the resource
484
+ */
485
+ getByResource(resource: string): QueueItem[];
486
+ /**
487
+ * Get queue size for a specific resource.
488
+ *
489
+ * @param resource - Resource identifier
490
+ */
491
+ sizeByResource(resource: string): number;
492
+ /**
493
+ * Iterate over all items (for inspection, not removal).
494
+ */
495
+ [Symbol.iterator](): Iterator<QueueItem>;
496
+ }
497
+
498
+ /**
499
+ * @module @kb-labs/core-resource-broker/rate-limit/in-memory-backend
500
+ * In-memory implementation of RateLimitBackend for single-process deployments.
501
+ */
502
+
503
+ /**
504
+ * In-memory rate limit backend.
505
+ *
506
+ * Uses sliding window approach for TPM/RPM/RPS tracking.
507
+ * Suitable for single-process deployments.
508
+ *
509
+ * @example
510
+ * ```typescript
511
+ * const backend = new InMemoryRateLimitBackend();
512
+ *
513
+ * const result = await backend.acquire('llm', 1000, {
514
+ * tokensPerMinute: 100000,
515
+ * requestsPerMinute: 1000,
516
+ * });
517
+ *
518
+ * if (result.allowed) {
519
+ * // Execute request
520
+ * await backend.release('llm');
521
+ * } else {
522
+ * // Wait and retry
523
+ * await sleep(result.waitTimeMs);
524
+ * }
525
+ * ```
526
+ */
527
+ declare class InMemoryRateLimitBackend implements RateLimitBackend {
528
+ private states;
529
+ /**
530
+ * Get or create state for a resource.
531
+ */
532
+ private getState;
533
+ /**
534
+ * Reset windows if time has passed.
535
+ */
536
+ private resetWindowsIfNeeded;
537
+ /**
538
+ * Check if all limits allow proceeding.
539
+ */
540
+ private checkLimits;
541
+ /**
542
+ * @inheritdoc
543
+ */
544
+ acquire(resource: string, tokens: number, config: RateLimitConfig): Promise<AcquireResult>;
545
+ /**
546
+ * @inheritdoc
547
+ */
548
+ release(resource: string): Promise<void>;
549
+ /**
550
+ * @inheritdoc
551
+ */
552
+ getStats(resource: string): Promise<RateLimitStats>;
553
+ /**
554
+ * @inheritdoc
555
+ */
556
+ reset(resource: string): Promise<void>;
557
+ /**
558
+ * Reset all resources.
559
+ */
560
+ resetAll(): void;
561
+ }
562
+
563
+ /**
564
+ * @module @kb-labs/core-resource-broker/rate-limit/state-broker-backend
565
+ * Distributed rate limit backend using StateBroker.
566
+ *
567
+ * Enables horizontal scaling by storing rate counters in a shared StateBroker
568
+ * (HTTP daemon or future Redis backend).
569
+ */
570
+
571
+ /**
572
+ * Distributed rate limit backend using StateBroker.
573
+ *
574
+ * Key patterns:
575
+ * - `ratelimit:{resource}:minute:{YYYY-MM-DDTHH:MM}` - Minute window counters
576
+ * - `ratelimit:{resource}:second:{YYYY-MM-DDTHH:MM:SS}` - Second window counters
577
+ * - `ratelimit:{resource}:active` - Active concurrent requests
578
+ * - `ratelimit:{resource}:stats` - Cumulative statistics
579
+ *
580
+ * TTL strategy:
581
+ * - Minute windows: 120s TTL (allows for clock skew)
582
+ * - Second windows: 10s TTL
583
+ * - Active counter: No TTL (managed explicitly)
584
+ * - Stats: No TTL (persisted)
585
+ *
586
+ * @example
587
+ * ```typescript
588
+ * import { createStateBroker } from '@kb-labs/core-state-broker';
589
+ *
590
+ * const broker = createStateBroker({ backend: 'http', url: 'http://localhost:7777' });
591
+ * const backend = new StateBrokerRateLimitBackend(broker);
592
+ *
593
+ * // Now rate limits are coordinated across all processes using the same daemon
594
+ * ```
595
+ */
596
+ declare class StateBrokerRateLimitBackend implements RateLimitBackend {
597
+ private broker;
598
+ constructor(broker: StateBroker);
599
+ /**
600
+ * Get current minute window key.
601
+ */
602
+ private getMinuteKey;
603
+ /**
604
+ * Get current second window key.
605
+ */
606
+ private getSecondKey;
607
+ /**
608
+ * Get active requests key.
609
+ */
610
+ private getActiveKey;
611
+ /**
612
+ * Get stats key.
613
+ */
614
+ private getStatsKey;
615
+ /**
616
+ * Get or initialize window state.
617
+ */
618
+ private getWindowState;
619
+ /**
620
+ * Get or initialize stats.
621
+ */
622
+ private getCumulativeStats;
623
+ /**
624
+ * @inheritdoc
625
+ */
626
+ acquire(resource: string, tokens: number, config: RateLimitConfig): Promise<AcquireResult>;
627
+ /**
628
+ * @inheritdoc
629
+ */
630
+ release(resource: string): Promise<void>;
631
+ /**
632
+ * @inheritdoc
633
+ */
634
+ getStats(resource: string): Promise<RateLimitStats>;
635
+ /**
636
+ * @inheritdoc
637
+ */
638
+ reset(resource: string): Promise<void>;
639
+ }
640
+
641
+ /**
642
+ * @module @kb-labs/core-resource-broker/rate-limit/presets
643
+ * Pre-configured rate limits for common providers.
644
+ */
645
+
646
+ /**
647
+ * Pre-configured rate limits for common providers.
648
+ */
649
+ declare const RATE_LIMIT_PRESETS: {
650
+ /**
651
+ * OpenAI Tier 1 (paid accounts, entry level)
652
+ * Updated Nov 2024: Tier 1 now has 1M TPM for embeddings
653
+ */
654
+ readonly 'openai-tier-1': {
655
+ tokensPerMinute: number;
656
+ requestsPerMinute: number;
657
+ maxTokensPerRequest: number;
658
+ safetyMargin: number;
659
+ };
660
+ /**
661
+ * OpenAI Tier 2 (after $50+ spent)
662
+ */
663
+ readonly 'openai-tier-2': {
664
+ tokensPerMinute: number;
665
+ requestsPerMinute: number;
666
+ maxTokensPerRequest: number;
667
+ safetyMargin: number;
668
+ };
669
+ /**
670
+ * OpenAI Tier 3
671
+ */
672
+ readonly 'openai-tier-3': {
673
+ tokensPerMinute: number;
674
+ requestsPerMinute: number;
675
+ maxTokensPerRequest: number;
676
+ safetyMargin: number;
677
+ };
678
+ /**
679
+ * OpenAI Tier 4
680
+ */
681
+ readonly 'openai-tier-4': {
682
+ tokensPerMinute: number;
683
+ requestsPerMinute: number;
684
+ maxTokensPerRequest: number;
685
+ safetyMargin: number;
686
+ };
687
+ /**
688
+ * OpenAI Tier 5 (enterprise)
689
+ */
690
+ readonly 'openai-tier-5': {
691
+ tokensPerMinute: number;
692
+ requestsPerMinute: number;
693
+ maxTokensPerRequest: number;
694
+ safetyMargin: number;
695
+ };
696
+ /**
697
+ * OpenAI GPT-4 specific limits (more restrictive)
698
+ */
699
+ readonly 'openai-gpt4': {
700
+ tokensPerMinute: number;
701
+ requestsPerMinute: number;
702
+ maxTokensPerRequest: number;
703
+ safetyMargin: number;
704
+ };
705
+ /**
706
+ * Anthropic Tier 1 (default)
707
+ */
708
+ readonly 'anthropic-tier-1': {
709
+ tokensPerMinute: number;
710
+ requestsPerMinute: number;
711
+ maxTokensPerRequest: number;
712
+ safetyMargin: number;
713
+ };
714
+ /**
715
+ * Anthropic Tier 2
716
+ */
717
+ readonly 'anthropic-tier-2': {
718
+ tokensPerMinute: number;
719
+ requestsPerMinute: number;
720
+ maxTokensPerRequest: number;
721
+ safetyMargin: number;
722
+ };
723
+ /**
724
+ * Anthropic Tier 3
725
+ */
726
+ readonly 'anthropic-tier-3': {
727
+ tokensPerMinute: number;
728
+ requestsPerMinute: number;
729
+ maxTokensPerRequest: number;
730
+ safetyMargin: number;
731
+ };
732
+ /**
733
+ * Anthropic Tier 4
734
+ */
735
+ readonly 'anthropic-tier-4': {
736
+ tokensPerMinute: number;
737
+ requestsPerMinute: number;
738
+ maxTokensPerRequest: number;
739
+ safetyMargin: number;
740
+ };
741
+ /**
742
+ * Sber GigaChat API
743
+ * Conservative limits for typical access
744
+ */
745
+ readonly 'sber-gigachat': {
746
+ requestsPerMinute: number;
747
+ requestsPerSecond: number;
748
+ safetyMargin: number;
749
+ };
750
+ /**
751
+ * Yandex GPT API
752
+ */
753
+ readonly 'yandex-gpt': {
754
+ requestsPerMinute: number;
755
+ requestsPerSecond: number;
756
+ safetyMargin: number;
757
+ };
758
+ /**
759
+ * Local Ollama
760
+ * No external rate limits, only GPU concurrency
761
+ */
762
+ readonly 'ollama-local': {
763
+ maxConcurrentRequests: number;
764
+ };
765
+ /**
766
+ * Self-hosted vLLM
767
+ */
768
+ readonly 'vllm-local': {
769
+ maxConcurrentRequests: number;
770
+ requestsPerSecond: number;
771
+ };
772
+ /**
773
+ * Self-hosted text-embeddings-inference
774
+ */
775
+ readonly 'tei-local': {
776
+ maxConcurrentRequests: number;
777
+ };
778
+ /**
779
+ * No rate limiting (for testing or unlimited APIs)
780
+ */
781
+ readonly unlimited: {};
782
+ /**
783
+ * Very conservative (for debugging rate limit issues)
784
+ */
785
+ readonly debug: {
786
+ tokensPerMinute: number;
787
+ requestsPerMinute: number;
788
+ maxConcurrentRequests: number;
789
+ safetyMargin: number;
790
+ };
791
+ };
792
+ type RateLimitPreset = keyof typeof RATE_LIMIT_PRESETS;
793
+ /**
794
+ * Get rate limit config from preset name or custom config.
795
+ *
796
+ * @param configOrPreset - Config object or preset name
797
+ * @returns Resolved rate limit configuration
798
+ *
799
+ * @example
800
+ * ```typescript
801
+ * // Use preset
802
+ * const config = getRateLimitConfig('openai-tier-2');
803
+ *
804
+ * // Use custom config
805
+ * const config = getRateLimitConfig({ tokensPerMinute: 100000 });
806
+ *
807
+ * // Default (openai-tier-2)
808
+ * const config = getRateLimitConfig();
809
+ * ```
810
+ */
811
+ declare function getRateLimitConfig(configOrPreset?: RateLimitConfig | RateLimitPreset | string): RateLimitConfig;
812
+ /**
813
+ * Estimate tokens for a text (rough approximation).
814
+ * Uses ~4 characters per token as a conservative estimate.
815
+ *
816
+ * @param text - Text to estimate
817
+ * @returns Estimated token count
818
+ */
819
+ declare function estimateTokens(text: string): number;
820
+ /**
821
+ * Estimate tokens for multiple texts.
822
+ *
823
+ * @param texts - Array of texts
824
+ * @returns Total estimated token count
825
+ */
826
+ declare function estimateBatchTokens(texts: string[]): number;
827
+
828
+ /**
829
+ * @module @kb-labs/core-resource-broker/retry/error-classifier
830
+ * Error classification for retry logic.
831
+ */
832
+
833
+ /**
834
+ * Classify an error for retry decision.
835
+ *
836
+ * @param error - Error to classify
837
+ * @returns Error type classification
838
+ */
839
+ declare function classifyError(error: unknown): ErrorType;
840
+ /**
841
+ * Check if an error is a rate limit error (429).
842
+ */
843
+ declare function isRateLimitError(error: unknown): boolean;
844
+ /**
845
+ * Check if an error is retryable.
846
+ *
847
+ * @param error - Error to check
848
+ * @param retryableTypes - Types that should be retried
849
+ */
850
+ declare function isRetryableError(error: unknown, retryableTypes?: ErrorType[]): boolean;
851
+ /**
852
+ * Extract retry-after hint from error if available.
853
+ *
854
+ * @param error - Error to extract hint from
855
+ * @returns Milliseconds to wait, or undefined
856
+ */
857
+ declare function extractRetryAfter(error: unknown): number | undefined;
858
+
859
+ /**
860
+ * @module @kb-labs/core-resource-broker/retry/retry-strategy
861
+ * Exponential backoff retry strategy with jitter.
862
+ */
863
+
864
+ /**
865
+ * Result of a retry decision.
866
+ */
867
+ interface RetryDecision {
868
+ /** Whether to retry */
869
+ shouldRetry: boolean;
870
+ /** Delay before retry (ms) */
871
+ delayMs: number;
872
+ /** Error classification */
873
+ errorType: ErrorType;
874
+ /** Current attempt number (0-indexed) */
875
+ attempt: number;
876
+ /** Maximum attempts allowed */
877
+ maxAttempts: number;
878
+ }
879
+ /**
880
+ * Calculate delay with exponential backoff and jitter.
881
+ *
882
+ * Formula: min(maxDelay, baseDelay * 2^attempt) * (1 + random * jitter)
883
+ *
884
+ * @param attempt - Current attempt (0-indexed)
885
+ * @param config - Retry configuration
886
+ * @param retryAfterHint - Optional retry-after hint from error (ms)
887
+ * @returns Delay in milliseconds
888
+ */
889
+ declare function calculateBackoffDelay(attempt: number, config: RetryConfig, retryAfterHint?: number): number;
890
+ /**
891
+ * Decide whether to retry based on error and attempt count.
892
+ *
893
+ * @param error - The error that occurred
894
+ * @param attempt - Current attempt (0-indexed)
895
+ * @param config - Retry configuration
896
+ * @returns Retry decision with delay
897
+ *
898
+ * @example
899
+ * ```typescript
900
+ * const decision = shouldRetry(error, 0, config);
901
+ *
902
+ * if (decision.shouldRetry) {
903
+ * await sleep(decision.delayMs);
904
+ * // retry...
905
+ * } else {
906
+ * throw error;
907
+ * }
908
+ * ```
909
+ */
910
+ declare function shouldRetry(error: unknown, attempt: number, config?: Partial<RetryConfig>): RetryDecision;
911
+ /**
912
+ * Execute a function with retry logic.
913
+ *
914
+ * @param fn - Function to execute
915
+ * @param config - Retry configuration
916
+ * @returns Result of the function
917
+ * @throws Last error if all retries exhausted
918
+ *
919
+ * @example
920
+ * ```typescript
921
+ * const result = await withRetry(
922
+ * async () => {
923
+ * return await llm.complete(prompt);
924
+ * },
925
+ * { maxRetries: 3, baseDelay: 1000 }
926
+ * );
927
+ * ```
928
+ */
929
+ declare function withRetry<T>(fn: () => Promise<T>, config?: Partial<RetryConfig>): Promise<{
930
+ result: T;
931
+ attempts: number;
932
+ }>;
933
+ /**
934
+ * Sleep for a specified duration.
935
+ *
936
+ * @param ms - Milliseconds to sleep
937
+ */
938
+ declare function sleep(ms: number): Promise<void>;
939
+ /**
940
+ * Create a retry configuration for rate-limited APIs.
941
+ *
942
+ * @param maxRetries - Maximum retry attempts (default: 5)
943
+ * @returns Retry config optimized for rate limits
944
+ */
945
+ declare function createRateLimitRetryConfig(maxRetries?: number): RetryConfig;
946
+ /**
947
+ * Create a retry configuration for quick operations.
948
+ *
949
+ * @param maxRetries - Maximum retry attempts (default: 3)
950
+ * @returns Retry config with fast retries
951
+ */
952
+ declare function createQuickRetryConfig(maxRetries?: number): RetryConfig;
953
+
954
+ /**
955
+ * @module @kb-labs/core-resource-broker/wrappers/queued-llm
956
+ * QueuedLLM - ILLM wrapper that routes requests through ResourceBroker.
957
+ */
958
+
959
+ /**
960
+ * Extended LLM options with priority.
961
+ */
962
+ interface QueuedLLMOptions extends LLMOptions {
963
+ /** Request priority (default: 'normal') */
964
+ priority?: ResourcePriority;
965
+ }
966
+ /**
967
+ * ILLM wrapper that routes requests through ResourceBroker.
968
+ *
969
+ * Features:
970
+ * - Transparent integration (implements ILLM interface)
971
+ * - Automatic token estimation for rate limiting
972
+ * - Priority support for different use cases
973
+ * - Retry and rate limiting handled by broker
974
+ *
975
+ * Note: stream() bypasses the queue for real-time UX.
976
+ *
977
+ * @example
978
+ * ```typescript
979
+ * const queuedLLM = new QueuedLLM(broker, realLLM);
980
+ *
981
+ * // Normal request (goes through queue)
982
+ * const response = await queuedLLM.complete(prompt);
983
+ *
984
+ * // High priority request
985
+ * const response = await queuedLLM.complete(prompt, { priority: 'high' });
986
+ *
987
+ * // Stream (bypasses queue for real-time)
988
+ * for await (const chunk of queuedLLM.stream(prompt)) {
989
+ * process.stdout.write(chunk);
990
+ * }
991
+ * ```
992
+ */
993
+ declare class QueuedLLM implements ILLM {
994
+ private broker;
995
+ private realLLM;
996
+ constructor(broker: IResourceBroker, realLLM: ILLM);
997
+ /**
998
+ * Generate a completion through the queue.
999
+ *
1000
+ * @param prompt - Text prompt
1001
+ * @param options - Optional generation options with priority
1002
+ * @returns LLM response
1003
+ * @throws Error if request fails after all retries
1004
+ */
1005
+ complete(prompt: string, options?: QueuedLLMOptions): Promise<LLMResponse>;
1006
+ getProtocolCapabilities(): Promise<LLMProtocolCapabilities>;
1007
+ /**
1008
+ * Stream a completion (bypasses queue for real-time UX).
1009
+ *
1010
+ * Streaming is passed through directly to the underlying LLM
1011
+ * because:
1012
+ * 1. Real-time user experience requires immediate response
1013
+ * 2. Token counting happens after streaming completes
1014
+ * 3. Rate limits are still enforced by the underlying adapter
1015
+ *
1016
+ * @param prompt - Text prompt
1017
+ * @param options - Optional generation options
1018
+ * @returns Async iterable of text chunks
1019
+ */
1020
+ stream(prompt: string, options?: LLMOptions): AsyncIterable<string>;
1021
+ /**
1022
+ * Chat with native tool calling support (proxies to underlying LLM).
1023
+ * Currently NOT queued - passes through directly for simplicity.
1024
+ * TODO: Add queueing support when needed.
1025
+ */
1026
+ chatWithTools(messages: LLMMessage[], options: LLMToolCallOptions): Promise<LLMToolCallResponse>;
1027
+ }
1028
+ /**
1029
+ * Create a QueuedLLM wrapper.
1030
+ *
1031
+ * @param broker - ResourceBroker instance
1032
+ * @param llm - Real ILLM implementation
1033
+ * @returns Wrapped ILLM that routes through broker
1034
+ */
1035
+ declare function createQueuedLLM(broker: IResourceBroker, llm: ILLM): QueuedLLM;
1036
+
1037
+ /**
1038
+ * @module @kb-labs/core-resource-broker/wrappers/queued-embeddings
1039
+ * QueuedEmbeddings - IEmbeddings wrapper that routes requests through ResourceBroker.
1040
+ */
1041
+
1042
+ /**
1043
+ * Options for queued embeddings operations.
1044
+ */
1045
+ interface QueuedEmbeddingsOptions {
1046
+ /** Request priority (default: 'normal') */
1047
+ priority?: ResourcePriority;
1048
+ }
1049
+ /**
1050
+ * IEmbeddings wrapper that routes requests through ResourceBroker.
1051
+ *
1052
+ * Features:
1053
+ * - Transparent integration (implements IEmbeddings interface)
1054
+ * - Automatic token estimation for rate limiting
1055
+ * - Batch operations with proper token accounting
1056
+ * - Priority support for different use cases
1057
+ *
1058
+ * @example
1059
+ * ```typescript
1060
+ * const queuedEmbeddings = new QueuedEmbeddings(broker, realEmbeddings);
1061
+ *
1062
+ * // Single embedding
1063
+ * const vector = await queuedEmbeddings.embed("Hello world");
1064
+ *
1065
+ * // Batch embedding
1066
+ * const vectors = await queuedEmbeddings.embedBatch(["Hello", "World"]);
1067
+ * ```
1068
+ */
1069
+ declare class QueuedEmbeddings implements IEmbeddings {
1070
+ private broker;
1071
+ private realEmbeddings;
1072
+ private _priority;
1073
+ constructor(broker: IResourceBroker, realEmbeddings: IEmbeddings);
1074
+ /**
1075
+ * Get embedding dimensions from the underlying implementation.
1076
+ */
1077
+ get dimensions(): number;
1078
+ /**
1079
+ * Set default priority for subsequent operations.
1080
+ *
1081
+ * @param priority - Priority level
1082
+ * @returns this for chaining
1083
+ */
1084
+ withPriority(priority: ResourcePriority): this;
1085
+ /**
1086
+ * Generate embedding vector for a single text through the queue.
1087
+ *
1088
+ * @param text - Input text
1089
+ * @returns Embedding vector
1090
+ * @throws Error if request fails after all retries
1091
+ */
1092
+ embed(text: string): Promise<number[]>;
1093
+ /**
1094
+ * Generate embedding vectors for multiple texts through the queue.
1095
+ *
1096
+ * @param texts - Array of input texts
1097
+ * @returns Array of embedding vectors
1098
+ * @throws Error if request fails after all retries
1099
+ */
1100
+ embedBatch(texts: string[]): Promise<number[][]>;
1101
+ /**
1102
+ * Get the dimensions of the embeddings.
1103
+ * This method is needed for IPC/Unix Socket transport to access the dimensions property.
1104
+ */
1105
+ getDimensions(): Promise<number>;
1106
+ }
1107
+ /**
1108
+ * Create a QueuedEmbeddings wrapper.
1109
+ *
1110
+ * @param broker - ResourceBroker instance
1111
+ * @param embeddings - Real IEmbeddings implementation
1112
+ * @returns Wrapped IEmbeddings that routes through broker
1113
+ */
1114
+ declare function createQueuedEmbeddings(broker: IResourceBroker, embeddings: IEmbeddings): QueuedEmbeddings;
1115
+
1116
+ /**
1117
+ * @module @kb-labs/core-resource-broker/wrappers/queued-vector-store
1118
+ * QueuedVectorStore - IVectorStore wrapper that routes requests through ResourceBroker.
1119
+ */
1120
+
1121
+ /**
1122
+ * Options for queued vector store operations.
1123
+ */
1124
+ interface QueuedVectorStoreOptions {
1125
+ /** Request priority (default: 'normal') */
1126
+ priority?: ResourcePriority;
1127
+ }
1128
+ /**
1129
+ * IVectorStore wrapper that routes requests through ResourceBroker.
1130
+ *
1131
+ * Features:
1132
+ * - Transparent integration (implements IVectorStore interface)
1133
+ * - Rate limiting for batch operations
1134
+ * - Priority support for different use cases
1135
+ * - Search operations prioritized over bulk upserts
1136
+ *
1137
+ * @example
1138
+ * ```typescript
1139
+ * const queuedVectorStore = new QueuedVectorStore(broker, realVectorStore);
1140
+ *
1141
+ * // Search (typically high priority)
1142
+ * const results = await queuedVectorStore.search(queryVector, 10);
1143
+ *
1144
+ * // Bulk upsert (typically normal/low priority)
1145
+ * await queuedVectorStore.upsert(vectors);
1146
+ * ```
1147
+ */
1148
+ declare class QueuedVectorStore implements IVectorStore {
1149
+ private broker;
1150
+ private realVectorStore;
1151
+ private _priority;
1152
+ constructor(broker: IResourceBroker, realVectorStore: IVectorStore);
1153
+ /**
1154
+ * Set default priority for subsequent operations.
1155
+ *
1156
+ * @param priority - Priority level
1157
+ * @returns this for chaining
1158
+ */
1159
+ withPriority(priority: ResourcePriority): this;
1160
+ /**
1161
+ * Search for similar vectors through the queue.
1162
+ *
1163
+ * @param query - Query embedding vector
1164
+ * @param limit - Maximum number of results
1165
+ * @param filter - Optional metadata filter
1166
+ * @returns Search results
1167
+ * @throws Error if request fails after all retries
1168
+ */
1169
+ search(query: number[], limit: number, filter?: VectorFilter): Promise<VectorSearchResult[]>;
1170
+ /**
1171
+ * Upsert vectors through the queue.
1172
+ *
1173
+ * @param vectors - Array of vector records to upsert
1174
+ * @throws Error if request fails after all retries
1175
+ */
1176
+ upsert(vectors: VectorRecord[]): Promise<void>;
1177
+ /**
1178
+ * Delete vectors through the queue.
1179
+ *
1180
+ * @param ids - Array of vector IDs to delete
1181
+ * @throws Error if request fails after all retries
1182
+ */
1183
+ delete(ids: string[]): Promise<void>;
1184
+ /**
1185
+ * Get total count of vectors through the queue.
1186
+ *
1187
+ * @returns Vector count
1188
+ * @throws Error if request fails after all retries
1189
+ */
1190
+ count(): Promise<number>;
1191
+ /**
1192
+ * Get vectors by IDs through the queue (if supported).
1193
+ *
1194
+ * @param ids - Array of vector IDs to retrieve
1195
+ * @returns Array of vector records
1196
+ * @throws Error if request fails or method not supported
1197
+ */
1198
+ get(ids: string[]): Promise<VectorRecord[]>;
1199
+ /**
1200
+ * Query vectors by filter through the queue (if supported).
1201
+ *
1202
+ * @param filter - Metadata filter to apply
1203
+ * @returns Array of matching vector records
1204
+ * @throws Error if request fails or method not supported
1205
+ */
1206
+ query(filter: VectorFilter): Promise<VectorRecord[]>;
1207
+ }
1208
+ /**
1209
+ * Create a QueuedVectorStore wrapper.
1210
+ *
1211
+ * @param broker - ResourceBroker instance
1212
+ * @param vectorStore - Real IVectorStore implementation
1213
+ * @returns Wrapped IVectorStore that routes through broker
1214
+ */
1215
+ declare function createQueuedVectorStore(broker: IResourceBroker, vectorStore: IVectorStore): QueuedVectorStore;
1216
+
1217
+ export { type AcquireResult, DEFAULT_RATE_LIMIT_CONFIG, DEFAULT_RETRY_CONFIG, type ErrorType, type IResourceBroker, InMemoryRateLimitBackend, PriorityQueue, type QueueItem, QueuedEmbeddings, type QueuedEmbeddingsOptions, QueuedLLM, type QueuedLLMOptions, QueuedVectorStore, type QueuedVectorStoreOptions, RATE_LIMIT_PRESETS, type RateLimitBackend, type RateLimitConfig, type RateLimitPreset, type RateLimitStats, ResourceBroker, type ResourceBrokerStats, type ResourceConfig, type ResourceExecutor, type ResourcePriority, type ResourceRequest, type ResourceResponse, type ResourceStats, type RetryConfig, type RetryDecision, StateBrokerRateLimitBackend, calculateBackoffDelay, classifyError, createQueuedEmbeddings, createQueuedLLM, createQueuedVectorStore, createQuickRetryConfig, createRateLimitRetryConfig, estimateBatchTokens, estimateTokens, extractRetryAfter, getRateLimitConfig, isRateLimitError, isRetryableError, shouldRetry, sleep, withRetry };