umans-gate 0.1.2 → 0.1.4

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +154 -0
  2. package/README.md +165 -45
  3. package/npm-shim.cjs +71 -0
  4. package/package.json +16 -80
  5. package/dashboard/dist/assets/alert-dialog-DlhAyxD3.js +0 -2
  6. package/dashboard/dist/assets/alert-dialog-DlhAyxD3.js.map +0 -1
  7. package/dashboard/dist/assets/clear-confirm-dialog-BOcl93wD.js +0 -2
  8. package/dashboard/dist/assets/clear-confirm-dialog-BOcl93wD.js.map +0 -1
  9. package/dashboard/dist/assets/config-tab-pnBjiSyC.js +0 -4
  10. package/dashboard/dist/assets/config-tab-pnBjiSyC.js.map +0 -1
  11. package/dashboard/dist/assets/economics-tab-BJXa5ydD.js +0 -2
  12. package/dashboard/dist/assets/economics-tab-BJXa5ydD.js.map +0 -1
  13. package/dashboard/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  14. package/dashboard/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  15. package/dashboard/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  16. package/dashboard/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  17. package/dashboard/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  18. package/dashboard/dist/assets/headers-viewer-C9FKdG-_.js +0 -2
  19. package/dashboard/dist/assets/headers-viewer-C9FKdG-_.js.map +0 -1
  20. package/dashboard/dist/assets/index-72wCsW4_.js +0 -3
  21. package/dashboard/dist/assets/index-72wCsW4_.js.map +0 -1
  22. package/dashboard/dist/assets/index-DFhG4t-C.css +0 -1
  23. package/dashboard/dist/assets/json-viewer-CXkZMoVn.js +0 -2
  24. package/dashboard/dist/assets/json-viewer-CXkZMoVn.js.map +0 -1
  25. package/dashboard/dist/assets/mode-toggle-BxkGFiYG.js +0 -2
  26. package/dashboard/dist/assets/mode-toggle-BxkGFiYG.js.map +0 -1
  27. package/dashboard/dist/assets/models-tab-Deqk3WT3.js +0 -2
  28. package/dashboard/dist/assets/models-tab-Deqk3WT3.js.map +0 -1
  29. package/dashboard/dist/assets/performance-meter-Bd152C4C.js +0 -2
  30. package/dashboard/dist/assets/performance-meter-Bd152C4C.js.map +0 -1
  31. package/dashboard/dist/assets/select-mZPf2BR3.js +0 -2
  32. package/dashboard/dist/assets/select-mZPf2BR3.js.map +0 -1
  33. package/dashboard/dist/assets/sheet-BgQXtbdw.js +0 -2
  34. package/dashboard/dist/assets/sheet-BgQXtbdw.js.map +0 -1
  35. package/dashboard/dist/assets/sonner-DGu1DGeO.js +0 -2
  36. package/dashboard/dist/assets/sonner-DGu1DGeO.js.map +0 -1
  37. package/dashboard/dist/assets/sse-viewer-BHnn3FcY.js +0 -3
  38. package/dashboard/dist/assets/sse-viewer-BHnn3FcY.js.map +0 -1
  39. package/dashboard/dist/assets/use-capture-done-listener-u5RxfYQP.js +0 -2
  40. package/dashboard/dist/assets/use-capture-done-listener-u5RxfYQP.js.map +0 -1
  41. package/dashboard/dist/assets/use-models-B4MLkfpt.js +0 -2
  42. package/dashboard/dist/assets/use-models-B4MLkfpt.js.map +0 -1
  43. package/dashboard/dist/assets/use-polling-resource-D_vWHFwW.js +0 -2
  44. package/dashboard/dist/assets/use-polling-resource-D_vWHFwW.js.map +0 -1
  45. package/dashboard/dist/assets/vendor-CVKsgXJU.js +0 -312
  46. package/dashboard/dist/assets/vendor-CVKsgXJU.js.map +0 -1
  47. package/dashboard/dist/assets/vendor-DtX4s2-2.css +0 -1
  48. package/dashboard/dist/assets/vendor-react-Dtud3GyP.js +0 -41
  49. package/dashboard/dist/assets/vendor-react-Dtud3GyP.js.map +0 -1
  50. package/dashboard/dist/assets/vision-calls-BquNiDzm.js +0 -3
  51. package/dashboard/dist/assets/vision-calls-BquNiDzm.js.map +0 -1
  52. package/dashboard/dist/index.html +0 -34
  53. package/dist/cli.d.ts +0 -1
  54. package/dist/cli.js +0 -6788
  55. package/dist/cli.js.map +0 -1
  56. package/dist/index.d.ts +0 -1094
  57. package/dist/index.js +0 -6443
  58. package/dist/index.js.map +0 -1
