UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

1,082 lines (1,081 loc) 34.1 kB
/** * Proxy type definitions for NeuroLink * * Consolidates all proxy-related types from: * - src/lib/proxy/claudeFormat.ts (Claude API types, SSE types, internal result) * - src/lib/proxy/cloaking/types.ts (cloaking pipeline types) * - src/lib/proxy/cloaking/plugins/ (plugin option types) * - src/lib/proxy/modelRouter.ts (routing types) * - src/lib/proxy/proxyConfig.ts (config file types) * - src/lib/proxy/requestLogger.ts (log entry type) * - src/lib/proxy/usageStats.ts (stats types) * - src/lib/proxy/tokenRefresh.ts (refresh types) * - src/lib/proxy/accountQuota.ts (quota type) * - src/lib/server/routes/claudeProxyRoutes.ts (runtime state, deps) */ import type { Counter, Histogram, Span } from "@opentelemetry/api"; import type { Hono } from "hono"; import type { Ora } from "ora"; import type { MCPToolRegistry } from "../mcp/toolRegistry.js"; import type { ProxyTracer } from "../proxy/proxyTracer.js"; import type { FallbackEntry, ProxyRoutingConfig, CloakingConfig } from "./subscription.js"; import type { RouteDeprecation } from "./server.js"; /** * Type describing the ModelRouter contract. * Defined here to avoid a circular dependency between types and implementation. */ export type ModelRouterInterface = { resolve(requestedModel: string): RouteResult; isClaudeTarget(requestedModel: string): boolean; getFallbackChain(): FallbackEntry[]; }; /** A single text block in a Claude content array. */ export type ClaudeTextBlock = { type: "text"; text: string; }; /** A single image block in a Claude content array. */ export type ClaudeImageBlock = { type: "image"; source: { type: "base64" | "url"; media_type?: string; data?: string; url?: string; }; }; /** Tool-use block returned by Claude in assistant messages. */ export type ClaudeToolUseBlock = { type: "tool_use"; id: string; name: string; input: Record<string, unknown>; }; /** Tool-result block sent back by the caller. */ export type ClaudeToolResultBlock = { type: "tool_result"; tool_use_id: string; content: string | ClaudeContentBlock[]; }; /** A thinking/reasoning block in a Claude content array. */ export type ClaudeThinkingBlock = { type: "thinking"; thinking: string; }; export type ClaudeContentBlock = ClaudeTextBlock | ClaudeImageBlock | ClaudeToolUseBlock | ClaudeToolResultBlock | ClaudeThinkingBlock; /** A single message in a Claude conversation. */ export type ClaudeMessage = { role: "user" | "assistant"; content: string | ClaudeContentBlock[]; }; /** Tool definition in the Claude Messages API format. */ export type ClaudeTool = { name: string; description?: string; input_schema: Record<string, unknown>; }; /** Metadata attached to a Claude Messages API request. */ export type ClaudeMetadata = { user_id?: string; }; /** * Inbound Claude Messages API request body. * Matches POST /v1/messages. */ export type ClaudeRequest = { model: string; messages: ClaudeMessage[]; max_tokens: number; system?: string | Array<{ type: "text"; text: string; }>; temperature?: number; top_p?: number; top_k?: number; stop_sequences?: string[]; stream?: boolean; tools?: ClaudeTool[]; tool_choice?: { type: "auto" | "any" | "none"; } | { type: "tool"; name: string; }; thinking?: { type: string; budget_tokens?: number; }; metadata?: ClaudeMetadata; }; /** Usage counters returned in a Claude response. */ export type ClaudeUsage = { input_tokens: number; output_tokens: number; cache_creation_input_tokens?: number; cache_read_input_tokens?: number; }; /** Non-streaming response matching the Claude Messages API. */ export type ClaudeResponse = { id: string; type: "message"; role: "assistant"; content: ClaudeContentBlock[]; model: string; stop_reason: string | null; stop_sequence: string | null; usage: ClaudeUsage; }; /** Claude API error envelope. */ export type ClaudeErrorResponse = { type: "error"; error: { type: string; message: string; }; }; /** Content block descriptor for content_block_start events. */ export type SSEContentBlockDescriptor = { type: "text"; text: ""; } | { type: "thinking"; thinking: ""; } | { type: "tool_use"; id: string; name: string; input: ""; }; /** Delta descriptor for content_block_delta events. */ export type SSEDeltaDescriptor = { type: "text_delta"; text: string; } | { type: "thinking_delta"; thinking: string; } | { type: "input_json_delta"; partial_json: string; }; export type SSEMessageStart = { type: "message_start"; message: Omit<ClaudeResponse, "content"> & { content: []; }; }; export type SSEContentBlockStart = { type: "content_block_start"; index: number; content_block: SSEContentBlockDescriptor; }; export type SSEContentBlockDelta = { type: "content_block_delta"; index: number; delta: SSEDeltaDescriptor; }; export type SSEContentBlockStop = { type: "content_block_stop"; index: number; }; export type SSEMessageDelta = { type: "message_delta"; delta: { stop_reason: string | null; stop_sequence: string | null; }; usage: { output_tokens: number; }; }; export type SSEMessageStop = { type: "message_stop"; }; export type SSEPing = { type: "ping"; }; export type SSEEvent = SSEMessageStart | SSEContentBlockStart | SSEContentBlockDelta | SSEContentBlockStop | SSEMessageDelta | SSEMessageStop | SSEPing; /** * Minimal subset of NeuroLink's GenerateResult that the proxy layer consumes. * Kept intentionally narrow so the proxy layer does not depend on every * field of the full type. */ export type InternalResult = { content: string; model?: string; finishReason?: string; /** Thinking/reasoning text from provider (Anthropic thinking blocks, Gemini thought parts) */ reasoning?: string; usage?: { input: number; output: number; total: number; cacheCreationTokens?: number; cacheReadTokens?: number; }; toolCalls?: Array<{ toolCallId: string; toolName: string; args: Record<string, unknown>; }>; }; /** * Parsed representation of a Claude request, ready for NeuroLink's * generate() / stream() pipeline. */ export type ParsedClaudeRequest = { model: string; maxTokens: number; temperature?: number; topP?: number; topK?: number; systemPrompt?: string | Array<{ type: string; text: string; }>; stream: boolean; /** Flat prompt string derived from the last user message. */ prompt: string; /** Images extracted from content blocks (base64 data URIs or URLs). */ images: string[]; /** * Full conversation history converted to NeuroLink's ChatMessage shape. * Includes all messages, not just the last one. */ conversationMessages: Array<{ role: string; content: string; }>; /** Tools translated to AI SDK-compatible shape for provider fallback. */ tools: Record<string, { description?: string; inputSchema: unknown; execute?: (...args: unknown[]) => unknown; }>; /** * Tool choice mapping from Claude format. * - "auto" -> let the model decide * - "required" -> force tool use (any tool) * - "none" -> no tool use */ toolChoice?: "auto" | "required" | "none"; /** When toolChoice came from `{type: "tool", name: "..."}`, the tool name. */ toolChoiceName?: string; /** Thinking configuration parsed from the request. */ thinkingConfig?: { enabled: boolean; budgetTokens?: number; thinkingLevel?: "minimal" | "low" | "medium" | "high"; }; /** Original request metadata (if any). */ metadata?: ClaudeMetadata; /** Stop sequences from the original request. */ stopSequences?: string[]; }; /** Lifecycle state for the SSE serializer. */ export type StreamLifecycleState = "idle" | "streaming" | "done" | "error"; /** The type of content block currently being streamed. */ export type ContentBlockType = "text" | "thinking" | "tool_use" | null; /** Minimal account shape needed by the cloaking pipeline. */ export type CloakingAccount = { id: string; type: "api_key" | "oauth"; status: "healthy" | "quota_exceeded" | "error"; consecutiveFailures: number; requestCount: number; lastUsed: number; apiKey?: string; }; /** Request envelope for cloaking pipeline. */ export type CloakingRequest = { headers: Record<string, string | undefined>; body: { messages: Array<{ role: string; content: string | Array<Record<string, unknown>>; }>; system?: string | Array<{ type: string; text: string; }>; metadata?: Record<string, unknown>; [key: string]: unknown; }; url: string; }; /** Response envelope for cloaking pipeline. */ export type CloakingResponse = { headers: Record<string, string | undefined>; body: Record<string, unknown>; status: number; }; /** Cloaking mode configuration. */ export type CloakingMode = "auto" | "always" | "never"; /** Context passed through the cloaking pipeline. */ export type CloakingContext = { request: CloakingRequest; account: CloakingAccount; config: { mode: CloakingMode; plugins: Record<string, unknown>; }; response?: { headers: Record<string, string>; body: unknown; }; }; /** Plugin interface for cloaking pipeline. */ export type CloakingPlugin = { /** Human-readable name for logging / debugging. */ name: string; /** Execution order -- lower numbers run first in processRequest. */ order: number; /** Whether this plugin is active. Disabled plugins are skipped. */ enabled: boolean; /** * Transform the outgoing request before it reaches the upstream API. * Must return a (possibly mutated) context. */ transformRequest: (ctx: CloakingContext) => Promise<CloakingContext>; /** * Transform the incoming response before it reaches the client. * Optional -- plugins that only touch requests can skip this. */ transformResponse?: (ctx: CloakingContext) => Promise<CloakingContext>; }; /** Options for the HeaderScrubber cloaking plugin. */ export type HeaderScrubberOptions = { /** Additional header names (lower-cased) to strip. */ extraHeaders?: string[]; }; /** Options for the SystemPromptInjector cloaking plugin. */ export type SystemPromptInjectorOptions = { /** IDE name to inject (default: "vscode"). */ ide?: string; /** IDE version (default: "1.96.2"). */ ideVersion?: string; /** Platform string (default: "darwin"). */ platform?: string; /** Working directory to inject (default: "/home/user/project"). */ cwd?: string; /** Extra preamble to prepend. */ preamble?: string; }; /** Options for the TlsFingerprint cloaking plugin. */ export type TlsFingerprintOptions = { /** Target fingerprint profile (e.g. "chrome-131", "node-22", "claude-code"). */ profile?: string; /** Whether the stub should log a warning that it is a no-op. */ warnOnUse?: boolean; }; /** * Proxy operating mode: * - "full" — managed accounts, retry, rotation, polyfill (default) * - "passthrough" — no polyfill/retry/rotation, but body is still parsed and re-serialized * - "transparent" — zero-mutation byte relay: raw body forwarded as-is, minimal header filtering, * SSE interceptor for cache metrics only (bytes pass through unmodified) */ export type ProxyMode = "full" | "passthrough" | "transparent"; export type RouteResult = { provider: string | null; model: string; }; /** Individual account configuration within a proxy config file. */ export type ProxyAccountConfig = { /** Human-readable name for the account */ name: string; /** API key or token (may contain env var references) */ apiKey: string; /** Base URL override for the provider endpoint */ baseUrl?: string; /** Organization ID (e.g., OpenAI orgs) */ orgId?: string; /** Weight for weighted round-robin selection (default: 1) */ weight?: number; /** Whether this account is currently enabled (default: true) */ enabled?: boolean; /** Maximum requests per minute for this account */ rateLimit?: number; /** Arbitrary metadata attached to the account */ metadata?: Record<string, unknown>; }; /** Top-level proxy configuration structure. */ export type ProxyConfigFile = { /** Configuration schema version */ version?: number; /** Default provider name to apply when not specified per-account */ defaultProvider?: string; /** Default base URL applied to accounts that omit baseUrl */ defaultBaseUrl?: string; /** Map of provider names to their account lists */ accounts: Record<string, ProxyAccountConfig[]>; /** Routing configuration (strategy, model mappings, fallback chain) */ routing?: Partial<ProxyRoutingConfig>; /** Cloaking plugin configuration */ cloaking?: CloakingConfig; }; /** Options for loadProxyConfig. */ export type LoadProxyConfigOptions = { /** Resolve environment variables in string values (default: true) */ resolveEnv?: boolean; /** Custom environment object (defaults to process.env) */ env?: Record<string, string | undefined>; }; export type RequestLogEntry = { timestamp: string; requestId: string; method: string; path: string; model: string; stream: boolean; toolCount: number; account: string; accountType: string; responseStatus: number; responseTimeMs: number; errorType?: string; errorMessage?: string; inputTokens?: number; outputTokens?: number; cacheCreationTokens?: number; cacheReadTokens?: number; /** OTel trace ID for correlation with distributed traces */ traceId?: string; /** OTel span ID for correlation with distributed traces */ spanId?: string; }; export type RequestAttemptLogEntry = { timestamp: string; requestId: string; attempt: number; method: string; path: string; model: string; stream: boolean; toolCount: number; account: string; accountType: string; responseStatus: number; responseTimeMs: number; errorType?: string; errorMessage?: string; inputTokens?: number; outputTokens?: number; cacheCreationTokens?: number; cacheReadTokens?: number; /** OTel trace ID for correlation with distributed traces */ traceId?: string; /** OTel span ID for correlation with distributed traces */ spanId?: string; }; export type ProxyBodyCaptureInput = { phase: string; headers?: Record<string, string>; body?: unknown; bodySize?: number; contentType?: string; responseStatus?: number; durationMs?: number; account?: string; accountType?: string; attempt?: number; metadata?: Record<string, unknown>; }; export type ProxyBodyCaptureLogger = (capture: ProxyBodyCaptureInput) => void; export type ClaudeFinalRequestLogger = (status: number, accountLabel: string, accountType: string, errorType?: string, errorMessage?: string, extra?: { inputTokens?: number; outputTokens?: number; cacheCreationTokens?: number; cacheReadTokens?: number; }) => void; export type ClaudeLoggedErrorBuilder = (status: number, message: string, errorType?: string, extra?: { account?: string; accountType?: string; attempt?: number; }) => ClaudeErrorResponse; export type ClaudeRequestRuntimeContext = { tracer?: ProxyTracer; requestStartTime: number; logProxyBody: ProxyBodyCaptureLogger; logFinalRequest: ClaudeFinalRequestLogger; buildLoggedClaudeError: ClaudeLoggedErrorBuilder; }; export type AnthropicAttemptLogger = (status: number, errorType?: string, errorMessage?: string, extra?: { inputTokens?: number; outputTokens?: number; cacheCreationTokens?: number; cacheReadTokens?: number; }) => void; export type AnthropicLoopState = { lastError: unknown; sawRateLimit: boolean; sawNetworkError: boolean; sawTransientFailure: boolean; invalidRequestFailure: { status: number; body: string; contentType?: string; } | null; authFailureMessage: string | null; attemptNumber: number; }; export type AnthropicUpstreamBody = { bodyStr: string; sessionId?: string; }; export type AnthropicUpstreamBodyBuilder = (token: string) => AnthropicUpstreamBody; export type LoadedClaudeAccountContext = { accounts: ProxyPassthroughAccount[]; enabledAccounts: ProxyPassthroughAccount[]; orderedAccounts: ProxyPassthroughAccount[]; bodyStr: string; requestStart: number; toolCount: number; url: string; clientHeaders: Record<string, string | undefined>; isClaudeClientRequest: boolean; }; export type AnthropicSuccessResult = { retryNextAccount: true; } | { response: Response | unknown; }; export type AnthropicAuthRetryResult = { response?: Response | unknown; continueLoop: boolean; lastError: unknown; authFailureMessage: string | null; sawRateLimit: boolean; sawTransientFailure: boolean; sawNetworkError: boolean; upstreamSpan?: Span; }; export type AnthropicNonOkResult = { response?: Response | unknown; continueLoop: boolean; retrySameAccount?: boolean; lastError: unknown; authFailureMessage: string | null; sawTransientFailure: boolean; invalidRequestFailure: { status: number; body: string; contentType?: string; } | null; upstreamSpan?: Span; }; export type PreparedAnthropicAccountAttempt = { continueLoop: boolean; lastError: unknown; authFailureMessage: string | null; headers?: Record<string, string>; buildUpstreamBody?: AnthropicUpstreamBodyBuilder; finalBodyStr?: string; fetchStartMs?: number; upstreamSpan?: Span; }; export type AnthropicUpstreamFetchResult = { continueLoop: boolean; retrySameAccount?: boolean; /** When set, the caller should wait this many ms before retrying (from upstream retry-after). */ retryAfterMs?: number; response?: Response; lastError: unknown; sawRateLimit: boolean; sawNetworkError: boolean; upstreamSpan?: Span; }; export type AccountStats = { label: string; type: string; attemptCount: number; successCount: number; errorCount: number; rateLimitCount: number; lastAttemptAt: number; lastErrorAt?: number; }; export type ProxyStats = { startedAt: number; totalAttempts: number; totalRequests: number; totalSuccess: number; totalErrors: number; totalRateLimits: number; accounts: Record<string, AccountStats>; }; export type RefreshableAccount = { token: string; refreshToken?: string; expiresAt?: number; label: string; }; export type RefreshResult = { success: boolean; error?: string; status?: number; }; export type TokenPersistTarget = string | { credPath: string; } | { providerKey: string; }; export type AccountQuota = { /** 0.0-1.0 (from unified-5h-utilization) */ sessionUsed: number; /** "allowed" | "throttled" | "rejected" */ sessionStatus: string; /** Unix timestamp (seconds) when the 5h window resets */ sessionResetAt: number; /** 0.0-1.0 (from unified-7d-utilization) */ weeklyUsed: number; /** "allowed" | "throttled" | "rejected" */ weeklyStatus: string; /** Unix timestamp (seconds) when the 7d window resets */ weeklyResetAt: number; /** 0.0-1.0 (from fallback-percentage) */ fallbackPercentage: number; /** "allowed" | "rejected" */ overageStatus: string; /** Epoch ms when we last captured this data */ lastUpdated: number; }; /** Runtime state for a proxy account. */ export type RuntimeAccountState = { consecutiveRefreshFailures: number; permanentlyDisabled: boolean; lastToken?: string; lastRefreshToken?: string; /** Epoch-ms timestamp until which the account should not be used for new * requests (set after 429 retries are exhausted). Other requests arriving * during this window will skip the account rather than hammering it again. */ coolingUntil?: number; }; /** A passthrough account used in the proxy route handler. */ export type ProxyPassthroughAccount = { key: string; label: string; token: string; refreshToken?: string; expiresAt?: number; type: "oauth" | "api_key"; persistTarget?: TokenPersistTarget; }; /** Dependencies for creating Claude proxy routes. */ export type ClaudeProxyDeps = { modelRouter?: ModelRouterInterface; }; /** Rate limit store entry (Koa adapter). */ export type KoaRateLimitEntry = { count: number; resetAt: number; }; /** Rate limit context (Fastify adapter). */ export type FastifyRateLimitContext = { ttl: number; ban?: boolean; }; /** Rate limit store entry (Hono adapter). */ export type HonoRateLimitEntry = { count: number; resetAt: number; }; /** Information about a deprecated route. */ export type DeprecatedRouteInfo = { method: string; path: string; deprecation: RouteDeprecation; }; /** Cache entry for response caching middleware. */ export type ResponseCacheEntry<T = unknown> = { value: T; expiresAt: number; }; /** Close handler for data stream writers. */ export type CloseHandler = () => void; /** Cached session entry with TTL for the SessionIdentity cloaking plugin. */ export type CachedSession = { userId: string; expiresAt: number; }; /** Model tier classification for proxy routing decisions. */ export type ClaudeProxyModelTier = "opus" | "sonnet" | "haiku" | "other"; /** A single provider attempt in the proxy translation plan. */ export type ProxyTranslationAttempt = { provider?: string; model?: string; label: string; }; /** Ordered plan of provider attempts for a proxy request. */ export type ProxyTranslationPlan = { requestedModel: string; modelTier: ClaudeProxyModelTier; attempts: ProxyTranslationAttempt[]; skipped: never[]; }; /** Mutable readiness state tracked by the proxy process. */ export type ProxyReadinessState = { startTimeMs: number; acceptingConnections: boolean; ready: boolean; readyAtMs?: number; }; /** Structured response returned by the proxy /health endpoint. */ export type ProxyHealthResponse = { status: "ok" | "starting"; ready: boolean; acceptingConnections: boolean; strategy: string; passthrough: boolean; version: string; startedAt: string; readyAt: string | null; uptime: number; healthPath: "/health"; statusPath: "/status"; }; export type ProxyPaths = { /** Base directory for proxy state files */ stateDir: string; /** logs/ — request/response logs */ logsDir: string; /** account-quotas.json — per-account rate limit state */ quotaFile: string; /** Whether this is a dev-mode isolated instance */ isDev: boolean; }; /** OTel metric instruments used by the proxy tracer. */ export type ProxyMetrics = { requestsTotal: Counter; requestDuration: Histogram; tokensInput: Counter; tokensOutput: Counter; tokensCacheRead: Counter; tokensCacheCreation: Counter; tokensReasoning: Counter; costTotal: Counter; errorsTotal: Counter; retriesTotal: Counter; modelSubstitutionTotal: Counter; requestBodySize: Histogram; responseBodySize: Histogram; fallbackAttemptsTotal: Counter; fallbackSuccessTotal: Counter; fallbackFailureTotal: Counter; }; /** Context for a proxy request at the root span level. */ export type ProxyRequestContext = { requestId: string; method: string; path: string; model: string; stream: boolean; toolCount: number; sessionId?: string; userAgent?: string; clientApp?: string; }; /** Context recorded when an account is selected for a proxy request. */ export type AccountSelectionContext = { strategy: string; accountsTotal: number; accountsHealthy: number; selectedAccount: string; accountType: string; rateLimitBefore5h?: number; rateLimitBefore7d?: number; }; /** Context for a single upstream attempt (one per retry). */ export type UpstreamAttemptContext = { attempt: number; account: string; polyfillHeaders: boolean; polyfillBody: boolean; upstreamUrl: string; }; /** Token usage and rate-limit utilisation recorded at end of request. */ export type UsageContext = { inputTokens: number; outputTokens: number; cacheCreationTokens: number; cacheReadTokens: number; reasoningTokens?: number; rateLimitAfter5h?: number; rateLimitAfter7d?: number; }; /** Where a proxy env file path was sourced from. */ export type ProxyEnvSource = "cli" | "environment" | "default" | "none"; /** Result of resolving which proxy env file to load. */ export type ProxyEnvResolution = { path?: string; source: ProxyEnvSource; required: boolean; }; /** Result of loading the proxy env file. */ export type ProxyEnvLoadResult = { loaded: boolean; path?: string; source: ProxyEnvSource; }; /** Options controlling proxy env file resolution. */ export type ProxyEnvOptions = { explicitEnvFile?: string; env?: NodeJS.ProcessEnv; homeDir?: string; }; /** Snapshot of proxy-related environment variables captured at startup. */ export type ProxyEnvironmentSnapshot = { httpsProxy?: string; httpProxy?: string; allProxy?: string; socksProxy?: string; noProxy?: string; }; /** Result of a traffic-quiet check. */ export type QuietStatus = { isQuiet: boolean; lastActivityAt: Date | null; silenceDurationMs: number; }; /** Accumulated upstream body capture from a raw stream. */ export type RawStreamCapture = { totalBytes: number; text: string; truncated: boolean; }; /** Transformed stream pair used to capture upstream bodies without buffering. */ export type RawStreamCaptureResult = { stream: TransformStream<Uint8Array, Uint8Array>; capture: Promise<RawStreamCapture>; }; /** Single captured body/headers entry written to disk by the proxy logger. */ export type ProxyBodyCaptureEntry = { timestamp: string; requestId: string; phase: string; model: string; stream: boolean; headers?: Record<string, string>; body?: unknown; bodySize?: number; contentType?: string; responseStatus?: number; durationMs?: number; account?: string; accountType?: string; attempt?: number; traceId?: string; spanId?: string; metadata?: Record<string, unknown>; }; /** Persisted artifact produced when a body is stored to disk. */ export type StoredBodyArtifact = { bodyPath?: string; bodySha256?: string; redactedBodyBytes?: number; storedFileBytes?: number; redactedBody?: string; bodyTruncated?: boolean; }; /** File the proxy logger tracks for rotation and cleanup. */ export type ManagedLogFile = { path: string; mtime: number; size: number; }; /** Individual content block observed during an SSE stream. */ export type SSEContentBlock = { index: number; type: "text" | "thinking" | "tool_use" | "tool_result"; /** Accumulated text for text blocks. Capped at MAX_BLOCK_CONTENT_BYTES. */ text?: string; /** Accumulated thinking content. Capped at MAX_BLOCK_CONTENT_BYTES. */ thinking?: string; /** Tool name for tool_use blocks. */ toolName?: string; /** Tool call id for tool_use blocks. */ toolId?: string; /** Accumulated partial JSON input for tool_use blocks. Capped at MAX_BLOCK_CONTENT_BYTES. */ toolInput?: string; }; /** Aggregated telemetry resolved when an SSE stream completes. */ export type SSETelemetry = { messageId: string; model: string; usage: { inputTokens: number; outputTokens: number; cacheCreationInputTokens: number; cacheReadInputTokens: number; totalTokens: number; }; contentBlocks: SSEContentBlock[]; stopReason: string | null; stopSequence: string | null; eventCount: number; streamDurationMs: number; totalBytesReceived: number; events: Array<{ type: string; timestamp: number; data: string; }>; rawText?: string; }; /** Mutable accumulator the SSE interceptor uses internally. */ export type TelemetryAccumulator = { messageId: string; model: string; inputTokens: number; outputTokens: number; cacheCreationInputTokens: number; cacheReadInputTokens: number; contentBlocks: SSEContentBlock[]; blockByteCounts: Map<number, number>; stopReason: string | null; stopSequence: string | null; eventCount: number; startTime: number; totalBytesReceived: number; events: Array<{ type: string; timestamp: number; data: string; }>; rawTextChunks?: string[]; rawTextBytes: number; rawTextTruncated: boolean; eventLogTruncated: boolean; }; /** Result of createSSEInterceptor: the pass-through stream and a telemetry promise. */ export type SSEInterceptorResult = { stream: TransformStream<Uint8Array, Uint8Array>; telemetry: Promise<SSETelemetry>; }; /** Options for createSSEInterceptor. */ export type SSEInterceptorOptions = { captureRawText?: boolean; }; /** Outcome of a proxy auto-update version check against npm. */ export type UpdateCheckResult = { currentVersion: string; latestVersion: string; updateAvailable: boolean; }; /** Parsed major.minor.patch components of a semver string. */ export type SemVer = { major: number; minor: number; patch: number; }; /** Entry describing a version suppressed from auto-update. */ export type SuppressedVersion = { suppressedAt: string; reason: string; }; /** Persisted state for the proxy auto-update feature. */ export type UpdateState = { lastCheckAt: string; lastCheckVersion: string; suppressedVersions: Record<string, SuppressedVersion>; lastUpdateAt: string | null; lastUpdateVersion: string | null; }; /** Shape of the dynamically-imported js-yaml module. `dump` is optional — * read-only consumers (proxy config loader) only need `load`; writers * (CLI primary-account commands) check `dump` before calling. */ export type YamlModule = { load(content: string): unknown; dump?: (obj: unknown, opts?: Record<string, unknown>) => string; default?: { load(content: string): unknown; dump?: (obj: unknown, opts?: Record<string, unknown>) => string; }; }; /** Snapshot of a parsed proxy config file used by CLI primary-account * read/edit/write helpers. Tracks the original format and whether comments * were present (so the CLI can warn that comments will not round-trip). */ export type CliProxyConfigDoc = { data: Record<string, unknown>; format: "yaml" | "json"; hadComments: boolean; }; /** Primary-account info exposed by the proxy `/status` endpoint. * `source` is "configured" when the operator's `routing.primaryAccount` is * authenticated and enabled, otherwise "fallback" — either no primary set * or the configured one is missing/disabled. */ export type ProxyStatusPrimaryAccount = { configured: string | null; key: string | null; label: string | null; source: "configured" | "fallback"; }; /** Parsed fields captured from a Claude Code client request body. */ export type ClaudeSnapshotBody = { metadataUserId?: string; billingHeader?: string; agentBlock?: string; sessionId?: string; }; /** Snapshot of headers and body from a Claude Code request, used for polyfill. */ export type ClaudeSnapshot = { accountKey: string; capturedAt: string; source: "claude-code"; headers: Record<string, string>; body?: ClaudeSnapshotBody; }; /** Parsed shape of a Claude API error body. */ export type ParsedClaudeError = { errorType?: string; message?: string; }; /** ora spinner instance held by proxy CLI commands, nullable when --quiet. */ export type ProxySpinner = Ora | null; /** Load-balancing strategy used by the proxy across accounts. */ export type ProxyStartStrategy = "round-robin" | "fill-first"; /** Alias for the model router's constructor configuration. */ export type ProxyModelRouterConfig = ProxyRoutingConfig; /** Partial proxy config consumed by the start command. */ export type LoadedProxyConfig = { routing?: Partial<ProxyModelRouterConfig> & { strategy?: ProxyStartStrategy; }; }; /** * Handle for a NeuroLink runtime created by the proxy start command. * The `neurolink` field is typed structurally (only the method used by the * proxy layer is exposed) so types/proxy.ts does not depend on the full * NeuroLink class. */ export type ProxyNeurolinkRuntime = { neurolink: { getToolRegistry(): MCPToolRegistry; }; cleanupLogs: (daysToKeep?: number, maxFiles?: number) => void; }; /** Hono app + readiness state created by the proxy start command. */ export type ProxyStartApp = { app: Hono; readiness: ProxyReadinessState; }; /** Stats shape consumed by the proxy status printer. */ export type StatusStats = { totalAttempts?: number; totalRequests: number; totalSuccess: number; totalErrors: number; totalRateLimits: number; accounts?: { label: string; type: string; attempts?: number; requests?: number; success?: number; errors?: number; rateLimits?: number; cooling: boolean; }[]; }; /** Sub-action of the `proxy telemetry` CLI command. */ export type ProxyTelemetryAction = "setup" | "start" | "stop" | "status" | "logs" | "import-dashboard";