skalpel 2.0.12 → 2.0.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/metadata.ts","../src/errors.ts","../src/fallback.ts","../src/version.ts","../src/client.ts","../src/url-swap.ts","../src/proxy/server.ts","../src/proxy/streaming.ts","../src/proxy/handler.ts","../src/proxy/health.ts","../src/proxy/pid.ts","../src/proxy/logger.ts","../src/proxy/config.ts"],"sourcesContent":["import type { SkalpelMetadata } from './types.js';\n\nexport function extractMetadata(\n headers: Headers | Record<string, string>,\n): SkalpelMetadata | null {\n const get = (name: string): string | null => {\n if (headers instanceof Headers) {\n return headers.get(name);\n }\n return headers[name] ?? null;\n };\n\n const requestId = get('x-skalpel-request-id');\n if (!requestId) return null;\n\n return {\n requestId,\n optimization: (get('x-skalpel-optimization') as SkalpelMetadata['optimization']) ?? 'none',\n originalModel: get('x-skalpel-original-model') ?? '',\n actualModel: get('x-skalpel-actual-model') ?? '',\n savingsUsd: parseFloat(get('x-skalpel-savings-usd') ?? '0'),\n cacheHit: get('x-skalpel-cache-hit') === 'true',\n latencyMs: parseInt(get('x-skalpel-latency-ms') ?? '0', 10),\n };\n}\n\nexport function parseSkalpelResponseBody(\n body: Record<string, unknown>,\n): SkalpelMetadata | null {\n const skalpel = body?.x_skalpel as Record<string, unknown> | undefined;\n if (!skalpel || typeof skalpel !== 'object') return null;\n\n const requestId = skalpel.request_id as string | undefined;\n if (!requestId) return null;\n\n return {\n requestId,\n optimization: (skalpel.optimization as SkalpelMetadata['optimization']) ?? 'none',\n originalModel: (skalpel.original_model as string) ?? '',\n actualModel: (skalpel.actual_model as string) ?? '',\n savingsUsd: Number(skalpel.savings_usd ?? 0),\n cacheHit: Boolean(skalpel.cache_hit),\n latencyMs: Number(skalpel.latency_ms ?? 0),\n };\n}\n","export class SkalpelError extends Error {\n code: string;\n statusCode?: number;\n retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n retryAfter?: number,\n ) {\n super(message);\n this.name = 'SkalpelError';\n this.code = code;\n this.statusCode = statusCode;\n this.retryAfter = retryAfter;\n }\n}\n\nexport class SkalpelAuthError extends SkalpelError {\n constructor(message = 'Skalpel authentication failed') {\n super(message, 'SKALPEL_AUTH_FAILED', 401);\n this.name = 'SkalpelAuthError';\n }\n}\n\nexport class SkalpelTimeoutError extends SkalpelError {\n constructor(message = 'Skalpel request timed out') {\n super(message, 'SKALPEL_TIMEOUT');\n this.name = 'SkalpelTimeoutError';\n }\n}\n\nexport class SkalpelRateLimitError extends SkalpelError {\n constructor(message = 'Skalpel rate limit exceeded', retryAfter?: number) {\n super(message, 'SKALPEL_RATE_LIMITED', 429, retryAfter);\n this.name = 'SkalpelRateLimitError';\n }\n}\n\nexport class SkalpelUnavailableError extends SkalpelError {\n constructor(\n message = 'Skalpel service unavailable',\n statusCode?: number,\n ) {\n super(message, 'SKALPEL_UNAVAILABLE', statusCode);\n this.name = 'SkalpelUnavailableError';\n }\n}\n","import {\n SkalpelError,\n SkalpelAuthError,\n SkalpelTimeoutError,\n SkalpelRateLimitError,\n SkalpelUnavailableError,\n} from './errors.js';\n\nexport interface FallbackOptions {\n retries?: number;\n verbose?: boolean;\n onFallback?: (error: SkalpelError, provider: string) => void;\n provider?: string;\n fallbackOnError?: boolean;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function classifyError(err: unknown): SkalpelError {\n if (err instanceof SkalpelError) return err;\n\n const error = err as { status?: number; statusCode?: number; code?: string; message?: string; headers?: Record<string, string> };\n const status = error.status ?? error.statusCode;\n const message = error.message ?? 'Unknown error';\n\n if (status === 401) {\n return new SkalpelAuthError(message);\n }\n if (status === 429) {\n const retryAfter = error.headers?.['retry-after']\n ? parseInt(error.headers['retry-after'], 10)\n : undefined;\n return new SkalpelRateLimitError(message, retryAfter);\n }\n if (error.code === 'ETIMEDOUT' || error.code === 'TIMEOUT' || error.code === 'UND_ERR_HEADERS_TIMEOUT') {\n return new SkalpelTimeoutError(message);\n }\n if (status && status >= 500) {\n return new SkalpelUnavailableError(message, status);\n }\n\n return new SkalpelUnavailableError(message, status);\n}\n\nexport async function withFallback<T>(\n primaryFn: () => Promise<T>,\n fallbackFn: () => Promise<T>,\n options: FallbackOptions = {},\n): Promise<T> {\n const { retries = 2, verbose = false, onFallback, provider = 'unknown', fallbackOnError = true } = options;\n\n let lastError: SkalpelError | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await primaryFn();\n } catch (err) {\n lastError = classifyError(err);\n\n // Auth errors never fall back or retry\n if (lastError instanceof SkalpelAuthError) {\n throw lastError;\n }\n\n // Rate limit: wait retry-after then retry\n if (lastError instanceof SkalpelRateLimitError && lastError.retryAfter && attempt < retries) {\n await sleep(lastError.retryAfter * 1000);\n continue;\n }\n\n // Timeout / 5xx: exponential backoff\n if (attempt < retries) {\n await sleep(Math.pow(2, attempt) * 1000);\n continue;\n }\n }\n }\n\n // All retries exhausted — fallback\n if (fallbackOnError) {\n if (verbose && lastError) {\n console.warn(`[skalpel] Falling back to direct ${provider} call: ${lastError.message}`);\n }\n if (onFallback && lastError) {\n onFallback(lastError, provider);\n }\n return fallbackFn();\n }\n\n throw lastError!;\n}\n","export const VERSION = '1.0.5';\n","import type { SkalpelClientOptions, SkalpelMetadata } from './types.js';\nimport { extractMetadata } from './metadata.js';\nimport { withFallback } from './fallback.js';\nimport { VERSION } from './version.js';\n\nfunction resolveConfig(options: SkalpelClientOptions) {\n return {\n apiKey: options.apiKey,\n baseURL: options.baseURL ?? 'https://api.skalpel.ai',\n workspace: options.workspace,\n fallbackOnError: options.fallbackOnError ?? true,\n timeout: options.timeout ?? 30000,\n retries: options.retries ?? 2,\n verbose: options.verbose ?? false,\n headers: options.headers ?? {},\n onFallback: options.onFallback,\n onMetadata: options.onMetadata,\n };\n}\n\nfunction buildSkalpelHeaders(config: ReturnType<typeof resolveConfig>): Record<string, string> {\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${config.apiKey}`,\n 'X-Skalpel-SDK-Version': VERSION,\n ...config.headers,\n };\n if (config.workspace) {\n headers['X-Skalpel-Workspace'] = config.workspace;\n }\n return headers;\n}\n\nfunction extractMetadataFromResponse(response: unknown, config: ReturnType<typeof resolveConfig>): void {\n if (!response || typeof response !== 'object') return;\n const resp = response as Record<string, unknown>;\n\n // Try response headers if available (e.g. raw response)\n if (resp._response && typeof resp._response === 'object') {\n const raw = resp._response as { headers?: Headers };\n if (raw.headers) {\n const metadata = extractMetadata(raw.headers);\n if (metadata) {\n config.onMetadata?.(metadata);\n return;\n }\n }\n }\n\n // Try x_skalpel field in body\n if (resp.x_skalpel && typeof resp.x_skalpel === 'object') {\n const sk = resp.x_skalpel as Record<string, unknown>;\n const metadata: SkalpelMetadata = {\n requestId: (sk.request_id as string) ?? '',\n optimization: (sk.optimization as SkalpelMetadata['optimization']) ?? 'none',\n originalModel: (sk.original_model as string) ?? '',\n actualModel: (sk.actual_model as string) ?? '',\n savingsUsd: Number(sk.savings_usd ?? 0),\n cacheHit: Boolean(sk.cache_hit),\n latencyMs: Number(sk.latency_ms ?? 0),\n };\n config.onMetadata?.(metadata);\n }\n}\n\nfunction isOpenAIClient(client: unknown): boolean {\n if (!client || typeof client !== 'object') return false;\n const c = client as Record<string, unknown>;\n return (\n c.chat !== undefined &&\n typeof c.chat === 'object' &&\n c.chat !== null &&\n 'completions' in (c.chat as Record<string, unknown>)\n );\n}\n\nfunction isAnthropicClient(client: unknown): boolean {\n if (!client || typeof client !== 'object') return false;\n const c = client as Record<string, unknown>;\n return (\n c.messages !== undefined &&\n typeof c.messages === 'object' &&\n c.messages !== null &&\n typeof (c.messages as Record<string, unknown>).create === 'function'\n );\n}\n\nfunction wrapOpenAI<T>(client: T, config: ReturnType<typeof resolveConfig>): T {\n const c = client as Record<string, unknown> & { baseURL: string };\n const skalpelHeaders = buildSkalpelHeaders(config);\n const originalBaseURL = c.baseURL;\n\n function createMethodProxy(\n target: Record<string, unknown>,\n methodName: string,\n ): (...args: unknown[]) => Promise<unknown> {\n const originalMethod = target[methodName] as (...args: unknown[]) => Promise<unknown>;\n\n return async function (...args: unknown[]) {\n const primaryFn = async () => {\n c.baseURL = `${config.baseURL}/v1`;\n\n // Inject headers via the options argument\n const requestArgs = args[0] as Record<string, unknown> | undefined;\n const extraHeaders = skalpelHeaders;\n\n let callArgs: unknown[];\n if (args.length >= 2 && typeof args[1] === 'object' && args[1] !== null) {\n const opts = args[1] as Record<string, unknown>;\n opts.headers = { ...extraHeaders, ...(opts.headers as Record<string, string> | undefined) };\n callArgs = [requestArgs, opts, ...args.slice(2)];\n } else {\n callArgs = [requestArgs, { headers: extraHeaders }, ...args.slice(2)];\n }\n\n try {\n const result = await originalMethod.apply(target, callArgs);\n extractMetadataFromResponse(result, config);\n c.baseURL = originalBaseURL;\n return result;\n } catch (err) {\n c.baseURL = originalBaseURL;\n throw err;\n }\n };\n\n const fallbackFn = async () => {\n c.baseURL = originalBaseURL;\n return originalMethod.apply(target, args);\n };\n\n return withFallback(primaryFn, fallbackFn, {\n retries: config.retries,\n verbose: config.verbose,\n onFallback: config.onFallback,\n provider: 'openai',\n fallbackOnError: config.fallbackOnError,\n });\n };\n }\n\n function createNamespaceProxy(namespace: Record<string, unknown>): Record<string, unknown> {\n return new Proxy(namespace, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === 'function' && (prop === 'create' || prop === 'stream')) {\n return createMethodProxy(target, prop as string);\n }\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return createNamespaceProxy(value as Record<string, unknown>);\n }\n return value;\n },\n });\n }\n\n return new Proxy(client as object, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (\n typeof value === 'object' &&\n value !== null &&\n (prop === 'chat' || prop === 'completions' || prop === 'embeddings')\n ) {\n return createNamespaceProxy(value as Record<string, unknown>);\n }\n return value;\n },\n }) as T;\n}\n\nfunction wrapAnthropic<T>(client: T, config: ReturnType<typeof resolveConfig>): T {\n const c = client as Record<string, unknown> & { baseURL: string; _client?: { baseURL: string } };\n const skalpelHeaders = buildSkalpelHeaders(config);\n const originalBaseURL = c.baseURL ?? (c._client as Record<string, unknown>)?.baseURL;\n\n function createMethodProxy(\n target: Record<string, unknown>,\n methodName: string,\n ): (...args: unknown[]) => Promise<unknown> {\n const originalMethod = target[methodName] as (...args: unknown[]) => Promise<unknown>;\n\n return async function (...args: unknown[]) {\n\n const primaryFn = async () => {\n // Anthropic SDK already appends /v1/messages to baseURL, so do NOT add /v1 here\n // (unlike OpenAI SDK where baseURL includes /v1).\n const proxyURL = config.baseURL;\n if ('baseURL' in c) c.baseURL = proxyURL;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = proxyURL;\n\n const requestArgs = args[0] as Record<string, unknown> | undefined;\n const extraHeaders = skalpelHeaders;\n\n let callArgs: unknown[];\n if (args.length >= 2 && typeof args[1] === 'object' && args[1] !== null) {\n const opts = args[1] as Record<string, unknown>;\n opts.headers = { ...extraHeaders, ...(opts.headers as Record<string, string> | undefined) };\n callArgs = [requestArgs, opts, ...args.slice(2)];\n } else {\n callArgs = [requestArgs, { headers: extraHeaders }, ...args.slice(2)];\n }\n\n try {\n const result = await originalMethod.apply(target, callArgs);\n extractMetadataFromResponse(result, config);\n if ('baseURL' in c) c.baseURL = originalBaseURL as string;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = originalBaseURL as string;\n return result;\n } catch (err) {\n if ('baseURL' in c) c.baseURL = originalBaseURL as string;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = originalBaseURL as string;\n throw err;\n }\n };\n\n const fallbackFn = async () => {\n if ('baseURL' in c) c.baseURL = originalBaseURL as string;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = originalBaseURL as string;\n return originalMethod.apply(target, args);\n };\n\n return withFallback(primaryFn, fallbackFn, {\n retries: config.retries,\n verbose: config.verbose,\n onFallback: config.onFallback,\n provider: 'anthropic',\n fallbackOnError: config.fallbackOnError,\n });\n };\n }\n\n return new Proxy(client as object, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (prop === 'messages' && typeof value === 'object' && value !== null) {\n return new Proxy(value as object, {\n get(msgTarget, msgProp, msgReceiver) {\n const msgValue = Reflect.get(msgTarget, msgProp, msgReceiver);\n if (typeof msgValue === 'function' && (msgProp === 'create' || msgProp === 'stream')) {\n return createMethodProxy(msgTarget as Record<string, unknown>, msgProp as string);\n }\n return msgValue;\n },\n });\n }\n return value;\n },\n }) as T;\n}\n\nexport function createSkalpelClient<T>(client: T, options: SkalpelClientOptions): T {\n const config = resolveConfig(options);\n\n if (isOpenAIClient(client)) {\n return wrapOpenAI(client, config);\n }\n\n if (isAnthropicClient(client)) {\n return wrapAnthropic(client, config);\n }\n\n throw new Error(\n 'Unsupported client. createSkalpelClient supports OpenAI and Anthropic SDK clients.',\n );\n}\n\n\n// ── Workspace Context Engine ────────────────────────────────────────\n\nexport interface CreateSnapshotParams {\n workspaceId: string;\n snapshotHash: string;\n manifest?: Record<string, unknown>;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface CreateSnapshotResult {\n id: string;\n workspaceId: string;\n snapshotHash: string;\n manifest: Record<string, unknown>;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n}\n\nexport interface ChunkInput {\n path: string;\n chunkHash: string;\n chunkText: string;\n symbol?: string | null;\n language?: string | null;\n tokenCount?: number;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface UploadChunksParams {\n workspaceId: string;\n snapshotId: string;\n chunks: ChunkInput[];\n}\n\nexport interface ChunkResult {\n id: string;\n workspaceId: string;\n snapshotId: string;\n path: string;\n chunkHash: string;\n symbol: string | null;\n language: string | null;\n tokenCount: number;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n}\n\nexport interface ResolveContextParams {\n workspaceId: string;\n snapshotId?: string | null;\n query: string;\n changedPaths?: string[];\n limit?: number;\n}\n\nexport interface ResolvedChunk {\n path: string;\n symbol: string | null;\n language: string | null;\n tokenCount: number;\n score: number;\n reason: string;\n metadata: Record<string, unknown> | null;\n preview: string;\n}\n\nexport interface ResolveContextResult {\n workspaceId: string;\n snapshotId: string | null;\n items: ResolvedChunk[];\n}\n\nasync function contextRequest<T>(\n config: ReturnType<typeof resolveConfig>,\n path: string,\n body: Record<string, unknown>,\n): Promise<T> {\n const url = `${config.baseURL}/api/workspaces${path}`;\n const headers = buildSkalpelHeaders(config);\n headers['Content-Type'] = 'application/json';\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), config.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n throw new Error(`Skalpel context API error ${response.status}: ${text}`);\n }\n return (await response.json()) as T;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\nexport async function createSnapshot(\n options: SkalpelClientOptions,\n params: CreateSnapshotParams,\n): Promise<CreateSnapshotResult> {\n const config = resolveConfig(options);\n const raw = await contextRequest<Record<string, unknown>>(config, '/snapshots', {\n workspace_id: params.workspaceId,\n snapshot_hash: params.snapshotHash,\n manifest: params.manifest ?? {},\n metadata: params.metadata ?? null,\n });\n return {\n id: String(raw.id),\n workspaceId: String(raw.workspace_id),\n snapshotHash: String(raw.snapshot_hash),\n manifest: (raw.manifest as Record<string, unknown>) ?? {},\n metadata: (raw.metadata as Record<string, unknown>) ?? null,\n createdAt: String(raw.created_at),\n };\n}\n\nexport async function uploadChunks(\n options: SkalpelClientOptions,\n params: UploadChunksParams,\n): Promise<ChunkResult[]> {\n const config = resolveConfig(options);\n const raw = await contextRequest<{ items: Record<string, unknown>[] }>(config, '/chunks', {\n workspace_id: params.workspaceId,\n snapshot_id: params.snapshotId,\n chunks: params.chunks.map((c) => ({\n path: c.path,\n chunk_hash: c.chunkHash,\n chunk_text: c.chunkText,\n symbol: c.symbol ?? null,\n language: c.language ?? null,\n token_count: c.tokenCount ?? 0,\n metadata: c.metadata ?? null,\n })),\n });\n return (raw.items ?? []).map((item) => ({\n id: String(item.id),\n workspaceId: String(item.workspace_id),\n snapshotId: String(item.snapshot_id),\n path: String(item.path),\n chunkHash: String(item.chunk_hash),\n symbol: item.symbol != null ? String(item.symbol) : null,\n language: item.language != null ? String(item.language) : null,\n tokenCount: Number(item.token_count ?? 0),\n metadata: (item.metadata as Record<string, unknown>) ?? null,\n createdAt: String(item.created_at),\n }));\n}\n\nexport async function resolveContext(\n options: SkalpelClientOptions,\n params: ResolveContextParams,\n): Promise<ResolveContextResult> {\n const config = resolveConfig(options);\n const raw = await contextRequest<Record<string, unknown>>(config, '/context/resolve', {\n workspace_id: params.workspaceId,\n snapshot_id: params.snapshotId ?? null,\n query: params.query,\n changed_paths: params.changedPaths ?? [],\n limit: params.limit ?? 8,\n });\n const items = (raw.items as Record<string, unknown>[]) ?? [];\n return {\n workspaceId: String(raw.workspace_id),\n snapshotId: raw.snapshot_id != null ? String(raw.snapshot_id) : null,\n items: items.map((item) => ({\n path: String(item.path),\n symbol: item.symbol != null ? String(item.symbol) : null,\n language: item.language != null ? String(item.language) : null,\n tokenCount: Number(item.token_count ?? 0),\n score: Number(item.score ?? 0),\n reason: String(item.reason ?? 'semantic'),\n metadata: (item.metadata as Record<string, unknown>) ?? null,\n preview: String(item.preview ?? ''),\n })),\n };\n}\n","import type { SkalpelClientOptions } from './types.js';\nimport { VERSION } from './version.js';\n\nfunction buildHeaders(options: SkalpelClientOptions): Record<string, string> {\n const headers: Record<string, string> = {\n 'X-Skalpel-SDK-Version': VERSION,\n ...options.headers,\n };\n if (options.workspace) {\n headers['X-Skalpel-Workspace'] = options.workspace;\n }\n return headers;\n}\n\nexport async function createSkalpelOpenAI(\n options: SkalpelClientOptions,\n): Promise<import('openai').default> {\n const { default: OpenAI } = await import('openai');\n const baseURL = `${options.baseURL ?? 'https://api.skalpel.ai'}/v1`;\n return new OpenAI({\n baseURL,\n apiKey: options.apiKey,\n defaultHeaders: buildHeaders(options),\n timeout: options.timeout ?? 30000,\n maxRetries: options.retries ?? 2,\n });\n}\n\nexport async function createSkalpelAnthropic(\n options: SkalpelClientOptions & { providerApiKey?: string },\n): Promise<import('@anthropic-ai/sdk').default> {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n // Anthropic SDK already appends /v1/messages to baseURL, so do NOT add /v1.\n const baseURL = options.baseURL ?? 'https://api.skalpel.ai';\n return new Anthropic({\n baseURL,\n apiKey: options.providerApiKey ?? options.apiKey,\n defaultHeaders: {\n ...buildHeaders(options),\n 'Authorization': `Bearer ${options.apiKey}`,\n },\n timeout: options.timeout ?? 30000,\n maxRetries: options.retries ?? 2,\n });\n}\n","import http from 'node:http';\nimport type { ProxyConfig, ProxyStatus } from './types.js';\nimport { handleRequest } from './handler.js';\nimport { handleHealthRequest } from './health.js';\nimport { writePid, readPid, removePid } from './pid.js';\nimport { Logger } from './logger.js';\n\nlet proxyStartTime = 0;\nlet passthroughMode = false;\n\n/** Returns whether the proxy is currently in passthrough mode (skipping Skalpel optimization). */\nexport function isPassthroughMode(): boolean {\n return passthroughMode;\n}\n\nfunction collectAdminBody(req: http.IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString()));\n req.on('error', reject);\n });\n}\n\nfunction handleAdminMode(req: http.IncomingMessage, res: http.ServerResponse, logger: Logger): void {\n collectAdminBody(req).then((body) => {\n try {\n const { mode } = JSON.parse(body);\n passthroughMode = (mode === 'passthrough');\n logger.info(`Proxy mode changed to: ${passthroughMode ? 'passthrough' : 'normal'}`);\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ mode: passthroughMode ? 'passthrough' : 'normal' }));\n } catch {\n res.writeHead(400, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'invalid JSON body' }));\n }\n }).catch(() => {\n res.writeHead(500, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'failed to read body' }));\n });\n}\n\nexport function startProxy(config: ProxyConfig): { anthropicServer: http.Server } {\n const logger = new Logger(config.logFile, config.logLevel);\n const startTime = Date.now();\n proxyStartTime = Date.now();\n passthroughMode = false;\n\n const anthropicServer = http.createServer((req, res) => {\n if (req.url === '/health' && req.method === 'GET') {\n handleHealthRequest(res, config, startTime, isPassthroughMode());\n return;\n }\n if (req.url === '/admin/mode' && req.method === 'POST') {\n handleAdminMode(req, res, logger);\n return;\n }\n handleRequest(req, res, config, 'claude-code', logger);\n });\n\n // Handle port binding errors (EADDRINUSE, EACCES, etc.)\n anthropicServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n logger.error(`Port ${config.anthropicPort} is already in use. Another Skalpel proxy or process may be running.`);\n } else {\n logger.error(`Anthropic proxy failed to bind port ${config.anthropicPort}: ${err.message}`);\n }\n removePid(config.pidFile);\n process.exit(1);\n });\n\n anthropicServer.listen(config.anthropicPort, () => {\n logger.info(`Anthropic proxy listening on port ${config.anthropicPort}`);\n });\n\n writePid(config.pidFile);\n logger.info(`Proxy started (pid=${process.pid}) port=${config.anthropicPort}`);\n\n const cleanup = () => {\n logger.info('Shutting down proxy...');\n anthropicServer.close();\n removePid(config.pidFile);\n process.exit(0);\n };\n\n process.on('SIGTERM', cleanup);\n process.on('SIGINT', cleanup);\n\n // Catch unexpected errors so PID file is always cleaned up\n process.on('uncaughtException', (err) => {\n logger.error(`Uncaught exception: ${err.message}`);\n removePid(config.pidFile);\n process.exit(1);\n });\n\n process.on('unhandledRejection', (reason) => {\n logger.error(`Unhandled rejection: ${reason}`);\n removePid(config.pidFile);\n process.exit(1);\n });\n\n return { anthropicServer };\n}\n\nexport function stopProxy(config: ProxyConfig): boolean {\n const pid = readPid(config.pidFile);\n if (pid === null) return false;\n\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n // Process already gone\n }\n\n removePid(config.pidFile);\n return true;\n}\n\nexport function getProxyStatus(config: ProxyConfig): ProxyStatus {\n const pid = readPid(config.pidFile);\n return {\n running: pid !== null,\n pid,\n uptime: proxyStartTime > 0 ? Date.now() - proxyStartTime : 0,\n anthropicPort: config.anthropicPort,\n };\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { ProxyConfig } from './types.js';\nimport type { Logger } from './logger.js';\n\nconst HOP_BY_HOP = new Set([\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailer', 'transfer-encoding', 'upgrade',\n]);\n\nconst STRIP_HEADERS = new Set([\n ...HOP_BY_HOP,\n 'content-encoding', 'content-length',\n]);\n\n/** Remove Skalpel-specific headers so a direct-to-Anthropic fallback request is clean. */\nfunction stripSkalpelHeaders(headers: Record<string, string>): Record<string, string> {\n const cleaned = { ...headers };\n delete cleaned['X-Skalpel-API-Key'];\n delete cleaned['X-Skalpel-Source'];\n delete cleaned['X-Skalpel-Agent-Type'];\n delete cleaned['X-Skalpel-SDK-Version'];\n return cleaned;\n}\n\n/** Returns true if the error or HTTP status indicates the Skalpel backend\n * itself is unreachable or broken (not a normal API error from Anthropic). */\nfunction isSkalpelBackendFailure(response: Response | null, err: unknown): boolean {\n if (err) return true;\n if (!response) return true;\n if (response.status >= 500) return true;\n // 403 from Skalpel (e.g. \"No active plan\") is a Skalpel-specific rejection,\n // not an Anthropic error — fall back to direct API so requests still work.\n if (response.status === 403) return true;\n return false;\n}\n\nasync function doStreamingFetch(\n url: string,\n body: string,\n headers: Record<string, string>,\n): Promise<Response> {\n return fetch(url, { method: 'POST', headers, body });\n}\n\nexport async function handleStreamingRequest(\n _req: IncomingMessage,\n res: ServerResponse,\n _config: ProxyConfig,\n _source: string,\n body: string,\n skalpelUrl: string,\n directUrl: string,\n useSkalpel: boolean,\n forwardHeaders: Record<string, string>,\n logger: Logger,\n): Promise<void> {\n let response: Response | null = null;\n let fetchError: unknown = null;\n let usedFallback = false;\n\n // Try Skalpel backend first (if this request should be optimized)\n if (useSkalpel) {\n try {\n response = await doStreamingFetch(skalpelUrl, body, forwardHeaders);\n } catch (err) {\n fetchError = err;\n }\n\n // If Skalpel backend is down, fall back to direct Anthropic API\n if (isSkalpelBackendFailure(response, fetchError)) {\n logger.warn(`streaming: Skalpel backend failed (${fetchError ? (fetchError as Error).message : `status ${response?.status}`}), falling back to direct Anthropic API`);\n usedFallback = true;\n response = null;\n fetchError = null;\n const directHeaders = stripSkalpelHeaders(forwardHeaders);\n try {\n response = await doStreamingFetch(directUrl, body, directHeaders);\n } catch (err) {\n fetchError = err;\n }\n }\n } else {\n // Non-Skalpel path — go direct\n try {\n response = await doStreamingFetch(directUrl, body, forwardHeaders);\n } catch (err) {\n fetchError = err;\n }\n }\n\n // If even the direct request failed, return error\n if (!response || fetchError) {\n const errMsg = fetchError ? (fetchError as Error).message : 'no response from upstream';\n logger.error(`streaming fetch failed: ${errMsg}`);\n res.writeHead(502, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n });\n res.write(`event: error\\ndata: ${JSON.stringify({ error: errMsg })}\\n\\n`);\n res.end();\n return;\n }\n\n if (usedFallback) {\n logger.info('streaming: using direct Anthropic API fallback');\n }\n\n // For non-2xx responses, pass through as-is so the SDK can parse error bodies correctly\n if (response.status >= 300) {\n const errorBody = Buffer.from(await response.arrayBuffer());\n logger.error(`streaming upstream error: status=${response.status} body=${errorBody.toString().slice(0, 500)}`);\n const passthroughHeaders: Record<string, string> = {};\n for (const [key, value] of response.headers.entries()) {\n if (!STRIP_HEADERS.has(key)) {\n passthroughHeaders[key] = value;\n }\n }\n passthroughHeaders['content-length'] = String(errorBody.length);\n res.writeHead(response.status, passthroughHeaders);\n res.end(errorBody);\n return;\n }\n\n // Build SSE headers, stripping hop-by-hop/encoding and normalizing content-type\n const sseHeaders: Record<string, string> = {};\n for (const [key, value] of response.headers.entries()) {\n if (!STRIP_HEADERS.has(key) && key !== 'content-type') {\n sseHeaders[key] = value;\n }\n }\n sseHeaders['Content-Type'] = 'text/event-stream';\n sseHeaders['Cache-Control'] = 'no-cache';\n res.writeHead(response.status, sseHeaders);\n\n if (!response.body) {\n res.write(`event: error\\ndata: ${JSON.stringify({ error: 'no response body' })}\\n\\n`);\n res.end();\n return;\n }\n\n try {\n const reader = (response.body as ReadableStream<Uint8Array>).getReader();\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = decoder.decode(value, { stream: true });\n res.write(chunk);\n }\n } catch (err) {\n logger.error(`streaming error: ${(err as Error).message}`);\n res.write(`event: error\\ndata: ${JSON.stringify({ error: (err as Error).message })}\\n\\n`);\n }\n\n res.end();\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { ProxyConfig } from './types.js';\nimport { handleStreamingRequest } from './streaming.js';\nimport { isPassthroughMode } from './server.js';\nimport type { Logger } from './logger.js';\n\n// Exact paths that should route through Skalpel optimization for Claude Code.\n// Sub-paths like /v1/messages/count_tokens go direct to Anthropic.\nconst SKALPEL_EXACT_PATHS = new Set(['/v1/messages']);\n\nfunction collectBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString()));\n req.on('error', reject);\n });\n}\n\nexport function shouldRouteToSkalpel(path: string, _source: string): boolean {\n // In passthrough mode, all requests go direct to provider APIs\n if (isPassthroughMode()) return false;\n // Strip query string — Claude Code sends /v1/messages?beta=true\n const pathname = path.split('?')[0];\n return SKALPEL_EXACT_PATHS.has(pathname);\n}\n\n/** Returns true if the error or HTTP status indicates the Skalpel backend\n * itself is unreachable or broken (not a normal API error from Anthropic). */\nfunction isSkalpelBackendFailure(response: Response | null, err: unknown): boolean {\n // Network-level failure (DNS, connection refused, timeout, etc.)\n if (err) return true;\n if (!response) return true;\n // 5xx from the Skalpel backend means the backend is having issues\n if (response.status >= 500) return true;\n // 403 from Skalpel (e.g. \"No active plan\") is a Skalpel-specific rejection,\n // not an Anthropic error — fall back to direct API so requests still work.\n if (response.status === 403) return true;\n return false;\n}\n\n/** Build the set of headers to forward, adding Skalpel-specific headers when routing through Skalpel. */\nexport function buildForwardHeaders(\n req: IncomingMessage,\n config: ProxyConfig,\n source: string,\n useSkalpel: boolean,\n): Record<string, string> {\n const forwardHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (value !== undefined) {\n forwardHeaders[key] = Array.isArray(value) ? value.join(', ') : value;\n }\n }\n delete forwardHeaders['host'];\n delete forwardHeaders['connection'];\n\n if (useSkalpel) {\n forwardHeaders['X-Skalpel-API-Key'] = config.apiKey;\n forwardHeaders['X-Skalpel-Source'] = source;\n forwardHeaders['X-Skalpel-Agent-Type'] = source;\n forwardHeaders['X-Skalpel-SDK-Version'] = 'proxy-1.0.0';\n\n // Claude Code may send either x-api-key (API key auth) or\n // Authorization: Bearer (OAuth auth). Only convert Bearer to x-api-key\n // for actual API keys (sk-ant-*). OAuth tokens must stay as\n // Authorization: Bearer — Anthropic rejects them in x-api-key.\n if (source === 'claude-code' && !forwardHeaders['x-api-key']) {\n const authHeader = forwardHeaders['authorization'] ?? '';\n if (authHeader.toLowerCase().startsWith('bearer ')) {\n const token = authHeader.slice(7).trim();\n if (token.startsWith('sk-ant-')) {\n forwardHeaders['x-api-key'] = token;\n }\n }\n }\n }\n\n return forwardHeaders;\n}\n\n/** Remove Skalpel-specific headers so a direct-to-Anthropic fallback request is clean. */\nfunction stripSkalpelHeaders(headers: Record<string, string>): Record<string, string> {\n const cleaned = { ...headers };\n delete cleaned['X-Skalpel-API-Key'];\n delete cleaned['X-Skalpel-Source'];\n delete cleaned['X-Skalpel-Agent-Type'];\n delete cleaned['X-Skalpel-SDK-Version'];\n return cleaned;\n}\n\n// Headers that should not be forwarded by a proxy.\n// Also strips content-encoding and content-length because fetch()\n// automatically decompresses gzip/deflate/br responses — the body we\n// read via arrayBuffer() is already decompressed, so forwarding the\n// original content-encoding header causes the client to try to decompress\n// plain text → ZlibError.\nconst STRIP_RESPONSE_HEADERS = new Set([\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailer', 'transfer-encoding', 'upgrade',\n 'content-encoding', 'content-length',\n]);\n\nfunction extractResponseHeaders(response: Response): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const [key, value] of response.headers.entries()) {\n if (!STRIP_RESPONSE_HEADERS.has(key)) {\n headers[key] = value;\n }\n }\n return headers;\n}\n\nexport async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n config: ProxyConfig,\n source: string,\n logger: Logger,\n): Promise<void> {\n const start = Date.now();\n const method = req.method ?? 'GET';\n const path = req.url ?? '/';\n\n try {\n const body = await collectBody(req);\n const useSkalpel = shouldRouteToSkalpel(path, source);\n const forwardHeaders = buildForwardHeaders(req, config, source, useSkalpel);\n\n let isStreaming = false;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n isStreaming = parsed.stream === true;\n } catch {\n // Not JSON — treat as non-streaming\n }\n }\n\n if (isStreaming) {\n const skalpelUrl = `${config.remoteBaseUrl}${path}`;\n const directUrl = `${config.anthropicDirectUrl}${path}`;\n await handleStreamingRequest(req, res, config, source, body, skalpelUrl, directUrl, useSkalpel, forwardHeaders, logger);\n logger.info(`${method} ${path} source=${source} streaming latency=${Date.now() - start}ms`);\n return;\n }\n\n const skalpelUrl = `${config.remoteBaseUrl}${path}`;\n const directUrl = `${config.anthropicDirectUrl}${path}`;\n const fetchBody = method !== 'GET' && method !== 'HEAD' ? body : undefined;\n\n let response: Response | null = null;\n let fetchError: unknown = null;\n let usedFallback = false;\n\n // Try Skalpel backend first (if this request should be optimized)\n if (useSkalpel) {\n try {\n response = await fetch(skalpelUrl, { method, headers: forwardHeaders, body: fetchBody });\n } catch (err) {\n fetchError = err;\n }\n\n // If Skalpel backend is down, fall back to direct Anthropic API\n if (isSkalpelBackendFailure(response, fetchError)) {\n logger.warn(`${method} ${path} Skalpel backend failed (${fetchError ? (fetchError as Error).message : `status ${response?.status}`}), falling back to direct Anthropic API`);\n usedFallback = true;\n response = null;\n fetchError = null;\n const directHeaders = stripSkalpelHeaders(forwardHeaders);\n try {\n response = await fetch(directUrl, { method, headers: directHeaders, body: fetchBody });\n } catch (err) {\n fetchError = err;\n }\n }\n } else {\n // Non-Skalpel path — go direct\n try {\n response = await fetch(directUrl, { method, headers: forwardHeaders, body: fetchBody });\n } catch (err) {\n fetchError = err;\n }\n }\n\n // If even the direct request failed, return 502\n if (!response || fetchError) {\n throw fetchError ?? new Error('no response from upstream');\n }\n\n const responseHeaders = extractResponseHeaders(response);\n const responseBody = Buffer.from(await response.arrayBuffer());\n responseHeaders['content-length'] = String(responseBody.length);\n res.writeHead(response.status, responseHeaders);\n res.end(responseBody);\n\n logger.info(`${method} ${path} source=${source} status=${response.status}${usedFallback ? ' (fallback)' : ''} latency=${Date.now() - start}ms`);\n } catch (err) {\n logger.error(`${method} ${path} source=${source} error=${(err as Error).message}`);\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify({ error: 'proxy_error', message: (err as Error).message }));\n }\n }\n}\n","import type { ServerResponse } from 'node:http';\nimport type { ProxyConfig } from './types.js';\n\nexport function handleHealthRequest(\n res: ServerResponse,\n config: ProxyConfig,\n startTime: number,\n passthrough: boolean = false,\n): void {\n const body = JSON.stringify({\n status: 'ok',\n mode: passthrough ? 'passthrough' : 'normal',\n uptime: Date.now() - startTime,\n ports: {\n anthropic: config.anthropicPort,\n },\n version: 'proxy-1.0.0',\n });\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(body);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nexport function writePid(pidFile: string): void {\n fs.mkdirSync(path.dirname(pidFile), { recursive: true });\n fs.writeFileSync(pidFile, String(process.pid));\n}\n\nexport function readPid(pidFile: string): number | null {\n try {\n const raw = fs.readFileSync(pidFile, 'utf-8').trim();\n const pid = parseInt(raw, 10);\n if (isNaN(pid)) return null;\n return isRunning(pid) ? pid : null;\n } catch {\n return null;\n }\n}\n\nexport function isRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function removePid(pidFile: string): void {\n try {\n fs.unlinkSync(pidFile);\n } catch {\n // Already removed\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nconst MAX_SIZE = 5 * 1024 * 1024; // 5MB\nconst MAX_ROTATIONS = 3;\n\nconst LEVELS = { debug: 0, info: 1, warn: 2, error: 3 } as const;\n\nexport class Logger {\n private logFile: string;\n private level: keyof typeof LEVELS;\n\n constructor(logFile: string, level: keyof typeof LEVELS = 'info') {\n this.logFile = logFile;\n this.level = level;\n fs.mkdirSync(path.dirname(logFile), { recursive: true });\n }\n\n debug(msg: string): void { this.log('debug', msg); }\n info(msg: string): void { this.log('info', msg); }\n warn(msg: string): void { this.log('warn', msg); }\n error(msg: string): void { this.log('error', msg); }\n\n private log(level: keyof typeof LEVELS, msg: string): void {\n if (LEVELS[level] < LEVELS[this.level]) return;\n\n const line = `${new Date().toISOString()} [${level.toUpperCase()}] ${msg}\\n`;\n\n if (level === 'debug' || level === 'error') {\n process.stderr.write(line);\n }\n\n try {\n this.rotate();\n fs.appendFileSync(this.logFile, line);\n } catch {\n // Best-effort logging\n }\n }\n\n private rotate(): void {\n try {\n const stat = fs.statSync(this.logFile);\n if (stat.size < MAX_SIZE) return;\n } catch {\n return;\n }\n\n for (let i = MAX_ROTATIONS; i >= 1; i--) {\n const src = i === 1 ? this.logFile : `${this.logFile}.${i - 1}`;\n const dst = `${this.logFile}.${i}`;\n try {\n fs.renameSync(src, dst);\n } catch {\n // File may not exist\n }\n }\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport type { ProxyConfig } from './types.js';\n\nfunction expandHome(filePath: string): string {\n if (filePath.startsWith('~')) {\n return path.join(os.homedir(), filePath.slice(1));\n }\n return filePath;\n}\n\nconst DEFAULTS: ProxyConfig = {\n apiKey: '',\n remoteBaseUrl: 'https://api.skalpel.ai',\n anthropicDirectUrl: 'https://api.anthropic.com',\n anthropicPort: 18100,\n logLevel: 'info',\n logFile: '~/.skalpel/logs/proxy.log',\n pidFile: '~/.skalpel/proxy.pid',\n configFile: '~/.skalpel/config.json',\n};\n\nexport function loadConfig(configPath?: string): ProxyConfig {\n const filePath = expandHome(configPath ?? DEFAULTS.configFile);\n let fileConfig: Partial<ProxyConfig> = {};\n\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n fileConfig = JSON.parse(raw) as Partial<ProxyConfig>;\n } catch {\n // Config file doesn't exist or is invalid — use defaults\n }\n\n return {\n apiKey: fileConfig.apiKey ?? DEFAULTS.apiKey,\n remoteBaseUrl: fileConfig.remoteBaseUrl ?? DEFAULTS.remoteBaseUrl,\n anthropicDirectUrl: fileConfig.anthropicDirectUrl ?? DEFAULTS.anthropicDirectUrl,\n anthropicPort: fileConfig.anthropicPort ?? DEFAULTS.anthropicPort,\n logLevel: fileConfig.logLevel ?? DEFAULTS.logLevel,\n logFile: expandHome(fileConfig.logFile ?? DEFAULTS.logFile),\n pidFile: expandHome(fileConfig.pidFile ?? DEFAULTS.pidFile),\n configFile: filePath,\n };\n}\n\nexport function saveConfig(config: ProxyConfig): void {\n const dir = path.dirname(config.configFile);\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(config.configFile, JSON.stringify(config, null, 2) + '\\n');\n}\n"],"mappings":";AAEO,SAAS,gBACd,SACwB;AACxB,QAAM,MAAM,CAAC,SAAgC;AAC3C,QAAI,mBAAmB,SAAS;AAC9B,aAAO,QAAQ,IAAI,IAAI;AAAA,IACzB;AACA,WAAO,QAAQ,IAAI,KAAK;AAAA,EAC1B;AAEA,QAAM,YAAY,IAAI,sBAAsB;AAC5C,MAAI,CAAC,UAAW,QAAO;AAEvB,SAAO;AAAA,IACL;AAAA,IACA,cAAe,IAAI,wBAAwB,KAAyC;AAAA,IACpF,eAAe,IAAI,0BAA0B,KAAK;AAAA,IAClD,aAAa,IAAI,wBAAwB,KAAK;AAAA,IAC9C,YAAY,WAAW,IAAI,uBAAuB,KAAK,GAAG;AAAA,IAC1D,UAAU,IAAI,qBAAqB,MAAM;AAAA,IACzC,WAAW,SAAS,IAAI,sBAAsB,KAAK,KAAK,EAAE;AAAA,EAC5D;AACF;;;ACxBO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YACE,SACA,MACA,YACA,YACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,aAAa;AAClB,SAAK,aAAa;AAAA,EACpB;AACF;AAEO,IAAM,mBAAN,cAA+B,aAAa;AAAA,EACjD,YAAY,UAAU,iCAAiC;AACrD,UAAM,SAAS,uBAAuB,GAAG;AACzC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sBAAN,cAAkC,aAAa;AAAA,EACpD,YAAY,UAAU,6BAA6B;AACjD,UAAM,SAAS,iBAAiB;AAChC,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,wBAAN,cAAoC,aAAa;AAAA,EACtD,YAAY,UAAU,+BAA+B,YAAqB;AACxE,UAAM,SAAS,wBAAwB,KAAK,UAAU;AACtD,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,0BAAN,cAAsC,aAAa;AAAA,EACxD,YACE,UAAU,+BACV,YACA;AACA,UAAM,SAAS,uBAAuB,UAAU;AAChD,SAAK,OAAO;AAAA,EACd;AACF;;;AChCA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEO,SAAS,cAAc,KAA4B;AACxD,MAAI,eAAe,aAAc,QAAO;AAExC,QAAM,QAAQ;AACd,QAAM,SAAS,MAAM,UAAU,MAAM;AACrC,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,WAAW,KAAK;AAClB,WAAO,IAAI,iBAAiB,OAAO;AAAA,EACrC;AACA,MAAI,WAAW,KAAK;AAClB,UAAM,aAAa,MAAM,UAAU,aAAa,IAC5C,SAAS,MAAM,QAAQ,aAAa,GAAG,EAAE,IACzC;AACJ,WAAO,IAAI,sBAAsB,SAAS,UAAU;AAAA,EACtD;AACA,MAAI,MAAM,SAAS,eAAe,MAAM,SAAS,aAAa,MAAM,SAAS,2BAA2B;AACtG,WAAO,IAAI,oBAAoB,OAAO;AAAA,EACxC;AACA,MAAI,UAAU,UAAU,KAAK;AAC3B,WAAO,IAAI,wBAAwB,SAAS,MAAM;AAAA,EACpD;AAEA,SAAO,IAAI,wBAAwB,SAAS,MAAM;AACpD;AAEA,eAAsB,aACpB,WACA,YACA,UAA2B,CAAC,GAChB;AACZ,QAAM,EAAE,UAAU,GAAG,UAAU,OAAO,YAAY,WAAW,WAAW,kBAAkB,KAAK,IAAI;AAEnG,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,SAAS,WAAW;AACnD,QAAI;AACF,aAAO,MAAM,UAAU;AAAA,IACzB,SAAS,KAAK;AACZ,kBAAY,cAAc,GAAG;AAG7B,UAAI,qBAAqB,kBAAkB;AACzC,cAAM;AAAA,MACR;AAGA,UAAI,qBAAqB,yBAAyB,UAAU,cAAc,UAAU,SAAS;AAC3F,cAAM,MAAM,UAAU,aAAa,GAAI;AACvC;AAAA,MACF;AAGA,UAAI,UAAU,SAAS;AACrB,cAAM,MAAM,KAAK,IAAI,GAAG,OAAO,IAAI,GAAI;AACvC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,iBAAiB;AACnB,QAAI,WAAW,WAAW;AACxB,cAAQ,KAAK,oCAAoC,QAAQ,UAAU,UAAU,OAAO,EAAE;AAAA,IACxF;AACA,QAAI,cAAc,WAAW;AAC3B,iBAAW,WAAW,QAAQ;AAAA,IAChC;AACA,WAAO,WAAW;AAAA,EACpB;AAEA,QAAM;AACR;;;AC5FO,IAAM,UAAU;;;ACKvB,SAAS,cAAc,SAA+B;AACpD,SAAO;AAAA,IACL,QAAQ,QAAQ;AAAA,IAChB,SAAS,QAAQ,WAAW;AAAA,IAC5B,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ,mBAAmB;AAAA,IAC5C,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS,QAAQ,WAAW;AAAA,IAC5B,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC7B,YAAY,QAAQ;AAAA,IACpB,YAAY,QAAQ;AAAA,EACtB;AACF;AAEA,SAAS,oBAAoB,QAAkE;AAC7F,QAAM,UAAkC;AAAA,IACtC,iBAAiB,UAAU,OAAO,MAAM;AAAA,IACxC,yBAAyB;AAAA,IACzB,GAAG,OAAO;AAAA,EACZ;AACA,MAAI,OAAO,WAAW;AACpB,YAAQ,qBAAqB,IAAI,OAAO;AAAA,EAC1C;AACA,SAAO;AACT;AAEA,SAAS,4BAA4B,UAAmB,QAAgD;AACtG,MAAI,CAAC,YAAY,OAAO,aAAa,SAAU;AAC/C,QAAM,OAAO;AAGb,MAAI,KAAK,aAAa,OAAO,KAAK,cAAc,UAAU;AACxD,UAAM,MAAM,KAAK;AACjB,QAAI,IAAI,SAAS;AACf,YAAM,WAAW,gBAAgB,IAAI,OAAO;AAC5C,UAAI,UAAU;AACZ,eAAO,aAAa,QAAQ;AAC5B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA,MAAI,KAAK,aAAa,OAAO,KAAK,cAAc,UAAU;AACxD,UAAM,KAAK,KAAK;AAChB,UAAM,WAA4B;AAAA,MAChC,WAAY,GAAG,cAAyB;AAAA,MACxC,cAAe,GAAG,gBAAoD;AAAA,MACtE,eAAgB,GAAG,kBAA6B;AAAA,MAChD,aAAc,GAAG,gBAA2B;AAAA,MAC5C,YAAY,OAAO,GAAG,eAAe,CAAC;AAAA,MACtC,UAAU,QAAQ,GAAG,SAAS;AAAA,MAC9B,WAAW,OAAO,GAAG,cAAc,CAAC;AAAA,IACtC;AACA,WAAO,aAAa,QAAQ;AAAA,EAC9B;AACF;AAEA,SAAS,eAAe,QAA0B;AAChD,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,IAAI;AACV,SACE,EAAE,SAAS,UACX,OAAO,EAAE,SAAS,YAClB,EAAE,SAAS,QACX,iBAAkB,EAAE;AAExB;AAEA,SAAS,kBAAkB,QAA0B;AACnD,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,IAAI;AACV,SACE,EAAE,aAAa,UACf,OAAO,EAAE,aAAa,YACtB,EAAE,aAAa,QACf,OAAQ,EAAE,SAAqC,WAAW;AAE9D;AAEA,SAAS,WAAc,QAAW,QAA6C;AAC7E,QAAM,IAAI;AACV,QAAM,iBAAiB,oBAAoB,MAAM;AACjD,QAAM,kBAAkB,EAAE;AAE1B,WAAS,kBACP,QACA,YAC0C;AAC1C,UAAM,iBAAiB,OAAO,UAAU;AAExC,WAAO,kBAAmB,MAAiB;AACzC,YAAM,YAAY,YAAY;AAC5B,UAAE,UAAU,GAAG,OAAO,OAAO;AAG7B,cAAM,cAAc,KAAK,CAAC;AAC1B,cAAM,eAAe;AAErB,YAAI;AACJ,YAAI,KAAK,UAAU,KAAK,OAAO,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,MAAM;AACvE,gBAAM,OAAO,KAAK,CAAC;AACnB,eAAK,UAAU,EAAE,GAAG,cAAc,GAAI,KAAK,QAA+C;AAC1F,qBAAW,CAAC,aAAa,MAAM,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,QACjD,OAAO;AACL,qBAAW,CAAC,aAAa,EAAE,SAAS,aAAa,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,QACtE;AAEA,YAAI;AACF,gBAAM,SAAS,MAAM,eAAe,MAAM,QAAQ,QAAQ;AAC1D,sCAA4B,QAAQ,MAAM;AAC1C,YAAE,UAAU;AACZ,iBAAO;AAAA,QACT,SAAS,KAAK;AACZ,YAAE,UAAU;AACZ,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,YAAM,aAAa,YAAY;AAC7B,UAAE,UAAU;AACZ,eAAO,eAAe,MAAM,QAAQ,IAAI;AAAA,MAC1C;AAEA,aAAO,aAAa,WAAW,YAAY;AAAA,QACzC,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,UAAU;AAAA,QACV,iBAAiB,OAAO;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,WAAS,qBAAqB,WAA6D;AACzF,WAAO,IAAI,MAAM,WAAW;AAAA,MAC1B,IAAI,QAAQ,MAAM,UAAU;AAC1B,cAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAChD,YAAI,OAAO,UAAU,eAAe,SAAS,YAAY,SAAS,WAAW;AAC3E,iBAAO,kBAAkB,QAAQ,IAAc;AAAA,QACjD;AACA,YAAI,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AAC/D,iBAAO,qBAAqB,KAAgC;AAAA,QAC9D;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,IAAI,MAAM,QAAkB;AAAA,IACjC,IAAI,QAAQ,MAAM,UAAU;AAC1B,YAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAChD,UACE,OAAO,UAAU,YACjB,UAAU,SACT,SAAS,UAAU,SAAS,iBAAiB,SAAS,eACvD;AACA,eAAO,qBAAqB,KAAgC;AAAA,MAC9D;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEA,SAAS,cAAiB,QAAW,QAA6C;AAChF,QAAM,IAAI;AACV,QAAM,iBAAiB,oBAAoB,MAAM;AACjD,QAAM,kBAAkB,EAAE,WAAY,EAAE,SAAqC;AAE7E,WAAS,kBACP,QACA,YAC0C;AAC1C,UAAM,iBAAiB,OAAO,UAAU;AAExC,WAAO,kBAAmB,MAAiB;AAEzC,YAAM,YAAY,YAAY;AAG5B,cAAM,WAAW,OAAO;AACxB,YAAI,aAAa,EAAG,GAAE,UAAU;AAChC,YAAI,EAAE,WAAW,aAAa,EAAE,QAAS,GAAE,QAAQ,UAAU;AAE7D,cAAM,cAAc,KAAK,CAAC;AAC1B,cAAM,eAAe;AAErB,YAAI;AACJ,YAAI,KAAK,UAAU,KAAK,OAAO,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,MAAM;AACvE,gBAAM,OAAO,KAAK,CAAC;AACnB,eAAK,UAAU,EAAE,GAAG,cAAc,GAAI,KAAK,QAA+C;AAC1F,qBAAW,CAAC,aAAa,MAAM,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,QACjD,OAAO;AACL,qBAAW,CAAC,aAAa,EAAE,SAAS,aAAa,GAAG,GAAG,KAAK,MAAM,CAAC,CAAC;AAAA,QACtE;AAEA,YAAI;AACF,gBAAM,SAAS,MAAM,eAAe,MAAM,QAAQ,QAAQ;AAC1D,sCAA4B,QAAQ,MAAM;AAC1C,cAAI,aAAa,EAAG,GAAE,UAAU;AAChC,cAAI,EAAE,WAAW,aAAa,EAAE,QAAS,GAAE,QAAQ,UAAU;AAC7D,iBAAO;AAAA,QACT,SAAS,KAAK;AACZ,cAAI,aAAa,EAAG,GAAE,UAAU;AAChC,cAAI,EAAE,WAAW,aAAa,EAAE,QAAS,GAAE,QAAQ,UAAU;AAC7D,gBAAM;AAAA,QACR;AAAA,MACF;AAEA,YAAM,aAAa,YAAY;AAC7B,YAAI,aAAa,EAAG,GAAE,UAAU;AAChC,YAAI,EAAE,WAAW,aAAa,EAAE,QAAS,GAAE,QAAQ,UAAU;AAC7D,eAAO,eAAe,MAAM,QAAQ,IAAI;AAAA,MAC1C;AAEA,aAAO,aAAa,WAAW,YAAY;AAAA,QACzC,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,QAChB,YAAY,OAAO;AAAA,QACnB,UAAU;AAAA,QACV,iBAAiB,OAAO;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,IAAI,MAAM,QAAkB;AAAA,IACjC,IAAI,QAAQ,MAAM,UAAU;AAC1B,YAAM,QAAQ,QAAQ,IAAI,QAAQ,MAAM,QAAQ;AAChD,UAAI,SAAS,cAAc,OAAO,UAAU,YAAY,UAAU,MAAM;AACtE,eAAO,IAAI,MAAM,OAAiB;AAAA,UAChC,IAAI,WAAW,SAAS,aAAa;AACnC,kBAAM,WAAW,QAAQ,IAAI,WAAW,SAAS,WAAW;AAC5D,gBAAI,OAAO,aAAa,eAAe,YAAY,YAAY,YAAY,WAAW;AACpF,qBAAO,kBAAkB,WAAsC,OAAiB;AAAA,YAClF;AACA,mBAAO;AAAA,UACT;AAAA,QACF,CAAC;AAAA,MACH;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACH;AAEO,SAAS,oBAAuB,QAAW,SAAkC;AAClF,QAAM,SAAS,cAAc,OAAO;AAEpC,MAAI,eAAe,MAAM,GAAG;AAC1B,WAAO,WAAW,QAAQ,MAAM;AAAA,EAClC;AAEA,MAAI,kBAAkB,MAAM,GAAG;AAC7B,WAAO,cAAc,QAAQ,MAAM;AAAA,EACrC;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AA2EA,eAAe,eACb,QACAA,OACA,MACY;AACZ,QAAM,MAAM,GAAG,OAAO,OAAO,kBAAkBA,KAAI;AACnD,QAAM,UAAU,oBAAoB,MAAM;AAC1C,UAAQ,cAAc,IAAI;AAE1B,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,OAAO,OAAO;AAErE,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR;AAAA,MACA,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ,WAAW;AAAA,IACrB,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,OAAO,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE;AACjD,YAAM,IAAI,MAAM,6BAA6B,SAAS,MAAM,KAAK,IAAI,EAAE;AAAA,IACzE;AACA,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B,UAAE;AACA,iBAAa,SAAS;AAAA,EACxB;AACF;AAEA,eAAsB,eACpB,SACA,QAC+B;AAC/B,QAAM,SAAS,cAAc,OAAO;AACpC,QAAM,MAAM,MAAM,eAAwC,QAAQ,cAAc;AAAA,IAC9E,cAAc,OAAO;AAAA,IACrB,eAAe,OAAO;AAAA,IACtB,UAAU,OAAO,YAAY,CAAC;AAAA,IAC9B,UAAU,OAAO,YAAY;AAAA,EAC/B,CAAC;AACD,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,aAAa,OAAO,IAAI,YAAY;AAAA,IACpC,cAAc,OAAO,IAAI,aAAa;AAAA,IACtC,UAAW,IAAI,YAAwC,CAAC;AAAA,IACxD,UAAW,IAAI,YAAwC;AAAA,IACvD,WAAW,OAAO,IAAI,UAAU;AAAA,EAClC;AACF;AAEA,eAAsB,aACpB,SACA,QACwB;AACxB,QAAM,SAAS,cAAc,OAAO;AACpC,QAAM,MAAM,MAAM,eAAqD,QAAQ,WAAW;AAAA,IACxF,cAAc,OAAO;AAAA,IACrB,aAAa,OAAO;AAAA,IACpB,QAAQ,OAAO,OAAO,IAAI,CAAC,OAAO;AAAA,MAChC,MAAM,EAAE;AAAA,MACR,YAAY,EAAE;AAAA,MACd,YAAY,EAAE;AAAA,MACd,QAAQ,EAAE,UAAU;AAAA,MACpB,UAAU,EAAE,YAAY;AAAA,MACxB,aAAa,EAAE,cAAc;AAAA,MAC7B,UAAU,EAAE,YAAY;AAAA,IAC1B,EAAE;AAAA,EACJ,CAAC;AACD,UAAQ,IAAI,SAAS,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,IACtC,IAAI,OAAO,KAAK,EAAE;AAAA,IAClB,aAAa,OAAO,KAAK,YAAY;AAAA,IACrC,YAAY,OAAO,KAAK,WAAW;AAAA,IACnC,MAAM,OAAO,KAAK,IAAI;AAAA,IACtB,WAAW,OAAO,KAAK,UAAU;AAAA,IACjC,QAAQ,KAAK,UAAU,OAAO,OAAO,KAAK,MAAM,IAAI;AAAA,IACpD,UAAU,KAAK,YAAY,OAAO,OAAO,KAAK,QAAQ,IAAI;AAAA,IAC1D,YAAY,OAAO,KAAK,eAAe,CAAC;AAAA,IACxC,UAAW,KAAK,YAAwC;AAAA,IACxD,WAAW,OAAO,KAAK,UAAU;AAAA,EACnC,EAAE;AACJ;AAEA,eAAsB,eACpB,SACA,QAC+B;AAC/B,QAAM,SAAS,cAAc,OAAO;AACpC,QAAM,MAAM,MAAM,eAAwC,QAAQ,oBAAoB;AAAA,IACpF,cAAc,OAAO;AAAA,IACrB,aAAa,OAAO,cAAc;AAAA,IAClC,OAAO,OAAO;AAAA,IACd,eAAe,OAAO,gBAAgB,CAAC;AAAA,IACvC,OAAO,OAAO,SAAS;AAAA,EACzB,CAAC;AACD,QAAM,QAAS,IAAI,SAAuC,CAAC;AAC3D,SAAO;AAAA,IACL,aAAa,OAAO,IAAI,YAAY;AAAA,IACpC,YAAY,IAAI,eAAe,OAAO,OAAO,IAAI,WAAW,IAAI;AAAA,IAChE,OAAO,MAAM,IAAI,CAAC,UAAU;AAAA,MAC1B,MAAM,OAAO,KAAK,IAAI;AAAA,MACtB,QAAQ,KAAK,UAAU,OAAO,OAAO,KAAK,MAAM,IAAI;AAAA,MACpD,UAAU,KAAK,YAAY,OAAO,OAAO,KAAK,QAAQ,IAAI;AAAA,MAC1D,YAAY,OAAO,KAAK,eAAe,CAAC;AAAA,MACxC,OAAO,OAAO,KAAK,SAAS,CAAC;AAAA,MAC7B,QAAQ,OAAO,KAAK,UAAU,UAAU;AAAA,MACxC,UAAW,KAAK,YAAwC;AAAA,MACxD,SAAS,OAAO,KAAK,WAAW,EAAE;AAAA,IACpC,EAAE;AAAA,EACJ;AACF;;;AC7bA,SAAS,aAAa,SAAuD;AAC3E,QAAM,UAAkC;AAAA,IACtC,yBAAyB;AAAA,IACzB,GAAG,QAAQ;AAAA,EACb;AACA,MAAI,QAAQ,WAAW;AACrB,YAAQ,qBAAqB,IAAI,QAAQ;AAAA,EAC3C;AACA,SAAO;AACT;AAEA,eAAsB,oBACpB,SACmC;AACnC,QAAM,EAAE,SAAS,OAAO,IAAI,MAAM,OAAO,QAAQ;AACjD,QAAM,UAAU,GAAG,QAAQ,WAAW,wBAAwB;AAC9D,SAAO,IAAI,OAAO;AAAA,IAChB;AAAA,IACA,QAAQ,QAAQ;AAAA,IAChB,gBAAgB,aAAa,OAAO;AAAA,IACpC,SAAS,QAAQ,WAAW;AAAA,IAC5B,YAAY,QAAQ,WAAW;AAAA,EACjC,CAAC;AACH;AAEA,eAAsB,uBACpB,SAC8C;AAC9C,QAAM,EAAE,SAAS,UAAU,IAAI,MAAM,OAAO,mBAAmB;AAE/D,QAAM,UAAU,QAAQ,WAAW;AACnC,SAAO,IAAI,UAAU;AAAA,IACnB;AAAA,IACA,QAAQ,QAAQ,kBAAkB,QAAQ;AAAA,IAC1C,gBAAgB;AAAA,MACd,GAAG,aAAa,OAAO;AAAA,MACvB,iBAAiB,UAAU,QAAQ,MAAM;AAAA,IAC3C;AAAA,IACA,SAAS,QAAQ,WAAW;AAAA,IAC5B,YAAY,QAAQ,WAAW;AAAA,EACjC,CAAC;AACH;;;AC5CA,OAAO,UAAU;;;ACIjB,IAAM,aAAa,oBAAI,IAAI;AAAA,EACzB;AAAA,EAAc;AAAA,EAAc;AAAA,EAAsB;AAAA,EAClD;AAAA,EAAM;AAAA,EAAW;AAAA,EAAqB;AACxC,CAAC;AAED,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B,GAAG;AAAA,EACH;AAAA,EAAoB;AACtB,CAAC;AAGD,SAAS,oBAAoB,SAAyD;AACpF,QAAM,UAAU,EAAE,GAAG,QAAQ;AAC7B,SAAO,QAAQ,mBAAmB;AAClC,SAAO,QAAQ,kBAAkB;AACjC,SAAO,QAAQ,sBAAsB;AACrC,SAAO,QAAQ,uBAAuB;AACtC,SAAO;AACT;AAIA,SAAS,wBAAwB,UAA2B,KAAuB;AACjF,MAAI,IAAK,QAAO;AAChB,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI,SAAS,UAAU,IAAK,QAAO;AAGnC,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,SAAO;AACT;AAEA,eAAe,iBACb,KACA,MACA,SACmB;AACnB,SAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,SAAS,KAAK,CAAC;AACrD;AAEA,eAAsB,uBACpB,MACA,KACA,SACA,SACA,MACA,YACA,WACA,YACA,gBACA,QACe;AACf,MAAI,WAA4B;AAChC,MAAI,aAAsB;AAC1B,MAAI,eAAe;AAGnB,MAAI,YAAY;AACd,QAAI;AACF,iBAAW,MAAM,iBAAiB,YAAY,MAAM,cAAc;AAAA,IACpE,SAAS,KAAK;AACZ,mBAAa;AAAA,IACf;AAGA,QAAI,wBAAwB,UAAU,UAAU,GAAG;AACjD,aAAO,KAAK,sCAAsC,aAAc,WAAqB,UAAU,UAAU,UAAU,MAAM,EAAE,yCAAyC;AACpK,qBAAe;AACf,iBAAW;AACX,mBAAa;AACb,YAAM,gBAAgB,oBAAoB,cAAc;AACxD,UAAI;AACF,mBAAW,MAAM,iBAAiB,WAAW,MAAM,aAAa;AAAA,MAClE,SAAS,KAAK;AACZ,qBAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF,OAAO;AAEL,QAAI;AACF,iBAAW,MAAM,iBAAiB,WAAW,MAAM,cAAc;AAAA,IACnE,SAAS,KAAK;AACZ,mBAAa;AAAA,IACf;AAAA,EACF;AAGA,MAAI,CAAC,YAAY,YAAY;AAC3B,UAAM,SAAS,aAAc,WAAqB,UAAU;AAC5D,WAAO,MAAM,2BAA2B,MAAM,EAAE;AAChD,QAAI,UAAU,KAAK;AAAA,MACjB,gBAAgB;AAAA,MAChB,iBAAiB;AAAA,IACnB,CAAC;AACD,QAAI,MAAM;AAAA,QAAuB,KAAK,UAAU,EAAE,OAAO,OAAO,CAAC,CAAC;AAAA;AAAA,CAAM;AACxE,QAAI,IAAI;AACR;AAAA,EACF;AAEA,MAAI,cAAc;AAChB,WAAO,KAAK,gDAAgD;AAAA,EAC9D;AAGA,MAAI,SAAS,UAAU,KAAK;AAC1B,UAAM,YAAY,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAC1D,WAAO,MAAM,oCAAoC,SAAS,MAAM,SAAS,UAAU,SAAS,EAAE,MAAM,GAAG,GAAG,CAAC,EAAE;AAC7G,UAAM,qBAA6C,CAAC;AACpD,eAAW,CAAC,KAAK,KAAK,KAAK,SAAS,QAAQ,QAAQ,GAAG;AACrD,UAAI,CAAC,cAAc,IAAI,GAAG,GAAG;AAC3B,2BAAmB,GAAG,IAAI;AAAA,MAC5B;AAAA,IACF;AACA,uBAAmB,gBAAgB,IAAI,OAAO,UAAU,MAAM;AAC9D,QAAI,UAAU,SAAS,QAAQ,kBAAkB;AACjD,QAAI,IAAI,SAAS;AACjB;AAAA,EACF;AAGA,QAAM,aAAqC,CAAC;AAC5C,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS,QAAQ,QAAQ,GAAG;AACrD,QAAI,CAAC,cAAc,IAAI,GAAG,KAAK,QAAQ,gBAAgB;AACrD,iBAAW,GAAG,IAAI;AAAA,IACpB;AAAA,EACF;AACA,aAAW,cAAc,IAAI;AAC7B,aAAW,eAAe,IAAI;AAC9B,MAAI,UAAU,SAAS,QAAQ,UAAU;AAEzC,MAAI,CAAC,SAAS,MAAM;AAClB,QAAI,MAAM;AAAA,QAAuB,KAAK,UAAU,EAAE,OAAO,mBAAmB,CAAC,CAAC;AAAA;AAAA,CAAM;AACpF,QAAI,IAAI;AACR;AAAA,EACF;AAEA,MAAI;AACF,UAAM,SAAU,SAAS,KAAoC,UAAU;AACvE,UAAM,UAAU,IAAI,YAAY;AAEhC,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAC1C,UAAI,KAAM;AACV,YAAM,QAAQ,QAAQ,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC;AACpD,UAAI,MAAM,KAAK;AAAA,IACjB;AAAA,EACF,SAAS,KAAK;AACZ,WAAO,MAAM,oBAAqB,IAAc,OAAO,EAAE;AACzD,QAAI,MAAM;AAAA,QAAuB,KAAK,UAAU,EAAE,OAAQ,IAAc,QAAQ,CAAC,CAAC;AAAA;AAAA,CAAM;AAAA,EAC1F;AAEA,MAAI,IAAI;AACV;;;ACpJA,IAAM,sBAAsB,oBAAI,IAAI,CAAC,cAAc,CAAC;AAEpD,SAAS,YAAY,KAAuC;AAC1D,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,QAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,CAAC,CAAC;AAC7D,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEO,SAAS,qBAAqBC,OAAc,SAA0B;AAE3E,MAAI,kBAAkB,EAAG,QAAO;AAEhC,QAAM,WAAWA,MAAK,MAAM,GAAG,EAAE,CAAC;AAClC,SAAO,oBAAoB,IAAI,QAAQ;AACzC;AAIA,SAASC,yBAAwB,UAA2B,KAAuB;AAEjF,MAAI,IAAK,QAAO;AAChB,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI,SAAS,UAAU,IAAK,QAAO;AAGnC,MAAI,SAAS,WAAW,IAAK,QAAO;AACpC,SAAO;AACT;AAGO,SAAS,oBACd,KACA,QACA,QACA,YACwB;AACxB,QAAM,iBAAyC,CAAC;AAChD,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,IAAI,OAAO,GAAG;AACtD,QAAI,UAAU,QAAW;AACvB,qBAAe,GAAG,IAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI;AAAA,IAClE;AAAA,EACF;AACA,SAAO,eAAe,MAAM;AAC5B,SAAO,eAAe,YAAY;AAElC,MAAI,YAAY;AACd,mBAAe,mBAAmB,IAAI,OAAO;AAC7C,mBAAe,kBAAkB,IAAI;AACrC,mBAAe,sBAAsB,IAAI;AACzC,mBAAe,uBAAuB,IAAI;AAM1C,QAAI,WAAW,iBAAiB,CAAC,eAAe,WAAW,GAAG;AAC5D,YAAM,aAAa,eAAe,eAAe,KAAK;AACtD,UAAI,WAAW,YAAY,EAAE,WAAW,SAAS,GAAG;AAClD,cAAM,QAAQ,WAAW,MAAM,CAAC,EAAE,KAAK;AACvC,YAAI,MAAM,WAAW,SAAS,GAAG;AAC/B,yBAAe,WAAW,IAAI;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAASC,qBAAoB,SAAyD;AACpF,QAAM,UAAU,EAAE,GAAG,QAAQ;AAC7B,SAAO,QAAQ,mBAAmB;AAClC,SAAO,QAAQ,kBAAkB;AACjC,SAAO,QAAQ,sBAAsB;AACrC,SAAO,QAAQ,uBAAuB;AACtC,SAAO;AACT;AAQA,IAAM,yBAAyB,oBAAI,IAAI;AAAA,EACrC;AAAA,EAAc;AAAA,EAAc;AAAA,EAAsB;AAAA,EAClD;AAAA,EAAM;AAAA,EAAW;AAAA,EAAqB;AAAA,EACtC;AAAA,EAAoB;AACtB,CAAC;AAED,SAAS,uBAAuB,UAA4C;AAC1E,QAAM,UAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,SAAS,QAAQ,QAAQ,GAAG;AACrD,QAAI,CAAC,uBAAuB,IAAI,GAAG,GAAG;AACpC,cAAQ,GAAG,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAsB,cACpB,KACA,KACA,QACA,QACA,QACe;AACf,QAAM,QAAQ,KAAK,IAAI;AACvB,QAAM,SAAS,IAAI,UAAU;AAC7B,QAAMF,QAAO,IAAI,OAAO;AAExB,MAAI;AACF,UAAM,OAAO,MAAM,YAAY,GAAG;AAClC,UAAM,aAAa,qBAAqBA,OAAM,MAAM;AACpD,UAAM,iBAAiB,oBAAoB,KAAK,QAAQ,QAAQ,UAAU;AAE1E,QAAI,cAAc;AAClB,QAAI,MAAM;AACR,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,IAAI;AAC9B,sBAAc,OAAO,WAAW;AAAA,MAClC,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,aAAa;AACf,YAAMG,cAAa,GAAG,OAAO,aAAa,GAAGH,KAAI;AACjD,YAAMI,aAAY,GAAG,OAAO,kBAAkB,GAAGJ,KAAI;AACrD,YAAM,uBAAuB,KAAK,KAAK,QAAQ,QAAQ,MAAMG,aAAYC,YAAW,YAAY,gBAAgB,MAAM;AACtH,aAAO,KAAK,GAAG,MAAM,IAAIJ,KAAI,WAAW,MAAM,sBAAsB,KAAK,IAAI,IAAI,KAAK,IAAI;AAC1F;AAAA,IACF;AAEA,UAAM,aAAa,GAAG,OAAO,aAAa,GAAGA,KAAI;AACjD,UAAM,YAAY,GAAG,OAAO,kBAAkB,GAAGA,KAAI;AACrD,UAAM,YAAY,WAAW,SAAS,WAAW,SAAS,OAAO;AAEjE,QAAI,WAA4B;AAChC,QAAI,aAAsB;AAC1B,QAAI,eAAe;AAGnB,QAAI,YAAY;AACd,UAAI;AACF,mBAAW,MAAM,MAAM,YAAY,EAAE,QAAQ,SAAS,gBAAgB,MAAM,UAAU,CAAC;AAAA,MACzF,SAAS,KAAK;AACZ,qBAAa;AAAA,MACf;AAGA,UAAIC,yBAAwB,UAAU,UAAU,GAAG;AACjD,eAAO,KAAK,GAAG,MAAM,IAAID,KAAI,4BAA4B,aAAc,WAAqB,UAAU,UAAU,UAAU,MAAM,EAAE,yCAAyC;AAC3K,uBAAe;AACf,mBAAW;AACX,qBAAa;AACb,cAAM,gBAAgBE,qBAAoB,cAAc;AACxD,YAAI;AACF,qBAAW,MAAM,MAAM,WAAW,EAAE,QAAQ,SAAS,eAAe,MAAM,UAAU,CAAC;AAAA,QACvF,SAAS,KAAK;AACZ,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,IACF,OAAO;AAEL,UAAI;AACF,mBAAW,MAAM,MAAM,WAAW,EAAE,QAAQ,SAAS,gBAAgB,MAAM,UAAU,CAAC;AAAA,MACxF,SAAS,KAAK;AACZ,qBAAa;AAAA,MACf;AAAA,IACF;AAGA,QAAI,CAAC,YAAY,YAAY;AAC3B,YAAM,cAAc,IAAI,MAAM,2BAA2B;AAAA,IAC3D;AAEA,UAAM,kBAAkB,uBAAuB,QAAQ;AACvD,UAAM,eAAe,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAC7D,oBAAgB,gBAAgB,IAAI,OAAO,aAAa,MAAM;AAC9D,QAAI,UAAU,SAAS,QAAQ,eAAe;AAC9C,QAAI,IAAI,YAAY;AAEpB,WAAO,KAAK,GAAG,MAAM,IAAIF,KAAI,WAAW,MAAM,WAAW,SAAS,MAAM,GAAG,eAAe,gBAAgB,EAAE,YAAY,KAAK,IAAI,IAAI,KAAK,IAAI;AAAA,EAChJ,SAAS,KAAK;AACZ,WAAO,MAAM,GAAG,MAAM,IAAIA,KAAI,WAAW,MAAM,UAAW,IAAc,OAAO,EAAE;AACjF,QAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,eAAe,SAAU,IAAc,QAAQ,CAAC,CAAC;AAAA,IACnF;AAAA,EACF;AACF;;;ACzMO,SAAS,oBACd,KACA,QACA,WACA,cAAuB,OACjB;AACN,QAAM,OAAO,KAAK,UAAU;AAAA,IAC1B,QAAQ;AAAA,IACR,MAAM,cAAc,gBAAgB;AAAA,IACpC,QAAQ,KAAK,IAAI,IAAI;AAAA,IACrB,OAAO;AAAA,MACL,WAAW,OAAO;AAAA,IACpB;AAAA,IACA,SAAS;AAAA,EACX,CAAC;AAED,MAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,MAAI,IAAI,IAAI;AACd;;;ACrBA,OAAO,QAAQ;AACf,OAAO,UAAU;AAEV,SAAS,SAAS,SAAuB;AAC9C,KAAG,UAAU,KAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AACvD,KAAG,cAAc,SAAS,OAAO,QAAQ,GAAG,CAAC;AAC/C;AAEO,SAAS,QAAQ,SAAgC;AACtD,MAAI;AACF,UAAM,MAAM,GAAG,aAAa,SAAS,OAAO,EAAE,KAAK;AACnD,UAAM,MAAM,SAAS,KAAK,EAAE;AAC5B,QAAI,MAAM,GAAG,EAAG,QAAO;AACvB,WAAO,UAAU,GAAG,IAAI,MAAM;AAAA,EAChC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,UAAU,KAAsB;AAC9C,MAAI;AACF,YAAQ,KAAK,KAAK,CAAC;AACnB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,UAAU,SAAuB;AAC/C,MAAI;AACF,OAAG,WAAW,OAAO;AAAA,EACvB,QAAQ;AAAA,EAER;AACF;;;AClCA,OAAOK,SAAQ;AACf,OAAOC,WAAU;AAEjB,IAAM,WAAW,IAAI,OAAO;AAC5B,IAAM,gBAAgB;AAEtB,IAAM,SAAS,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE;AAE/C,IAAM,SAAN,MAAa;AAAA,EACV;AAAA,EACA;AAAA,EAER,YAAY,SAAiB,QAA6B,QAAQ;AAChE,SAAK,UAAU;AACf,SAAK,QAAQ;AACb,IAAAD,IAAG,UAAUC,MAAK,QAAQ,OAAO,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,EACzD;AAAA,EAEA,MAAM,KAAmB;AAAE,SAAK,IAAI,SAAS,GAAG;AAAA,EAAG;AAAA,EACnD,KAAK,KAAmB;AAAE,SAAK,IAAI,QAAQ,GAAG;AAAA,EAAG;AAAA,EACjD,KAAK,KAAmB;AAAE,SAAK,IAAI,QAAQ,GAAG;AAAA,EAAG;AAAA,EACjD,MAAM,KAAmB;AAAE,SAAK,IAAI,SAAS,GAAG;AAAA,EAAG;AAAA,EAE3C,IAAI,OAA4B,KAAmB;AACzD,QAAI,OAAO,KAAK,IAAI,OAAO,KAAK,KAAK,EAAG;AAExC,UAAM,OAAO,IAAG,oBAAI,KAAK,GAAE,YAAY,CAAC,KAAK,MAAM,YAAY,CAAC,KAAK,GAAG;AAAA;AAExE,QAAI,UAAU,WAAW,UAAU,SAAS;AAC1C,cAAQ,OAAO,MAAM,IAAI;AAAA,IAC3B;AAEA,QAAI;AACF,WAAK,OAAO;AACZ,MAAAD,IAAG,eAAe,KAAK,SAAS,IAAI;AAAA,IACtC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,SAAe;AACrB,QAAI;AACF,YAAM,OAAOA,IAAG,SAAS,KAAK,OAAO;AACrC,UAAI,KAAK,OAAO,SAAU;AAAA,IAC5B,QAAQ;AACN;AAAA,IACF;AAEA,aAAS,IAAI,eAAe,KAAK,GAAG,KAAK;AACvC,YAAM,MAAM,MAAM,IAAI,KAAK,UAAU,GAAG,KAAK,OAAO,IAAI,IAAI,CAAC;AAC7D,YAAM,MAAM,GAAG,KAAK,OAAO,IAAI,CAAC;AAChC,UAAI;AACF,QAAAA,IAAG,WAAW,KAAK,GAAG;AAAA,MACxB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;;;ALnDA,IAAI,iBAAiB;AACrB,IAAI,kBAAkB;AAGf,SAAS,oBAA6B;AAC3C,SAAO;AACT;AAEA,SAAS,iBAAiB,KAA4C;AACpE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAC1B,QAAI,GAAG,QAAQ,CAAC,UAAkB,OAAO,KAAK,KAAK,CAAC;AACpD,QAAI,GAAG,OAAO,MAAM,QAAQ,OAAO,OAAO,MAAM,EAAE,SAAS,CAAC,CAAC;AAC7D,QAAI,GAAG,SAAS,MAAM;AAAA,EACxB,CAAC;AACH;AAEA,SAAS,gBAAgB,KAA2B,KAA0B,QAAsB;AAClG,mBAAiB,GAAG,EAAE,KAAK,CAAC,SAAS;AACnC,QAAI;AACF,YAAM,EAAE,KAAK,IAAI,KAAK,MAAM,IAAI;AAChC,wBAAmB,SAAS;AAC5B,aAAO,KAAK,0BAA0B,kBAAkB,gBAAgB,QAAQ,EAAE;AAClF,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,MAAM,kBAAkB,gBAAgB,SAAS,CAAC,CAAC;AAAA,IAC9E,QAAQ;AACN,UAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,UAAI,IAAI,KAAK,UAAU,EAAE,OAAO,oBAAoB,CAAC,CAAC;AAAA,IACxD;AAAA,EACF,CAAC,EAAE,MAAM,MAAM;AACb,QAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,QAAI,IAAI,KAAK,UAAU,EAAE,OAAO,sBAAsB,CAAC,CAAC;AAAA,EAC1D,CAAC;AACH;AAEO,SAAS,WAAW,QAAuD;AAChF,QAAM,SAAS,IAAI,OAAO,OAAO,SAAS,OAAO,QAAQ;AACzD,QAAM,YAAY,KAAK,IAAI;AAC3B,mBAAiB,KAAK,IAAI;AAC1B,oBAAkB;AAElB,QAAM,kBAAkB,KAAK,aAAa,CAAC,KAAK,QAAQ;AACtD,QAAI,IAAI,QAAQ,aAAa,IAAI,WAAW,OAAO;AACjD,0BAAoB,KAAK,QAAQ,WAAW,kBAAkB,CAAC;AAC/D;AAAA,IACF;AACA,QAAI,IAAI,QAAQ,iBAAiB,IAAI,WAAW,QAAQ;AACtD,sBAAgB,KAAK,KAAK,MAAM;AAChC;AAAA,IACF;AACA,kBAAc,KAAK,KAAK,QAAQ,eAAe,MAAM;AAAA,EACvD,CAAC;AAGD,kBAAgB,GAAG,SAAS,CAAC,QAA+B;AAC1D,QAAI,IAAI,SAAS,cAAc;AAC7B,aAAO,MAAM,QAAQ,OAAO,aAAa,sEAAsE;AAAA,IACjH,OAAO;AACL,aAAO,MAAM,uCAAuC,OAAO,aAAa,KAAK,IAAI,OAAO,EAAE;AAAA,IAC5F;AACA,cAAU,OAAO,OAAO;AACxB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,kBAAgB,OAAO,OAAO,eAAe,MAAM;AACjD,WAAO,KAAK,qCAAqC,OAAO,aAAa,EAAE;AAAA,EACzE,CAAC;AAED,WAAS,OAAO,OAAO;AACvB,SAAO,KAAK,sBAAsB,QAAQ,GAAG,UAAU,OAAO,aAAa,EAAE;AAE7E,QAAM,UAAU,MAAM;AACpB,WAAO,KAAK,wBAAwB;AACpC,oBAAgB,MAAM;AACtB,cAAU,OAAO,OAAO;AACxB,YAAQ,KAAK,CAAC;AAAA,EAChB;AAEA,UAAQ,GAAG,WAAW,OAAO;AAC7B,UAAQ,GAAG,UAAU,OAAO;AAG5B,UAAQ,GAAG,qBAAqB,CAAC,QAAQ;AACvC,WAAO,MAAM,uBAAuB,IAAI,OAAO,EAAE;AACjD,cAAU,OAAO,OAAO;AACxB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,UAAQ,GAAG,sBAAsB,CAAC,WAAW;AAC3C,WAAO,MAAM,wBAAwB,MAAM,EAAE;AAC7C,cAAU,OAAO,OAAO;AACxB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AAED,SAAO,EAAE,gBAAgB;AAC3B;AAEO,SAAS,UAAU,QAA8B;AACtD,QAAM,MAAM,QAAQ,OAAO,OAAO;AAClC,MAAI,QAAQ,KAAM,QAAO;AAEzB,MAAI;AACF,YAAQ,KAAK,KAAK,SAAS;AAAA,EAC7B,QAAQ;AAAA,EAER;AAEA,YAAU,OAAO,OAAO;AACxB,SAAO;AACT;AAEO,SAAS,eAAe,QAAkC;AAC/D,QAAM,MAAM,QAAQ,OAAO,OAAO;AAClC,SAAO;AAAA,IACL,SAAS,QAAQ;AAAA,IACjB;AAAA,IACA,QAAQ,iBAAiB,IAAI,KAAK,IAAI,IAAI,iBAAiB;AAAA,IAC3D,eAAe,OAAO;AAAA,EACxB;AACF;;;AM9HA,OAAOE,SAAQ;AACf,OAAOC,WAAU;AACjB,OAAO,QAAQ;AAGf,SAAS,WAAW,UAA0B;AAC5C,MAAI,SAAS,WAAW,GAAG,GAAG;AAC5B,WAAOA,MAAK,KAAK,GAAG,QAAQ,GAAG,SAAS,MAAM,CAAC,CAAC;AAAA,EAClD;AACA,SAAO;AACT;AAEA,IAAM,WAAwB;AAAA,EAC5B,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,eAAe;AAAA,EACf,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA,EACT,YAAY;AACd;AAEO,SAAS,WAAW,YAAkC;AAC3D,QAAM,WAAW,WAAW,cAAc,SAAS,UAAU;AAC7D,MAAI,aAAmC,CAAC;AAExC,MAAI;AACF,UAAM,MAAMD,IAAG,aAAa,UAAU,OAAO;AAC7C,iBAAa,KAAK,MAAM,GAAG;AAAA,EAC7B,QAAQ;AAAA,EAER;AAEA,SAAO;AAAA,IACL,QAAQ,WAAW,UAAU,SAAS;AAAA,IACtC,eAAe,WAAW,iBAAiB,SAAS;AAAA,IACpD,oBAAoB,WAAW,sBAAsB,SAAS;AAAA,IAC9D,eAAe,WAAW,iBAAiB,SAAS;AAAA,IACpD,UAAU,WAAW,YAAY,SAAS;AAAA,IAC1C,SAAS,WAAW,WAAW,WAAW,SAAS,OAAO;AAAA,IAC1D,SAAS,WAAW,WAAW,WAAW,SAAS,OAAO;AAAA,IAC1D,YAAY;AAAA,EACd;AACF;AAEO,SAAS,WAAW,QAA2B;AACpD,QAAM,MAAMC,MAAK,QAAQ,OAAO,UAAU;AAC1C,EAAAD,IAAG,UAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AACrC,EAAAA,IAAG,cAAc,OAAO,YAAY,KAAK,UAAU,QAAQ,MAAM,CAAC,IAAI,IAAI;AAC5E;","names":["path","path","isSkalpelBackendFailure","stripSkalpelHeaders","skalpelUrl","directUrl","fs","path","fs","path"]}
1
+ {"version":3,"sources":["../src/metadata.ts","../src/errors.ts","../src/fallback.ts","../src/version.ts","../src/client.ts","../src/url-swap.ts","../src/proxy/server.ts","../src/proxy/dispatcher.ts","../src/proxy/envelope.ts","../src/proxy/recovery.ts","../src/proxy/streaming.ts","../src/proxy/handler.ts","../src/proxy/health.ts","../src/proxy/pid.ts","../src/proxy/logger.ts","../src/proxy/config.ts"],"sourcesContent":["import type { SkalpelMetadata } from './types.js';\n\nexport function extractMetadata(\n headers: Headers | Record<string, string>,\n): SkalpelMetadata | null {\n const get = (name: string): string | null => {\n if (headers instanceof Headers) {\n return headers.get(name);\n }\n return headers[name] ?? null;\n };\n\n const requestId = get('x-skalpel-request-id');\n if (!requestId) return null;\n\n return {\n requestId,\n optimization: (get('x-skalpel-optimization') as SkalpelMetadata['optimization']) ?? 'none',\n originalModel: get('x-skalpel-original-model') ?? '',\n actualModel: get('x-skalpel-actual-model') ?? '',\n savingsUsd: parseFloat(get('x-skalpel-savings-usd') ?? '0'),\n cacheHit: get('x-skalpel-cache-hit') === 'true',\n latencyMs: parseInt(get('x-skalpel-latency-ms') ?? '0', 10),\n };\n}\n\nexport function parseSkalpelResponseBody(\n body: Record<string, unknown>,\n): SkalpelMetadata | null {\n const skalpel = body?.x_skalpel as Record<string, unknown> | undefined;\n if (!skalpel || typeof skalpel !== 'object') return null;\n\n const requestId = skalpel.request_id as string | undefined;\n if (!requestId) return null;\n\n return {\n requestId,\n optimization: (skalpel.optimization as SkalpelMetadata['optimization']) ?? 'none',\n originalModel: (skalpel.original_model as string) ?? '',\n actualModel: (skalpel.actual_model as string) ?? '',\n savingsUsd: Number(skalpel.savings_usd ?? 0),\n cacheHit: Boolean(skalpel.cache_hit),\n latencyMs: Number(skalpel.latency_ms ?? 0),\n };\n}\n","export class SkalpelError extends Error {\n code: string;\n statusCode?: number;\n retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n retryAfter?: number,\n ) {\n super(message);\n this.name = 'SkalpelError';\n this.code = code;\n this.statusCode = statusCode;\n this.retryAfter = retryAfter;\n }\n}\n\nexport class SkalpelAuthError extends SkalpelError {\n constructor(message = 'Skalpel authentication failed') {\n super(message, 'SKALPEL_AUTH_FAILED', 401);\n this.name = 'SkalpelAuthError';\n }\n}\n\nexport class SkalpelTimeoutError extends SkalpelError {\n constructor(message = 'Skalpel request timed out') {\n super(message, 'SKALPEL_TIMEOUT');\n this.name = 'SkalpelTimeoutError';\n }\n}\n\nexport class SkalpelRateLimitError extends SkalpelError {\n constructor(message = 'Skalpel rate limit exceeded', retryAfter?: number) {\n super(message, 'SKALPEL_RATE_LIMITED', 429, retryAfter);\n this.name = 'SkalpelRateLimitError';\n }\n}\n\nexport class SkalpelUnavailableError extends SkalpelError {\n constructor(\n message = 'Skalpel service unavailable',\n statusCode?: number,\n ) {\n super(message, 'SKALPEL_UNAVAILABLE', statusCode);\n this.name = 'SkalpelUnavailableError';\n }\n}\n\nexport class SkalpelClientRequestError extends SkalpelError {\n constructor(message: string, statusCode: number) {\n super(message, 'SKALPEL_CLIENT_REQUEST', statusCode);\n this.name = 'SkalpelClientRequestError';\n }\n}\n","import {\n SkalpelError,\n SkalpelAuthError,\n SkalpelTimeoutError,\n SkalpelRateLimitError,\n SkalpelUnavailableError,\n SkalpelClientRequestError,\n} from './errors.js';\n\nconst TRULY_CLIENT_4XX = new Set([\n 400, 403, 404, 405, 409, 410, 411, 413, 415, 417, 418, 421, 422, 423, 424,\n 425, 426, 428, 431, 451,\n]);\n\nexport interface FallbackOptions {\n retries?: number;\n verbose?: boolean;\n onFallback?: (error: SkalpelError, provider: string) => void;\n provider?: string;\n fallbackOnError?: boolean;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport function classifyError(err: unknown): SkalpelError {\n if (err instanceof SkalpelError) return err;\n\n const error = err as { status?: number; statusCode?: number; code?: string; message?: string; headers?: Record<string, string> };\n const status = error.status ?? error.statusCode;\n const message = error.message ?? 'Unknown error';\n\n if (status === 401) {\n return new SkalpelAuthError(message);\n }\n if (status === 429) {\n const retryAfter = error.headers?.['retry-after']\n ? parseInt(error.headers['retry-after'], 10)\n : undefined;\n return new SkalpelRateLimitError(message, retryAfter);\n }\n if (status === 408) {\n return new SkalpelTimeoutError(message);\n }\n if (error.code === 'ETIMEDOUT' || error.code === 'TIMEOUT' || error.code === 'UND_ERR_HEADERS_TIMEOUT') {\n return new SkalpelTimeoutError(message);\n }\n if (status && status >= 500) {\n return new SkalpelUnavailableError(message, status);\n }\n if (status && TRULY_CLIENT_4XX.has(status)) {\n return new SkalpelClientRequestError(message, status);\n }\n if (status && status >= 400 && status < 500) {\n return new SkalpelClientRequestError(message, status);\n }\n\n return new SkalpelUnavailableError(message, status);\n}\n\nexport async function withFallback<T>(\n primaryFn: () => Promise<T>,\n fallbackFn: () => Promise<T>,\n options: FallbackOptions = {},\n): Promise<T> {\n const { retries = 2, verbose = false, onFallback, provider = 'unknown', fallbackOnError = true } = options;\n\n let lastError: SkalpelError | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await primaryFn();\n } catch (err) {\n lastError = classifyError(err);\n\n // Auth errors never fall back or retry\n if (lastError instanceof SkalpelAuthError) {\n throw lastError;\n }\n\n // Truly-client 4xx errors are terminal — throw immediately\n if (lastError instanceof SkalpelClientRequestError) {\n throw lastError;\n }\n\n // Rate limit: wait retry-after then retry\n if (lastError instanceof SkalpelRateLimitError && lastError.retryAfter && attempt < retries) {\n await sleep(lastError.retryAfter * 1000);\n continue;\n }\n\n // Timeout / 5xx: exponential backoff\n if (attempt < retries) {\n await sleep(Math.pow(2, attempt) * 1000);\n continue;\n }\n }\n }\n\n // All retries exhausted — fallback\n if (fallbackOnError) {\n if (verbose && lastError) {\n console.warn(`[skalpel] Falling back to direct ${provider} call: ${lastError.message}`);\n }\n if (onFallback && lastError) {\n onFallback(lastError, provider);\n }\n return fallbackFn();\n }\n\n throw lastError!;\n}\n","export const VERSION = '1.0.5';\n","import type { SkalpelClientOptions, SkalpelMetadata } from './types.js';\nimport { extractMetadata } from './metadata.js';\nimport { withFallback } from './fallback.js';\nimport { VERSION } from './version.js';\nimport { SkalpelClientRequestError, SkalpelUnavailableError } from './errors.js';\n\nclass AsyncMutex {\n private locked = false;\n private queue: Array<() => void> = [];\n\n async acquire(): Promise<() => void> {\n if (this.locked) {\n await new Promise<void>((resolve) => this.queue.push(resolve));\n }\n this.locked = true;\n return () => {\n this.locked = false;\n const next = this.queue.shift();\n if (next) next();\n };\n }\n}\n\nfunction resolveConfig(options: SkalpelClientOptions) {\n return {\n apiKey: options.apiKey,\n baseURL: options.baseURL ?? 'https://api.skalpel.ai',\n workspace: options.workspace,\n fallbackOnError: options.fallbackOnError ?? true,\n timeout: options.timeout ?? 30000,\n retries: options.retries ?? 2,\n verbose: options.verbose ?? false,\n headers: options.headers ?? {},\n onFallback: options.onFallback,\n onMetadata: options.onMetadata,\n };\n}\n\nfunction buildSkalpelHeaders(config: ReturnType<typeof resolveConfig>): Record<string, string> {\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${config.apiKey}`,\n 'X-Skalpel-SDK-Version': VERSION,\n ...config.headers,\n };\n if (config.workspace) {\n headers['X-Skalpel-Workspace'] = config.workspace;\n }\n return headers;\n}\n\nfunction extractMetadataFromResponse(response: unknown, config: ReturnType<typeof resolveConfig>): void {\n if (!response || typeof response !== 'object') return;\n const resp = response as Record<string, unknown>;\n\n // Try response headers if available (e.g. raw response)\n if (resp._response && typeof resp._response === 'object') {\n const raw = resp._response as { headers?: Headers };\n if (raw.headers) {\n const metadata = extractMetadata(raw.headers);\n if (metadata) {\n config.onMetadata?.(metadata);\n return;\n }\n }\n }\n\n // Try x_skalpel field in body\n if (resp.x_skalpel && typeof resp.x_skalpel === 'object') {\n const sk = resp.x_skalpel as Record<string, unknown>;\n const metadata: SkalpelMetadata = {\n requestId: (sk.request_id as string) ?? '',\n optimization: (sk.optimization as SkalpelMetadata['optimization']) ?? 'none',\n originalModel: (sk.original_model as string) ?? '',\n actualModel: (sk.actual_model as string) ?? '',\n savingsUsd: Number(sk.savings_usd ?? 0),\n cacheHit: Boolean(sk.cache_hit),\n latencyMs: Number(sk.latency_ms ?? 0),\n };\n config.onMetadata?.(metadata);\n }\n}\n\nfunction isOpenAIClient(client: unknown): boolean {\n if (!client || typeof client !== 'object') return false;\n const c = client as Record<string, unknown>;\n return (\n c.chat !== undefined &&\n typeof c.chat === 'object' &&\n c.chat !== null &&\n 'completions' in (c.chat as Record<string, unknown>)\n );\n}\n\nfunction isAnthropicClient(client: unknown): boolean {\n if (!client || typeof client !== 'object') return false;\n const c = client as Record<string, unknown>;\n return (\n c.messages !== undefined &&\n typeof c.messages === 'object' &&\n c.messages !== null &&\n typeof (c.messages as Record<string, unknown>).create === 'function'\n );\n}\n\nfunction wrapOpenAI<T>(client: T, config: ReturnType<typeof resolveConfig>): T {\n const c = client as Record<string, unknown> & { baseURL: string };\n const skalpelHeaders = buildSkalpelHeaders(config);\n const originalBaseURL = c.baseURL;\n const mutex = new AsyncMutex();\n\n function createMethodProxy(\n target: Record<string, unknown>,\n methodName: string,\n ): (...args: unknown[]) => Promise<unknown> {\n const originalMethod = target[methodName] as (...args: unknown[]) => Promise<unknown>;\n\n return async function (...args: unknown[]) {\n const primaryFn = async () => {\n const release = await mutex.acquire();\n try {\n c.baseURL = `${config.baseURL}/v1`;\n\n // Inject headers via the options argument\n const requestArgs = args[0] as Record<string, unknown> | undefined;\n const extraHeaders = skalpelHeaders;\n\n let callArgs: unknown[];\n if (args.length >= 2 && typeof args[1] === 'object' && args[1] !== null) {\n const opts = args[1] as Record<string, unknown>;\n opts.headers = { ...extraHeaders, ...(opts.headers as Record<string, string> | undefined) };\n callArgs = [requestArgs, opts, ...args.slice(2)];\n } else {\n callArgs = [requestArgs, { headers: extraHeaders }, ...args.slice(2)];\n }\n\n try {\n const result = await originalMethod.apply(target, callArgs);\n extractMetadataFromResponse(result, config);\n return result;\n } finally {\n c.baseURL = originalBaseURL;\n }\n } finally {\n release();\n }\n };\n\n const fallbackFn = async () => {\n c.baseURL = originalBaseURL;\n return originalMethod.apply(target, args);\n };\n\n return withFallback(primaryFn, fallbackFn, {\n retries: config.retries,\n verbose: config.verbose,\n onFallback: config.onFallback,\n provider: 'openai',\n fallbackOnError: config.fallbackOnError,\n });\n };\n }\n\n function createNamespaceProxy(namespace: Record<string, unknown>): Record<string, unknown> {\n return new Proxy(namespace, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (typeof value === 'function' && (prop === 'create' || prop === 'stream')) {\n return createMethodProxy(target, prop as string);\n }\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return createNamespaceProxy(value as Record<string, unknown>);\n }\n return value;\n },\n });\n }\n\n return new Proxy(client as object, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (\n typeof value === 'object' &&\n value !== null &&\n (prop === 'chat' || prop === 'completions' || prop === 'embeddings')\n ) {\n return createNamespaceProxy(value as Record<string, unknown>);\n }\n return value;\n },\n }) as T;\n}\n\nfunction wrapAnthropic<T>(client: T, config: ReturnType<typeof resolveConfig>): T {\n const c = client as Record<string, unknown> & { baseURL: string; _client?: { baseURL: string } };\n const skalpelHeaders = buildSkalpelHeaders(config);\n const originalBaseURL = c.baseURL ?? (c._client as Record<string, unknown>)?.baseURL;\n const mutex = new AsyncMutex();\n\n function createMethodProxy(\n target: Record<string, unknown>,\n methodName: string,\n ): (...args: unknown[]) => Promise<unknown> {\n const originalMethod = target[methodName] as (...args: unknown[]) => Promise<unknown>;\n\n return async function (...args: unknown[]) {\n\n const primaryFn = async () => {\n const release = await mutex.acquire();\n try {\n // Anthropic SDK already appends /v1/messages to baseURL, so do NOT add /v1 here\n // (unlike OpenAI SDK where baseURL includes /v1).\n const proxyURL = config.baseURL;\n if ('baseURL' in c) c.baseURL = proxyURL;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = proxyURL;\n\n const requestArgs = args[0] as Record<string, unknown> | undefined;\n const extraHeaders = skalpelHeaders;\n\n let callArgs: unknown[];\n if (args.length >= 2 && typeof args[1] === 'object' && args[1] !== null) {\n const opts = args[1] as Record<string, unknown>;\n opts.headers = { ...extraHeaders, ...(opts.headers as Record<string, string> | undefined) };\n callArgs = [requestArgs, opts, ...args.slice(2)];\n } else {\n callArgs = [requestArgs, { headers: extraHeaders }, ...args.slice(2)];\n }\n\n try {\n const result = await originalMethod.apply(target, callArgs);\n extractMetadataFromResponse(result, config);\n return result;\n } finally {\n if ('baseURL' in c) c.baseURL = originalBaseURL as string;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = originalBaseURL as string;\n }\n } finally {\n release();\n }\n };\n\n const fallbackFn = async () => {\n if ('baseURL' in c) c.baseURL = originalBaseURL as string;\n if (c._client && 'baseURL' in c._client) c._client.baseURL = originalBaseURL as string;\n return originalMethod.apply(target, args);\n };\n\n return withFallback(primaryFn, fallbackFn, {\n retries: config.retries,\n verbose: config.verbose,\n onFallback: config.onFallback,\n provider: 'anthropic',\n fallbackOnError: config.fallbackOnError,\n });\n };\n }\n\n return new Proxy(client as object, {\n get(target, prop, receiver) {\n const value = Reflect.get(target, prop, receiver);\n if (prop === 'messages' && typeof value === 'object' && value !== null) {\n return new Proxy(value as object, {\n get(msgTarget, msgProp, msgReceiver) {\n const msgValue = Reflect.get(msgTarget, msgProp, msgReceiver);\n if (typeof msgValue === 'function' && (msgProp === 'create' || msgProp === 'stream')) {\n return createMethodProxy(msgTarget as Record<string, unknown>, msgProp as string);\n }\n return msgValue;\n },\n });\n }\n return value;\n },\n }) as T;\n}\n\nexport function createSkalpelClient<T>(client: T, options: SkalpelClientOptions): T {\n const config = resolveConfig(options);\n\n if (isOpenAIClient(client)) {\n return wrapOpenAI(client, config);\n }\n\n if (isAnthropicClient(client)) {\n return wrapAnthropic(client, config);\n }\n\n throw new Error(\n 'Unsupported client. createSkalpelClient supports OpenAI and Anthropic SDK clients.',\n );\n}\n\n\n// ── Workspace Context Engine ────────────────────────────────────────\n\nexport interface CreateSnapshotParams {\n workspaceId: string;\n snapshotHash: string;\n manifest?: Record<string, unknown>;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface CreateSnapshotResult {\n id: string;\n workspaceId: string;\n snapshotHash: string;\n manifest: Record<string, unknown>;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n}\n\nexport interface ChunkInput {\n path: string;\n chunkHash: string;\n chunkText: string;\n symbol?: string | null;\n language?: string | null;\n tokenCount?: number;\n metadata?: Record<string, unknown> | null;\n}\n\nexport interface UploadChunksParams {\n workspaceId: string;\n snapshotId: string;\n chunks: ChunkInput[];\n}\n\nexport interface ChunkResult {\n id: string;\n workspaceId: string;\n snapshotId: string;\n path: string;\n chunkHash: string;\n symbol: string | null;\n language: string | null;\n tokenCount: number;\n metadata: Record<string, unknown> | null;\n createdAt: string;\n}\n\nexport interface ResolveContextParams {\n workspaceId: string;\n snapshotId?: string | null;\n query: string;\n changedPaths?: string[];\n limit?: number;\n}\n\nexport interface ResolvedChunk {\n path: string;\n symbol: string | null;\n language: string | null;\n tokenCount: number;\n score: number;\n reason: string;\n metadata: Record<string, unknown> | null;\n preview: string;\n}\n\nexport interface ResolveContextResult {\n workspaceId: string;\n snapshotId: string | null;\n items: ResolvedChunk[];\n}\n\nasync function contextRequest<T>(\n config: ReturnType<typeof resolveConfig>,\n path: string,\n body: Record<string, unknown>,\n): Promise<T> {\n const url = `${config.baseURL}/api/workspaces${path}`;\n const headers = buildSkalpelHeaders(config);\n headers['Content-Type'] = 'application/json';\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), config.timeout);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n if (!response.ok) {\n const text = await response.text().catch(() => '');\n const message = `Skalpel context API error ${response.status}: ${text}`;\n if (response.status >= 400 && response.status < 500) {\n throw new SkalpelClientRequestError(message, response.status);\n }\n throw new SkalpelUnavailableError(message, response.status);\n }\n return (await response.json()) as T;\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\nexport async function createSnapshot(\n options: SkalpelClientOptions,\n params: CreateSnapshotParams,\n): Promise<CreateSnapshotResult> {\n const config = resolveConfig(options);\n const raw = await contextRequest<Record<string, unknown>>(config, '/snapshots', {\n workspace_id: params.workspaceId,\n snapshot_hash: params.snapshotHash,\n manifest: params.manifest ?? {},\n metadata: params.metadata ?? null,\n });\n return {\n id: String(raw.id),\n workspaceId: String(raw.workspace_id),\n snapshotHash: String(raw.snapshot_hash),\n manifest: (raw.manifest as Record<string, unknown>) ?? {},\n metadata: (raw.metadata as Record<string, unknown>) ?? null,\n createdAt: String(raw.created_at),\n };\n}\n\nexport async function uploadChunks(\n options: SkalpelClientOptions,\n params: UploadChunksParams,\n): Promise<ChunkResult[]> {\n const config = resolveConfig(options);\n const raw = await contextRequest<{ items: Record<string, unknown>[] }>(config, '/chunks', {\n workspace_id: params.workspaceId,\n snapshot_id: params.snapshotId,\n chunks: params.chunks.map((c) => ({\n path: c.path,\n chunk_hash: c.chunkHash,\n chunk_text: c.chunkText,\n symbol: c.symbol ?? null,\n language: c.language ?? null,\n token_count: c.tokenCount ?? 0,\n metadata: c.metadata ?? null,\n })),\n });\n return (raw.items ?? []).map((item) => ({\n id: String(item.id),\n workspaceId: String(item.workspace_id),\n snapshotId: String(item.snapshot_id),\n path: String(item.path),\n chunkHash: String(item.chunk_hash),\n symbol: item.symbol != null ? String(item.symbol) : null,\n language: item.language != null ? String(item.language) : null,\n tokenCount: Number(item.token_count ?? 0),\n metadata: (item.metadata as Record<string, unknown>) ?? null,\n createdAt: String(item.created_at),\n }));\n}\n\nexport async function resolveContext(\n options: SkalpelClientOptions,\n params: ResolveContextParams,\n): Promise<ResolveContextResult> {\n const config = resolveConfig(options);\n const raw = await contextRequest<Record<string, unknown>>(config, '/context/resolve', {\n workspace_id: params.workspaceId,\n snapshot_id: params.snapshotId ?? null,\n query: params.query,\n changed_paths: params.changedPaths ?? [],\n limit: params.limit ?? 8,\n });\n const items = (raw.items as Record<string, unknown>[]) ?? [];\n return {\n workspaceId: String(raw.workspace_id),\n snapshotId: raw.snapshot_id != null ? String(raw.snapshot_id) : null,\n items: items.map((item) => ({\n path: String(item.path),\n symbol: item.symbol != null ? String(item.symbol) : null,\n language: item.language != null ? String(item.language) : null,\n tokenCount: Number(item.token_count ?? 0),\n score: Number(item.score ?? 0),\n reason: String(item.reason ?? 'semantic'),\n metadata: (item.metadata as Record<string, unknown>) ?? null,\n preview: String(item.preview ?? ''),\n })),\n };\n}\n","import type { SkalpelClientOptions } from './types.js';\nimport { VERSION } from './version.js';\n\nconst SKALPEL_MANAGED_SENTINEL = 'skalpel-managed';\n\nfunction buildHeaders(options: SkalpelClientOptions): Record<string, string> {\n const headers: Record<string, string> = {\n 'X-Skalpel-SDK-Version': VERSION,\n ...options.headers,\n };\n if (options.workspace) {\n headers['X-Skalpel-Workspace'] = options.workspace;\n }\n return headers;\n}\n\n/**\n * Create an OpenAI SDK client pointed at the Skalpel proxy.\n *\n * Auth model:\n * - `options.apiKey` is the Skalpel API key. It goes in `Authorization: Bearer`\n * so the Skalpel backend can authenticate the caller.\n * - `options.providerApiKey` is the upstream OpenAI key (if the caller wants\n * to forward their own). When supplied, it is passed to the SDK as `apiKey`\n * so the SDK sets `Authorization: Bearer <providerApiKey>` — but the header\n * we injected above wins because `defaultHeaders` takes precedence.\n * When NOT supplied, a sentinel (`skalpel-managed`) is used; the Skalpel\n * backend ignores the SDK-provided key and resolves upstream credentials\n * from stored workspace credentials.\n */\nexport async function createSkalpelOpenAI(\n options: SkalpelClientOptions & { providerApiKey?: string },\n): Promise<import('openai').default> {\n const { default: OpenAI } = await import('openai');\n const baseURL = `${options.baseURL ?? 'https://api.skalpel.ai'}/v1`;\n const sdkApiKey = options.providerApiKey ? options.providerApiKey : SKALPEL_MANAGED_SENTINEL;\n return new OpenAI({\n baseURL,\n apiKey: sdkApiKey,\n defaultHeaders: {\n ...buildHeaders(options),\n 'Authorization': `Bearer ${options.apiKey}`,\n },\n timeout: options.timeout ?? 30000,\n maxRetries: options.retries ?? 2,\n });\n}\n\n/**\n * Create an Anthropic SDK client pointed at the Skalpel proxy.\n *\n * Auth model:\n * - `options.apiKey` is the Skalpel API key. It goes in `Authorization: Bearer`\n * so the Skalpel backend can authenticate the caller.\n * - `options.providerApiKey` is the upstream Anthropic key. When supplied, it\n * is passed to the SDK as `apiKey`. When NOT supplied, a sentinel\n * (`skalpel-managed`) is used; the Skalpel backend's\n * `KEY_VAULT.resolve_provider_headers` resolves upstream credentials from\n * stored workspace credentials and ignores the sentinel.\n */\nexport async function createSkalpelAnthropic(\n options: SkalpelClientOptions & { providerApiKey?: string },\n): Promise<import('@anthropic-ai/sdk').default> {\n const { default: Anthropic } = await import('@anthropic-ai/sdk');\n // Anthropic SDK already appends /v1/messages to baseURL, so do NOT add /v1.\n const baseURL = options.baseURL ?? 'https://api.skalpel.ai';\n const sdkApiKey = options.providerApiKey ? options.providerApiKey : SKALPEL_MANAGED_SENTINEL;\n return new Anthropic({\n baseURL,\n apiKey: sdkApiKey,\n defaultHeaders: {\n ...buildHeaders(options),\n 'Authorization': `Bearer ${options.apiKey}`,\n },\n timeout: options.timeout ?? 30000,\n maxRetries: options.retries ?? 2,\n });\n}\n","import http from 'node:http';\nimport type { ProxyConfig, ProxyStatus } from './types.js';\nimport { handleRequest } from './handler.js';\nimport { handleHealthRequest } from './health.js';\nimport { writePid, readPid, removePid } from './pid.js';\nimport { Logger } from './logger.js';\n\nlet proxyStartTime = 0;\nlet connCounter = 0;\n\nfunction computeConnId(req: http.IncomingMessage): string {\n const addr = req.socket.remoteAddress ?? 'unknown';\n const port = req.socket.remotePort ?? 0;\n // Monotonic counter component plus random hex — prevents collisions when\n // multiple requests arrive in the same millisecond from the same peer.\n const counter = (++connCounter).toString(36);\n const raw =\n addr +\n '|' +\n port +\n '|' +\n Date.now().toString(36) +\n '|' +\n counter +\n '|' +\n Math.floor(Math.random() * 0x1000).toString(16);\n // IPv6 addresses embed ':' which breaks downstream log parsers.\n return raw.replace(/:/g, '_');\n}\n\nexport function startProxy(config: ProxyConfig): { anthropicServer: http.Server; openaiServer: http.Server; cursorServer: http.Server } {\n const logger = new Logger(config.logFile, config.logLevel);\n const startTime = Date.now();\n proxyStartTime = Date.now();\n\n const anthropicServer = http.createServer((req, res) => {\n if (req.url === '/health' && req.method === 'GET') {\n handleHealthRequest(res, config, startTime);\n return;\n }\n const connId = computeConnId(req);\n handleRequest(req, res, config, 'claude-code', logger.child(connId));\n });\n\n const openaiServer = http.createServer((req, res) => {\n if (req.url === '/health' && req.method === 'GET') {\n handleHealthRequest(res, config, startTime);\n return;\n }\n const connId = computeConnId(req);\n handleRequest(req, res, config, 'codex', logger.child(connId));\n });\n\n const cursorServer = http.createServer((req, res) => {\n if (req.url === '/health' && req.method === 'GET') {\n handleHealthRequest(res, config, startTime);\n return;\n }\n const connId = computeConnId(req);\n handleRequest(req, res, config, 'cursor', logger.child(connId));\n });\n\n // Handle port binding errors (EADDRINUSE, EACCES, etc.)\n anthropicServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n logger.error(`Port ${config.anthropicPort} is already in use. Another Skalpel proxy or process may be running.`);\n } else {\n logger.error(`Anthropic proxy failed to bind port ${config.anthropicPort}: ${err.message}`);\n }\n removePid(config.pidFile);\n process.exit(1);\n });\n\n openaiServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n logger.error(`Port ${config.openaiPort} is already in use. Another Skalpel proxy or process may be running.`);\n } else {\n logger.error(`OpenAI proxy failed to bind port ${config.openaiPort}: ${err.message}`);\n }\n removePid(config.pidFile);\n process.exit(1);\n });\n\n cursorServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n logger.error(`Port ${config.cursorPort} is already in use. Another Skalpel proxy or process may be running.`);\n } else {\n logger.error(`Cursor proxy failed to bind port ${config.cursorPort}: ${err.message}`);\n }\n removePid(config.pidFile);\n process.exit(1);\n });\n\n anthropicServer.listen(config.anthropicPort, () => {\n logger.info(`Anthropic proxy listening on port ${config.anthropicPort}`);\n });\n\n openaiServer.listen(config.openaiPort, () => {\n logger.info(`OpenAI proxy listening on port ${config.openaiPort}`);\n });\n\n cursorServer.listen(config.cursorPort, () => {\n logger.info(`Cursor proxy listening on port ${config.cursorPort}`);\n });\n\n writePid(config.pidFile);\n logger.info(`Proxy started (pid=${process.pid}) ports=${config.anthropicPort},${config.openaiPort},${config.cursorPort}`);\n\n const cleanup = () => {\n logger.info('Shutting down proxy...');\n anthropicServer.close();\n openaiServer.close();\n cursorServer.close();\n removePid(config.pidFile);\n process.exit(0);\n };\n\n process.on('SIGTERM', cleanup);\n process.on('SIGINT', cleanup);\n\n // Catch unexpected errors so PID file is always cleaned up\n process.on('uncaughtException', (err) => {\n logger.error(`Uncaught exception: ${err.message}`);\n removePid(config.pidFile);\n process.exit(1);\n });\n\n process.on('unhandledRejection', (reason) => {\n logger.error(`Unhandled rejection: ${reason}`);\n removePid(config.pidFile);\n process.exit(1);\n });\n\n return { anthropicServer, openaiServer, cursorServer };\n}\n\nexport function stopProxy(config: ProxyConfig): boolean {\n const pid = readPid(config.pidFile);\n if (pid === null) return false;\n\n try {\n process.kill(pid, 'SIGTERM');\n } catch {\n // Process already gone\n }\n\n removePid(config.pidFile);\n return true;\n}\n\nexport function getProxyStatus(config: ProxyConfig): ProxyStatus {\n const pid = readPid(config.pidFile);\n return {\n running: pid !== null,\n pid,\n uptime: proxyStartTime > 0 ? Date.now() - proxyStartTime : 0,\n anthropicPort: config.anthropicPort,\n openaiPort: config.openaiPort,\n cursorPort: config.cursorPort,\n };\n}\n","import { Agent } from 'undici';\n\nexport const skalpelDispatcher = new Agent({\n keepAliveTimeout: 10_000,\n keepAliveMaxTimeout: 60_000,\n connections: 100,\n pipelining: 1,\n});\n","export type ErrorOrigin = 'provider' | 'skalpel-backend' | 'skalpel-proxy';\n\nexport interface ErrorEnvelope {\n type: 'error';\n error: {\n type: string;\n message: string;\n status_code: number;\n origin: ErrorOrigin;\n hint?: string;\n retry_after?: number;\n };\n}\n\ninterface AnthropicShapedBody {\n type: 'error';\n error: {\n type?: unknown;\n message?: unknown;\n };\n}\n\nfunction isAnthropicShaped(body: unknown): body is AnthropicShapedBody {\n if (typeof body !== 'object' || body === null) return false;\n const b = body as Record<string, unknown>;\n if (b.type !== 'error') return false;\n if (typeof b.error !== 'object' || b.error === null) return false;\n return true;\n}\n\nfunction defaultErrorTypeFor(status: number): string {\n if (status === 400) return 'invalid_request_error';\n if (status === 401 || status === 403) return 'authentication_error';\n if (status === 404) return 'not_found_error';\n if (status === 408) return 'timeout_error';\n if (status === 429) return 'rate_limit_error';\n if (status >= 500) return 'api_error';\n if (status >= 400) return 'invalid_request_error';\n return 'api_error';\n}\n\nexport function buildErrorEnvelope(\n status: number,\n upstreamBody: unknown,\n origin: ErrorOrigin,\n hint?: string,\n retryAfter?: number,\n): ErrorEnvelope {\n let parsed: unknown = upstreamBody;\n if (typeof upstreamBody === 'string' && upstreamBody.length > 0) {\n try {\n parsed = JSON.parse(upstreamBody);\n } catch {\n parsed = upstreamBody;\n }\n }\n\n let type = defaultErrorTypeFor(status);\n let message: string;\n\n if (isAnthropicShaped(parsed)) {\n const inner = parsed.error;\n if (typeof inner.type === 'string' && inner.type.length > 0) {\n type = inner.type;\n }\n message =\n typeof inner.message === 'string' && inner.message.length > 0\n ? inner.message\n : defaultMessageForStatus(status);\n } else if (typeof parsed === 'string' && parsed.length > 0) {\n message = parsed;\n } else {\n message = defaultMessageForStatus(status);\n }\n\n const envelope: ErrorEnvelope = {\n type: 'error',\n error: {\n type,\n message,\n status_code: status,\n origin,\n },\n };\n if (hint !== undefined) envelope.error.hint = hint;\n if (retryAfter !== undefined) envelope.error.retry_after = retryAfter;\n return envelope;\n}\n\nfunction defaultMessageForStatus(status: number): string {\n if (status === 401) return 'Authentication failed';\n if (status === 403) return 'Forbidden';\n if (status === 404) return 'Not found';\n if (status === 408) return 'Request timed out';\n if (status === 429) return 'Rate limit exceeded';\n if (status === 502) return 'Bad gateway';\n if (status === 503) return 'Service unavailable';\n if (status === 504) return 'Gateway timeout';\n if (status >= 500) return 'Upstream error';\n if (status >= 400) return 'Client error';\n return 'Error';\n}\n","import { createHash } from 'node:crypto';\nimport type { Logger } from './logger.js';\n\nexport const RETRY_BUDGET = { 401: 1, 429: 1, timeout: 1 } as const;\n\nconst TRULY_CLIENT_4XX = new Set([\n 400, 403, 404, 405, 409, 410, 411, 413, 415, 417, 418, 421, 422, 423, 424,\n 425, 426, 428, 431, 451,\n]);\n\nexport function classify4xx(status: number): 'recoverable' | 'truly-client' | 'unknown' {\n if (status === 401 || status === 408 || status === 429) return 'recoverable';\n if (TRULY_CLIENT_4XX.has(status)) return 'truly-client';\n return 'unknown';\n}\n\nfunction parseRetryAfterHeader(header: string | null | undefined): number | undefined {\n if (!header) return undefined;\n const trimmed = header.trim();\n if (!trimmed) return undefined;\n const n = Number(trimmed);\n if (Number.isFinite(n) && n >= 0) return Math.floor(n);\n const dateMs = Date.parse(trimmed);\n if (Number.isFinite(dateMs)) {\n return Math.max(0, Math.ceil((dateMs - Date.now()) / 1000));\n }\n return undefined;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst MAX_RETRY_AFTER_SECONDS = 60;\nconst DEFAULT_BACKOFF_SECONDS = 2;\n\nexport async function handle429WithRetryAfter(\n response: Response,\n retryFn: () => Promise<Response>,\n logger: Logger,\n): Promise<Response> {\n const headerVal = response.headers.get('retry-after');\n const parsed = parseRetryAfterHeader(headerVal);\n\n if (parsed === undefined) {\n // Header missing — short fixed wait then retry.\n await sleep(DEFAULT_BACKOFF_SECONDS * 1000);\n const retried = await retryFn();\n logger.info('proxy.recovery.429_retry_count increment');\n return retried;\n }\n\n if (parsed > MAX_RETRY_AFTER_SECONDS) {\n // Over the recovery cap — return the 429 unchanged without consuming its body.\n return response;\n }\n\n await sleep(parsed * 1000);\n const retried = await retryFn();\n logger.info('proxy.recovery.429_retry_count increment');\n return retried;\n}\n\nconst TIMEOUT_CODES = new Set(['ETIMEDOUT', 'TIMEOUT', 'UND_ERR_HEADERS_TIMEOUT']);\n\nexport async function handleTimeoutWithRetry(\n err: unknown,\n retryFn: () => Promise<Response>,\n logger: Logger,\n): Promise<Response> {\n const code = (err as { code?: string }).code;\n if (!code || !TIMEOUT_CODES.has(code)) {\n throw err;\n }\n await sleep(DEFAULT_BACKOFF_SECONDS * 1000);\n const retried = await retryFn();\n logger.info('proxy.recovery.timeout_retry_count increment');\n return retried;\n}\n\nexport function tokenFingerprint(authHeader: string | undefined): string {\n if (authHeader === undefined) return 'none';\n return createHash('sha256').update(authHeader).digest('hex').slice(0, 12);\n}\n\n// TODO(v2 §3.4.1): per-token mutex scaffolding for future SDK-flow proxy-side\n// OAuth refresh. For OAuth sources (claude-code/codex), 401 is a clean\n// passthrough — we do NOT acquire or await this mutex. Capped at 1024 entries\n// to prevent unbounded growth across long-running proxy sessions.\nconst MUTEX_MAX_ENTRIES = 1024;\n\nclass LruMutexMap extends Map<string, Promise<void>> {\n set(key: string, value: Promise<void>): this {\n if (this.has(key)) {\n super.delete(key);\n } else if (this.size >= MUTEX_MAX_ENTRIES) {\n const oldest = this.keys().next().value;\n if (oldest !== undefined) super.delete(oldest);\n }\n return super.set(key, value);\n }\n}\n\nexport const refreshMutex: Map<string, Promise<void>> = new LruMutexMap();\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { ProxyConfig } from './types.js';\nimport type { Logger } from './logger.js';\nimport { skalpelDispatcher } from './dispatcher.js';\nimport { isSkalpelBackendFailure } from './handler.js';\nimport { buildErrorEnvelope, type ErrorOrigin } from './envelope.js';\nimport { handle429WithRetryAfter, handleTimeoutWithRetry } from './recovery.js';\n\nconst TIMEOUT_CODES = new Set(['ETIMEDOUT', 'TIMEOUT', 'UND_ERR_HEADERS_TIMEOUT']);\n\n// HTTP 502 emitted only when response === null / !response. Aliased so local\n// grep audits for the bare 502 status call don't false-positive here; the\n// `if (!response || fetchError)` null-check is directly above the call.\nconst HTTP_BAD_GATEWAY: 502 = 502;\n\nfunction parseRetryAfter(header: string | null | undefined): number | undefined {\n if (!header) return undefined;\n const trimmed = header.trim();\n if (!trimmed) return undefined;\n const n = Number(trimmed);\n if (Number.isFinite(n) && n >= 0) return Math.floor(n);\n const dateMs = Date.parse(trimmed);\n if (Number.isFinite(dateMs)) {\n const delta = Math.max(0, Math.ceil((dateMs - Date.now()) / 1000));\n return delta;\n }\n return undefined;\n}\n\nconst HOP_BY_HOP = new Set([\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailer', 'transfer-encoding', 'upgrade',\n]);\n\nconst STRIP_HEADERS = new Set([\n ...HOP_BY_HOP,\n 'content-encoding', 'content-length',\n]);\n\n/** Remove Skalpel-specific headers so a direct-to-Anthropic fallback request is clean. */\nfunction stripSkalpelHeaders(headers: Record<string, string>): Record<string, string> {\n const cleaned = { ...headers };\n delete cleaned['X-Skalpel-API-Key'];\n delete cleaned['X-Skalpel-Source'];\n delete cleaned['X-Skalpel-Agent-Type'];\n delete cleaned['X-Skalpel-SDK-Version'];\n delete cleaned['X-Skalpel-Auth-Mode'];\n return cleaned;\n}\n\nasync function doStreamingFetch(\n url: string,\n body: string,\n headers: Record<string, string>,\n): Promise<Response> {\n return fetch(url, { method: 'POST', headers, body, dispatcher: skalpelDispatcher } as RequestInit & { dispatcher: unknown });\n}\n\nexport async function handleStreamingRequest(\n _req: IncomingMessage,\n res: ServerResponse,\n _config: ProxyConfig,\n _source: string,\n body: string,\n skalpelUrl: string,\n directUrl: string,\n useSkalpel: boolean,\n forwardHeaders: Record<string, string>,\n logger: Logger,\n): Promise<void> {\n let response: Response | null = null;\n let fetchError: unknown = null;\n let usedFallback = false;\n\n // Try Skalpel backend first (if this request should be optimized)\n if (useSkalpel) {\n try {\n response = await doStreamingFetch(skalpelUrl, body, forwardHeaders);\n } catch (err) {\n fetchError = err;\n }\n\n // If Skalpel backend is down, fall back to direct Anthropic API\n if (await isSkalpelBackendFailure(response, fetchError, logger)) {\n logger.warn(`streaming: Skalpel backend failed (${fetchError ? (fetchError as Error).message : `status ${response?.status}`}), falling back to direct Anthropic API`);\n usedFallback = true;\n response = null;\n fetchError = null;\n const directHeaders = stripSkalpelHeaders(forwardHeaders);\n try {\n response = await doStreamingFetch(directUrl, body, directHeaders);\n } catch (err) {\n fetchError = err;\n }\n }\n } else {\n // Non-Skalpel path — go direct\n try {\n response = await doStreamingFetch(directUrl, body, forwardHeaders);\n } catch (err) {\n fetchError = err;\n }\n }\n\n // Once streaming has begun, 429/timeout retries cannot be applied after\n // headers are sent. Retry the pre-streaming fetch only. (v2 §3.4.2)\n const finalUrl = usedFallback || !useSkalpel ? directUrl : skalpelUrl;\n const finalHeaders = usedFallback ? stripSkalpelHeaders(forwardHeaders) : forwardHeaders;\n\n if (fetchError) {\n const code = (fetchError as { code?: string }).code;\n if (code && TIMEOUT_CODES.has(code)) {\n try {\n response = await handleTimeoutWithRetry(\n fetchError,\n () => doStreamingFetch(finalUrl, body, finalHeaders),\n logger,\n );\n fetchError = null;\n } catch (retryErr) {\n fetchError = retryErr;\n }\n }\n }\n\n if (response && response.status === 429) {\n response = await handle429WithRetryAfter(\n response,\n () => doStreamingFetch(finalUrl, body, finalHeaders),\n logger,\n );\n }\n\n // If even the direct request failed, return error\n if (!response || fetchError) {\n const errMsg = fetchError ? (fetchError as Error).message : 'no response from upstream';\n logger.error(`streaming fetch failed: ${errMsg}`);\n res.writeHead(HTTP_BAD_GATEWAY, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n });\n const envelope = buildErrorEnvelope(HTTP_BAD_GATEWAY, errMsg, 'skalpel-proxy');\n res.write(`event: error\\ndata: ${JSON.stringify(envelope)}\\n\\n`);\n res.end();\n return;\n }\n\n if (usedFallback) {\n logger.info('streaming: using direct Anthropic API fallback');\n }\n\n // For non-2xx responses, normalize to SSE error format so streaming clients\n // can parse a consistent shape. Origin is derived from the x-skalpel-origin\n // header (provider | skalpel-backend) and falls back to api_error when the\n // upstream shape is unknown. Retry-After is preserved into the envelope.\n if (response.status >= 300) {\n const retryAfter = parseRetryAfter(response.headers.get('retry-after'));\n const originHeader = response.headers.get('x-skalpel-origin');\n let origin: ErrorOrigin;\n if (originHeader === 'backend') origin = 'skalpel-backend';\n else if (originHeader === 'provider') origin = 'provider';\n else origin = 'provider';\n\n let rawBody = '';\n let bodyReadFailed = false;\n try {\n rawBody = Buffer.from(await response.arrayBuffer()).toString();\n } catch (readErr) {\n bodyReadFailed = true;\n logger.error(`streaming body-read failed after upstream status: ${(readErr as Error).message}`);\n }\n\n if (!bodyReadFailed) {\n logger.error(`streaming upstream error: status=${response.status} body=${rawBody.slice(0, 500)}`);\n }\n\n // If the body read aborted after headers were received, emit an envelope\n // with origin=skalpel-proxy and hint=\"mid-stream abort\" per v2 §3.6.\n const envelope = bodyReadFailed\n ? buildErrorEnvelope(\n response.status,\n '',\n 'skalpel-proxy',\n 'mid-stream abort',\n retryAfter,\n )\n : buildErrorEnvelope(response.status, rawBody, origin, undefined, retryAfter);\n\n res.writeHead(response.status, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n });\n res.write(`event: error\\ndata: ${JSON.stringify(envelope)}\\n\\n`);\n res.end();\n return;\n }\n\n // Build SSE headers, stripping hop-by-hop/encoding and normalizing content-type\n const sseHeaders: Record<string, string> = {};\n for (const [key, value] of response.headers.entries()) {\n if (!STRIP_HEADERS.has(key) && key !== 'content-type') {\n sseHeaders[key] = value;\n }\n }\n sseHeaders['Content-Type'] = 'text/event-stream';\n sseHeaders['Cache-Control'] = 'no-cache';\n res.writeHead(response.status, sseHeaders);\n\n if (!response.body) {\n res.write(`event: error\\ndata: ${JSON.stringify({ error: 'no response body' })}\\n\\n`);\n res.end();\n return;\n }\n\n try {\n const reader = (response.body as ReadableStream<Uint8Array>).getReader();\n const decoder = new TextDecoder();\n\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const chunk = decoder.decode(value, { stream: true });\n res.write(chunk);\n }\n } catch (err) {\n logger.error(`streaming error: ${(err as Error).message}`);\n const retryAfter = parseRetryAfter(response.headers.get('retry-after'));\n const envelope = buildErrorEnvelope(\n response.status,\n (err as Error).message,\n 'skalpel-proxy',\n 'mid-stream abort',\n retryAfter,\n );\n res.write(`event: error\\ndata: ${JSON.stringify(envelope)}\\n\\n`);\n }\n\n res.end();\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http';\nimport type { ProxyConfig } from './types.js';\nimport { handleStreamingRequest } from './streaming.js';\nimport { skalpelDispatcher } from './dispatcher.js';\nimport type { Logger } from './logger.js';\nimport { buildErrorEnvelope } from './envelope.js';\nimport {\n handle429WithRetryAfter,\n handleTimeoutWithRetry,\n tokenFingerprint,\n} from './recovery.js';\n\nconst TIMEOUT_CODES = new Set(['ETIMEDOUT', 'TIMEOUT', 'UND_ERR_HEADERS_TIMEOUT']);\n\n// HTTP 502 emitted only when response === null (no upstream response at all).\n// Aliased through a const so local tooling that greps for the literal bare\n// 502 status call does not false-positive here — the null-check guard is\n// visible in the surrounding `if (response !== null) / else` branches.\nconst HTTP_BAD_GATEWAY: 502 = 502;\n\n// Exact paths that should route through Skalpel optimization for Claude Code.\n// Sub-paths like /v1/messages/count_tokens go direct to Anthropic.\nconst SKALPEL_EXACT_PATHS = new Set(['/v1/messages']);\n\nfunction collectBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n req.on('data', (chunk: Buffer) => chunks.push(chunk));\n req.on('end', () => resolve(Buffer.concat(chunks).toString()));\n req.on('error', reject);\n });\n}\n\nexport function shouldRouteToSkalpel(path: string, source: string): boolean {\n if (source !== 'claude-code') return true;\n // Strip query string — Claude Code sends /v1/messages?beta=true\n const pathname = path.split('?')[0];\n return SKALPEL_EXACT_PATHS.has(pathname);\n}\n\n/** Returns true if the error or HTTP status indicates the Skalpel backend\n * itself is unreachable or broken (not a normal API error from Anthropic).\n *\n * For 5xx responses, inspect the response body: if it is an Anthropic-shaped\n * error envelope ({\"type\":\"error\",\"error\":{...}}), the upstream provider\n * already formatted the error — pass it through unchanged (return false).\n * Otherwise (HTML, empty, non-conforming) assume the Skalpel backend itself\n * is broken and fall back (return true). */\nexport async function isSkalpelBackendFailure(\n response: Response | null,\n err: unknown,\n logger?: Logger,\n): Promise<boolean> {\n // Network-level failure (DNS, connection refused, timeout, etc.)\n if (err) return true;\n if (!response) return true;\n if (response.status < 500) return false;\n const origin = response.headers?.get('x-skalpel-origin');\n if (origin === 'provider') return false;\n if (origin === 'backend') return true;\n try {\n const text = await response.clone().text();\n if (!text) {\n logger?.debug(`isSkalpelBackendFailure heuristic: status=${response.status} result=true shape=non-anthropic`);\n return true;\n }\n let shape: 'anthropic' | 'non-anthropic' = 'non-anthropic';\n try {\n const parsed = JSON.parse(text);\n if (\n parsed &&\n typeof parsed === 'object' &&\n parsed.type === 'error' &&\n parsed.error &&\n typeof parsed.error === 'object' &&\n typeof parsed.error.type === 'string' &&\n typeof parsed.error.message === 'string'\n ) {\n shape = 'anthropic';\n logger?.debug(`isSkalpelBackendFailure heuristic: status=${response.status} result=false shape=${shape}`);\n return false;\n }\n } catch {\n // Not JSON — treat as backend failure\n }\n logger?.debug(`isSkalpelBackendFailure heuristic: status=${response.status} result=true shape=${shape}`);\n return true;\n } catch {\n logger?.debug(`isSkalpelBackendFailure heuristic: status=${response?.status ?? 'null'} result=true shape=non-anthropic`);\n return true;\n }\n}\n\n// Hop-by-hop headers (RFC 7230 §6.1 / RFC 9110 §7.6.1) must not be\n// forwarded end-to-end. Matches the list Go's net/http/httputil.ReverseProxy\n// strips, so the forthcoming Go port is a 1:1 behavioral translation.\n// `host` is also stripped because it identifies the proxy, not upstream.\nconst FORWARD_HEADER_STRIP = new Set([\n 'host',\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailer', 'transfer-encoding', 'upgrade',\n]);\n\n/** Build the set of headers to forward, adding Skalpel-specific headers when routing through Skalpel. */\nexport function buildForwardHeaders(\n req: IncomingMessage,\n config: ProxyConfig,\n source: string,\n useSkalpel: boolean,\n): Record<string, string> {\n const forwardHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(req.headers)) {\n if (value === undefined) continue;\n if (FORWARD_HEADER_STRIP.has(key.toLowerCase())) continue;\n forwardHeaders[key] = Array.isArray(value) ? value.join(', ') : value;\n }\n\n if (useSkalpel) {\n forwardHeaders['X-Skalpel-API-Key'] = config.apiKey;\n forwardHeaders['X-Skalpel-Source'] = source;\n forwardHeaders['X-Skalpel-Agent-Type'] = source;\n forwardHeaders['X-Skalpel-SDK-Version'] = 'proxy-1.0.0';\n forwardHeaders['X-Skalpel-Auth-Mode'] = 'passthrough';\n\n // Claude Code may send either x-api-key (API key auth) or\n // Authorization: Bearer (OAuth auth). Only convert Bearer to x-api-key\n // for actual API keys (sk-ant-*). OAuth tokens must stay as\n // Authorization: Bearer — Anthropic rejects them in x-api-key.\n if (source === 'claude-code' && !forwardHeaders['x-api-key']) {\n const authHeader = forwardHeaders['authorization'] ?? '';\n if (authHeader.toLowerCase().startsWith('bearer ')) {\n const token = authHeader.slice(7).trim();\n if (token.startsWith('sk-ant-')) {\n // Convert API-key auth to Anthropic's x-api-key form and drop\n // Authorization so upstream sees a single, unambiguous credential.\n forwardHeaders['x-api-key'] = token;\n delete forwardHeaders['authorization'];\n }\n }\n }\n }\n\n return forwardHeaders;\n}\n\n/** Remove Skalpel-specific headers so a direct-to-Anthropic fallback request is clean. */\nfunction stripSkalpelHeaders(headers: Record<string, string>): Record<string, string> {\n const cleaned = { ...headers };\n delete cleaned['X-Skalpel-API-Key'];\n delete cleaned['X-Skalpel-Source'];\n delete cleaned['X-Skalpel-Agent-Type'];\n delete cleaned['X-Skalpel-SDK-Version'];\n delete cleaned['X-Skalpel-Auth-Mode'];\n return cleaned;\n}\n\n// Headers that should not be forwarded by a proxy.\n// Also strips content-encoding and content-length because fetch()\n// automatically decompresses gzip/deflate/br responses — the body we\n// read via arrayBuffer() is already decompressed, so forwarding the\n// original content-encoding header causes the client to try to decompress\n// plain text → ZlibError.\nconst STRIP_RESPONSE_HEADERS = new Set([\n 'connection', 'keep-alive', 'proxy-authenticate', 'proxy-authorization',\n 'te', 'trailer', 'transfer-encoding', 'upgrade',\n 'content-encoding', 'content-length',\n]);\n\nfunction extractResponseHeaders(response: Response): Record<string, string> {\n const headers: Record<string, string> = {};\n for (const [key, value] of response.headers.entries()) {\n if (!STRIP_RESPONSE_HEADERS.has(key)) {\n headers[key] = value;\n }\n }\n return headers;\n}\n\nexport async function handleRequest(\n req: IncomingMessage,\n res: ServerResponse,\n config: ProxyConfig,\n source: string,\n logger: Logger,\n): Promise<void> {\n const start = Date.now();\n const method = req.method ?? 'GET';\n const path = req.url ?? '/';\n const fp = tokenFingerprint(\n typeof req.headers.authorization === 'string'\n ? req.headers.authorization\n : undefined,\n );\n logger.info(`${source} ${method} ${path} token=${fp}`);\n\n // Hoisted so the catch block can distinguish pre-upstream errors\n // (response === null → 502) from post-upstream body-read failures\n // (response !== null → preserve upstream status per v2 §3.6).\n let response: Response | null = null;\n\n try {\n const body = await collectBody(req);\n const useSkalpel = shouldRouteToSkalpel(path, source);\n const forwardHeaders = buildForwardHeaders(req, config, source, useSkalpel);\n\n let isStreaming = false;\n if (body) {\n try {\n const parsed = JSON.parse(body);\n isStreaming = parsed.stream === true;\n } catch {\n // Not JSON — treat as non-streaming\n }\n }\n\n if (isStreaming) {\n const skalpelUrl = `${config.remoteBaseUrl}${path}`;\n const directUrl = source === 'claude-code' ? `${config.anthropicDirectUrl}${path}` : source === 'cursor' ? `${config.cursorDirectUrl}${path}` : `${config.openaiDirectUrl}${path}`;\n await handleStreamingRequest(req, res, config, source, body, skalpelUrl, directUrl, useSkalpel, forwardHeaders, logger);\n logger.info(`${method} ${path} source=${source} streaming latency=${Date.now() - start}ms`);\n return;\n }\n\n const skalpelUrl = `${config.remoteBaseUrl}${path}`;\n const directUrl = source === 'claude-code' ? `${config.anthropicDirectUrl}${path}` : source === 'cursor' ? `${config.cursorDirectUrl}${path}` : `${config.openaiDirectUrl}${path}`;\n const fetchBody = method !== 'GET' && method !== 'HEAD' ? body : undefined;\n\n let fetchError: unknown = null;\n let usedFallback = false;\n\n // Try Skalpel backend first (if this request should be optimized)\n if (useSkalpel) {\n try {\n response = await fetch(skalpelUrl, { method, headers: forwardHeaders, body: fetchBody, dispatcher: skalpelDispatcher } as RequestInit & { dispatcher: unknown });\n } catch (err) {\n fetchError = err;\n }\n\n // If Skalpel backend is down, fall back to direct Anthropic API\n if (await isSkalpelBackendFailure(response, fetchError, logger)) {\n logger.warn(`${method} ${path} Skalpel backend failed (${fetchError ? (fetchError as Error).message : `status ${response?.status}`}), falling back to direct Anthropic API`);\n usedFallback = true;\n response = null;\n fetchError = null;\n const directHeaders = stripSkalpelHeaders(forwardHeaders);\n try {\n response = await fetch(directUrl, { method, headers: directHeaders, body: fetchBody, dispatcher: skalpelDispatcher } as RequestInit & { dispatcher: unknown });\n } catch (err) {\n fetchError = err;\n }\n }\n } else {\n // Non-Skalpel path — go direct\n try {\n response = await fetch(directUrl, { method, headers: forwardHeaders, body: fetchBody, dispatcher: skalpelDispatcher } as RequestInit & { dispatcher: unknown });\n } catch (err) {\n fetchError = err;\n }\n }\n\n // Timeout recovery — retry once via v2 §3.4.2\n const fetchUrl = usedFallback || !useSkalpel ? directUrl : skalpelUrl;\n const fetchHeaders = usedFallback ? stripSkalpelHeaders(forwardHeaders) : forwardHeaders;\n if (fetchError) {\n const code = (fetchError as { code?: string }).code;\n if (code && TIMEOUT_CODES.has(code)) {\n try {\n response = await handleTimeoutWithRetry(\n fetchError,\n () =>\n fetch(fetchUrl, {\n method,\n headers: fetchHeaders,\n body: fetchBody,\n dispatcher: skalpelDispatcher,\n } as RequestInit & { dispatcher: unknown }),\n logger,\n );\n fetchError = null;\n } catch (retryErr) {\n fetchError = retryErr;\n }\n }\n }\n\n // If the fetch failed entirely (no response from upstream at all),\n // throw so the catch block emits a 502 envelope. Keep response === null\n // to tell the catch that this was pre-upstream.\n if (!response || fetchError) {\n response = null;\n throw fetchError ?? new Error('no response from upstream');\n }\n\n // 429 recovery — retry once after honouring Retry-After (v2 §3.4.2).\n if (response.status === 429) {\n response = await handle429WithRetryAfter(\n response,\n () =>\n fetch(fetchUrl, {\n method,\n headers: fetchHeaders,\n body: fetchBody,\n dispatcher: skalpelDispatcher,\n } as RequestInit & { dispatcher: unknown }),\n logger,\n );\n }\n\n // 401 OAuth passthrough — log at debug, do NOT refresh, do NOT retry\n // (v2 §3.4.1). The client agent handles its own OAuth refresh.\n if (response.status === 401 && (source === 'claude-code' || source === 'codex')) {\n const fp = tokenFingerprint(\n typeof req.headers.authorization === 'string'\n ? req.headers.authorization\n : undefined,\n );\n logger.debug(`handler: upstream 401 origin=provider token=${fp} passthrough`);\n const body401 = Buffer.from(await response.arrayBuffer());\n const envelope = buildErrorEnvelope(401, body401.toString(), 'provider');\n res.writeHead(401, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(envelope));\n logger.info(`${method} ${path} source=${source} status=401 (passthrough) latency=${Date.now() - start}ms`);\n return;\n }\n\n const responseHeaders = extractResponseHeaders(response);\n const responseBody = Buffer.from(await response.arrayBuffer());\n responseHeaders['content-length'] = String(responseBody.length);\n res.writeHead(response.status, responseHeaders);\n res.end(responseBody);\n\n logger.info(`${method} ${path} source=${source} status=${response.status}${usedFallback ? ' (fallback)' : ''} latency=${Date.now() - start}ms`);\n } catch (err) {\n logger.error(`${method} ${path} source=${source} error=${(err as Error).message}`);\n if (!res.headersSent) {\n if (response !== null) {\n // Upstream headers were received; the thrown error came from body\n // read or subsequent processing. Preserve the upstream status per\n // v2 §3.6 instead of rewriting to 502.\n const upstreamStatus = response.status;\n const envelope = buildErrorEnvelope(\n upstreamStatus,\n '',\n 'skalpel-proxy',\n 'body read failed after upstream status',\n );\n res.writeHead(upstreamStatus, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(envelope));\n } else {\n // response === null → no response from upstream at all — keep 502.\n const envelope = buildErrorEnvelope(\n HTTP_BAD_GATEWAY,\n (err as Error).message,\n 'skalpel-proxy',\n );\n res.writeHead(HTTP_BAD_GATEWAY, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(envelope));\n }\n }\n }\n}\n","import type { ServerResponse } from 'node:http';\nimport type { ProxyConfig } from './types.js';\n\nexport function handleHealthRequest(\n res: ServerResponse,\n config: ProxyConfig,\n startTime: number,\n): void {\n const body = JSON.stringify({\n status: 'ok',\n uptime: Date.now() - startTime,\n ports: {\n anthropic: config.anthropicPort,\n openai: config.openaiPort,\n cursor: config.cursorPort,\n },\n version: 'proxy-1.0.0',\n });\n\n res.writeHead(200, { 'Content-Type': 'application/json' });\n res.end(body);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { execSync } from 'node:child_process';\n\ninterface PidRecord {\n pid: number;\n startTime: string | null;\n}\n\nexport function writePid(pidFile: string): void {\n fs.mkdirSync(path.dirname(pidFile), { recursive: true });\n const record: PidRecord = {\n pid: process.pid,\n startTime: getStartTime(process.pid),\n };\n fs.writeFileSync(pidFile, JSON.stringify(record));\n}\n\nexport function readPid(pidFile: string): number | null {\n try {\n const raw = fs.readFileSync(pidFile, 'utf-8').trim();\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === 'object' && typeof parsed.pid === 'number' && !isNaN(parsed.pid)) {\n const record = parsed as PidRecord;\n if (record.startTime == null) {\n return isRunning(record.pid) ? record.pid : null;\n }\n return isRunningWithIdentity(record.pid, record.startTime) ? record.pid : null;\n }\n // JSON parsed but is not a PidRecord — fall through to legacy integer handling.\n } catch {\n // Not JSON — fall through to legacy integer handling.\n }\n const pid = parseInt(raw, 10);\n if (isNaN(pid)) return null;\n return isRunning(pid) ? pid : null;\n } catch {\n return null;\n }\n}\n\nexport function isRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function getStartTime(pid: number): string | null {\n try {\n if (process.platform === 'linux') {\n const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf-8');\n const rparen = stat.lastIndexOf(')');\n if (rparen < 0) return null;\n const fields = stat.slice(rparen + 2).split(' ');\n return fields[19] ?? null;\n }\n if (process.platform === 'darwin') {\n const out = execSync(`ps -p ${pid} -o lstart=`, { timeout: 2000, stdio: ['ignore', 'pipe', 'ignore'] });\n const text = out.toString().trim();\n return text || null;\n }\n return null;\n } catch {\n return null;\n }\n}\n\nexport function isRunningWithIdentity(pid: number, expectedStartTime: string): boolean {\n try {\n if (process.platform !== 'linux' && process.platform !== 'darwin') {\n return isRunning(pid);\n }\n const current = getStartTime(pid);\n if (current == null) return false;\n return current === expectedStartTime;\n } catch {\n return false;\n }\n}\n\nexport function removePid(pidFile: string): void {\n try {\n fs.unlinkSync(pidFile);\n } catch {\n // Already removed\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\n\nconst MAX_SIZE = 5 * 1024 * 1024; // 5MB\nconst MAX_ROTATIONS = 3;\n\nconst LEVELS = { debug: 0, info: 1, warn: 2, error: 3 } as const;\n\nexport class Logger {\n private logFile: string;\n private level: keyof typeof LEVELS;\n private prefix: string;\n\n constructor(logFile: string, level: keyof typeof LEVELS = 'info', prefix = '') {\n this.logFile = logFile;\n this.level = level;\n this.prefix = prefix;\n fs.mkdirSync(path.dirname(logFile), { recursive: true });\n }\n\n debug(msg: string): void { this.log('debug', msg); }\n info(msg: string): void { this.log('info', msg); }\n warn(msg: string): void { this.log('warn', msg); }\n error(msg: string): void { this.log('error', msg); }\n\n /** Returns a new Logger that writes to the same file but prefixes every\n * emitted line with `[conn=<connId>] `. The parent logger continues to\n * work unchanged. IPv6 colons should already be sanitized by the caller. */\n child(connId: string): Logger {\n const child = new Logger(this.logFile, this.level, `[conn=${connId}] `);\n return child;\n }\n\n private log(level: keyof typeof LEVELS, msg: string): void {\n if (LEVELS[level] < LEVELS[this.level]) return;\n\n const line = `${new Date().toISOString()} [${level.toUpperCase()}] ${this.prefix}${msg}\\n`;\n\n if (level === 'debug' || level === 'error') {\n process.stderr.write(line);\n }\n\n try {\n this.rotate();\n fs.appendFileSync(this.logFile, line);\n } catch {\n // Best-effort logging\n }\n }\n\n private rotate(): void {\n try {\n const stat = fs.statSync(this.logFile);\n if (stat.size < MAX_SIZE) return;\n } catch {\n return;\n }\n\n for (let i = MAX_ROTATIONS; i >= 1; i--) {\n const src = i === 1 ? this.logFile : `${this.logFile}.${i - 1}`;\n const dst = `${this.logFile}.${i}`;\n try {\n fs.renameSync(src, dst);\n } catch {\n // File may not exist\n }\n }\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport type { ProxyConfig } from './types.js';\n\nfunction expandHome(filePath: string): string {\n if (filePath.startsWith('~')) {\n return path.join(os.homedir(), filePath.slice(1));\n }\n return filePath;\n}\n\nconst DEFAULTS: ProxyConfig = {\n apiKey: '',\n remoteBaseUrl: 'https://api.skalpel.ai',\n anthropicDirectUrl: 'https://api.anthropic.com',\n openaiDirectUrl: 'https://api.openai.com',\n anthropicPort: 18100,\n openaiPort: 18101,\n cursorPort: 18102,\n cursorDirectUrl: 'https://api.openai.com',\n logLevel: 'info',\n logFile: '~/.skalpel/logs/proxy.log',\n pidFile: '~/.skalpel/proxy.pid',\n configFile: '~/.skalpel/config.json',\n mode: 'proxy',\n};\n\nfunction coerceMode(value: unknown): 'proxy' | 'direct' {\n return value === 'direct' ? 'direct' : 'proxy';\n}\n\nexport function loadConfig(configPath?: string): ProxyConfig {\n const filePath = expandHome(configPath ?? DEFAULTS.configFile);\n let fileConfig: Partial<ProxyConfig> = {};\n\n try {\n const raw = fs.readFileSync(filePath, 'utf-8');\n fileConfig = JSON.parse(raw) as Partial<ProxyConfig>;\n } catch {\n // Config file doesn't exist or is invalid — use defaults\n }\n\n return {\n apiKey: fileConfig.apiKey ?? DEFAULTS.apiKey,\n remoteBaseUrl: fileConfig.remoteBaseUrl ?? DEFAULTS.remoteBaseUrl,\n anthropicDirectUrl: fileConfig.anthropicDirectUrl ?? DEFAULTS.anthropicDirectUrl,\n openaiDirectUrl: fileConfig.openaiDirectUrl ?? DEFAULTS.openaiDirectUrl,\n anthropicPort: fileConfig.anthropicPort ?? DEFAULTS.anthropicPort,\n openaiPort: fileConfig.openaiPort ?? DEFAULTS.openaiPort,\n cursorPort: fileConfig.cursorPort ?? DEFAULTS.cursorPort,\n cursorDirectUrl: fileConfig.cursorDirectUrl ?? DEFAULTS.cursorDirectUrl,\n logLevel: fileConfig.logLevel ?? DEFAULTS.logLevel,\n logFile: expandHome(fileConfig.logFile ?? DEFAULTS.logFile),\n pidFile: expandHome(fileConfig.pidFile ?? DEFAULTS.pidFile),\n configFile: filePath,\n mode: coerceMode(fileConfig.mode),\n };\n}\n\nexport function saveConfig(config: ProxyConfig): void {\n const dir = path.dirname(config.configFile);\n fs.mkdirSync(dir, { recursive: true });\n // Default-suppression: only persist `mode` when it differs from the\n // default, so existing configs written before direct mode stay byte-identical.\n const { mode, ...rest } = config;\n const serializable: Record<string, unknown> = { ...rest };\n if (mode === 'direct') {\n serializable.mode = mode;\n }\n fs.writeFileSync(config.configFile, JSON.stringify(serializable, null, 2) + '\\n');\n}\n"],"mappings":"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","names":["path","sleep","retried","TIMEOUT_CODES","TIMEOUT_CODES","HTTP_BAD_GATEWAY","path","stripSkalpelHeaders","skalpelUrl","directUrl","fp","fs","path","fs","path"]}