package/dist/index.d.ts DELETED
@@ -1,1094 +0,0 @@
1
- import { Database } from 'bun:sqlite';
2
-
3
- /** Normalized per-request usage metrics. All fields nullable. */
4
- interface UsageMetrics {
5
- /** Provider: "anthropic" | "openai" */
6
- provider: "anthropic" | "openai";
7
- /** Streaming or non-streaming response. */
8
- streaming: boolean;
9
- /** Non-cached input tokens. */
10
- input_tokens: number | null;
11
- /** Output tokens (cumulative, authoritative, billed). */
12
- output_tokens: number | null;
13
- /** Tokens written to cache (Anthropic: cache_creation_input_tokens; OpenAI: n/a). */
14
- cache_creation_tokens: number | null;
15
- /** Tokens read from cache (Anthropic: cache_read_input_tokens; OpenAI: prompt_tokens_details.cached_tokens). */
16
- cache_read_tokens: number | null;
17
- /** Total input = input + cache_creation + cache_read (Anthropic) or prompt_tokens (OpenAI). */
18
- total_input_tokens: number | null;
19
- /** Total output (same as output_tokens for Anthropic; completion_tokens for OpenAI). */
20
- total_output_tokens: number | null;
21
- /** Tokens spent on internal reasoning (optional, nullable). */
22
- thinking_tokens: number | null;
23
- /** Time-to-first-token in ms. DERIVED from event timing, never an API field. */
24
- ttft_ms: number | null;
25
- /** Full request duration in ms. */
26
- duration_ms: number | null;
27
- /** Tokens-per-second = output_tokens / ((duration_ms - ttft_ms) / 1000). Null if not computable. */
28
- tps: number | null;
29
- /** True if usage was absent (stream aborted, or include_usage not set). */
30
- usage_missing: boolean;
31
- /** Model name (set by extractUsage wrapper; not populated by individual extractors). */
32
- model?: string;
33
- }
34
- /** A chunk of SSE data with its wall-clock receive timestamp. */
35
- interface TimedChunk {
36
- text: string;
37
- time: number;
38
- }
39
- /** Aggregated per-model performance stats (computed in SQL, not JS). */
40
- interface PerformanceStatsRow {
41
- model: string;
42
- provider: "anthropic" | "openai";
43
- request_count: number;
44
- streaming_count: number;
45
- total_input_tokens: number;
46
- total_output_tokens: number;
47
- total_cache_read_tokens: number;
48
- total_thinking_tokens: number;
49
- cached_pct: number;
50
- ttft_mean: number | null;
51
- ttft_p10: number | null;
52
- ttft_p50: number | null;
53
- ttft_p95: number | null;
54
- ttft_outlier_count: number;
55
- tps_mean: number | null;
56
- tps_p10: number | null;
57
- tps_p50: number | null;
58
- tps_p95: number | null;
59
- tps_outlier_count: number;
60
- }
61
-
62
- /** HTTP protocol used for the upstream connection. */
63
- type UpstreamProtocol = "http2" | "http1.1";
64
- /** HTTP protocol for incoming connections (always http1.1 without TLS). */
65
- type IncomingProtocol = "http1.1";
66
- /** Capture state lifecycle. */
67
- type CaptureState = "enqueued" | "streaming" | "done";
68
- /** A full capture row from the database. */
69
- interface CaptureRow {
70
- id: number;
71
- method: string;
72
- path: string;
73
- url: string;
74
- request_headers: string | null;
75
- request_body: string | null;
76
- request_size: number;
77
- response_status: number | null;
78
- response_headers: string | null;
79
- response_body: string | null;
80
- response_size: number;
81
- content_type: string | null;
82
- is_sse: number;
83
- duration_ms: number;
84
- state: CaptureState;
85
- started_at: number | null;
86
- finished_at: number | null;
87
- incoming_protocol: string | null;
88
- upstream_protocol: string | null;
89
- provider: string | null;
90
- model: string | null;
91
- streaming: number | null;
92
- input_tokens: number | null;
93
- output_tokens: number | null;
94
- cache_creation_tokens: number | null;
95
- cache_read_tokens: number | null;
96
- total_input_tokens: number | null;
97
- total_output_tokens: number | null;
98
- thinking_tokens: number | null;
99
- ttft_ms: number | null;
100
- tps: number | null;
101
- usage_missing: number | null;
102
- metrics_extracted_at: number | null;
103
- is_vision: number;
104
- parent_capture_id: number | null;
105
- status_source: string | null;
106
- gate_reason: string | null;
107
- }
108
- /** Summary of a capture (no body data) — used in list view and WS broadcasts. */
109
- interface CaptureSummary {
110
- id: number;
111
- method: string;
112
- path: string;
113
- response_status: number | null;
114
- is_sse: boolean;
115
- content_type: string | null;
116
- request_size: number;
117
- response_size: number;
118
- duration_ms: number;
119
- state: CaptureState;
120
- started_at: number | null;
121
- finished_at: number | null;
122
- incoming_protocol: string;
123
- upstream_protocol: string;
124
- model: string | null;
125
- usage_missing: boolean | null;
126
- /** Time-to-first-token in ms (null if not computed or non-streaming). */
127
- ttft_ms: number | null;
128
- /** Tokens-per-second (null if not computable). */
129
- tps: number | null;
130
- /** Tokens written to cache (Anthropic cache_creation_input_tokens). */
131
- cache_creation_tokens: number | null;
132
- /** Tokens read from cache (cache hits). */
133
- cache_read_tokens: number | null;
134
- /** Total input tokens (input + cache_creation + cache_read). */
135
- total_input_tokens: number | null;
136
- /** Output tokens (non-cached, billed). */
137
- output_tokens: number | null;
138
- /** Total output tokens (same as output_tokens for most providers). */
139
- total_output_tokens: number | null;
140
- /** True if this row is a vision-model API call (merged into captures). */
141
- is_vision: boolean;
142
- /** "upstream" = status from upstream API; "gate" = proxy-generated; null = not yet recorded. */
143
- status_source: "upstream" | "gate" | null;
144
- /** Human-readable explanation when the proxy generated the HTTP status. */
145
- gate_reason: string | null;
146
- }
147
- /** Request metadata captured at proxy time. */
148
- interface RequestMeta {
149
- method: string;
150
- path: string;
151
- request_size: number;
152
- started_at: number;
153
- }
154
- /** Response metadata queued for write-behind. */
155
- interface ResponseMeta {
156
- $status: number;
157
- $rh: string;
158
- $rb: string;
159
- $rs: number;
160
- $ct: string;
161
- $sse: number;
162
- $dur: number;
163
- $fin: number;
164
- $status_source: "upstream" | "gate" | null;
165
- $gate_reason: string | null;
166
- $usage?: UsageMetrics | null;
167
- $model?: string | null;
168
- }
169
- /** WebSocket message types broadcast to connected inspector clients. */
170
- type WsMessage = {
171
- type: "new";
172
- capture: CaptureSummary;
173
- } | {
174
- type: "update";
175
- capture: CaptureSummary;
176
- } | {
177
- type: "state";
178
- captureId: number;
179
- state: CaptureState;
180
- } | {
181
- type: "gate";
182
- stats: GateStats;
183
- } | {
184
- type: "clear";
185
- } | {
186
- type: "vision-clear";
187
- };
188
- /** Configuration object resolved from environment variables. */
189
- interface ProxyConfig {
190
- port: number;
191
- host: string;
192
- target: string;
193
- maxCaptures: number;
194
- dbPath: string;
195
- viewerPrefix: string;
196
- flushIntervalMs: number;
197
- flushBatch: number;
198
- idleTimeout: number;
199
- upstreamProtocol: UpstreamProtocol;
200
- incomingProtocol: IncomingProtocol;
201
- /** Apply the Claude Code stamp bundle on Anthropic requests (TTL, top_k, max_tokens, thinking, output_config, context_management). */
202
- stampClaudeCode: boolean;
203
- /** Value to inject as `reasoning_effort` on OpenAI request bodies. Null = disabled. */
204
- stampReasoningEffort: "high" | "max" | null;
205
- openaiPath: string;
206
- /** Upstream connection warmer — pings upstream to prevent TLS handshake overhead on first request. */
207
- warmerEnabled: boolean;
208
- /** Warmer ping interval in milliseconds. */
209
- warmerIntervalMs: number;
210
- /** Path appended to `target` for warmer pings (no auth required). */
211
- warmerPath: string;
212
- /** Umans API key for /v1/usage calls (required for tier-aware limits). Null = fail-safe mode. */
213
- umansApiKey: string | null;
214
- /** Polling interval for /v1/usage reconciliation, in ms. */
215
- usageRefreshMs: number;
216
- /** Polling interval for /v1/models fetch (model weights + listing), in ms. */
217
- modelsRefreshMs: number;
218
- /** Persisted concurrency hard cap (from /v1/usage, editable for robustness testing). */
219
- concurrencyHardCap: number;
220
- /** Persisted concurrency soft limit (from /v1/usage, read-only display). */
221
- concurrencySoftLimit: number;
222
- /** Pro-tier rolling window: -1 = unlimited (no limiter), 0 = auto-derive from /v1/usage, >0 = explicit limit. */
223
- rateLimitRequests: number;
224
- /** Max time a request can wait in the queue before 503, in ms. */
225
- queueTimeoutMs: number;
226
- /** Max depth of the enqueued-waiters queue before 503-on-full. */
227
- maxQueueDepth: number;
228
- /** Cooldown after releasing a permit before reusing the slot, in ms. */
229
- releaseCooldownMs: number;
230
- /** Concurrency-429 count to trip the circuit breaker. */
231
- breakerThreshold: number;
232
- /** Time window for breaker 429 counting, in ms. */
233
- breakerWindowMs: number;
234
- /** Circuit breaker OPEN cooldown before HALF_OPEN probe, in ms. */
235
- breakerCooldownMs: number;
236
- /** Vision handoff strategy: never (off), catalog (model lookup), always. */
237
- visionStrategy: "never" | "catalog" | "always";
238
- /** URL of vision model API, or null to disable. */
239
- visionTarget: string | null;
240
- /** Model name sent to the vision API. */
241
- visionModel: string | null;
242
- /** Prompt sent to the vision model. */
243
- visionPrompt: string;
244
- /** Prompt version, for cache invalidation. */
245
- visionPromptVersion: number;
246
- /** Max images to process per request. */
247
- visionMaxImages: number;
248
- /** Max tokens for the description returned by the vision model. */
249
- visionMaxDescriptionTokens: number;
250
- /** Reasoning effort for vision model ("none"|"low"|"medium"|"high"). Null = don't send field. */
251
- visionReasoningEffort: "none" | "low" | "medium" | "high" | null;
252
- /** Timeout for vision model calls, in ms. */
253
- visionTimeoutMs: number;
254
- /** LRU cache size for vision descriptions. */
255
- visionCacheSize: number;
256
- /** TTL for vision cache entries (both in-memory and persistent), in ms. */
257
- visionCacheTtlMs: number;
258
- /** Hard row ceiling for the persistent vision cache table. */
259
- visionCacheMaxRows: number;
260
- /** Enable SQLite-backed persistent description cache. */
261
- visionPersistentCache: boolean;
262
- /** When true (catalog strategy), also intercept images for vision-capable
263
- * models — converting them to cacheable text descriptions for KV cache
264
- * efficiency and to bypass the 10-image-per-session limit. */
265
- visionForceInterceptCapable: boolean;
266
- /** Max concurrent vision-model API calls across all requests (default 1). */
267
- visionConcurrency: number;
268
- /** Max image dimension (longest side) after transcode, in pixels. */
269
- visionMaxDimension: number;
270
- /** JPEG quality 1–100 (used only when image_format is "jpeg"). */
271
- visionJpegQuality: number;
272
- /** Image format for transcoded images: "jpeg" (lossy) or "png" (lossless). */
273
- visionImageFormat: "jpeg" | "png";
274
- /** OpenAI image_url detail parameter: "auto", "low", or "high". */
275
- visionImageDetail: "auto" | "low" | "high";
276
- /** When true, vision cache misses forward the original body and process vision in the background. */
277
- backgroundVision: boolean;
278
- /** Reserved concurrency slots for the "main" intention (default 1). */
279
- concurrencyMainReservation: number;
280
- /** Reserved concurrency slots for the "vision" intention (default 1). */
281
- concurrencyVisionReservation: number;
282
- /** Max captured request/response body size in bytes. 0 = unlimited. */
283
- captureBodyMaxBytes: number;
284
- /** Max depth of the write-behind response queue. Distinct from waiters queue. */
285
- queueMaxDepth: number;
286
- /** WebSocket backpressure limit in bytes. 0 = use Bun default. */
287
- wsBackpressureLimit: number;
288
- /** Close WebSocket connections that exceed the backpressure limit. */
289
- wsCloseOnBackpressureLimit: boolean;
290
- /** Max pending vision requests to batch together. */
291
- visionPendingMaxBatch: number;
292
- /** Enable zstd compression for captured text payloads. */
293
- compressionEnabled: boolean;
294
- /** Use a Bun Worker for write-behind batch updates (offloads event loop blocking). */
295
- useWriteWorker: boolean;
296
- /** Hard timeout for upstream requests in milliseconds. Prevents permit leaks when upstream hangs and client stays connected. */
297
- upstreamTimeoutMs: number;
298
- }
299
- /** Upstream/incoming protocol fields — used by summary builders. */
300
- interface ProtocolConfig {
301
- incomingProtocol: ProxyConfig["incomingProtocol"];
302
- upstreamProtocol: ProxyConfig["upstreamProtocol"];
303
- upstreamTimeoutMs: ProxyConfig["upstreamTimeoutMs"];
304
- }
305
- /** Stamp-related fields used by the proxy stamp pipeline. */
306
- interface StampConfig {
307
- stampClaudeCode: ProxyConfig["stampClaudeCode"];
308
- stampReasoningEffort: ProxyConfig["stampReasoningEffort"];
309
- openaiPath: ProxyConfig["openaiPath"];
310
- }
311
- /** Capture-related fields used by the proxy for body truncation + DB path. */
312
- interface CaptureConfig {
313
- target: ProxyConfig["target"];
314
- captureBodyMaxBytes: ProxyConfig["captureBodyMaxBytes"];
315
- maxCaptures: ProxyConfig["maxCaptures"];
316
- dbPath: ProxyConfig["dbPath"];
317
- backgroundVision: ProxyConfig["backgroundVision"];
318
- }
319
- /** Gate-related fields for concurrency/rate-limit/circuit-breaker tuning. */
320
- interface GateConfig {
321
- concurrencyHardCap: ProxyConfig["concurrencyHardCap"];
322
- concurrencySoftLimit: ProxyConfig["concurrencySoftLimit"];
323
- rateLimitRequests: ProxyConfig["rateLimitRequests"];
324
- queueTimeoutMs: ProxyConfig["queueTimeoutMs"];
325
- maxQueueDepth: ProxyConfig["maxQueueDepth"];
326
- releaseCooldownMs: ProxyConfig["releaseCooldownMs"];
327
- breakerThreshold: ProxyConfig["breakerThreshold"];
328
- breakerWindowMs: ProxyConfig["breakerWindowMs"];
329
- breakerCooldownMs: ProxyConfig["breakerCooldownMs"];
330
- concurrencyMainReservation: ProxyConfig["concurrencyMainReservation"];
331
- concurrencyVisionReservation: ProxyConfig["concurrencyVisionReservation"];
332
- }
333
- /** Write-behind queue flush fields used by WriteQueue. */
334
- interface QueueConfig {
335
- flushIntervalMs: ProxyConfig["flushIntervalMs"];
336
- flushBatch: ProxyConfig["flushBatch"];
337
- queueMaxDepth: ProxyConfig["queueMaxDepth"];
338
- }
339
- /** A cache_control block in an Anthropic message body. */
340
- interface CacheControlBlock {
341
- type: string;
342
- ttl?: string;
343
- }
344
- /** Anthropic message content block that may carry cache_control. */
345
- interface ContentBlock {
346
- type?: string;
347
- text?: string;
348
- cache_control?: CacheControlBlock;
349
- [key: string]: unknown;
350
- }
351
- /** Anthropic `thinking` block injected for matching models. */
352
- interface ThinkingConfig {
353
- type: "adaptive";
354
- }
355
- /** Anthropic `output_config` block injected for matching models. */
356
- interface OutputConfig {
357
- effort: "high" | "max";
358
- }
359
- /** Anthropic request body shape (subset we care about for TTL stamping). */
360
- interface AnthropicBody {
361
- system?: ContentBlock[] | string;
362
- messages?: Array<{
363
- role: string;
364
- content: ContentBlock[] | string;
365
- }>;
366
- max_tokens?: number;
367
- thinking?: ThinkingConfig;
368
- output_config?: OutputConfig;
369
- context_management?: {
370
- edits: Array<{
371
- type: string;
372
- keep: string;
373
- }>;
374
- };
375
- [key: string]: unknown;
376
- }
377
- /** Snapshot of /v1/usage response (subset we care about). */
378
- interface UsageSnapshot {
379
- ok: boolean;
380
- fetchedAt: number;
381
- plan: "Code Pro" | "Code Max" | "unknown";
382
- requestsLimit: number | null;
383
- requestsHardCap: number | null;
384
- requestsWindowSeconds: number | null;
385
- concurrencySoftLimit: number;
386
- concurrencyHardCap: number;
387
- requestsInWindow: number;
388
- requestsRemaining: number | null;
389
- concurrentSessions: number;
390
- priorityLow: boolean;
391
- boxedUntil: number | null;
392
- boxedReason: string | null;
393
- unitsDemoted: boolean;
394
- demotedUntil: number | null;
395
- }
396
- /** Discriminated state of the circuit breaker. */
397
- type BreakerState = "closed" | "open" | "half_open";
398
- /** Stats snapshot for the dashboard gate panel. */
399
- interface GateStats {
400
- active: number;
401
- queued: number;
402
- softLimit: number;
403
- hardCap: number;
404
- tier: "Code Pro" | "Code Max" | "unknown";
405
- breaker: BreakerState;
406
- boxed: boolean;
407
- boxedReason: string | null;
408
- boxedUntil: number | null;
409
- priorityLow: boolean;
410
- unitsDemoted: boolean;
411
- demotedUntil: number | null;
412
- requestsRemaining: number | null;
413
- requestsInWindow: number;
414
- requestsLimit: number | null;
415
- windowSeconds: number | null;
416
- usageOk: boolean;
417
- lastUsageFetch: number | null;
418
- /** Active permits grouped by intention. */
419
- activeByIntention: Record<string, number>;
420
- /** Queued waiters grouped by intention. */
421
- queuedByIntention: Record<string, number>;
422
- /** Reserved concurrency slots per intention. */
423
- reservations: Record<string, number>;
424
- }
425
-
426
- /** Resolve the config directory path following OS conventions. */
427
- declare function resolveConfigDir(): string;
428
- /** Resolve the config file path (JSON single source of truth). */
429
- declare function resolveConfigPath(): string;
430
- /**
431
- * Fields removed from user config (hardcoded — app is Umans-specific):
432
- * target → "https://api.code.umans.ai"
433
- * openai_path → "chat/completions"
434
- * warmer_path → "/v1/models"
435
- * rate_limit_window_seconds → derived from /v1/usage (inherent, not configurable)
436
- * vision_target → derived from target + "/v1/chat/completions"
437
- * host → hardcoded "127.0.0.1" (local-only; use SSH tunnel for remote access)
438
- */
439
- interface RawConfig {
440
- port?: number;
441
- max_captures?: number;
442
- db_path?: string;
443
- idle_timeout?: number;
444
- upstream_protocol?: string;
445
- /** When true, applies the full Claude Code stamp bundle on Anthropic requests (TTL, top_k, max_tokens, thinking, output_config, context_management). */
446
- stamp_claude_code_enabled?: boolean;
447
- /** When true, stamps reasoning_effort onto OpenAI-compatible requests (effort=max for umans-glm* models, effort=high for all others) and removes max_tokens/thinking. */
448
- stamp_reasoning_effort_enabled?: boolean;
449
- warmer_enabled?: boolean;
450
- warmer_interval_ms?: number;
451
- umans_api_key?: string;
452
- usage_refresh_ms?: number;
453
- models_refresh_ms?: number;
454
- concurrency_hard_cap?: number;
455
- concurrency_soft_limit?: number;
456
- /** Pro-tier rolling-window request limit. -1 = unlimited (no limiter), 0 = auto-derive from /v1/usage, >0 = explicit limit. */
457
- rate_limit_requests?: number;
458
- queue_timeout_ms?: number;
459
- max_queue_depth?: number;
460
- release_cooldown_ms?: number;
461
- breaker_threshold?: number;
462
- breaker_window_ms?: number;
463
- breaker_cooldown_ms?: number;
464
- vision_strategy?: "never" | "catalog" | "always";
465
- vision_model?: string;
466
- vision_prompt?: string;
467
- vision_prompt_version?: number;
468
- vision_max_images?: number;
469
- vision_max_description_tokens?: number;
470
- vision_reasoning_effort?: "none" | "low" | "medium" | "high" | null;
471
- vision_timeout_ms?: number;
472
- vision_cache_size?: number;
473
- vision_cache_ttl_ms?: number;
474
- vision_cache_max_rows?: number;
475
- vision_persistent_cache?: boolean;
476
- vision_concurrency?: number;
477
- vision_max_dimension?: number;
478
- vision_jpeg_quality?: number;
479
- vision_image_format?: "jpeg" | "png";
480
- vision_image_detail?: "auto" | "low" | "high";
481
- concurrency_main_reservation?: number;
482
- concurrency_vision_reservation?: number;
483
- /** Max captured request/response body size in bytes. 0 = unlimited. */
484
- capture_body_max_bytes?: number;
485
- /** Max depth of the write-behind response queue. Distinct from waiters queue. */
486
- queue_max_depth?: number;
487
- /** WebSocket backpressure limit in bytes. 0 = use Bun default. */
488
- ws_backpressure_limit?: number;
489
- /** Close WebSocket connections that exceed the backpressure limit. */
490
- ws_close_on_backpressure_limit?: boolean;
491
- /** Max pending vision requests to batch together. */
492
- vision_pending_max_batch?: number;
493
- /** Compress stored request/response bodies with zstd. Default true (on). */
494
- compression_enabled?: boolean;
495
- upstream_timeout_ms?: number;
496
- }
497
- /**
498
- * Input shape accepted by validateConfig/saveConfig. Numeric fields accept
499
- * strings because HTML form inputs and env vars produce strings. Coercion
500
- * to RawConfig happens inside validateConfig.
501
- */
502
- type RawConfigInput = {
503
- [K in keyof RawConfig]?: NonNullable<RawConfig[K]> extends number ? RawConfig[K] | string : RawConfig[K];
504
- };
505
- /** Validation result. */
506
- interface ValidationResult {
507
- ok: boolean;
508
- errors: string[];
509
- warnings: string[];
510
- normalized: RawConfig;
511
- }
512
- /** Reload result returned by the reload API. */
513
- interface ReloadResult {
514
- ok: boolean;
515
- errors: string[];
516
- warnings: string[];
517
- applied: string[];
518
- restartRequired: string[];
519
- configPath: string;
520
- }
521
- /**
522
- * Validate a raw config object. Returns errors (blocking), warnings (non-blocking),
523
- * and a normalized copy with defaults filled in.
524
- */
525
- declare function validateConfig(raw: RawConfigInput): ValidationResult;
526
- /**
527
- * Write the default config template if no config file exists.
528
- */
529
- declare function ensureConfigFile(): string;
530
- /**
531
- * Load configuration.
532
- * Precedence: env vars > JSON config file > defaults.
533
- * Writes the default config on first run if no file exists.
534
- * Removed-from-config fields (target, openai_path, warmer_path, vision_target,
535
- * rate_limit_window_seconds) are hardcoded — app is Umans-specific.
536
- * Misconfigured numeric fields fall back to their defaults.
537
- */
538
- declare function loadConfig(env?: Record<string, string | undefined>): ProxyConfig;
539
- /**
540
- * Read the raw config.json from disk (for the config UI).
541
- * Returns defaults merged with the file contents (no env override).
542
- */
543
- declare function readConfigFile(): RawConfig;
544
- /**
545
- * Save a partial config to disk (validate first, merge with existing).
546
- * Returns validation result + the merged config that was written.
547
- */
548
- declare function saveConfig(patch: RawConfigInput): {
549
- ok: boolean;
550
- errors: string[];
551
- warnings: string[];
552
- written: RawConfig | null;
553
- };
554
-
555
- interface Permit {
556
- release: () => void;
557
- }
558
- interface ConcurrencyGateOptions {
559
- hardCap: number;
560
- softLimit: number;
561
- releaseCooldownMs: number;
562
- breakerThreshold: number;
563
- breakerWindowMs: number;
564
- breakerCooldownMs: number;
565
- maxQueueDepth: number;
566
- queueTimeoutMs: number;
567
- intentions?: Record<string, number>;
568
- }
569
-
570
- declare class ConcurrencyGate {
571
- private readonly semaphore;
572
- private readonly breaker;
573
- private onStatsCb;
574
- constructor(opts: ConcurrencyGateOptions);
575
- /** Hot-reload reconfigurable parameters. Does NOT affect the soft limit
576
- * (which is driven by usage.onChange). Updates breaker/queue/cooldown. */
577
- reconfigure(opts: Partial<ConcurrencyGateOptions>): void;
578
- onStatsChange(cb: () => void): void;
579
- getLimit(): number;
580
- getIntentionActive(intention: string): number;
581
- getIntentionQueued(intention: string): number;
582
- resize(newLimit: number): void;
583
- /** Update the hard cap (e.g. from /v1/usage reconciliation).
584
- * Clamps the soft limit down if it now exceeds the new hard cap.
585
- *
586
- * Policy: `hard_cap` is a hard grant boundary, NOT a hard real-time ceiling.
587
- * Lowering the cap does NOT evict active permits. Transient over-cap states
588
- * are expected until in-flight permits complete naturally. */
589
- setHardCap(newHardCap: number): void;
590
- /** Update the persisted soft limit (from /v1/usage). Does NOT change the
591
- * effective limit — that's driven by usage.onChange with priorityLow adjustment. */
592
- setSoftLimit(newSoftLimit: number): void;
593
- acquire(opts?: {
594
- weight?: number;
595
- signal?: AbortSignal;
596
- onAcquire?: () => void;
597
- intention?: string;
598
- }): Promise<Permit>;
599
- record429(type: "concurrency" | "rate_limit" | "gateway"): void;
600
- recordSuccess(): void;
601
- getStats(snapshot: UsageSnapshot): GateStats;
602
- shutdown(): void;
603
- private emitStats;
604
- }
605
-
606
- /** Tristate capability: true = supports vision, false = does not, "via-handoff" = only via handoff. */
607
- type VisionTristate = true | false | "via-handoff";
608
- /** Lookup interface for vision-capability queries. Implemented by ModelsClient + ModelInfoClient. */
609
- interface VisionLookup {
610
- getVisionSupport(modelName: string): VisionTristate | null;
611
- }
612
-
613
- /** A Bun WebSocket server instance. */
614
- interface BunServerWebSocket {
615
- send(data: string): number;
616
- close(code?: number, reason?: string): void;
617
- readyState: number;
618
- }
619
- /**
620
- * Manages the set of connected WebSocket clients and broadcasts messages.
621
- * Decoupled from the server lifecycle so tests can stub it.
622
- */
623
- declare class WsBroadcaster {
624
- private clients;
625
- /** Add a client to the broadcast set. */
626
- add(ws: BunServerWebSocket): void;
627
- /** Remove a client from the broadcast set. */
628
- remove(ws: BunServerWebSocket): void;
629
- /** Broadcast a message to all connected clients. Swallows per-client errors. */
630
- broadcast(msg: WsMessage): void;
631
- /** Current number of connected clients. */
632
- get size(): number;
633
- }
634
-
635
- /** A recorded vision call for debugging and dashboard visibility. */
636
- interface VisionCallRecord {
637
- id: number;
638
- timestamp: number;
639
- captureId: number | null;
640
- model: string;
641
- target: string;
642
- imageSize: number;
643
- imageHash: string | null;
644
- status: "ok" | "cache_hit" | "http_error" | "timeout" | "fetch_error" | "parse_error" | "empty" | "skipped" | "aborted";
645
- httpStatus: number | null;
646
- latencyMs: number;
647
- description: string;
648
- error: string | null;
649
- incomingProtocol: string;
650
- upstreamProtocol: string;
651
- state: CaptureState;
652
- }
653
-
654
- /** Prepared statement parameter types. */
655
- interface InsertParams {
656
- $method: string;
657
- $path: string;
658
- $url: string;
659
- $rh: string;
660
- $rb: string;
661
- $rs: number;
662
- $st: number;
663
- $state: string;
664
- $inp: string;
665
- $outp: string;
666
- }
667
- interface UpdateParams {
668
- $id: number;
669
- $status: number;
670
- $rh: string;
671
- $rb: string;
672
- $rs: number;
673
- $ct: string;
674
- $sse: number;
675
- $dur: number;
676
- $fin: number;
677
- $status_source: "upstream" | "gate" | null;
678
- $gate_reason: string | null;
679
- $usage?: UsageMetrics | null;
680
- $model?: string | null;
681
- }
682
- interface VisionInsertParams {
683
- $method: string;
684
- $path: string;
685
- $url: string;
686
- $rh: string;
687
- $rb: string;
688
- $rs: number;
689
- $status: number | null;
690
- $rh2: string;
691
- $rb2: string;
692
- $rs2: number;
693
- $ct: string;
694
- $dur: number;
695
- $state: CaptureState;
696
- $started_at: number;
697
- $finished_at: number;
698
- $inp: string;
699
- $outp: string;
700
- $model: string;
701
- $parent_capture_id: number | null;
702
- $vision_meta: string | null;
703
- $provider: string | null;
704
- $streaming: number | null;
705
- $input_tokens: number | null;
706
- $output_tokens: number | null;
707
- $cache_creation_tokens: number | null;
708
- $cache_read_tokens: number | null;
709
- $total_input_tokens: number | null;
710
- $total_output_tokens: number | null;
711
- $thinking_tokens: number | null;
712
- $ttft_ms: number | null;
713
- $tps: number | null;
714
- $usage_missing: number | null;
715
- $metrics_extracted_at: number | null;
716
- }
717
- interface VisionUpdateParams {
718
- $id: number;
719
- $status: number | null;
720
- $rh: string;
721
- $rb: string;
722
- $rs: number;
723
- $ct: string;
724
- $sse: number;
725
- $dur: number;
726
- $fin: number;
727
- $status_source: "upstream" | "gate" | null;
728
- $gate_reason: string | null;
729
- $vision_meta: string | null;
730
- $model: string | null;
731
- $provider: string | null;
732
- $streaming: number | null;
733
- $input_tokens: number | null;
734
- $output_tokens: number | null;
735
- $cache_creation_tokens: number | null;
736
- $cache_read_tokens: number | null;
737
- $total_input_tokens: number | null;
738
- $total_output_tokens: number | null;
739
- $thinking_tokens: number | null;
740
- $ttft_ms: number | null;
741
- $tps: number | null;
742
- $usage_missing: number | null;
743
- $metrics_extracted_at: number | null;
744
- }
745
- /** Capture database — wraps a bun:sqlite Database with prepared statements. */
746
- declare class CaptureDB {
747
- private db;
748
- private stmtInsert;
749
- private stmtUpdate;
750
- private stmtDeleteOld;
751
- private stmtGet;
752
- private stmtList;
753
- private stmtCount;
754
- private stmtSetState;
755
- private stmtUpdateRequestBody;
756
- private stmtPerformanceStats;
757
- private stmtInsertVision;
758
- private stmtUpdateVision;
759
- private stmtListVision;
760
- private stmtClearVision;
761
- private stmtListVisionRecords;
762
- private readonly visionDescStore;
763
- private rowCount;
764
- readonly maxCaptures: number;
765
- compressionEnabled: boolean;
766
- constructor(config: Pick<ProxyConfig, "dbPath" | "maxCaptures"> & Partial<Pick<ProxyConfig, "compressionEnabled">>);
767
- /** Mark captures stuck in "streaming" or "enqueued" from a previous run as "done".
768
- * Called once on startup so the dashboard doesn't show phantom "running" rows. */
769
- private sweepStaleCaptures;
770
- /** Insert a new capture row and enforce the ring buffer. Returns the new id. */
771
- startCapture(params: InsertParams): number;
772
- /** Update a capture row with response data. */
773
- updateCapture(params: UpdateParams): void;
774
- /** Transition a capture's state (enqueued → streaming → done). */
775
- setState(id: number, state: "enqueued" | "streaming" | "done"): void;
776
- /** Update request_body and request_size after in-flight modification (e.g. vision handoff). */
777
- updateRequestBody(id: number, body: string, size: number): void;
778
- /** Batch-update multiple captures in a single transaction. */
779
- batchUpdate(items: Array<{
780
- id: number;
781
- res: Omit<UpdateParams, "$id">;
782
- }>): Promise<void>;
783
- /** Get a single capture by id (full row including bodies). */
784
- get(id: number): CaptureRow | null;
785
- /** List recent capture summaries (no body data). */
786
- list(limit: number): CaptureRow[];
787
- /** Compute per-model performance stats entirely in SQL (p10/p50/p95, sums, cached%).
788
- * Uses the v_latest_requests_per_model view + nearest-rank percentiles.
789
- * Returns PerformanceStatsRow[] — no JS post-processing needed. */
790
- getPerformanceStats(): PerformanceStatsRow[];
791
- /** Delete all captures. */
792
- clear(): void;
793
- /** Insert a vision-call capture row. Returns the new row id. */
794
- insertVisionCapture(params: VisionInsertParams): number;
795
- /** Update a vision-call capture row with final response data and mark it done. */
796
- updateVisionCapture(params: VisionUpdateParams): void;
797
- /** List recent vision-call capture summaries (is_vision=1). */
798
- listVisionCaptures(limit: number): CaptureRow[];
799
- /** Delete only vision-call captures (is_vision=1). */
800
- clearVisionCaptures(): void;
801
- /**
802
- * Reconstruct VisionCallRecord[] from stored vision-call rows.
803
- * The metadata is persisted as JSON in vision_meta by addRecord().
804
- */
805
- getVisionCallRecords(limit: number): VisionCallRecord[];
806
- /** Close the database connection. */
807
- close(): void;
808
- /** Access the raw bun:sqlite Database (for economics queries). */
809
- get rawDb(): Database;
810
- /** Insert or update a vision description in the persistent store. */
811
- upsertVisionDescription(params: {
812
- $key: string;
813
- $image_hash: string;
814
- $model: string;
815
- $prompt_version: number;
816
- $description: string;
817
- $now: number;
818
- }): void;
819
- /** Look up a vision description by key. Returns null if not found. */
820
- getVisionDescription(key: string): {
821
- description: string;
822
- created_at: number;
823
- } | null;
824
- deleteVisionDescription(key: string): void;
825
- evictVisionDescriptions(cutoff: number, maxRows: number): number;
826
- /** List recent non-expired vision descriptions for cache warming. Returns up to `limit` entries. */
827
- listVisionDescriptionsForWarming(limit: number, cutoff: number): Array<{
828
- key: string;
829
- description: string;
830
- }>;
831
- }
832
-
833
- /** Tristate vision support as encoded by the upstream API. */
834
- type VisionSupport = boolean | "via-handoff";
835
-
836
- /** Rich model info from /v1/models/info — faithfully typed from the upstream API. */
837
- interface ModelInfo {
838
- name: string;
839
- display_name: string;
840
- description: string;
841
- base_model: {
842
- name: string;
843
- provider?: string;
844
- family?: string;
845
- oss_base?: string;
846
- };
847
- capabilities: {
848
- max_completion_tokens: number;
849
- recommended_max_tokens: number;
850
- context_window: number;
851
- supports_vision: VisionSupport;
852
- supports_tools: boolean;
853
- reasoning: {
854
- supported: boolean;
855
- can_disable: boolean;
856
- levels: string[];
857
- default_level: string | null;
858
- };
859
- };
860
- benchmarks: Record<string, unknown>;
861
- weights: {
862
- precision: string | undefined;
863
- hf_url: string | undefined;
864
- };
865
- stage?: string;
866
- lifecycle?: {
867
- playground_start_date?: string;
868
- };
869
- }
870
- interface ModelEntry {
871
- id: string;
872
- context_length: number;
873
- pricing: {
874
- input: number;
875
- output: number;
876
- } | null;
877
- weight: number;
878
- info: ModelInfo | null;
879
- }
880
- interface ModelsClientOptions {
881
- target: string;
882
- apiKey?: string | null;
883
- refreshMs: number;
884
- /** Path appended to target for the model list. */
885
- path?: string;
886
- /** Path appended to target for the model info endpoint. */
887
- infoPath?: string;
888
- }
889
- /**
890
- * Fetches /v1/models on a timer, derives weights, and exposes synchronous
891
- * lookups. Failures are best-effort: last-known-good is served with ok=false.
892
- */
893
- declare class ModelsClient implements VisionLookup {
894
- private entries;
895
- private fetchedAt;
896
- private ok;
897
- private timer;
898
- private fetching;
899
- private onChangeCb;
900
- private readonly target;
901
- private readonly apiKey;
902
- private readonly refreshMs;
903
- private readonly path;
904
- private readonly infoPath;
905
- constructor(opts: ModelsClientOptions);
906
- start(): void;
907
- stop(): void;
908
- /** Subscribe to catalog updates (fired after each successful or failed refresh). */
909
- onChange(cb: () => void): void;
910
- /** True if the catalog has been successfully fetched at least once. */
911
- isReady(): boolean;
912
- /** Timestamp (ms) of the last successful fetch, or 0 if never. */
913
- lastFetchedAt(): number;
914
- /** Current fetch health. */
915
- healthy(): boolean;
916
- /**
917
- * Look up the derived weight for a model id.
918
- * Returns DEFAULT_MODEL_WEIGHT if the model is unknown or the catalog
919
- * has not been fetched yet.
920
- */
921
- getWeight(modelId: string): number;
922
- getVisionSupport(modelName: string): VisionTristate | null;
923
- /** Get a model entry, or null if unknown. */
924
- get(modelId: string): ModelEntry | null;
925
- /** Snapshot of all known models (sorted by id). */
926
- list(): ModelEntry[];
927
- /**
928
- * Fetch the model list from the upstream API.
929
- * Deduplicates concurrent calls. Returns true on success, false on failure.
930
- */
931
- refresh(): Promise<boolean>;
932
- private doFetch;
933
- }
934
-
935
- /** Abstraction over the capture persistence layer used by WriteQueue. */
936
- interface CaptureStore {
937
- updateCapture(params: UpdateParams): void;
938
- batchUpdate(items: Array<{
939
- id: number;
940
- res: Omit<UpdateParams, "$id">;
941
- }>): Promise<void>;
942
- }
943
- /**
944
- * Batches response metadata updates and flushes them to the database
945
- * in a single transaction. Broadcasts WebSocket updates after each flush
946
- * via the optional onFlush callback.
947
- */
948
- declare class WriteQueue {
949
- private queue;
950
- private flushTimer;
951
- private readonly flushIntervalMs;
952
- private readonly flushBatch;
953
- private readonly queueMaxDepth;
954
- private store;
955
- private onFlush?;
956
- private config;
957
- droppedCount: number;
958
- constructor(store: CaptureStore, config: QueueConfig & ProtocolConfig, onFlush?: (messages: WsMessage[]) => void);
959
- /** Queue a response metadata update for a capture. */
960
- queueUpdate(id: number, reqMeta: RequestMeta, res: ResponseMeta): void;
961
- get length(): number;
962
- get hasTimer(): boolean;
963
- /** Flush all queued updates to the database immediately.
964
- * On batchUpdate failure, re-queues the batch at the front so items are
965
- * not permanently lost. The drop path in queueUpdate() will activate
966
- * if the queue overflows after a failed flush. */
967
- flushNow(): Promise<void>;
968
- }
969
-
970
- interface RateLimitConfig {
971
- limit: number;
972
- windowSeconds: number;
973
- }
974
- interface RateCheckResult {
975
- allowed: boolean;
976
- remaining: number;
977
- retryAfterSeconds: number | null;
978
- }
979
- declare class SlidingWindowRateLimiter {
980
- private entries;
981
- private runningSum;
982
- private readonly limit;
983
- private readonly windowMs;
984
- constructor(config: RateLimitConfig);
985
- /** Record a request with the given weight. Returns whether it was allowed. */
986
- check(weight?: number, now?: number): RateCheckResult;
987
- /** Check whether a request with the given weight would be allowed, without recording. */
988
- peek(weight?: number, now?: number): RateCheckResult;
989
- private prune;
990
- /** Total weight of entries currently in the window. */
991
- count(now?: number): number;
992
- }
993
-
994
- declare class UmansUsageClient {
995
- private snapshot;
996
- private timer;
997
- private fetching;
998
- private readonly target;
999
- private readonly apiKey;
1000
- private readonly refreshMs;
1001
- private onChangeCb;
1002
- constructor(config: Pick<ProxyConfig, "target" | "umansApiKey" | "usageRefreshMs">);
1003
- onChange(cb: (s: UsageSnapshot) => void): void;
1004
- start(): void;
1005
- stop(): void;
1006
- getSnapshot(): UsageSnapshot;
1007
- refresh(): Promise<void>;
1008
- /** One-shot fetch of /v1/usage to extract concurrency hard_cap + soft_limit.
1009
- * Does NOT update live snapshot. */
1010
- fetchLimitsFromSource(): Promise<{
1011
- ok: true;
1012
- hardCap: number;
1013
- softLimit: number;
1014
- } | {
1015
- ok: false;
1016
- error: string;
1017
- }>;
1018
- /** One-shot fetch of /v1/usage to extract requests limits for rate_limit_requests validation.
1019
- * Returns {limit, hardCap, windowSeconds} or null if not set (unlimited). */
1020
- fetchRequestsLimit(): Promise<{
1021
- ok: true;
1022
- limit: number | null;
1023
- hardCap: number | null;
1024
- windowSeconds: number | null;
1025
- } | {
1026
- ok: false;
1027
- error: string;
1028
- }>;
1029
- private applySnapshot;
1030
- private applyFailedSnapshot;
1031
- }
1032
-
1033
- declare class ConnectionWarmer {
1034
- private readonly target;
1035
- private readonly intervalMs;
1036
- private readonly path;
1037
- private readonly upstreamProtocol;
1038
- private timer;
1039
- private lastTrafficAt;
1040
- private warmedOnce;
1041
- constructor(config: Pick<ProxyConfig, "target" | "warmerIntervalMs" | "warmerPath" | "upstreamProtocol">);
1042
- start(): void;
1043
- stop(): void;
1044
- /** Called by the proxy on every upstream request — connection is already warm. */
1045
- notifyTraffic(): void;
1046
- private ping;
1047
- }
1048
-
1049
- /**
1050
- * Stamp `ttl` onto Anthropic-style cache_control ephemeral blocks that lack one.
1051
- * Mutates the body in place. Returns the count of blocks stamped (caller
1052
- * re-serializes only when > 0). Non-array system (e.g. a plain string) is
1053
- * skipped safely.
1054
- */
1055
- declare function stampCacheTtl(body: AnthropicBody, ttl: string): number;
1056
-
1057
- /** Options for creating a proxy server. */
1058
- interface CreateProxyServerOptions {
1059
- /** Override env config. Pass a partial config to merge with defaults.
1060
- * Note: `host` is hardcoded to `127.0.0.1` and cannot be overridden. */
1061
- config?: Omit<Partial<ProxyConfig>, "host">;
1062
- /** Use an existing CaptureDB instance instead of creating one. */
1063
- db?: CaptureDB;
1064
- /** Use an existing WsBroadcaster instead of creating one. */
1065
- ws?: WsBroadcaster;
1066
- /** Print the startup banner (default: true). */
1067
- banner?: boolean;
1068
- }
1069
- /** The running proxy server handle. */
1070
- interface ProxyServer {
1071
- server: ReturnType<typeof Bun.serve>;
1072
- db: CaptureDB;
1073
- ws: WsBroadcaster;
1074
- queue: WriteQueue;
1075
- warmer: ConnectionWarmer | null;
1076
- gate: ConcurrencyGate;
1077
- usage: UmansUsageClient;
1078
- models: ModelsClient;
1079
- rate: SlidingWindowRateLimiter | null;
1080
- config: ProxyConfig;
1081
- /** Reload config from disk and apply hot-reloadable fields. */
1082
- reloadConfig(): ReloadResult;
1083
- shutdown(): Promise<void>;
1084
- }
1085
- /**
1086
- * Create and start the LLM capture proxy server.
1087
- *
1088
- * This is the main programmatic entry point. It sets up the database,
1089
- * WebSocket broadcaster, write-behind queue, viewer router, and proxy handler,
1090
- * then starts listening on the configured port.
1091
- */
1092
- declare function createProxyServer(options?: CreateProxyServerOptions): ProxyServer;
1093
-
1094
- export { type BreakerState, type BunServerWebSocket, type CaptureConfig, CaptureDB, type CaptureRow, type CaptureSummary, ConcurrencyGate, ConnectionWarmer, type CreateProxyServerOptions, type GateConfig, type GateStats, type ProtocolConfig, type ProxyConfig, type ProxyServer, type QueueConfig, type RawConfig, type RawConfigInput, type ReloadResult, SlidingWindowRateLimiter, type StampConfig, type TimedChunk, UmansUsageClient, type UsageSnapshot, type ValidationResult, WriteQueue, WsBroadcaster, type WsMessage, createProxyServer, ensureConfigFile, loadConfig, readConfigFile, resolveConfigDir, resolveConfigPath, saveConfig, stampCacheTtl, validateConfig };