@cognisos/liminal 2.3.0 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/bin.js +2751 -533
  2. package/dist/bin.js.map +1 -1
  3. package/package.json +4 -2
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/version.ts","../src/commands/init.ts","../src/config/loader.ts","../src/config/paths.ts","../src/config/schema.ts","../src/ui/prompts.ts","../src/commands/login.ts","../src/auth/supabase.ts","../src/commands/logout.ts","../src/rsc/pipeline.ts","../src/proxy/completions.ts","../src/rsc/message-compressor.ts","../src/rsc/content-segmenter.ts","../src/rsc/learning.ts","../src/proxy/streaming.ts","../src/proxy/messages.ts","../src/proxy/anthropic-streaming.ts","../src/proxy/handler.ts","../src/proxy/server.ts","../src/daemon/logger.ts","../src/daemon/lifecycle.ts","../src/commands/start.ts","../src/commands/stop.ts","../src/commands/status.ts","../src/commands/summary.ts","../src/commands/config.ts","../src/commands/logs.ts","../src/bin.ts"],"sourcesContent":["declare const __VERSION__: string\nexport const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.2.1'\n\n// FIGlet-style \"LIMINAL\" banner\nconst BANNER_LINES = [\n ' ___ ___ _____ ______ ___ ________ ________ ___',\n '|\\\\ \\\\ |\\\\ \\\\|\\\\ _ \\\\ _ \\\\|\\\\ \\\\|\\\\ ___ \\\\|\\\\ __ \\\\|\\\\ \\\\',\n '\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\\\\\__\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\|__| \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ __ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\____\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\____',\n ' \\\\ \\\\_______\\\\ \\\\__\\\\ \\\\__\\\\ \\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\\\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\ \\\\_______\\\\',\n ' \\\\|_______|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__|\\\\|_______|',\n]\n\nexport function printBanner(): void {\n console.log()\n for (const line of BANNER_LINES) {\n console.log(line)\n }\n console.log()\n console.log(` v${VERSION} -- brought to you by Cognisos`)\n console.log()\n}\n","import { createInterface } from 'node:readline/promises'\nimport { stdin, stdout } from 'node:process'\nimport { existsSync, readFileSync, appendFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\nimport { saveConfig, ensureDirectories } from '../config/loader.js'\nimport { DEFAULTS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\nimport { printBanner } from '../version.js'\nimport { multiSelectPrompt, selectPrompt } from '../ui/prompts.js'\nimport { runAuthFlow } from './login.js'\nimport type { Tool } from '../types.js'\n\n// ─── Shell profile detection ─────────────────────────────────────────\n\ninterface ShellProfile {\n name: string\n path: string\n}\n\nfunction detectShellProfile(): ShellProfile | null {\n const shell = process.env.SHELL || ''\n const home = homedir()\n\n // Prefer the user's actual shell\n if (shell.endsWith('/zsh')) {\n const zshrc = join(home, '.zshrc')\n return { name: '~/.zshrc', path: zshrc }\n }\n\n if (shell.endsWith('/bash')) {\n // macOS uses .bash_profile, Linux uses .bashrc\n const bashProfile = join(home, '.bash_profile')\n if (existsSync(bashProfile)) {\n return { name: '~/.bash_profile', path: bashProfile }\n }\n return { name: '~/.bashrc', path: join(home, '.bashrc') }\n }\n\n // Fallback: check common files\n const candidates: ShellProfile[] = [\n { name: '~/.zshrc', path: join(home, '.zshrc') },\n { name: '~/.bashrc', path: join(home, '.bashrc') },\n { name: '~/.profile', path: join(home, '.profile') },\n ]\n\n for (const c of candidates) {\n if (existsSync(c.path)) return c\n }\n\n return null\n}\n\n/**\n * Build the export lines needed for the selected tools.\n */\nfunction getExportLines(tools: Tool[], port: number): string[] {\n const base = `http://127.0.0.1:${port}`\n const lines: string[] = []\n\n if (tools.includes('claude-code')) {\n lines.push(`export ANTHROPIC_BASE_URL=${base}`)\n }\n if (tools.includes('codex') || tools.includes('openai-compatible')) {\n lines.push(`export OPENAI_BASE_URL=${base}/v1`)\n }\n\n return lines\n}\n\n/**\n * Check if a line already exists in a file (avoids duplicate entries).\n */\nfunction lineExistsInFile(filePath: string, line: string): boolean {\n if (!existsSync(filePath)) return false\n try {\n const content = readFileSync(filePath, 'utf-8')\n return content.includes(line)\n } catch {\n return false\n }\n}\n\n/**\n * Append export lines to shell profile, with a Liminal comment header.\n */\nfunction appendToShellProfile(profile: ShellProfile, lines: string[]): void {\n const block = [\n '',\n '# Liminal — route AI tools through compression proxy',\n ...lines,\n ].join('\\n') + '\\n'\n\n appendFileSync(profile.path, block, 'utf-8')\n}\n\nexport async function initCommand(): Promise<void> {\n printBanner()\n console.log(' Welcome to Liminal -- Your Transparency & Context Partner')\n console.log()\n console.log(\" Let's start evolving.\")\n console.log()\n\n // ── Authenticate ──────────────────────────────────────────────\n const apiKey = await runAuthFlow()\n console.log()\n\n // ── Port selection (readline) ─────────────────────────────────\n const rl = createInterface({ input: stdin, output: stdout })\n let port: number\n\n try {\n const portInput = await rl.question(` Proxy port [${DEFAULTS.port}]: `)\n port = portInput.trim() ? parseInt(portInput.trim(), 10) : DEFAULTS.port\n if (isNaN(port) || port < 1 || port > 65535) {\n console.error('\\n Error: Invalid port number.')\n process.exit(1)\n }\n } finally {\n rl.close()\n }\n\n console.log()\n\n // ── Interactive prompts (raw mode) ──────────────────────────────\n const toolsResult = await multiSelectPrompt<Tool>({\n message: 'Which AI tools will you use with Liminal?',\n options: [\n { label: 'Claude Code', value: 'claude-code', default: true },\n { label: 'Codex', value: 'codex' },\n { label: 'Cursor', value: 'cursor' },\n { label: 'Other / OpenAI', value: 'openai-compatible' },\n ],\n })\n const tools: Tool[] = toolsResult ?? ['claude-code']\n\n console.log()\n\n const learnResult = await selectPrompt<boolean>({\n message: 'Learn from LLM responses?',\n options: [\n { label: 'Yes', value: true, description: 'Improve compression over time' },\n { label: 'No', value: false, description: 'Skip response learning' },\n ],\n defaultIndex: 0,\n })\n const learnFromResponses = learnResult ?? true\n\n console.log()\n\n // ── Save config ─────────────────────────────────────────────────\n const apiBaseUrl = DEFAULTS.apiBaseUrl\n ensureDirectories()\n saveConfig({\n apiKey,\n apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port,\n learnFromResponses,\n tools,\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n })\n\n console.log()\n console.log(` Configuration saved to ${CONFIG_FILE}`)\n console.log()\n\n // ── Shell auto-configuration ────────────────────────────────────\n const exportLines = getExportLines(tools, port)\n const hasCursor = tools.includes('cursor')\n\n if (exportLines.length > 0) {\n const profile = detectShellProfile()\n\n if (profile) {\n // Check if already configured\n const allExist = exportLines.every((line) => lineExistsInFile(profile.path, line))\n\n if (allExist) {\n console.log(` Shell already configured in ${profile.name}`)\n } else {\n const autoResult = await selectPrompt<boolean>({\n message: 'Configure shell automatically?',\n options: [\n { label: 'Yes', value: true, description: `Add to ${profile.name}` },\n { label: 'No', value: false, description: \"I'll set it up manually\" },\n ],\n defaultIndex: 0,\n })\n\n if (autoResult === true) {\n // Only append lines that don't already exist\n const newLines = exportLines.filter((line) => !lineExistsInFile(profile.path, line))\n if (newLines.length > 0) {\n appendToShellProfile(profile, newLines)\n }\n console.log()\n console.log(` Added to ${profile.name}:`)\n for (const line of exportLines) {\n console.log(` ${line}`)\n }\n console.log()\n console.log(` Run \\x1b[1msource ${profile.name}\\x1b[0m or restart your terminal to apply.`)\n } else {\n console.log()\n console.log(' Add these to your shell profile:')\n console.log()\n for (const line of exportLines) {\n console.log(` ${line}`)\n }\n }\n }\n } else {\n // No shell profile detected — show manual instructions\n console.log(' Add these to your shell profile:')\n console.log()\n for (const line of exportLines) {\n console.log(` ${line}`)\n }\n }\n }\n\n // Cursor requires manual GUI configuration\n if (hasCursor) {\n console.log()\n console.log(' Cursor setup (manual):')\n console.log(` Settings > Models > OpenAI API Base URL: http://127.0.0.1:${port}/v1`)\n }\n\n console.log()\n console.log(' Next step:')\n console.log(' liminal start')\n console.log()\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LIMINAL_DIR, CONFIG_FILE, LOG_DIR } from './paths.js'\nimport { DEFAULTS } from './schema.js'\nimport type { RSCConfig } from './schema.js'\n\n/**\n * Load config from ~/.liminal/config.json, merged with defaults and env var overrides.\n * Priority: env vars > config file > defaults\n */\nexport function loadConfig(): RSCConfig {\n let fileConfig: Partial<RSCConfig> = {}\n\n if (existsSync(CONFIG_FILE)) {\n try {\n const raw = readFileSync(CONFIG_FILE, 'utf-8')\n fileConfig = JSON.parse(raw)\n } catch {\n // Corrupted config file — fall through to defaults\n }\n }\n\n const merged: RSCConfig = {\n apiKey: fileConfig.apiKey ?? '',\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port: DEFAULTS.port,\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n learnFromResponses: DEFAULTS.learnFromResponses,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n tools: DEFAULTS.tools,\n ...fileConfig,\n }\n\n // Environment variable overrides\n if (process.env.LIMINAL_API_KEY) merged.apiKey = process.env.LIMINAL_API_KEY\n if (process.env.LIMINAL_API_URL) merged.apiBaseUrl = process.env.LIMINAL_API_URL\n if (process.env.LIMINAL_UPSTREAM_URL) merged.upstreamBaseUrl = process.env.LIMINAL_UPSTREAM_URL\n if (process.env.LIMINAL_ANTHROPIC_URL) merged.anthropicUpstreamUrl = process.env.LIMINAL_ANTHROPIC_URL\n if (process.env.LIMINAL_PORT) merged.port = parseInt(process.env.LIMINAL_PORT, 10)\n\n return merged\n}\n\n/**\n * Apply CLI flag overrides on top of loaded config.\n */\nexport function applyOverrides(\n config: RSCConfig,\n overrides: Partial<Pick<RSCConfig, 'port' | 'upstreamBaseUrl'>>,\n): RSCConfig {\n return { ...config, ...overrides }\n}\n\n/**\n * Save config to ~/.liminal/config.json. Creates ~/.liminal/ and ~/.liminal/logs/ if needed.\n */\nexport function saveConfig(config: Partial<RSCConfig>): void {\n ensureDirectories()\n\n let existing: Partial<RSCConfig> = {}\n if (existsSync(CONFIG_FILE)) {\n try {\n existing = JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'))\n } catch {\n // Overwrite corrupted file\n }\n }\n\n const merged = { ...existing, ...config }\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + '\\n', 'utf-8')\n}\n\n/**\n * Ensure ~/.liminal/ and ~/.liminal/logs/ directories exist.\n */\nexport function ensureDirectories(): void {\n if (!existsSync(LIMINAL_DIR)) mkdirSync(LIMINAL_DIR, { recursive: true })\n if (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true })\n // Ensure parent of config file exists\n const configDir = dirname(CONFIG_FILE)\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true })\n}\n\n/**\n * Check if a valid config file exists with an API key.\n */\nexport function isConfigured(): boolean {\n try {\n const config = loadConfig()\n return config.apiKey.length > 0\n } catch {\n return false\n }\n}\n\n/**\n * Mask an API key for display: show first 8 chars + last 4.\n */\nexport function maskApiKey(key: string): string {\n if (key.length <= 12) return '****'\n return key.slice(0, 8) + '...' + key.slice(-4)\n}\n","import { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const LIMINAL_DIR = join(homedir(), '.liminal')\nexport const CONFIG_FILE = join(LIMINAL_DIR, 'config.json')\nexport const PID_FILE = join(LIMINAL_DIR, 'liminal.pid')\nexport const LOG_DIR = join(LIMINAL_DIR, 'logs')\nexport const LOG_FILE = join(LOG_DIR, 'liminal.log')\n","export interface RSCConfig {\n apiKey: string\n apiBaseUrl: string\n upstreamBaseUrl: string\n anthropicUpstreamUrl: string\n port: number\n compressionThreshold: number\n compressRoles: string[]\n learnFromResponses: boolean\n latencyBudgetMs: number\n enabled: boolean\n tools: string[]\n}\n\nexport const DEFAULTS: Omit<RSCConfig, 'apiKey'> = {\n apiBaseUrl: 'https://rsc-platform-production.up.railway.app',\n upstreamBaseUrl: 'https://api.openai.com',\n anthropicUpstreamUrl: 'https://api.anthropic.com',\n port: 3141,\n compressionThreshold: 100,\n compressRoles: ['user'],\n learnFromResponses: true,\n latencyBudgetMs: 5000,\n enabled: true,\n tools: [],\n}\n\n/** Keys that can be set via `liminal config --set` */\nexport const CONFIGURABLE_KEYS = new Set<string>([\n 'apiBaseUrl',\n 'upstreamBaseUrl',\n 'anthropicUpstreamUrl',\n 'port',\n 'compressionThreshold',\n 'compressRoles',\n 'learnFromResponses',\n 'latencyBudgetMs',\n 'enabled',\n 'tools',\n])\n","/**\n * Lightweight interactive terminal prompts — zero external dependencies.\n * Uses raw stdin mode for arrow-key navigation.\n */\n\n// ─── ANSI escape sequences ───────────────────────────────────────────\n\nconst ANSI = {\n HIDE_CURSOR: '\\x1b[?25l',\n SHOW_CURSOR: '\\x1b[?25h',\n CLEAR_LINE: '\\x1b[2K',\n BOLD: '\\x1b[1m',\n DIM: '\\x1b[2m',\n CYAN: '\\x1b[36m',\n RESET: '\\x1b[0m',\n moveUp: (n: number) => (n > 0 ? `\\x1b[${n}A` : ''),\n} as const\n\n// ─── Key parsing ─────────────────────────────────────────────────────\n\nexport type KeyPress =\n | { type: 'up' }\n | { type: 'down' }\n | { type: 'enter' }\n | { type: 'space' }\n | { type: 'escape' }\n | { type: 'ctrlc' }\n | { type: 'backspace' }\n | { type: 'char'; char: string }\n | { type: 'other' }\n\nexport function parseKey(data: Buffer): KeyPress {\n if (data.length === 0) return { type: 'other' }\n\n // Ctrl+C\n if (data[0] === 0x03) return { type: 'ctrlc' }\n\n // Arrow keys: ESC [ A/B\n if (data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b) {\n if (data[2] === 0x41) return { type: 'up' }\n if (data[2] === 0x42) return { type: 'down' }\n return { type: 'other' }\n }\n\n // Standalone Escape\n if (data.length === 1 && data[0] === 0x1b) return { type: 'escape' }\n\n // Enter\n if (data[0] === 0x0d || data[0] === 0x0a) return { type: 'enter' }\n\n // Space\n if (data[0] === 0x20) return { type: 'space' }\n\n // Backspace (DEL on macOS)\n if (data[0] === 0x7f || data[0] === 0x08) return { type: 'backspace' }\n\n // Printable ASCII characters (0x21-0x7e)\n if (data.length === 1 && data[0] >= 0x21 && data[0] <= 0x7e) {\n return { type: 'char', char: String.fromCharCode(data[0]) }\n }\n\n return { type: 'other' }\n}\n\n// ─── Types ───────────────────────────────────────────────────────────\n\nexport interface SelectOption<T> {\n label: string\n value: T\n description?: string\n}\n\nexport interface MultiSelectOption<T> extends SelectOption<T> {\n default?: boolean\n}\n\ninterface Streams {\n stdin: NodeJS.ReadableStream & { setRawMode?: (mode: boolean) => void; isTTY?: boolean }\n stdout: { write: (s: string) => boolean }\n}\n\ninterface SelectConfig<T> {\n message: string\n options: SelectOption<T>[]\n defaultIndex?: number\n _streams?: Streams\n}\n\ninterface MultiSelectConfig<T> {\n message: string\n options: MultiSelectOption<T>[]\n _streams?: Streams\n}\n\n// ─── Render helpers ──────────────────────────────────────────────────\n\nexport interface RenderResult {\n text: string\n lineCount: number\n}\n\nexport function renderSelect<T>(\n options: SelectOption<T>[],\n cursorIndex: number,\n message: string,\n): RenderResult {\n const lines: string[] = []\n lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`)\n lines.push('')\n\n const maxLabel = Math.max(...options.map((o) => o.label.length))\n\n for (let i = 0; i < options.length; i++) {\n const focused = i === cursorIndex\n const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : ' '\n const label = focused\n ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}`\n : `${options[i].label.padEnd(maxLabel)}`\n const desc = options[i].description\n ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}`\n : ''\n lines.push(` ${pointer} ${label}${desc}`)\n }\n\n lines.push('')\n return { text: lines.join('\\n'), lineCount: lines.length }\n}\n\nexport function renderMultiSelect<T>(\n options: MultiSelectOption<T>[],\n cursorIndex: number,\n selected: Set<number>,\n message: string,\n): RenderResult {\n const lines: string[] = []\n lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`)\n lines.push('')\n\n const maxLabel = Math.max(...options.map((o) => o.label.length))\n\n for (let i = 0; i < options.length; i++) {\n const focused = i === cursorIndex\n const checked = selected.has(i)\n const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : ' '\n const box = checked\n ? `${ANSI.CYAN}[x]${ANSI.RESET}`\n : `${ANSI.DIM}[ ]${ANSI.RESET}`\n const label = focused\n ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}`\n : `${options[i].label.padEnd(maxLabel)}`\n const desc = options[i].description\n ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}`\n : ''\n lines.push(` ${pointer} ${box} ${label}${desc}`)\n }\n\n lines.push('')\n lines.push(` ${ANSI.DIM}Space to toggle, Enter to confirm${ANSI.RESET}`)\n lines.push('')\n return { text: lines.join('\\n'), lineCount: lines.length }\n}\n\n// ─── Raw mode lifecycle ──────────────────────────────────────────────\n\nfunction withRawMode<T>(\n streams: Streams,\n handler: (\n resolve: (value: T) => void,\n ) => (key: KeyPress) => void,\n): Promise<T> {\n const { stdin, stdout } = streams\n\n return new Promise<T>((resolve, reject) => {\n let cleaned = false\n\n function cleanup() {\n if (cleaned) return\n cleaned = true\n stdin.removeListener('data', onData)\n if (stdin.setRawMode) stdin.setRawMode(false)\n if ('pause' in stdin && typeof (stdin as any).pause === 'function') {\n (stdin as any).pause()\n }\n stdout.write(ANSI.SHOW_CURSOR)\n process.removeListener('exit', cleanup)\n }\n\n function onData(data: Buffer) {\n const key = parseKey(data)\n if (key.type === 'ctrlc') {\n cleanup()\n process.exit(130)\n }\n keyHandler(key)\n }\n\n const keyHandler = handler((value: T) => {\n cleanup()\n resolve(value)\n })\n\n // Safety: restore terminal on unexpected exit\n process.on('exit', cleanup)\n\n try {\n if (stdin.setRawMode) stdin.setRawMode(true)\n stdout.write(ANSI.HIDE_CURSOR)\n stdin.on('data', onData)\n if ('resume' in stdin && typeof (stdin as any).resume === 'function') {\n (stdin as any).resume()\n }\n } catch (err) {\n cleanup()\n reject(err)\n }\n })\n}\n\n// ─── Public API ──────────────────────────────────────────────────────\n\nexport async function selectPrompt<T>(config: SelectConfig<T>): Promise<T | null> {\n const { message, options, defaultIndex = 0, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let cursorIndex = defaultIndex\n let prevLineCount = 0\n\n function draw() {\n const { text, lineCount } = renderSelect(options, cursorIndex, message)\n // Move up to overwrite previous render\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n // Clear and write each line\n const lines = text.split('\\n')\n for (const line of lines) {\n streams.stdout.write(ANSI.CLEAR_LINE + line + '\\n')\n }\n prevLineCount = lineCount\n }\n\n draw()\n\n const result = await withRawMode<T | null>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'up':\n cursorIndex = (cursorIndex - 1 + options.length) % options.length\n draw()\n break\n case 'down':\n cursorIndex = (cursorIndex + 1) % options.length\n draw()\n break\n case 'enter':\n resolve(options[cursorIndex].value)\n break\n case 'escape':\n resolve(null)\n break\n }\n }\n })\n\n // Show confirmed selection\n if (result !== null) {\n const selected = options.find((o) => o.value === result)\n if (selected) {\n // Overwrite prompt with confirmed value\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n for (let i = 0; i < prevLineCount; i++) {\n streams.stdout.write(ANSI.CLEAR_LINE + '\\n')\n }\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${selected.label}${ANSI.RESET}\\n`)\n }\n }\n\n return result\n}\n\nexport async function multiSelectPrompt<T>(config: MultiSelectConfig<T>): Promise<T[] | null> {\n const { message, options, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let cursorIndex = 0\n const selected = new Set<number>()\n let prevLineCount = 0\n\n // Pre-fill defaults\n for (let i = 0; i < options.length; i++) {\n if (options[i].default) selected.add(i)\n }\n\n function draw() {\n const { text, lineCount } = renderMultiSelect(options, cursorIndex, selected, message)\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n const lines = text.split('\\n')\n for (const line of lines) {\n streams.stdout.write(ANSI.CLEAR_LINE + line + '\\n')\n }\n prevLineCount = lineCount\n }\n\n draw()\n\n const result = await withRawMode<T[] | null>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'up':\n cursorIndex = (cursorIndex - 1 + options.length) % options.length\n draw()\n break\n case 'down':\n cursorIndex = (cursorIndex + 1) % options.length\n draw()\n break\n case 'space':\n if (selected.has(cursorIndex)) {\n selected.delete(cursorIndex)\n } else {\n selected.add(cursorIndex)\n }\n draw()\n break\n case 'enter':\n if (selected.size > 0) {\n const values = [...selected].sort().map((i) => options[i].value)\n resolve(values)\n }\n // If nothing selected, ignore Enter (must select at least 1)\n break\n case 'escape':\n resolve(null)\n break\n }\n }\n })\n\n // Show confirmed selection\n if (result !== null) {\n const labels = [...selected].sort().map((i) => options[i].label)\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n for (let i = 0; i < prevLineCount; i++) {\n streams.stdout.write(ANSI.CLEAR_LINE + '\\n')\n }\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${labels.join(', ')}${ANSI.RESET}\\n`)\n }\n\n return result\n}\n\n// ─── Password prompt ─────────────────────────────────────────────────\n\ninterface PasswordConfig {\n message: string\n _streams?: Streams\n}\n\nexport async function passwordPrompt(config: PasswordConfig): Promise<string> {\n const { message, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let password = ''\n\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET}: `)\n\n const result = await withRawMode<string>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'char':\n password += (key as { type: 'char'; char: string }).char\n streams.stdout.write('*')\n break\n case 'space':\n password += ' '\n streams.stdout.write('*')\n break\n case 'backspace':\n if (password.length > 0) {\n password = password.slice(0, -1)\n streams.stdout.write('\\b \\b')\n }\n break\n case 'enter':\n streams.stdout.write('\\n')\n resolve(password)\n break\n case 'escape':\n streams.stdout.write('\\n')\n resolve('')\n break\n }\n }\n })\n\n return result\n}\n","import { createInterface } from 'node:readline/promises'\nimport { stdin, stdout } from 'node:process'\nimport { signIn, signUp, authenticateAndGetKey } from '../auth/supabase.js'\nimport { saveConfig, ensureDirectories, loadConfig } from '../config/loader.js'\nimport { DEFAULTS } from '../config/schema.js'\nimport { printBanner } from '../version.js'\nimport { selectPrompt, passwordPrompt } from '../ui/prompts.js'\nimport type { AuthError } from '../auth/supabase.js'\n\nexport async function loginCommand(): Promise<void> {\n printBanner()\n\n // Check if already logged in\n try {\n const config = loadConfig()\n if (config.apiKey && config.apiKey.startsWith('fmcp_')) {\n console.log(' Already logged in.')\n console.log(' Run \\x1b[1mliminal logout\\x1b[0m first to switch accounts.')\n return\n }\n } catch {\n // No config yet — proceed with login\n }\n\n await runAuthFlow()\n}\n\n/**\n * Shared auth flow used by both `liminal login` and `liminal init`.\n * Returns the API key on success.\n */\nexport async function runAuthFlow(): Promise<string> {\n const modeResult = await selectPrompt<'login' | 'signup'>({\n message: 'Welcome to Liminal',\n options: [\n { label: 'Log in', value: 'login', description: 'I have an account' },\n { label: 'Create account', value: 'signup', description: 'New to Liminal' },\n ],\n defaultIndex: 0,\n })\n const mode = modeResult ?? 'login'\n\n console.log()\n\n // Collect credentials\n const rl = createInterface({ input: stdin, output: stdout })\n let name = ''\n let email: string\n\n try {\n if (mode === 'signup') {\n name = (await rl.question(' \\x1b[1mName\\x1b[0m: ')).trim()\n if (!name) {\n console.error('\\n Error: Name is required.')\n process.exit(1)\n }\n }\n\n email = (await rl.question(' \\x1b[1mEmail\\x1b[0m: ')).trim()\n if (!email) {\n console.error('\\n Error: Email is required.')\n process.exit(1)\n }\n } finally {\n rl.close()\n }\n\n // Password (masked)\n const password = await passwordPrompt({ message: 'Password' })\n if (!password) {\n console.error('\\n Error: Password is required.')\n process.exit(1)\n }\n\n console.log()\n\n // Authenticate\n const action = mode === 'signup' ? 'Creating account' : 'Logging in'\n process.stdout.write(` ${action}... `)\n\n try {\n const auth = mode === 'signup'\n ? await signUp(email, password, name)\n : await signIn(email, password)\n\n console.log('OK')\n\n // Fetch or create API key\n process.stdout.write(' Setting up API key... ')\n const apiKey = await authenticateAndGetKey(auth)\n console.log('OK')\n\n // Save to config\n ensureDirectories()\n saveConfig({\n apiKey,\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n })\n\n console.log()\n console.log(` Logged in as \\x1b[1m${auth.email}\\x1b[0m`)\n\n return apiKey\n } catch (err) {\n console.log('FAILED')\n const authErr = err as AuthError\n console.error(`\\n ${authErr.message}`)\n\n if (mode === 'login' && authErr.message?.includes('Invalid login')) {\n console.error(' Check your email and password, then try again.')\n }\n\n process.exit(1)\n }\n}\n","/**\n * Lightweight Supabase Auth client using fetch — zero npm dependencies.\n * Uses the public anon key (same as web frontend).\n */\nimport { randomBytes } from 'node:crypto'\n\nconst SUPABASE_URL = 'https://nzcneiyymvgxvttbenhp.supabase.co'\nconst SUPABASE_ANON_KEY =\n 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im56Y25laXl5bXZneHZ0dGJlbmhwIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQwNjQ0MjcsImV4cCI6MjA2OTY0MDQyN30.x3E-zGRadbPMmxRqT_PB_KOi00htKpgeb8GiQa4g2z0'\n\n// ─── Types ───────────────────────────────────────────────────────────\n\nexport interface AuthResult {\n accessToken: string\n userId: string\n email: string\n}\n\nexport interface AuthError {\n message: string\n status?: number\n}\n\n// ─── Auth ────────────────────────────────────────────────────────────\n\nfunction supabaseHeaders(accessToken?: string): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'apikey': SUPABASE_ANON_KEY,\n }\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`\n }\n return headers\n}\n\n/**\n * Sign in with email and password.\n */\nexport async function signIn(email: string, password: string): Promise<AuthResult> {\n const res = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, {\n method: 'POST',\n headers: supabaseHeaders(),\n body: JSON.stringify({ email, password }),\n })\n\n const body = (await res.json()) as Record<string, any>\n\n if (!res.ok) {\n const msg = body?.error_description || body?.error || body?.msg || 'Authentication failed'\n const err: AuthError = { message: msg, status: res.status }\n throw err\n }\n\n return {\n accessToken: body.access_token,\n userId: body.user?.id,\n email: body.user?.email ?? email,\n }\n}\n\n/**\n * Sign up with email, password, and name.\n */\nexport async function signUp(\n email: string,\n password: string,\n name: string,\n): Promise<AuthResult> {\n const res = await fetch(`${SUPABASE_URL}/auth/v1/signup`, {\n method: 'POST',\n headers: supabaseHeaders(),\n body: JSON.stringify({\n email,\n password,\n data: { name },\n }),\n })\n\n const body = (await res.json()) as Record<string, any>\n\n if (!res.ok) {\n const msg = body?.error_description || body?.error || body?.msg || 'Sign up failed'\n const err: AuthError = { message: msg, status: res.status }\n throw err\n }\n\n // Supabase may return identities: [] if email confirmation is required\n if (body.user?.identities?.length === 0) {\n const err: AuthError = { message: 'Account already exists. Try logging in instead.' }\n throw err\n }\n\n return {\n accessToken: body.access_token,\n userId: body.user?.id,\n email: body.user?.email ?? email,\n }\n}\n\n// ─── API Key Management ──────────────────────────────────────────────\n\n/**\n * Fetch existing active API key for the authenticated user.\n */\nexport async function fetchApiKey(accessToken: string, userId: string): Promise<string | null> {\n const params = new URLSearchParams({\n user_id: `eq.${userId}`,\n is_active: 'eq.true',\n select: 'api_key',\n limit: '1',\n })\n\n const res = await fetch(`${SUPABASE_URL}/rest/v1/user_api_keys?${params}`, {\n headers: supabaseHeaders(accessToken),\n })\n\n if (!res.ok) return null\n\n const rows = await res.json()\n if (Array.isArray(rows) && rows.length > 0 && rows[0].api_key) {\n return rows[0].api_key as string\n }\n\n return null\n}\n\n/**\n * Generate and insert a new API key for the authenticated user.\n */\nexport async function createApiKey(accessToken: string, userId: string): Promise<string> {\n const apiKey = `fmcp_${randomBytes(32).toString('hex')}`\n\n const res = await fetch(`${SUPABASE_URL}/rest/v1/user_api_keys`, {\n method: 'POST',\n headers: {\n ...supabaseHeaders(accessToken),\n 'Prefer': 'return=representation',\n },\n body: JSON.stringify({\n user_id: userId,\n key_name: 'Liminal CLI',\n api_key: apiKey,\n is_active: true,\n }),\n })\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as Record<string, any>\n const msg = body?.message || body?.error || 'Failed to create API key'\n throw { message: msg, status: res.status } as AuthError\n }\n\n return apiKey\n}\n\n/**\n * Full login flow: authenticate then fetch or create API key.\n */\nexport async function authenticateAndGetKey(\n auth: AuthResult,\n): Promise<string> {\n // Try to fetch existing key first\n const existingKey = await fetchApiKey(auth.accessToken, auth.userId)\n if (existingKey) return existingKey\n\n // No key found — create one\n return createApiKey(auth.accessToken, auth.userId)\n}\n","import { saveConfig, isConfigured } from '../config/loader.js'\n\nexport async function logoutCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log(' Not currently logged in.')\n return\n }\n\n saveConfig({ apiKey: '' })\n console.log(' Logged out.')\n console.log(' Run \\x1b[1mliminal login\\x1b[0m to reconnect.')\n}\n","import {\n CompressionPipeline,\n RSCTransport,\n RSCEventEmitter,\n Session,\n CircuitBreaker,\n} from '@cognisos/rsc-sdk'\nimport type { SessionSummary, CircuitState } from '@cognisos/rsc-sdk'\n\nexport interface PipelineConfig {\n rscApiKey: string\n rscBaseUrl: string\n compressionThreshold: number\n learnFromResponses: boolean\n latencyBudgetMs?: number\n sessionId?: string\n}\n\nexport class RSCPipelineWrapper {\n readonly pipeline: CompressionPipeline\n readonly session: Session\n readonly events: RSCEventEmitter\n readonly transport: RSCTransport\n private readonly circuitBreaker: CircuitBreaker\n\n constructor(config: PipelineConfig) {\n this.circuitBreaker = new CircuitBreaker(5, 5 * 60 * 1000)\n\n this.transport = new RSCTransport({\n baseUrl: config.rscBaseUrl,\n apiKey: config.rscApiKey,\n timeout: 30_000,\n maxRetries: 3,\n circuitBreaker: this.circuitBreaker,\n })\n\n this.events = new RSCEventEmitter()\n this.session = new Session(config.sessionId)\n\n this.pipeline = new CompressionPipeline(\n this.transport,\n {\n threshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs,\n sessionId: this.session.sessionId,\n },\n this.events,\n )\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n await this.transport.get<{ status: string }>('/health')\n return true\n } catch {\n return false\n }\n }\n\n getSessionSummary(): SessionSummary {\n return this.session.getSummary()\n }\n\n getCircuitState(): CircuitState {\n return this.circuitBreaker.getState()\n }\n\n isCircuitOpen(): boolean {\n return this.circuitBreaker.getState() === 'open'\n }\n\n resetCircuitBreaker(): void {\n this.circuitBreaker.reset()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeSSEResponse } from './streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionRequest, ResolvedConfig } from '../types.js'\nimport type { Logger } from './handler.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\n/**\n * Extract the bearer token from the Authorization header.\n * This is the user's LLM API key — used to forward to the upstream LLM.\n */\nfunction extractBearerToken(req: http.IncomingMessage): string | null {\n const auth = req.headers.authorization\n if (!auth || !auth.startsWith('Bearer ')) return null\n return auth.slice(7)\n}\n\nexport async function handleChatCompletions(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const request = body as ChatCompletionRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendJSON(res, 400, {\n error: { message: 'messages is required and must be an array', type: 'invalid_request_error' },\n })\n return\n }\n\n // Extract LLM API key from the incoming request\n const llmApiKey = extractBearerToken(req)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n // Compress messages (or passthrough if circuit is open / disabled)\n let messages = request.messages\n let anyCompressed = false\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n try {\n const compressRoles = new Set(config.compressRoles)\n const result = await compressMessages(\n request.messages,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n messages = result.messages\n anyCompressed = result.anyCompressed\n\n if (result.totalTokensSaved > 0) {\n logger.log(`[COMPRESS] Saved ${result.totalTokensSaved} tokens`)\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log('[DEGRADE] Circuit breaker open — passing through directly')\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n // Fall through with original messages\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.upstreamBaseUrl}/v1/chat/completions`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n 'Authorization': `Bearer ${llmApiKey}`,\n 'Content-Type': 'application/json',\n }\n\n // Forward streaming preference\n if (request.stream) {\n upstreamHeaders['Accept'] = 'text/event-stream'\n }\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n await pipeSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(responseBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const content = parsed?.choices?.[0]?.message?.content\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream LLM: ${message}`, type: 'server_error' },\n })\n }\n }\n}\n","import type { CompressionPipeline, Session } from '@cognisos/rsc-sdk'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport type { ChatCompletionMessage, ContentPart } from '../types.js'\nimport { segmentContent } from './content-segmenter.js'\n\nexport interface CompressedMessagesResult {\n messages: ChatCompletionMessage[]\n anyCompressed: boolean\n totalTokensSaved: number\n}\n\n/**\n * Walk an array of ChatCompletion messages and compress eligible ones\n * via the RSC CompressionPipeline. Non-eligible roles and non-text\n * content parts pass through unchanged.\n */\nexport async function compressMessages(\n messages: ChatCompletionMessage[],\n pipeline: CompressionPipeline,\n session: Session,\n compressRoles: Set<string>,\n): Promise<CompressedMessagesResult> {\n let anyCompressed = false\n let totalTokensSaved = 0\n\n const compressed = await Promise.all(\n messages.map(async (msg) => {\n if (!compressRoles.has(msg.role)) return msg\n\n // String content\n if (typeof msg.content === 'string') {\n return compressStringContent(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }\n\n // Array content (vision messages with text + image parts)\n if (Array.isArray(msg.content)) {\n return compressArrayContent(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }\n\n // null or other content — pass through\n return msg\n }),\n )\n\n return { messages: compressed, anyCompressed, totalTokensSaved }\n}\n\nasync function compressStringContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<ChatCompletionMessage> {\n const text = msg.content as string\n const segments = segmentContent(text)\n const hasCode = segments.some(s => s.type === 'code')\n\n // Fast path: no code detected — compress the whole string as before\n if (!hasCode) {\n try {\n const result = await pipeline.compressForLLM(text)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return { ...msg, content: result.text }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return msg\n }\n }\n\n // Segment-aware: compress prose, pass code through verbatim\n try {\n const parts = await Promise.all(\n segments.map(async (seg) => {\n if (seg.type === 'code') return seg.text\n if (seg.text.trim().length === 0) return seg.text\n try {\n const result = await pipeline.compressForLLM(seg.text)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return result.text\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) throw err\n session.recordFailure()\n return seg.text\n }\n }),\n )\n return { ...msg, content: parts.join('') }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return msg\n }\n}\n\nasync function compressTextWithSegmentation(\n text: string,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<string> {\n const segments = segmentContent(text)\n const hasCode = segments.some(s => s.type === 'code')\n\n if (!hasCode) {\n const result = await pipeline.compressForLLM(text)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return result.text\n }\n\n const parts = await Promise.all(\n segments.map(async (seg) => {\n if (seg.type === 'code') return seg.text\n if (seg.text.trim().length === 0) return seg.text\n try {\n const result = await pipeline.compressForLLM(seg.text)\n session.recordCompression(result.metrics)\n record(!result.metrics.skipped, result.metrics.tokensSaved)\n return result.text\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) throw err\n session.recordFailure()\n return seg.text\n }\n }),\n )\n return parts.join('')\n}\n\nasync function compressArrayContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: (compressed: boolean, saved: number) => void,\n): Promise<ChatCompletionMessage> {\n const parts = msg.content as ContentPart[]\n\n const compressedParts = await Promise.all(\n parts.map(async (part) => {\n if (part.type === 'text' && typeof part.text === 'string') {\n try {\n const compressed = await compressTextWithSegmentation(part.text, pipeline, session, record)\n return { ...part, text: compressed }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return part\n }\n }\n // Pass through image_url, tool_use, etc.\n return part\n }),\n )\n\n return { ...msg, content: compressedParts }\n}\n","/**\n * Content segmenter — splits mixed text into code and prose segments.\n * Code segments (fenced blocks, indented blocks) pass through compression\n * unchanged to avoid destructive normalization (casefold, punct strip, lemmatize).\n */\n\nexport interface ContentSegment {\n type: 'prose' | 'code'\n text: string\n}\n\n/**\n * Segment text content into code and prose blocks.\n *\n * Detection rules:\n * 1. Fenced code blocks: ``` or ~~~ (with optional language tag) through closing fence\n * 2. Indented code blocks: 4+ space or tab-indented contiguous lines\n * 3. Everything else → prose\n *\n * Round-trip invariant: segments.map(s => s.text).join('') === input\n */\nexport function segmentContent(text: string): ContentSegment[] {\n if (text.length === 0) return [{ type: 'prose', text: '' }]\n\n const segments: ContentSegment[] = []\n const lines = text.split('\\n')\n let i = 0\n let proseBuf: string[] = []\n\n function flushProse(): void {\n if (proseBuf.length > 0) {\n segments.push({ type: 'prose', text: proseBuf.join('\\n') })\n proseBuf = []\n }\n }\n\n while (i < lines.length) {\n const line = lines[i]\n\n // Check for fenced code block opening\n const fenceMatch = matchFenceOpen(line)\n if (fenceMatch) {\n // Before flushing prose, add the newline that separated prose from this fence\n if (proseBuf.length > 0) {\n // The newline before this line belongs to the prose segment\n flushProse()\n // Add the newline separator between prose and code\n segments[segments.length - 1].text += '\\n'\n }\n\n const codeBuf: string[] = [line]\n i++\n\n // Scan until closing fence of same type and length\n let closed = false\n while (i < lines.length) {\n codeBuf.push(lines[i])\n if (matchFenceClose(lines[i], fenceMatch.char, fenceMatch.length)) {\n closed = true\n i++\n break\n }\n i++\n }\n\n // Add trailing newline if not at end of input\n let codeText = codeBuf.join('\\n')\n if (i < lines.length) {\n codeText += '\\n'\n }\n\n segments.push({ type: 'code', text: codeText })\n continue\n }\n\n // Check for indented code block (4+ spaces or tab)\n if (isIndentedCodeLine(line)) {\n if (proseBuf.length > 0) {\n flushProse()\n segments[segments.length - 1].text += '\\n'\n }\n\n const codeBuf: string[] = [line]\n i++\n\n // Consume contiguous indented lines (allow blank lines within)\n while (i < lines.length) {\n if (isIndentedCodeLine(lines[i])) {\n codeBuf.push(lines[i])\n i++\n } else if (lines[i].trim() === '' && i + 1 < lines.length && isIndentedCodeLine(lines[i + 1])) {\n // Blank line between indented lines — still part of code block\n codeBuf.push(lines[i])\n i++\n } else {\n break\n }\n }\n\n let codeText = codeBuf.join('\\n')\n if (i < lines.length) {\n codeText += '\\n'\n }\n\n segments.push({ type: 'code', text: codeText })\n continue\n }\n\n // Regular prose line\n if (proseBuf.length > 0) {\n proseBuf.push(line)\n } else {\n proseBuf.push(line)\n }\n i++\n }\n\n // Flush remaining prose\n if (proseBuf.length > 0) {\n flushProse()\n }\n\n // Ensure at least one segment\n if (segments.length === 0) {\n return [{ type: 'prose', text }]\n }\n\n return segments\n}\n\ninterface FenceInfo {\n char: string\n length: number\n}\n\nfunction matchFenceOpen(line: string): FenceInfo | null {\n // Match ``` or ~~~ with optional language tag, allowing leading whitespace (0-3 spaces)\n const match = line.match(/^( {0,3})((`{3,})|~{3,})(.*)$/)\n if (!match) return null\n\n const fenceStr = match[2]\n const char = fenceStr[0]\n\n // Backtick fences: info string must not contain backticks\n if (char === '`' && match[4] && match[4].includes('`')) return null\n\n return { char, length: fenceStr.length }\n}\n\nfunction matchFenceClose(line: string, char: string, minLength: number): boolean {\n const match = line.match(/^( {0,3})((`{3,})|(~{3,}))\\s*$/)\n if (!match) return false\n const fenceStr = match[2]\n return fenceStr[0] === char && fenceStr.length >= minLength\n}\n\nfunction isIndentedCodeLine(line: string): boolean {\n // 4+ spaces or starts with tab (and not blank)\n return (line.startsWith(' ') || line.startsWith('\\t')) && line.trim().length > 0\n}\n","import type { CompressionPipeline } from '@cognisos/rsc-sdk'\n\n/**\n * Creates a buffer that accumulates streamed response text and triggers\n * background learning when the stream completes.\n */\nexport function createStreamLearningBuffer(pipeline: CompressionPipeline) {\n let buffer = ''\n\n return {\n /** Append a text delta from an SSE chunk */\n append(text: string): void {\n buffer += text\n },\n\n /** Flush the buffer — triggers fire-and-forget learning */\n flush(): void {\n if (buffer.length > 0) {\n pipeline.triggerLearning(buffer)\n buffer = ''\n }\n },\n\n /** Get current buffer contents (for testing) */\n getBuffer(): string {\n return buffer\n },\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an SSE response from an upstream LLM to the client,\n * parsing content deltas for the learning buffer.\n *\n * Writes each chunk immediately — zero buffering, zero added latency.\n */\nexport async function pipeSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Write immediately to client\n clientRes.write(chunk)\n\n // Parse SSE lines for learning (best-effort, never blocks the pipe)\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const json = JSON.parse(line.slice(6))\n const content = json?.choices?.[0]?.delta?.content\n if (typeof content === 'string') {\n onContentDelta(content)\n }\n } catch {\n // Malformed SSE data — ignore for learning, chunk already piped\n }\n }\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeAnthropicSSEResponse } from './anthropic-streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionMessage, ResolvedConfig } from '../types.js'\nimport type { AnthropicMessagesRequest, AnthropicMessage, AnthropicContentBlock } from '../types/anthropic.js'\nimport type { Logger } from './handler.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta')\n}\n\nfunction sendAnthropicError(res: http.ServerResponse, status: number, type: string, message: string): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ type: 'error', error: { type, message } }))\n}\n\n/**\n * Extract auth headers from incoming request.\n * Supports both x-api-key (API users) and Authorization: Bearer (subscription/OAuth users).\n */\nfunction extractAuthHeaders(req: http.IncomingMessage): Record<string, string> {\n const headers: Record<string, string> = {}\n\n const xApiKey = req.headers['x-api-key']\n if (typeof xApiKey === 'string' && xApiKey.length > 0) {\n headers['x-api-key'] = xApiKey\n }\n\n const auth = req.headers['authorization']\n if (typeof auth === 'string' && auth.length > 0) {\n headers['Authorization'] = auth\n }\n\n return headers\n}\n\n/**\n * Convert Anthropic messages to ChatCompletionMessage[] for the compressor.\n * The structures are compatible — this is a thin adapter.\n */\nfunction convertAnthropicToCompressible(messages: AnthropicMessage[]): ChatCompletionMessage[] {\n return messages.map((msg) => ({\n role: msg.role,\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\n/**\n * Convert compressed ChatCompletionMessage[] back to Anthropic format.\n */\nfunction convertCompressedToAnthropic(messages: ChatCompletionMessage[]): AnthropicMessage[] {\n return messages.map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\nexport async function handleAnthropicMessages(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const request = body as AnthropicMessagesRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendAnthropicError(res, 400, 'invalid_request_error', 'messages is required and must be an array')\n return\n }\n\n if (typeof request.max_tokens !== 'number') {\n sendAnthropicError(res, 400, 'invalid_request_error', 'max_tokens is required')\n return\n }\n\n // Extract auth headers (x-api-key for API users, Authorization for subscription/OAuth)\n const authHeaders = extractAuthHeaders(req)\n if (Object.keys(authHeaders).length === 0) {\n sendAnthropicError(res, 401, 'authentication_error', 'Authentication required (x-api-key or Authorization header)')\n return\n }\n\n // Compress messages (reuse existing compressor via format conversion)\n let messages = request.messages\n let anyCompressed = false\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n try {\n const compressRoles = new Set(config.compressRoles)\n const compressible = convertAnthropicToCompressible(request.messages)\n const result = await compressMessages(\n compressible,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n messages = convertCompressedToAnthropic(result.messages)\n anyCompressed = result.anyCompressed\n\n if (result.totalTokensSaved > 0) {\n logger.log(`[COMPRESS] Saved ${result.totalTokensSaved} tokens`)\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log('[DEGRADE] Circuit breaker open -- passing through directly')\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.anthropicUpstreamUrl}/v1/messages`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n ...authHeaders,\n 'anthropic-version': (req.headers['anthropic-version'] as string) || '2023-06-01',\n 'Content-Type': 'application/json',\n }\n\n // Forward anthropic-beta header if present\n const betaHeader = req.headers['anthropic-beta']\n if (typeof betaHeader === 'string') {\n upstreamHeaders['anthropic-beta'] = betaHeader\n }\n\n // Log request details for debugging\n const authTypes = Object.keys(authHeaders).join(', ') || 'none'\n logger.log(`[ANTHROPIC] ${request.model} → ${upstreamUrl} (auth: ${authTypes})`)\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n logger.log(`[ANTHROPIC] Upstream error ${upstreamResponse.status}: ${errorBody.slice(0, 500)}`)\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n await pipeAnthropicSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(responseBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const textBlocks = parsed?.content?.filter(\n (b: AnthropicContentBlock) => b.type === 'text' && typeof b.text === 'string',\n )\n const content = textBlocks?.map((b: AnthropicContentBlock) => b.text).join('')\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendAnthropicError(res, 502, 'api_error', `Failed to reach upstream: ${message}`)\n }\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an Anthropic SSE response from the upstream to the client,\n * parsing content_block_delta events for the learning buffer.\n *\n * Anthropic SSE format:\n * event: content_block_delta\n * data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"Hello\"}}\n *\n * Writes each chunk immediately — zero buffering, zero added latency.\n */\nexport async function pipeAnthropicSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n let currentEvent = ''\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Write immediately to client\n clientRes.write(chunk)\n\n // Parse SSE lines for learning (best-effort, never blocks the pipe)\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n } else if (line.startsWith('data: ') && currentEvent === 'content_block_delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (json?.delta?.type === 'text_delta' && typeof json.delta.text === 'string') {\n onContentDelta(json.delta.text)\n }\n } catch {\n // Malformed data — ignore for learning, chunk already piped\n }\n }\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { handleChatCompletions } from './completions.js'\nimport { handleAnthropicMessages } from './messages.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ResolvedConfig } from '../types.js'\n\nexport interface Logger {\n log(message: string): void\n}\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta')\n res.setHeader('Access-Control-Max-Age', '86400')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(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('utf-8')))\n req.on('error', reject)\n })\n}\n\n/**\n * Passthrough proxy for Anthropic sub-routes (count_tokens, batches, etc.).\n * Forwards the request to upstream Anthropic without modification.\n */\nasync function passthroughAnthropic(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n fullUrl: string,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const upstreamUrl = `${config.anthropicUpstreamUrl}${fullUrl}`\n\n // Forward auth headers\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n const xApiKey = req.headers['x-api-key']\n if (typeof xApiKey === 'string') headers['x-api-key'] = xApiKey\n const auth = req.headers['authorization']\n if (typeof auth === 'string') headers['Authorization'] = auth\n const version = req.headers['anthropic-version']\n if (typeof version === 'string') headers['anthropic-version'] = version\n const beta = req.headers['anthropic-beta']\n if (typeof beta === 'string') headers['anthropic-beta'] = beta\n\n try {\n const body = await readBody(req)\n const upstreamRes = await fetch(upstreamUrl, {\n method: 'POST',\n headers,\n body,\n })\n const responseBody = await upstreamRes.text()\n setCORSHeaders(res)\n res.writeHead(upstreamRes.status, {\n 'Content-Type': upstreamRes.headers.get('Content-Type') || 'application/json',\n })\n res.end(responseBody)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Passthrough failed: ${message}`)\n setCORSHeaders(res)\n res.writeHead(502, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ type: 'error', error: { type: 'api_error', message: `Failed to reach upstream: ${message}` } }))\n }\n}\n\nexport function createRequestHandler(\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n): (req: http.IncomingMessage, res: http.ServerResponse) => void {\n const startTime = Date.now()\n\n return async (req, res) => {\n try {\n const method = req.method?.toUpperCase() ?? ''\n const fullUrl = req.url ?? ''\n const url = fullUrl.split('?')[0] // Strip query string for route matching\n\n // Log every incoming request\n const authType = req.headers['x-api-key'] ? 'x-api-key' : req.headers['authorization'] ? 'bearer' : 'none'\n logger.log(`[REQUEST] ${method} ${fullUrl} (auth: ${authType})`)\n\n // CORS preflight\n if (method === 'OPTIONS') {\n setCORSHeaders(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n // Health check (extended with session summary for `liminal status` / `liminal summary`)\n if (method === 'GET' && (url === '/health' || url === '/')) {\n const summary = pipeline.getSessionSummary()\n sendJSON(res, 200, {\n status: 'ok',\n version: config.rscApiKey ? 'connected' : 'no-api-key',\n rsc_connected: !pipeline.isCircuitOpen(),\n circuit_state: pipeline.getCircuitState(),\n session_id: summary.sessionId,\n uptime_ms: Date.now() - startTime,\n session: {\n tokens_processed: summary.tokensProcessed,\n tokens_saved: summary.tokensSaved,\n calls_total: summary.totalCalls,\n calls_compressed: summary.compressedCalls,\n calls_skipped: summary.skippedCalls,\n calls_failed: summary.failedCalls,\n patterns_learned: summary.patternsLearned,\n estimated_cost_saved_usd: summary.estimatedCostSaved,\n },\n })\n return\n }\n\n // Model listing — proxy to upstream LLM\n if (method === 'GET' && (url === '/v1/models' || url === '/models')) {\n const llmApiKey = req.headers.authorization?.slice(7)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n try {\n const upstreamRes = await fetch(`${config.upstreamBaseUrl}/v1/models`, {\n headers: { 'Authorization': `Bearer ${llmApiKey}` },\n })\n const body = await upstreamRes.text()\n setCORSHeaders(res)\n res.writeHead(upstreamRes.status, {\n 'Content-Type': upstreamRes.headers.get('Content-Type') || 'application/json',\n })\n res.end(body)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream: ${message}`, type: 'server_error' },\n })\n }\n return\n }\n\n // Main route: chat completions\n if (method === 'POST' && (url === '/v1/chat/completions' || url === '/chat/completions')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n sendJSON(res, 400, {\n error: { message: 'Invalid JSON body', type: 'invalid_request_error' },\n })\n return\n }\n\n await handleChatCompletions(req, res, parsed, pipeline, config, logger)\n return\n }\n\n // Anthropic Messages route\n if (method === 'POST' && (url === '/v1/messages' || url === '/messages')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body)\n } catch {\n sendJSON(res, 400, {\n type: 'error',\n error: { type: 'invalid_request_error', message: 'Invalid JSON body' },\n })\n return\n }\n\n await handleAnthropicMessages(req, res, parsed, pipeline, config, logger)\n return\n }\n\n // Anthropic passthrough routes (count_tokens, batches, etc.)\n if (method === 'POST' && url.startsWith('/v1/messages/')) {\n await passthroughAnthropic(req, res, fullUrl, config, logger)\n return\n }\n\n // 404\n sendJSON(res, 404, {\n error: { message: `Not found: ${method} ${url}`, type: 'invalid_request_error' },\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Proxy handler error: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 500, {\n error: { message: 'Internal proxy error', type: 'server_error' },\n })\n }\n }\n }\n}\n","import * as http from 'node:http'\n\nconst MAX_PORT_RETRIES = 5\n\nexport class ProxyServer {\n private server: http.Server | null = null\n private activePort: number | null = null\n private readonly requestedPort: number\n private readonly handler: (req: http.IncomingMessage, res: http.ServerResponse) => void\n\n constructor(\n port: number,\n handler: (req: http.IncomingMessage, res: http.ServerResponse) => void,\n ) {\n this.requestedPort = port\n this.handler = handler\n }\n\n async start(): Promise<number> {\n let lastError: Error | null = null\n\n for (let attempt = 0; attempt < MAX_PORT_RETRIES; attempt++) {\n const port = this.requestedPort + attempt\n try {\n await this.listen(port)\n this.activePort = port\n return port\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n if ((err as NodeJS.ErrnoException).code !== 'EADDRINUSE') {\n throw lastError\n }\n }\n }\n\n throw lastError ?? new Error(`All ports ${this.requestedPort}-${this.requestedPort + MAX_PORT_RETRIES - 1} in use`)\n }\n\n private listen(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = http.createServer(this.handler)\n server.on('error', reject)\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', reject)\n this.server = server\n resolve()\n })\n })\n }\n\n async stop(): Promise<void> {\n if (!this.server) return\n return new Promise((resolve) => {\n this.server!.close(() => {\n this.server = null\n this.activePort = null\n resolve()\n })\n })\n }\n\n isRunning(): boolean {\n return this.server !== null && this.server.listening\n }\n\n getPort(): number | null {\n return this.activePort\n }\n}\n","import { appendFileSync, statSync, renameSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LOG_FILE, LOG_DIR } from '../config/paths.js'\nimport type { Logger } from '../proxy/handler.js'\n\nconst MAX_LOG_SIZE = 10 * 1024 * 1024 // 10 MB\nconst MAX_BACKUPS = 2\n\nexport class FileLogger implements Logger {\n private readonly logFile: string\n private readonly mirrorStdout: boolean\n\n constructor(options?: { logFile?: string; mirrorStdout?: boolean }) {\n this.logFile = options?.logFile ?? LOG_FILE\n this.mirrorStdout = options?.mirrorStdout ?? false\n\n // Ensure log directory exists\n const logDir = dirname(this.logFile)\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true })\n }\n }\n\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n const line = `[${timestamp}] ${message}\\n`\n\n try {\n appendFileSync(this.logFile, line)\n } catch {\n // If log write fails, try stdout as fallback\n process.stderr.write(`[LOG-WRITE-FAILED] ${line}`)\n }\n\n if (this.mirrorStdout) {\n process.stdout.write(line)\n }\n\n this.rotateIfNeeded()\n }\n\n private rotateIfNeeded(): void {\n try {\n const stats = statSync(this.logFile)\n if (stats.size <= MAX_LOG_SIZE) return\n\n // Rotate: liminal.log -> liminal.log.1 -> liminal.log.2 (drop oldest)\n for (let i = MAX_BACKUPS - 1; i >= 1; i--) {\n const from = `${this.logFile}.${i}`\n const to = `${this.logFile}.${i + 1}`\n if (existsSync(from)) renameSync(from, to)\n }\n renameSync(this.logFile, `${this.logFile}.1`)\n } catch {\n // Rotation failure is non-fatal\n }\n }\n\n getLogFile(): string {\n return this.logFile\n }\n}\n\n/**\n * A simple logger that only writes to stdout (for use during init or when log file isn't available).\n */\nexport class ConsoleLogger implements Logger {\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n process.stdout.write(`[${timestamp}] ${message}\\n`)\n }\n}\n","import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs'\nimport { fork } from 'node:child_process'\nimport { fileURLToPath } from 'node:url'\nimport { PID_FILE } from '../config/paths.js'\nimport type { ProxyServer } from '../proxy/server.js'\nimport type { Logger } from '../proxy/handler.js'\n\n/**\n * Write the current process PID to ~/.liminal/liminal.pid.\n */\nexport function writePidFile(pid: number): void {\n writeFileSync(PID_FILE, String(pid), 'utf-8')\n}\n\n/**\n * Read PID from ~/.liminal/liminal.pid. Returns null if file doesn't exist.\n */\nexport function readPidFile(): number | null {\n if (!existsSync(PID_FILE)) return null\n try {\n const content = readFileSync(PID_FILE, 'utf-8').trim()\n const pid = parseInt(content, 10)\n return isNaN(pid) ? null : pid\n } catch {\n return null\n }\n}\n\n/**\n * Remove the PID file.\n */\nexport function removePidFile(): void {\n try {\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE)\n } catch {\n // Ignore — file may already be gone\n }\n}\n\n/**\n * Check if a process with the given PID is alive.\n */\nexport function isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Check if the Liminal daemon is currently running.\n * Cleans up stale PID files automatically.\n */\nexport function isDaemonRunning(): { running: boolean; pid?: number } {\n const pid = readPidFile()\n if (pid === null) return { running: false }\n\n if (isProcessAlive(pid)) {\n return { running: true, pid }\n }\n\n // Stale PID file — process is dead\n removePidFile()\n return { running: false }\n}\n\n/**\n * Set up signal handlers for graceful shutdown.\n */\nexport function setupSignalHandlers(server: ProxyServer, logger: Logger): void {\n const shutdown = async (signal: string) => {\n logger.log(`[DAEMON] Received ${signal}, shutting down...`)\n try {\n await server.stop()\n } catch {\n // Best-effort server stop\n }\n removePidFile()\n logger.log('[DAEMON] Stopped.')\n process.exit(0)\n }\n\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n process.on('SIGINT', () => shutdown('SIGINT'))\n\n process.on('uncaughtException', (err) => {\n logger.log(`[FATAL] Uncaught exception: ${err.message}`)\n removePidFile()\n process.exit(1)\n })\n\n process.on('unhandledRejection', (reason) => {\n const message = reason instanceof Error ? reason.message : String(reason)\n logger.log(`[FATAL] Unhandled rejection: ${message}`)\n removePidFile()\n process.exit(1)\n })\n}\n\n/**\n * Fork a detached child process to run the daemon in the background.\n * Returns the child PID.\n */\nexport function forkDaemon(binPath: string, extraArgs: string[] = []): number {\n const child = fork(binPath, ['start', '--_forked', ...extraArgs], {\n detached: true,\n stdio: 'ignore',\n })\n\n child.unref()\n return child.pid!\n}\n\n/**\n * Resolve the bin.ts/bin.js entry point path from import.meta.url.\n */\nexport function resolveBinPath(importMetaUrl: string): string {\n return fileURLToPath(importMetaUrl)\n}\n\n/**\n * Sleep for a given number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { loadConfig, applyOverrides, isConfigured } from '../config/loader.js'\nimport { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport { createRequestHandler } from '../proxy/handler.js'\nimport { ProxyServer } from '../proxy/server.js'\nimport { FileLogger } from '../daemon/logger.js'\nimport {\n isDaemonRunning,\n writePidFile,\n setupSignalHandlers,\n forkDaemon,\n resolveBinPath,\n} from '../daemon/lifecycle.js'\nimport type { ResolvedConfig, Tool } from '../types.js'\nimport { printBanner } from '../version.js'\n\nexport async function startCommand(flags: Map<string, string | true>): Promise<void> {\n const isDaemon = flags.has('d') || flags.has('daemon')\n const isForked = flags.has('_forked')\n\n // Check if already running (skip for forked processes — parent already checked)\n if (!isForked) {\n const state = isDaemonRunning()\n if (state.running) {\n console.error(`Liminal daemon is already running (PID ${state.pid}).`)\n console.error('Use \"liminal stop\" first, or \"liminal status\" to check.')\n process.exit(1)\n }\n }\n\n // Check config\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n\n // Load and apply config\n let config = loadConfig()\n const portOverride = flags.get('port')\n const upstreamOverride = flags.get('upstream')\n config = applyOverrides(config, {\n ...(typeof portOverride === 'string' ? { port: parseInt(portOverride, 10) } : {}),\n ...(typeof upstreamOverride === 'string' ? { upstreamBaseUrl: upstreamOverride } : {}),\n })\n\n // Background mode: fork and exit parent\n if (isDaemon && !isForked) {\n const extraArgs: string[] = []\n if (portOverride) extraArgs.push('--port', String(portOverride))\n if (upstreamOverride) extraArgs.push('--upstream', String(upstreamOverride))\n\n const binPath = resolveBinPath(import.meta.url)\n const childPid = forkDaemon(binPath, extraArgs)\n\n console.log(`Liminal daemon started in background (PID ${childPid})`)\n console.log(`Proxy: http://127.0.0.1:${config.port}/v1`)\n console.log('Logs: ~/.liminal/logs/liminal.log')\n process.exit(0)\n }\n\n // Foreground mode: run the server in this process\n const isForeground = !isDaemon || isForked\n const logger = new FileLogger({ mirrorStdout: isForeground && !isForked })\n\n // Build the resolved config for the proxy\n const resolvedConfig: ResolvedConfig = {\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n proxyPort: config.port,\n compressionThreshold: config.compressionThreshold,\n compressRoles: config.compressRoles,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n upstreamBaseUrl: config.upstreamBaseUrl,\n anthropicUpstreamUrl: config.anthropicUpstreamUrl,\n enabled: config.enabled,\n tools: config.tools as Tool[],\n }\n\n // Create RSC pipeline\n const pipeline = new RSCPipelineWrapper({\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n compressionThreshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n })\n\n // Wire up pipeline events for logging\n pipeline.events.on('compression', (event) => {\n if (event.tokensSaved > 0) {\n logger.log(`[LIMINAL] Compressed: ${event.tokensSaved} tokens saved (${event.ratio.toFixed(3)} ratio)`)\n }\n })\n pipeline.events.on('compression_skipped', (event) => {\n logger.log(`[LIMINAL] Skipped: ${event.reason}`)\n })\n pipeline.events.on('error', (event) => {\n logger.log(`[LIMINAL] Error: ${event.error.message}`)\n })\n pipeline.events.on('degradation', (event) => {\n logger.log(`[LIMINAL] Circuit ${event.circuitState}: ${event.reason}`)\n })\n\n // Create server\n const handler = createRequestHandler(pipeline, resolvedConfig, logger)\n const server = new ProxyServer(config.port, handler)\n\n // Setup graceful shutdown\n setupSignalHandlers(server, logger)\n\n // Start listening\n try {\n const actualPort = await server.start()\n writePidFile(process.pid)\n\n logger.log(`[DAEMON] Liminal proxy started on http://127.0.0.1:${actualPort}`)\n logger.log(`[DAEMON] Upstream (OpenAI): ${config.upstreamBaseUrl}`)\n logger.log(`[DAEMON] Upstream (Anthropic): ${config.anthropicUpstreamUrl}`)\n logger.log(`[DAEMON] Liminal API: ${config.apiBaseUrl}`)\n logger.log(`[DAEMON] PID: ${process.pid}`)\n\n if (isForeground && !isForked) {\n printBanner()\n console.log(` Liminal proxy running on http://127.0.0.1:${actualPort}/v1`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n console.log(' Point your AI tool\\'s base URL here. Press Ctrl+C to stop.')\n console.log()\n }\n\n // Check RSC API health on startup\n const healthy = await pipeline.healthCheck()\n if (healthy) {\n logger.log('[DAEMON] Liminal API health check: OK')\n } else {\n logger.log('[DAEMON] Liminal API health check: FAILED (will retry on first request)')\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Failed to start proxy: ${message}`)\n process.exit(1)\n }\n}\n","import {\n isDaemonRunning,\n readPidFile,\n removePidFile,\n isProcessAlive,\n sleep,\n} from '../daemon/lifecycle.js'\n\nexport async function stopCommand(): Promise<void> {\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running.')\n return\n }\n\n const pid = state.pid\n console.log(`Stopping Liminal daemon (PID ${pid})...`)\n\n // Send SIGTERM for graceful shutdown\n try {\n process.kill(pid, 'SIGTERM')\n } catch {\n // Process may have already exited\n removePidFile()\n console.log('Liminal daemon stopped.')\n return\n }\n\n // Poll for up to 5 seconds\n for (let i = 0; i < 25; i++) {\n await sleep(200)\n if (!isProcessAlive(pid)) {\n removePidFile()\n console.log(`Liminal daemon stopped (PID ${pid}).`)\n return\n }\n }\n\n // Force kill after timeout\n try {\n process.kill(pid, 'SIGKILL')\n } catch {\n // Already dead\n }\n\n removePidFile()\n console.log(`Liminal daemon force-killed (PID ${pid}).`)\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function statusCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal: not configured')\n console.log('Run \"liminal init\" to set up.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal Daemon: stopped')\n console.log('Run \"liminal start\" to start the proxy.')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n // Try to reach the daemon's /health endpoint\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n status: string\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log(`Circuit: ${data.circuit_state}`)\n console.log(`Session: ${data.session_id}`)\n console.log(`Uptime: ${uptime}`)\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n console.log()\n console.log(`Tokens: ${s.tokens_processed.toLocaleString()} processed, ${s.tokens_saved.toLocaleString()} saved (${savingsPercent}%)`)\n console.log(`Calls: ${s.calls_total} total (${s.calls_compressed} compressed, ${s.calls_skipped} skipped, ${s.calls_failed} failed)`)\n }\n } catch {\n // Can't reach the daemon, but PID is alive — might still be starting\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log('Circuit: unknown (could not reach /health)')\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function summaryCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal is not configured. Run \"liminal init\" first.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running. Start it with \"liminal start\".')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n patterns_learned: number\n estimated_cost_saved_usd: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log()\n console.log(` Session: ${data.session_id}`)\n console.log(` Uptime: ${uptime}`)\n console.log()\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n const compressionRate = s.calls_total > 0\n ? ((s.calls_compressed / s.calls_total) * 100).toFixed(0)\n : '0'\n\n console.log(' Compression:')\n console.log(` Tokens processed: ${s.tokens_processed.toLocaleString()}`)\n console.log(` Tokens saved: ${s.tokens_saved.toLocaleString()} (${savingsPercent}%)`)\n console.log(` Compression rate: ${compressionRate}% of calls compressed`)\n console.log(` Patterns learned: ${s.patterns_learned.toLocaleString()}`)\n console.log()\n console.log(' Calls:')\n console.log(` Total: ${s.calls_total}`)\n console.log(` Compressed: ${s.calls_compressed}`)\n console.log(` Skipped: ${s.calls_skipped}`)\n console.log(` Failed: ${s.calls_failed}`)\n console.log()\n console.log(' Cost Savings:')\n console.log(` Estimated: $${s.estimated_cost_saved_usd.toFixed(4)} USD`)\n console.log()\n } else {\n console.log(' No session data available yet.')\n console.log()\n }\n\n console.log(` Circuit: ${data.circuit_state}`)\n console.log(` API: ${config.apiBaseUrl}`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n } catch {\n console.error('Could not reach the Liminal daemon. Is it running?')\n console.error(`Tried http://127.0.0.1:${port}/health`)\n process.exit(1)\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { loadConfig, saveConfig, isConfigured, maskApiKey } from '../config/loader.js'\nimport { CONFIGURABLE_KEYS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\n\nexport async function configCommand(flags: Map<string, string | true>): Promise<void> {\n const getKey = flags.get('get')\n const setKv = flags.get('set')\n\n // rsc config --get <key>\n if (typeof getKey === 'string') {\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n const config = loadConfig()\n const value = (config as unknown as Record<string, unknown>)[getKey]\n if (value === undefined) {\n console.error(`Unknown config key: ${getKey}`)\n process.exit(1)\n }\n console.log(getKey === 'apiKey' ? maskApiKey(String(value)) : String(value))\n return\n }\n\n // rsc config --set <key>=<value>\n if (typeof setKv === 'string') {\n const eqIdx = setKv.indexOf('=')\n if (eqIdx === -1) {\n console.error('Usage: liminal config --set key=value')\n process.exit(1)\n }\n const key = setKv.slice(0, eqIdx)\n const rawValue = setKv.slice(eqIdx + 1)\n\n if (!CONFIGURABLE_KEYS.has(key) && key !== 'apiKey') {\n console.error(`Unknown or non-configurable key: ${key}`)\n console.error(`Configurable keys: ${[...CONFIGURABLE_KEYS].join(', ')}`)\n process.exit(1)\n }\n\n // Parse value based on key type\n let parsedValue: unknown = rawValue\n if (key === 'port' || key === 'compressionThreshold' || key === 'latencyBudgetMs') {\n parsedValue = parseInt(rawValue, 10)\n if (isNaN(parsedValue as number)) {\n console.error(`Invalid number for ${key}: ${rawValue}`)\n process.exit(1)\n }\n } else if (key === 'learnFromResponses' || key === 'enabled') {\n parsedValue = rawValue === 'true' || rawValue === '1'\n } else if (key === 'compressRoles') {\n parsedValue = rawValue.split(',').map((s) => s.trim())\n }\n\n saveConfig({ [key]: parsedValue })\n console.log(`Set ${key} = ${key === 'apiKey' ? maskApiKey(rawValue) : rawValue}`)\n return\n }\n\n // rsc config (no flags) — show all\n if (!isConfigured()) {\n console.log(`Liminal is not configured. Run \"liminal init\" first.`)\n console.log(`Config file: ${CONFIG_FILE}`)\n return\n }\n\n const config = loadConfig()\n console.log()\n console.log(` Config: ${CONFIG_FILE}`)\n console.log()\n console.log(` apiKey: ${maskApiKey(config.apiKey)}`)\n console.log(` apiBaseUrl: ${config.apiBaseUrl}`)\n console.log(` upstreamBaseUrl: ${config.upstreamBaseUrl}`)\n console.log(` anthropicUpstreamUrl: ${config.anthropicUpstreamUrl}`)\n console.log(` tools: ${config.tools.length > 0 ? config.tools.join(', ') : '(none)'}`)\n console.log(` port: ${config.port}`)\n console.log(` compressionThreshold: ${config.compressionThreshold}`)\n console.log(` compressRoles: ${config.compressRoles.join(', ')}`)\n console.log(` learnFromResponses: ${config.learnFromResponses}`)\n console.log(` latencyBudgetMs: ${config.latencyBudgetMs || 'auto'}`)\n console.log(` enabled: ${config.enabled}`)\n console.log()\n}\n","import { readFileSync, existsSync, statSync, createReadStream } from 'node:fs'\nimport { watchFile, unwatchFile } from 'node:fs'\nimport { LOG_FILE } from '../config/paths.js'\n\nexport async function logsCommand(flags: Map<string, string | true>): Promise<void> {\n const follow = flags.has('follow') || flags.has('f')\n const linesFlag = flags.get('lines') ?? flags.get('n')\n const lines = typeof linesFlag === 'string' ? parseInt(linesFlag, 10) : 50\n\n if (!existsSync(LOG_FILE)) {\n console.log('No log file found. Start the daemon with \"liminal start\" to generate logs.')\n return\n }\n\n // Read and display last N lines\n const content = readFileSync(LOG_FILE, 'utf-8')\n const allLines = content.split('\\n')\n const tail = allLines.slice(-lines - 1) // -1 to account for trailing newline\n process.stdout.write(tail.join('\\n'))\n\n if (!follow) return\n\n // Follow mode: watch for changes and stream new content\n let lastSize = statSync(LOG_FILE).size\n\n watchFile(LOG_FILE, { interval: 500 }, (curr) => {\n if (curr.size > lastSize) {\n const stream = createReadStream(LOG_FILE, { start: lastSize, encoding: 'utf-8' })\n stream.on('data', (chunk) => process.stdout.write(chunk as string))\n stream.on('end', () => { lastSize = curr.size })\n } else if (curr.size < lastSize) {\n // File was rotated — read from beginning\n lastSize = 0\n }\n })\n\n // Keep the process alive and handle Ctrl+C\n process.on('SIGINT', () => {\n unwatchFile(LOG_FILE)\n process.exit(0)\n })\n\n // Block forever\n await new Promise(() => {})\n}\n","import { VERSION } from './version.js'\nimport { initCommand } from './commands/init.js'\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { startCommand } from './commands/start.js'\nimport { stopCommand } from './commands/stop.js'\nimport { statusCommand } from './commands/status.js'\nimport { summaryCommand } from './commands/summary.js'\nimport { configCommand } from './commands/config.js'\nimport { logsCommand } from './commands/logs.js'\n\nconst USAGE = `\n liminal v${VERSION} — Transparent LLM context compression proxy\n\n Usage:\n liminal init Set up Liminal (login, config)\n liminal login Log in or create an account\n liminal logout Log out of your account\n liminal start [-d] [--port PORT] Start the compression proxy\n liminal stop Stop the running proxy\n liminal status Show proxy health and stats\n liminal summary Detailed session metrics\n liminal config [--set k=v] [--get k] View or edit configuration\n liminal logs [--follow] [--lines N] View proxy logs\n\n Options:\n -h, --help Show this help message\n -v, --version Show version number\n\n Getting started:\n 1. liminal init # Log in + select tools\n 2. liminal start # Start the proxy\n 3. Connect your AI tools:\n Claude Code: export ANTHROPIC_BASE_URL=http://localhost:3141\n Codex: export OPENAI_BASE_URL=http://localhost:3141/v1\n Cursor: Settings > Models > Base URL > http://localhost:3141/v1\n`\n\nfunction parseArgs(argv: string[]): { command: string; flags: Map<string, string | true> } {\n const command = argv[2] ?? ''\n const flags = new Map<string, string | true>()\n\n for (let i = 3; i < argv.length; i++) {\n const arg = argv[i]\n if (arg.startsWith('--')) {\n const key = arg.slice(2)\n // Check if next arg is a value (not another flag)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n } else if (arg.startsWith('-') && arg.length === 2) {\n const key = arg.slice(1)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n }\n }\n\n return { command, flags }\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv)\n\n // Global flags — handle --help and --version as both commands and flags\n if (flags.has('h') || flags.has('help') || command === 'help' || command === '--help' || command === '-h') {\n console.log(USAGE)\n process.exit(0)\n }\n\n if (flags.has('v') || flags.has('version') || command === 'version' || command === '--version' || command === '-v') {\n console.log(VERSION)\n process.exit(0)\n }\n\n try {\n switch (command) {\n case 'init':\n await initCommand()\n break\n\n case 'login':\n await loginCommand()\n break\n\n case 'logout':\n await logoutCommand()\n break\n\n case 'start':\n await startCommand(flags)\n break\n\n case 'stop':\n await stopCommand()\n break\n\n case 'status':\n await statusCommand()\n break\n\n case 'summary':\n await summaryCommand()\n break\n\n case 'config':\n await configCommand(flags)\n break\n\n case 'logs':\n await logsCommand(flags)\n break\n\n case '':\n console.log(USAGE)\n process.exit(0)\n break\n\n default:\n console.error(`Unknown command: ${command}`)\n console.log(USAGE)\n process.exit(1)\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Error: ${message}`)\n process.exit(1)\n }\n}\n\nmain()\n"],"mappings":"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","names":["createInterface","stdin","stdout","existsSync","readFileSync","join","homedir","stdin","stdout","homedir","join","existsSync","readFileSync","createInterface","stdin","stdout","RSCCircuitOpenError","RSCCircuitOpenError","RSCCircuitOpenError","setCORSHeaders","RSCCircuitOpenError","setCORSHeaders","sendJSON","appendFileSync","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","appendFileSync","readFileSync","writeFileSync","existsSync","writeFileSync","existsSync","readFileSync","formatUptime","config","readFileSync","existsSync","statSync","existsSync","readFileSync","statSync"]}
1
+ {"version":3,"sources":["../src/rsc/pipeline.ts","../src/version.ts","../src/config/loader.ts","../src/config/paths.ts","../src/config/schema.ts","../src/config/shell.ts","../src/ui/prompts.ts","../src/commands/login.ts","../src/auth/supabase.ts","../src/connectors/claude-code.ts","../src/connectors/codex.ts","../src/connectors/cursor.ts","../src/connectors/openai-compatible.ts","../src/connectors/index.ts","../src/commands/init.ts","../src/commands/logout.ts","../src/proxy/completions.ts","../src/rsc/message-compressor.ts","../src/rsc/content-segmenter.ts","../src/rsc/conversation-analyzer.ts","../src/rsc/learning.ts","../src/proxy/streaming.ts","../src/terminology.ts","../src/proxy/messages.ts","../src/proxy/anthropic-streaming.ts","../src/proxy/responses.ts","../src/proxy/responses-streaming.ts","../src/proxy/session-identity.ts","../src/proxy/handler.ts","../src/proxy/server.ts","../src/daemon/logger.ts","../src/rsc/session-manager.ts","../src/rsc/semaphore.ts","../src/rsc/latency-monitor.ts","../src/tls/connect-handler.ts","../src/tls/allowlist.ts","../src/tls/ca.ts","../src/tls/trust.ts","../src/tls/mitm-bridge.ts","../src/tls/cert-generator.ts","../src/daemon/lifecycle.ts","../src/commands/start.ts","../src/commands/stop.ts","../src/commands/status.ts","../src/commands/summary.ts","../src/commands/config.ts","../src/commands/logs.ts","../src/commands/uninstall.ts","../src/commands/trust-ca.ts","../src/commands/untrust-ca.ts","../src/bin.ts"],"sourcesContent":["import {\n CompressionPipeline,\n RSCTransport,\n RSCEventEmitter,\n Session,\n CircuitBreaker,\n} from '@cognisos/rsc-sdk'\nimport type { SessionSummary, CircuitState } from '@cognisos/rsc-sdk'\n\nexport interface PipelineConfig {\n rscApiKey: string\n rscBaseUrl: string\n compressionThreshold: number\n learnFromResponses: boolean\n latencyBudgetMs?: number\n sessionId?: string\n}\n\nexport class RSCPipelineWrapper {\n readonly pipeline: CompressionPipeline\n readonly session: Session\n readonly events: RSCEventEmitter\n readonly transport: RSCTransport\n private readonly circuitBreaker: CircuitBreaker\n\n constructor(config: PipelineConfig) {\n this.circuitBreaker = new CircuitBreaker(5, 5 * 60 * 1000)\n\n this.transport = new RSCTransport({\n baseUrl: config.rscBaseUrl,\n apiKey: config.rscApiKey,\n timeout: 30_000,\n maxRetries: 3,\n circuitBreaker: this.circuitBreaker,\n })\n\n this.events = new RSCEventEmitter()\n this.session = new Session(config.sessionId)\n\n this.pipeline = new CompressionPipeline(\n this.transport,\n {\n threshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs,\n sessionId: this.session.sessionId,\n },\n this.events,\n )\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n await this.transport.get<{ status: string }>('/health')\n return true\n } catch {\n return false\n }\n }\n\n getSessionSummary(): SessionSummary {\n return this.session.getSummary()\n }\n\n getCircuitState(): CircuitState {\n return this.circuitBreaker.getState()\n }\n\n isCircuitOpen(): boolean {\n return this.circuitBreaker.getState() === 'open'\n }\n\n resetCircuitBreaker(): void {\n this.circuitBreaker.reset()\n }\n}\n","declare const __VERSION__: string\nexport const VERSION = typeof __VERSION__ !== 'undefined' ? __VERSION__ : '0.2.1'\n\n// FIGlet-style \"LIMINAL\" banner\nconst BANNER_LINES = [\n ' ___ ___ _____ ______ ___ ________ ________ ___',\n '|\\\\ \\\\ |\\\\ \\\\|\\\\ _ \\\\ _ \\\\|\\\\ \\\\|\\\\ ___ \\\\|\\\\ __ \\\\|\\\\ \\\\',\n '\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\\\\\__\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\|\\\\ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\|__| \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ __ \\\\ \\\\ \\\\',\n ' \\\\ \\\\ \\\\____\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\\\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\ \\\\____',\n ' \\\\ \\\\_______\\\\ \\\\__\\\\ \\\\__\\\\ \\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\\\\\ \\\\__\\\\ \\\\__\\\\ \\\\__\\\\ \\\\_______\\\\',\n ' \\\\|_______|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__| \\\\|__|\\\\|__|\\\\|__|\\\\|_______|',\n]\n\nexport function printBanner(): void {\n console.log()\n for (const line of BANNER_LINES) {\n console.log(line)\n }\n console.log()\n console.log(` v${VERSION} -- brought to you by Cognisos`)\n console.log()\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LIMINAL_DIR, CONFIG_FILE, LOG_DIR } from './paths.js'\nimport { DEFAULTS } from './schema.js'\nimport type { RSCConfig } from './schema.js'\n\n/**\n * Load config from ~/.liminal/config.json, merged with defaults and env var overrides.\n * Priority: env vars > config file > defaults\n */\nexport function loadConfig(): RSCConfig {\n let fileConfig: Partial<RSCConfig> = {}\n\n if (existsSync(CONFIG_FILE)) {\n try {\n const raw = readFileSync(CONFIG_FILE, 'utf-8')\n fileConfig = JSON.parse(raw)\n } catch {\n // Corrupted config file — fall through to defaults\n }\n }\n\n const merged: RSCConfig = {\n apiKey: fileConfig.apiKey ?? '',\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port: DEFAULTS.port,\n compressionThreshold: DEFAULTS.compressionThreshold,\n aggregateThreshold: DEFAULTS.aggregateThreshold,\n hotFraction: DEFAULTS.hotFraction,\n coldFraction: DEFAULTS.coldFraction,\n compressRoles: DEFAULTS.compressRoles,\n compressToolResults: DEFAULTS.compressToolResults,\n learnFromResponses: DEFAULTS.learnFromResponses,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n tools: DEFAULTS.tools,\n concurrencyLimit: DEFAULTS.concurrencyLimit,\n concurrencyTimeoutMs: DEFAULTS.concurrencyTimeoutMs,\n maxSessions: DEFAULTS.maxSessions,\n sessionTtlMs: DEFAULTS.sessionTtlMs,\n latencyWarningMs: DEFAULTS.latencyWarningMs,\n latencyCriticalMs: DEFAULTS.latencyCriticalMs,\n ...fileConfig,\n }\n\n // Environment variable overrides\n if (process.env.LIMINAL_API_KEY) merged.apiKey = process.env.LIMINAL_API_KEY\n if (process.env.LIMINAL_API_URL) merged.apiBaseUrl = process.env.LIMINAL_API_URL\n if (process.env.LIMINAL_UPSTREAM_URL) merged.upstreamBaseUrl = process.env.LIMINAL_UPSTREAM_URL\n if (process.env.LIMINAL_ANTHROPIC_URL) merged.anthropicUpstreamUrl = process.env.LIMINAL_ANTHROPIC_URL\n if (process.env.LIMINAL_PORT) merged.port = parseInt(process.env.LIMINAL_PORT, 10)\n\n return merged\n}\n\n/**\n * Apply CLI flag overrides on top of loaded config.\n */\nexport function applyOverrides(\n config: RSCConfig,\n overrides: Partial<Pick<RSCConfig, 'port' | 'upstreamBaseUrl'>>,\n): RSCConfig {\n return { ...config, ...overrides }\n}\n\n/**\n * Save config to ~/.liminal/config.json. Creates ~/.liminal/ and ~/.liminal/logs/ if needed.\n */\nexport function saveConfig(config: Partial<RSCConfig>): void {\n ensureDirectories()\n\n let existing: Partial<RSCConfig> = {}\n if (existsSync(CONFIG_FILE)) {\n try {\n existing = JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'))\n } catch {\n // Overwrite corrupted file\n }\n }\n\n const merged = { ...existing, ...config }\n writeFileSync(CONFIG_FILE, JSON.stringify(merged, null, 2) + '\\n', { encoding: 'utf-8', mode: 0o600 })\n try { chmodSync(CONFIG_FILE, 0o600) } catch { /* best effort */ }\n}\n\n/**\n * Ensure ~/.liminal/ and ~/.liminal/logs/ directories exist.\n */\nexport function ensureDirectories(): void {\n if (!existsSync(LIMINAL_DIR)) mkdirSync(LIMINAL_DIR, { recursive: true, mode: 0o700 })\n if (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true, mode: 0o700 })\n // Ensure parent of config file exists\n const configDir = dirname(CONFIG_FILE)\n if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true })\n}\n\n/**\n * Check if a valid config file exists with an API key.\n */\nexport function isConfigured(): boolean {\n try {\n const config = loadConfig()\n return config.apiKey.length > 0\n } catch {\n return false\n }\n}\n\n/**\n * Mask an API key for display: show first 8 chars + last 4.\n */\nexport function maskApiKey(key: string): string {\n if (key.length <= 12) return '****'\n return key.slice(0, 8) + '...' + key.slice(-4)\n}\n","import { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport const LIMINAL_DIR = join(homedir(), '.liminal')\nexport const CONFIG_FILE = join(LIMINAL_DIR, 'config.json')\nexport const PID_FILE = join(LIMINAL_DIR, 'liminal.pid')\nexport const LOG_DIR = join(LIMINAL_DIR, 'logs')\nexport const LOG_FILE = join(LOG_DIR, 'liminal.log')\n","export interface RSCConfig {\n apiKey: string\n apiBaseUrl: string\n upstreamBaseUrl: string\n anthropicUpstreamUrl: string\n port: number\n compressionThreshold: number\n aggregateThreshold: number\n hotFraction: number\n coldFraction: number\n compressRoles: string[]\n compressToolResults: boolean\n learnFromResponses: boolean\n latencyBudgetMs: number\n enabled: boolean\n tools: string[]\n // Multi-session concurrency settings\n concurrencyLimit: number\n concurrencyTimeoutMs: number\n maxSessions: number\n sessionTtlMs: number\n latencyWarningMs: number\n latencyCriticalMs: number\n}\n\nexport const DEFAULTS: Omit<RSCConfig, 'apiKey'> = {\n apiBaseUrl: 'https://api.cognisos.ai',\n upstreamBaseUrl: 'https://api.openai.com',\n anthropicUpstreamUrl: 'https://api.anthropic.com',\n port: 3141,\n compressionThreshold: 100,\n aggregateThreshold: 500,\n hotFraction: 0.3,\n coldFraction: 0.3,\n compressRoles: ['user', 'assistant'],\n compressToolResults: true,\n learnFromResponses: true,\n latencyBudgetMs: 5000,\n enabled: true,\n tools: [],\n concurrencyLimit: 6,\n concurrencyTimeoutMs: 15000,\n maxSessions: 10,\n sessionTtlMs: 1800000,\n latencyWarningMs: 4000,\n latencyCriticalMs: 8000,\n}\n\n/** Keys that can be set via `liminal config --set` */\nexport const CONFIGURABLE_KEYS = new Set<string>([\n 'apiBaseUrl',\n 'upstreamBaseUrl',\n 'anthropicUpstreamUrl',\n 'port',\n 'compressionThreshold',\n 'aggregateThreshold',\n 'hotFraction',\n 'coldFraction',\n 'compressRoles',\n 'compressToolResults',\n 'learnFromResponses',\n 'latencyBudgetMs',\n 'enabled',\n 'tools',\n 'concurrencyLimit',\n 'concurrencyTimeoutMs',\n 'maxSessions',\n 'sessionTtlMs',\n 'latencyWarningMs',\n 'latencyCriticalMs',\n])\n","/**\n * Shell profile detection and modification utilities.\n * Shared by init (append exports) and uninstall (remove exports).\n */\n\nimport { existsSync, readFileSync, writeFileSync, appendFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport interface ShellProfile {\n name: string\n path: string\n}\n\nconst LIMINAL_BLOCK_HEADER = '# Liminal — route AI tools through compression proxy'\n\n/**\n * Detect the user's shell profile file.\n */\nexport function detectShellProfile(): ShellProfile | null {\n const shell = process.env.SHELL || ''\n const home = homedir()\n\n if (shell.endsWith('/zsh')) {\n return { name: '~/.zshrc', path: join(home, '.zshrc') }\n }\n\n if (shell.endsWith('/bash')) {\n const bashProfile = join(home, '.bash_profile')\n if (existsSync(bashProfile)) {\n return { name: '~/.bash_profile', path: bashProfile }\n }\n return { name: '~/.bashrc', path: join(home, '.bashrc') }\n }\n\n const candidates: ShellProfile[] = [\n { name: '~/.zshrc', path: join(home, '.zshrc') },\n { name: '~/.bashrc', path: join(home, '.bashrc') },\n { name: '~/.profile', path: join(home, '.profile') },\n ]\n\n for (const c of candidates) {\n if (existsSync(c.path)) return c\n }\n\n return null\n}\n\n/**\n * Check if a line already exists in a file.\n */\nexport function lineExistsInFile(filePath: string, line: string): boolean {\n if (!existsSync(filePath)) return false\n try {\n const content = readFileSync(filePath, 'utf-8')\n return content.includes(line)\n } catch {\n return false\n }\n}\n\n/**\n * Append export lines to shell profile with a Liminal comment header.\n * Only appends lines that don't already exist.\n */\nexport function appendToShellProfile(profile: ShellProfile, lines: string[]): string[] {\n const newLines = lines.filter((line) => !lineExistsInFile(profile.path, line))\n if (newLines.length === 0) return []\n\n const block = [\n '',\n LIMINAL_BLOCK_HEADER,\n ...newLines,\n ].join('\\n') + '\\n'\n\n appendFileSync(profile.path, block, 'utf-8')\n return newLines\n}\n\n/**\n * Remove all Liminal-related lines from a shell profile.\n * Removes the header comment and any export lines containing Liminal proxy URLs.\n * Returns the lines that were removed.\n */\nexport function removeLiminalFromShellProfile(profile: ShellProfile): string[] {\n if (!existsSync(profile.path)) return []\n\n let content: string\n try {\n content = readFileSync(profile.path, 'utf-8')\n } catch {\n return []\n }\n\n const lines = content.split('\\n')\n const removed: string[] = []\n const kept: string[] = []\n\n for (const line of lines) {\n if (line.trim() === LIMINAL_BLOCK_HEADER) {\n removed.push(line)\n continue\n }\n\n // Match Liminal proxy export lines:\n // export ANTHROPIC_BASE_URL=http://127.0.0.1:XXXX\n // export OPENAI_BASE_URL=http://127.0.0.1:XXXX/v1\n if (isLiminalExportLine(line)) {\n removed.push(line)\n continue\n }\n\n kept.push(line)\n }\n\n if (removed.length > 0) {\n // Clean up consecutive blank lines left by removal\n const cleaned = kept.join('\\n').replace(/\\n{3,}/g, '\\n\\n')\n writeFileSync(profile.path, cleaned, 'utf-8')\n }\n\n return removed\n}\n\n/**\n * Check if a line is a Liminal proxy export.\n */\nfunction isLiminalExportLine(line: string): boolean {\n const trimmed = line.trim()\n if (!trimmed.startsWith('export ')) return false\n // Match export ANTHROPIC_BASE_URL=http://127.0.0.1:XXXX or similar\n if (trimmed.includes('ANTHROPIC_BASE_URL=http://127.0.0.1:')) return true\n if (trimmed.includes('OPENAI_BASE_URL=http://127.0.0.1:')) return true\n return false\n}\n\n/**\n * Find all Liminal export lines currently in a shell profile.\n */\nexport function findLiminalExportsInProfile(profile: ShellProfile): string[] {\n if (!existsSync(profile.path)) return []\n try {\n const content = readFileSync(profile.path, 'utf-8')\n return content.split('\\n').filter(isLiminalExportLine)\n } catch {\n return []\n }\n}\n","/**\n * Lightweight interactive terminal prompts — zero external dependencies.\n * Uses raw stdin mode for arrow-key navigation.\n */\n\n// ─── ANSI escape sequences ───────────────────────────────────────────\n\nconst ANSI = {\n HIDE_CURSOR: '\\x1b[?25l',\n SHOW_CURSOR: '\\x1b[?25h',\n CLEAR_LINE: '\\x1b[2K',\n BOLD: '\\x1b[1m',\n DIM: '\\x1b[2m',\n CYAN: '\\x1b[36m',\n RESET: '\\x1b[0m',\n moveUp: (n: number) => (n > 0 ? `\\x1b[${n}A` : ''),\n} as const\n\n// ─── Key parsing ─────────────────────────────────────────────────────\n\nexport type KeyPress =\n | { type: 'up' }\n | { type: 'down' }\n | { type: 'enter' }\n | { type: 'space' }\n | { type: 'escape' }\n | { type: 'ctrlc' }\n | { type: 'backspace' }\n | { type: 'char'; char: string }\n | { type: 'other' }\n\nexport function parseKey(data: Buffer): KeyPress {\n if (data.length === 0) return { type: 'other' }\n\n // Ctrl+C\n if (data[0] === 0x03) return { type: 'ctrlc' }\n\n // Arrow keys: ESC [ A/B\n if (data.length >= 3 && data[0] === 0x1b && data[1] === 0x5b) {\n if (data[2] === 0x41) return { type: 'up' }\n if (data[2] === 0x42) return { type: 'down' }\n return { type: 'other' }\n }\n\n // Standalone Escape\n if (data.length === 1 && data[0] === 0x1b) return { type: 'escape' }\n\n // Enter\n if (data[0] === 0x0d || data[0] === 0x0a) return { type: 'enter' }\n\n // Space\n if (data[0] === 0x20) return { type: 'space' }\n\n // Backspace (DEL on macOS)\n if (data[0] === 0x7f || data[0] === 0x08) return { type: 'backspace' }\n\n // Printable ASCII characters (0x21-0x7e)\n if (data.length === 1 && data[0] >= 0x21 && data[0] <= 0x7e) {\n return { type: 'char', char: String.fromCharCode(data[0]) }\n }\n\n return { type: 'other' }\n}\n\n// ─── Types ───────────────────────────────────────────────────────────\n\nexport interface SelectOption<T> {\n label: string\n value: T\n description?: string\n}\n\nexport interface MultiSelectOption<T> extends SelectOption<T> {\n default?: boolean\n}\n\ninterface Streams {\n stdin: NodeJS.ReadableStream & { setRawMode?: (mode: boolean) => void; isTTY?: boolean }\n stdout: { write: (s: string) => boolean }\n}\n\ninterface SelectConfig<T> {\n message: string\n options: SelectOption<T>[]\n defaultIndex?: number\n _streams?: Streams\n}\n\ninterface MultiSelectConfig<T> {\n message: string\n options: MultiSelectOption<T>[]\n _streams?: Streams\n}\n\n// ─── Render helpers ──────────────────────────────────────────────────\n\nexport interface RenderResult {\n text: string\n lineCount: number\n}\n\nexport function renderSelect<T>(\n options: SelectOption<T>[],\n cursorIndex: number,\n message: string,\n): RenderResult {\n const lines: string[] = []\n lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`)\n lines.push('')\n\n const maxLabel = Math.max(...options.map((o) => o.label.length))\n\n for (let i = 0; i < options.length; i++) {\n const focused = i === cursorIndex\n const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : ' '\n const label = focused\n ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}`\n : `${options[i].label.padEnd(maxLabel)}`\n const desc = options[i].description\n ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}`\n : ''\n lines.push(` ${pointer} ${label}${desc}`)\n }\n\n lines.push('')\n return { text: lines.join('\\n'), lineCount: lines.length }\n}\n\nexport function renderMultiSelect<T>(\n options: MultiSelectOption<T>[],\n cursorIndex: number,\n selected: Set<number>,\n message: string,\n): RenderResult {\n const lines: string[] = []\n lines.push(` ${ANSI.BOLD}${message}${ANSI.RESET}`)\n lines.push('')\n\n const maxLabel = Math.max(...options.map((o) => o.label.length))\n\n for (let i = 0; i < options.length; i++) {\n const focused = i === cursorIndex\n const checked = selected.has(i)\n const pointer = focused ? `${ANSI.CYAN}->${ANSI.RESET}` : ' '\n const box = checked\n ? `${ANSI.CYAN}[x]${ANSI.RESET}`\n : `${ANSI.DIM}[ ]${ANSI.RESET}`\n const label = focused\n ? `${ANSI.BOLD}${options[i].label.padEnd(maxLabel)}${ANSI.RESET}`\n : `${options[i].label.padEnd(maxLabel)}`\n const desc = options[i].description\n ? ` ${ANSI.DIM}${options[i].description}${ANSI.RESET}`\n : ''\n lines.push(` ${pointer} ${box} ${label}${desc}`)\n }\n\n lines.push('')\n lines.push(` ${ANSI.DIM}↑/↓ Navigate ${ANSI.RESET}${ANSI.CYAN}Space${ANSI.RESET}${ANSI.DIM} Select ${ANSI.RESET}${ANSI.CYAN}Enter${ANSI.RESET}${ANSI.DIM} Confirm${ANSI.RESET}`)\n lines.push('')\n return { text: lines.join('\\n'), lineCount: lines.length }\n}\n\n// ─── Raw mode lifecycle ──────────────────────────────────────────────\n\nfunction withRawMode<T>(\n streams: Streams,\n handler: (\n resolve: (value: T) => void,\n ) => (key: KeyPress) => void,\n): Promise<T> {\n const { stdin, stdout } = streams\n\n return new Promise<T>((resolve, reject) => {\n let cleaned = false\n\n function cleanup() {\n if (cleaned) return\n cleaned = true\n stdin.removeListener('data', onData)\n if (stdin.setRawMode) stdin.setRawMode(false)\n if ('pause' in stdin && typeof (stdin as any).pause === 'function') {\n (stdin as any).pause()\n }\n stdout.write(ANSI.SHOW_CURSOR)\n process.removeListener('exit', cleanup)\n }\n\n function onData(data: Buffer) {\n const key = parseKey(data)\n if (key.type === 'ctrlc') {\n cleanup()\n process.exit(130)\n }\n keyHandler(key)\n }\n\n const keyHandler = handler((value: T) => {\n cleanup()\n resolve(value)\n })\n\n // Safety: restore terminal on unexpected exit\n process.on('exit', cleanup)\n\n try {\n if (stdin.setRawMode) stdin.setRawMode(true)\n stdout.write(ANSI.HIDE_CURSOR)\n stdin.on('data', onData)\n if ('resume' in stdin && typeof (stdin as any).resume === 'function') {\n (stdin as any).resume()\n }\n } catch (err) {\n cleanup()\n reject(err)\n }\n })\n}\n\n// ─── Public API ──────────────────────────────────────────────────────\n\nexport async function selectPrompt<T>(config: SelectConfig<T>): Promise<T | null> {\n const { message, options, defaultIndex = 0, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let cursorIndex = defaultIndex\n let prevLineCount = 0\n\n function draw() {\n const { text, lineCount } = renderSelect(options, cursorIndex, message)\n // Move up to overwrite previous render\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n // Clear and write each line\n const lines = text.split('\\n')\n for (const line of lines) {\n streams.stdout.write(ANSI.CLEAR_LINE + line + '\\n')\n }\n prevLineCount = lineCount\n }\n\n draw()\n\n const result = await withRawMode<T | null>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'up':\n cursorIndex = (cursorIndex - 1 + options.length) % options.length\n draw()\n break\n case 'down':\n cursorIndex = (cursorIndex + 1) % options.length\n draw()\n break\n case 'enter':\n resolve(options[cursorIndex].value)\n break\n case 'escape':\n resolve(null)\n break\n }\n }\n })\n\n // Show confirmed selection\n if (result !== null) {\n const selected = options.find((o) => o.value === result)\n if (selected) {\n // Overwrite prompt with confirmed value\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n for (let i = 0; i < prevLineCount; i++) {\n streams.stdout.write(ANSI.CLEAR_LINE + '\\n')\n }\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${selected.label}${ANSI.RESET}\\n`)\n }\n }\n\n return result\n}\n\nexport async function multiSelectPrompt<T>(config: MultiSelectConfig<T>): Promise<T[] | null> {\n const { message, options, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let cursorIndex = 0\n const selected = new Set<number>()\n let prevLineCount = 0\n\n // Pre-fill defaults\n for (let i = 0; i < options.length; i++) {\n if (options[i].default) selected.add(i)\n }\n\n function draw() {\n const { text, lineCount } = renderMultiSelect(options, cursorIndex, selected, message)\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n const lines = text.split('\\n')\n for (const line of lines) {\n streams.stdout.write(ANSI.CLEAR_LINE + line + '\\n')\n }\n prevLineCount = lineCount\n }\n\n draw()\n\n const result = await withRawMode<T[] | null>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'up':\n cursorIndex = (cursorIndex - 1 + options.length) % options.length\n draw()\n break\n case 'down':\n cursorIndex = (cursorIndex + 1) % options.length\n draw()\n break\n case 'space':\n if (selected.has(cursorIndex)) {\n selected.delete(cursorIndex)\n } else {\n selected.add(cursorIndex)\n }\n draw()\n break\n case 'enter':\n if (selected.size > 0) {\n const values = [...selected].sort().map((i) => options[i].value)\n resolve(values)\n }\n // If nothing selected, ignore Enter (must select at least 1)\n break\n case 'escape':\n resolve(null)\n break\n }\n }\n })\n\n // Show confirmed selection\n if (result !== null) {\n const labels = [...selected].sort().map((i) => options[i].label)\n if (prevLineCount > 0) {\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n }\n for (let i = 0; i < prevLineCount; i++) {\n streams.stdout.write(ANSI.CLEAR_LINE + '\\n')\n }\n streams.stdout.write(ANSI.moveUp(prevLineCount))\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET} ${ANSI.CYAN}${labels.join(', ')}${ANSI.RESET}\\n`)\n }\n\n return result\n}\n\n// ─── Password prompt ─────────────────────────────────────────────────\n\ninterface PasswordConfig {\n message: string\n _streams?: Streams\n}\n\nexport async function passwordPrompt(config: PasswordConfig): Promise<string> {\n const { message, _streams } = config\n const streams = _streams ?? { stdin: process.stdin, stdout: process.stdout }\n let password = ''\n\n streams.stdout.write(` ${ANSI.BOLD}${message}${ANSI.RESET}: `)\n\n const result = await withRawMode<string>(streams, (resolve) => {\n return (key: KeyPress) => {\n switch (key.type) {\n case 'char':\n password += (key as { type: 'char'; char: string }).char\n streams.stdout.write('*')\n break\n case 'space':\n password += ' '\n streams.stdout.write('*')\n break\n case 'backspace':\n if (password.length > 0) {\n password = password.slice(0, -1)\n streams.stdout.write('\\b \\b')\n }\n break\n case 'enter':\n streams.stdout.write('\\n')\n resolve(password)\n break\n case 'escape':\n streams.stdout.write('\\n')\n resolve('')\n break\n }\n }\n })\n\n return result\n}\n","import { createInterface } from 'node:readline/promises'\nimport { stdin, stdout } from 'node:process'\nimport { signIn, signUp, authenticateAndGetKey } from '../auth/supabase.js'\nimport { saveConfig, ensureDirectories, loadConfig } from '../config/loader.js'\nimport { DEFAULTS } from '../config/schema.js'\nimport { printBanner } from '../version.js'\nimport { selectPrompt, passwordPrompt } from '../ui/prompts.js'\nimport type { AuthError } from '../auth/supabase.js'\n\nexport async function loginCommand(): Promise<void> {\n printBanner()\n\n // Check if already logged in\n try {\n const config = loadConfig()\n if (config.apiKey && (config.apiKey.startsWith('lim_') || config.apiKey.startsWith('fmcp_'))) {\n console.log(' Already logged in.')\n console.log(' Run \\x1b[1mliminal logout\\x1b[0m first to switch accounts.')\n return\n }\n } catch {\n // No config yet — proceed with login\n }\n\n await runAuthFlow()\n}\n\n/**\n * Shared auth flow used by both `liminal login` and `liminal init`.\n * Returns the API key on success.\n */\nexport async function runAuthFlow(): Promise<string> {\n const modeResult = await selectPrompt<'login' | 'signup'>({\n message: 'Welcome to Liminal',\n options: [\n { label: 'Log in', value: 'login', description: 'I have an account' },\n { label: 'Create account', value: 'signup', description: 'New to Liminal' },\n ],\n defaultIndex: 0,\n })\n const mode = modeResult ?? 'login'\n\n console.log()\n\n // Collect credentials\n const rl = createInterface({ input: stdin, output: stdout })\n let name = ''\n let email: string\n\n try {\n if (mode === 'signup') {\n name = (await rl.question(' \\x1b[1mName\\x1b[0m: ')).trim()\n if (!name) {\n console.error('\\n Error: Name is required.')\n process.exit(1)\n }\n }\n\n email = (await rl.question(' \\x1b[1mEmail\\x1b[0m: ')).trim()\n if (!email) {\n console.error('\\n Error: Email is required.')\n process.exit(1)\n }\n } finally {\n rl.close()\n }\n\n // Password (masked)\n const password = await passwordPrompt({ message: 'Password' })\n if (!password) {\n console.error('\\n Error: Password is required.')\n process.exit(1)\n }\n\n console.log()\n\n // Authenticate\n const action = mode === 'signup' ? 'Creating account' : 'Logging in'\n process.stdout.write(` ${action}... `)\n\n try {\n const auth = mode === 'signup'\n ? await signUp(email, password, name)\n : await signIn(email, password)\n\n console.log('OK')\n\n // Fetch or create API key\n process.stdout.write(' Setting up API key... ')\n const apiKey = await authenticateAndGetKey(auth)\n console.log('OK')\n\n // Save to config\n ensureDirectories()\n saveConfig({\n apiKey,\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n })\n\n console.log()\n console.log(` Logged in as \\x1b[1m${auth.email}\\x1b[0m`)\n\n return apiKey\n } catch (err) {\n console.log('FAILED')\n const authErr = err as AuthError\n console.error(`\\n ${authErr.message}`)\n\n if (mode === 'login' && authErr.message?.includes('Invalid login')) {\n console.error(' Check your email and password, then try again.')\n }\n\n process.exit(1)\n }\n}\n","/**\n * Lightweight Supabase Auth client using fetch — zero npm dependencies.\n * Uses the public anon key (same as web frontend).\n */\nimport { randomBytes, createHash } from 'node:crypto'\n\nconst SUPABASE_URL = 'https://nzcneiyymvgxvttbenhp.supabase.co'\nconst SUPABASE_ANON_KEY =\n 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im56Y25laXl5bXZneHZ0dGJlbmhwIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTQwNjQ0MjcsImV4cCI6MjA2OTY0MDQyN30.x3E-zGRadbPMmxRqT_PB_KOi00htKpgeb8GiQa4g2z0'\n\n// ─── Types ───────────────────────────────────────────────────────────\n\nexport interface AuthResult {\n accessToken: string\n userId: string\n email: string\n}\n\nexport interface AuthError {\n message: string\n status?: number\n}\n\n// ─── Auth ────────────────────────────────────────────────────────────\n\nfunction supabaseHeaders(accessToken?: string): Record<string, string> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'apikey': SUPABASE_ANON_KEY,\n }\n if (accessToken) {\n headers['Authorization'] = `Bearer ${accessToken}`\n }\n return headers\n}\n\n/**\n * Sign in with email and password.\n */\nexport async function signIn(email: string, password: string): Promise<AuthResult> {\n const res = await fetch(`${SUPABASE_URL}/auth/v1/token?grant_type=password`, {\n method: 'POST',\n headers: supabaseHeaders(),\n body: JSON.stringify({ email, password }),\n })\n\n const body = (await res.json()) as Record<string, any>\n\n if (!res.ok) {\n const msg = body?.error_description || body?.error || body?.msg || 'Authentication failed'\n const err: AuthError = { message: msg, status: res.status }\n throw err\n }\n\n return {\n accessToken: body.access_token,\n userId: body.user?.id,\n email: body.user?.email ?? email,\n }\n}\n\n/**\n * Sign up with email, password, and name.\n */\nexport async function signUp(\n email: string,\n password: string,\n name: string,\n): Promise<AuthResult> {\n const res = await fetch(`${SUPABASE_URL}/auth/v1/signup`, {\n method: 'POST',\n headers: supabaseHeaders(),\n body: JSON.stringify({\n email,\n password,\n data: { name },\n }),\n })\n\n const body = (await res.json()) as Record<string, any>\n\n if (!res.ok) {\n const msg = body?.error_description || body?.error || body?.msg || 'Sign up failed'\n const err: AuthError = { message: msg, status: res.status }\n throw err\n }\n\n // Supabase may return identities: [] if email confirmation is required\n if (body.user?.identities?.length === 0) {\n const err: AuthError = { message: 'Account already exists. Try logging in instead.' }\n throw err\n }\n\n return {\n accessToken: body.access_token,\n userId: body.user?.id,\n email: body.user?.email ?? email,\n }\n}\n\n// ─── API Key Management ──────────────────────────────────────────────\n\n/**\n * Check if the user already has an active API key.\n * Since only key_hash is stored (not plaintext), we can only check existence.\n */\nexport async function hasExistingKey(accessToken: string, userId: string): Promise<boolean> {\n const params = new URLSearchParams({\n user_id: `eq.${userId}`,\n is_active: 'eq.true',\n select: 'id',\n limit: '1',\n })\n\n const res = await fetch(`${SUPABASE_URL}/rest/v1/user_api_keys?${params}`, {\n headers: supabaseHeaders(accessToken),\n })\n\n if (!res.ok) return false\n\n const rows = await res.json()\n return Array.isArray(rows) && rows.length > 0\n}\n\n/**\n * Generate a new API key, store its SHA-256 hash in the database,\n * and return the plaintext key (only shown once).\n */\nexport async function createApiKey(accessToken: string, userId: string): Promise<string> {\n // Delete any existing keys to avoid unique constraint on (user_id, key_name)\n await fetch(`${SUPABASE_URL}/rest/v1/user_api_keys?user_id=eq.${userId}`, {\n method: 'DELETE',\n headers: supabaseHeaders(accessToken),\n })\n\n const apiKey = `lim_${randomBytes(32).toString('hex')}`\n const keyHash = createHash('sha256').update(apiKey).digest('hex')\n\n const res = await fetch(`${SUPABASE_URL}/rest/v1/user_api_keys`, {\n method: 'POST',\n headers: {\n ...supabaseHeaders(accessToken),\n 'Prefer': 'return=representation',\n },\n body: JSON.stringify({\n user_id: userId,\n key_name: 'Liminal CLI',\n key_hash: keyHash,\n is_active: true,\n }),\n })\n\n if (!res.ok) {\n const body = (await res.json().catch(() => ({}))) as Record<string, any>\n const msg = body?.message || body?.error || 'Failed to create API key'\n throw { message: msg, status: res.status } as AuthError\n }\n\n return apiKey\n}\n\n/**\n * Full login flow: authenticate then create API key.\n * Since only hashes are stored, we always generate a fresh key.\n * The plaintext is saved locally in ~/.liminal/config.json.\n */\nexport async function authenticateAndGetKey(\n auth: AuthResult,\n): Promise<string> {\n return createApiKey(auth.accessToken, auth.userId)\n}\n","/**\n * Claude Code connector.\n *\n * Claude Code reads the ANTHROPIC_BASE_URL environment variable to determine\n * where to send API requests. Setting this to Liminal's proxy address routes\n * all traffic through the compression pipeline.\n *\n * Protocol: Anthropic Messages API (POST /v1/messages)\n * Auth: x-api-key header (user's Anthropic API key)\n * Setup: Shell profile export — fully automatic\n */\n\nimport { execSync } from 'node:child_process'\nimport type { Connector, ConnectorInfo, ConnectorStatus, SetupResult, TeardownResult } from './types.js'\n\nconst ENV_VAR = 'ANTHROPIC_BASE_URL'\n\nconst INFO: ConnectorInfo = {\n id: 'claude-code',\n label: 'Claude Code',\n description: 'Anthropic CLI for coding with Claude',\n protocol: 'anthropic-messages',\n automatable: true,\n}\n\nfunction isClaudeInstalled(): boolean {\n try {\n execSync('which claude', { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nfunction getCurrentBaseUrl(): string | undefined {\n return process.env[ENV_VAR] || undefined\n}\n\nexport const claudeCodeConnector: Connector = {\n info: INFO,\n\n async detect(): Promise<ConnectorStatus> {\n const installed = isClaudeInstalled()\n const currentUrl = getCurrentBaseUrl()\n const configured = currentUrl?.includes('127.0.0.1') ?? false\n\n if (!installed) {\n return { installed, configured: false, detail: 'Claude Code not found in PATH' }\n }\n\n if (configured) {\n return { installed, configured, detail: `Routing through ${currentUrl}` }\n }\n\n return { installed, configured, detail: 'Installed but not routing through Liminal' }\n },\n\n getShellExports(port: number): string[] {\n return [`export ${ENV_VAR}=http://127.0.0.1:${port}`]\n },\n\n async setup(port: number): Promise<SetupResult> {\n const exports = this.getShellExports(port)\n\n return {\n success: true,\n shellExports: exports,\n postSetupInstructions: [\n 'Claude Code will automatically route through Liminal.',\n 'Make sure to source your shell profile or restart your terminal.',\n ],\n }\n },\n\n async teardown(): Promise<TeardownResult> {\n return {\n success: true,\n manualSteps: [\n `Remove the line \\`export ${ENV_VAR}=...\\` from your shell profile (~/.zshrc or ~/.bashrc).`,\n 'Restart your terminal or run: unset ANTHROPIC_BASE_URL',\n ],\n }\n },\n}\n","/**\n * OpenAI Codex CLI connector.\n *\n * Codex CLI reads OPENAI_BASE_URL to override its API endpoint. It can also\n * be configured via ~/.codex/config.toml with a custom provider block.\n *\n * Protocol: OpenAI Responses API (POST /v1/responses) — this is the default\n * wire format. Chat completions is a secondary option via config.toml\n * (wire_api = \"chat_completions\") but Responses API is primary.\n * Auth: Authorization: Bearer header (user's OpenAI API key)\n * Setup: Shell profile export — fully automatic. Optional TOML config\n * for advanced users who want a named provider.\n */\n\nimport { execSync } from 'node:child_process'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\nimport type { Connector, ConnectorInfo, ConnectorStatus, SetupResult, TeardownResult } from './types.js'\n\nconst ENV_VAR = 'OPENAI_BASE_URL'\nconst CODEX_CONFIG_DIR = join(homedir(), '.codex')\nconst CODEX_CONFIG_FILE = join(CODEX_CONFIG_DIR, 'config.toml')\n\nconst INFO: ConnectorInfo = {\n id: 'codex',\n label: 'Codex CLI',\n description: 'OpenAI CLI agent for coding (Responses API)',\n protocol: 'openai-responses',\n automatable: true,\n}\n\nfunction isCodexInstalled(): boolean {\n try {\n execSync('which codex', { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nfunction getCurrentBaseUrl(): string | undefined {\n return process.env[ENV_VAR] || undefined\n}\n\nfunction hasCodexConfig(): boolean {\n return existsSync(CODEX_CONFIG_FILE)\n}\n\nfunction codexConfigMentionsLiminal(): boolean {\n if (!hasCodexConfig()) return false\n try {\n const content = readFileSync(CODEX_CONFIG_FILE, 'utf-8')\n return content.includes('127.0.0.1') || content.includes('liminal')\n } catch {\n return false\n }\n}\n\nexport const codexConnector: Connector = {\n info: INFO,\n\n async detect(): Promise<ConnectorStatus> {\n const installed = isCodexInstalled()\n const currentUrl = getCurrentBaseUrl()\n const envConfigured = currentUrl?.includes('127.0.0.1') ?? false\n const tomlConfigured = codexConfigMentionsLiminal()\n const configured = envConfigured || tomlConfigured\n\n if (!installed) {\n return { installed, configured: false, detail: 'Codex CLI not found in PATH' }\n }\n\n if (configured) {\n const via = envConfigured ? ENV_VAR : 'config.toml'\n return { installed, configured, detail: `Routing through Liminal (via ${via})` }\n }\n\n return { installed, configured, detail: 'Installed but not routing through Liminal' }\n },\n\n getShellExports(port: number): string[] {\n // Codex expects base_url to include /v1\n return [`export ${ENV_VAR}=http://127.0.0.1:${port}/v1`]\n },\n\n async setup(port: number): Promise<SetupResult> {\n const exports = this.getShellExports(port)\n\n const instructions = [\n 'Codex CLI will automatically route through Liminal.',\n 'Make sure to source your shell profile or restart your terminal.',\n ]\n\n // Note about Responses API requirement\n instructions.push(\n 'Codex uses the OpenAI Responses API (/v1/responses) by default.',\n )\n\n return {\n success: true,\n shellExports: exports,\n postSetupInstructions: instructions,\n }\n },\n\n async teardown(): Promise<TeardownResult> {\n const steps = [\n `Remove the line \\`export ${ENV_VAR}=...\\` from your shell profile (~/.zshrc or ~/.bashrc).`,\n 'Restart your terminal or run: unset OPENAI_BASE_URL',\n ]\n\n if (codexConfigMentionsLiminal()) {\n steps.push(\n `Remove the Liminal provider block from ${CODEX_CONFIG_FILE}.`,\n )\n }\n\n return { success: true, manualSteps: steps }\n },\n}\n","/**\n * Cursor IDE connector.\n *\n * Cursor stores its AI settings in a SQLite database, not a plain config file.\n * It does NOT read OPENAI_BASE_URL or any env vars for its own LLM calls.\n * Configuration must be done through the Cursor Settings GUI:\n * Settings > Models > \"Override OpenAI Base URL (when using key)\"\n *\n * IMPORTANT: Cursor routes API requests through its cloud servers, NOT\n * from the user's local machine. This means localhost/127.0.0.1 URLs\n * are blocked by Cursor's SSRF protection. Users must either:\n * 1. Use a tunnel (cloudflared, ngrok) to expose the local proxy\n * 2. Deploy the proxy to a public URL\n *\n * Protocol: OpenAI Chat Completions (POST /v1/chat/completions) for basic\n * chat, and OpenAI Responses API (POST /v1/responses) in Agent mode.\n * All requests use OpenAI wire format, even when calling Claude models.\n * Auth: User's real LLM API key (proxy forwards it to the upstream provider)\n * Setup: Manual GUI configuration — cannot be fully automated.\n * The SQLite DB at ~/Library/Application Support/Cursor/User/globalStorage/state.vscdb\n * could be written to programmatically but requires Cursor restart and\n * is fragile across Cursor updates. Guided instructions are safer.\n */\n\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\nimport type { Connector, ConnectorInfo, ConnectorStatus, SetupResult, TeardownResult } from './types.js'\n\nconst INFO: ConnectorInfo = {\n id: 'cursor',\n label: 'Cursor',\n description: 'AI-first code editor (GUI config required)',\n protocol: 'openai-chat',\n automatable: false,\n}\n\n/** Platform-specific Cursor app paths */\nfunction getCursorPaths(): { app: string; data: string } {\n const platform = process.platform\n const home = homedir()\n\n if (platform === 'darwin') {\n return {\n app: '/Applications/Cursor.app',\n data: join(home, 'Library', 'Application Support', 'Cursor'),\n }\n }\n\n if (platform === 'win32') {\n const appData = process.env.APPDATA || join(home, 'AppData', 'Roaming')\n const localAppData = process.env.LOCALAPPDATA || join(home, 'AppData', 'Local')\n return {\n app: join(localAppData, 'Programs', 'Cursor', 'Cursor.exe'),\n data: join(appData, 'Cursor'),\n }\n }\n\n // Linux\n return {\n app: '/usr/bin/cursor',\n data: join(home, '.config', 'Cursor'),\n }\n}\n\nfunction isCursorInstalled(): boolean {\n const { app, data } = getCursorPaths()\n return existsSync(app) || existsSync(data)\n}\n\nfunction getSettingsDbPath(): string {\n const { data } = getCursorPaths()\n return join(data, 'User', 'globalStorage', 'state.vscdb')\n}\n\nexport const cursorConnector: Connector = {\n info: INFO,\n\n async detect(): Promise<ConnectorStatus> {\n const installed = isCursorInstalled()\n const dbExists = existsSync(getSettingsDbPath())\n\n if (!installed) {\n return { installed, configured: false, detail: 'Cursor not found on this system' }\n }\n\n // We can't reliably check if Cursor is configured to use Liminal\n // without reading the SQLite DB, which requires a sqlite3 dependency.\n // Report as installed but unknown configuration state.\n return {\n installed,\n configured: false,\n detail: dbExists\n ? 'Installed — configuration requires Cursor Settings GUI'\n : 'Installed but settings database not found',\n }\n },\n\n getShellExports(_port: number): string[] {\n // Cursor does not read env vars for its LLM base URL\n return []\n },\n\n async setup(port: number): Promise<SetupResult> {\n return {\n success: true,\n shellExports: [], // No env vars — GUI only\n postSetupInstructions: [\n 'Cursor routes API calls through its cloud servers, so localhost',\n 'URLs are blocked. You need a tunnel to expose the proxy:',\n '',\n ` npx cloudflared tunnel --url http://localhost:${port}`,\n '',\n 'Then configure Cursor with the tunnel URL:',\n '',\n ' 1. Open Cursor Settings (not VS Code settings)',\n ' 2. Go to Models',\n ' 3. Enable \"Override OpenAI Base URL (when using key)\"',\n ' 4. Set the base URL to your tunnel URL + /v1',\n ' (e.g., https://abc123.trycloudflare.com/v1)',\n ' 5. Enter your real OpenAI/Anthropic API key',\n ' 6. Restart Cursor',\n '',\n 'Cursor uses OpenAI format for all models, including Claude.',\n 'Both Chat Completions and Agent mode (Responses API) are supported.',\n ],\n }\n },\n\n async teardown(): Promise<TeardownResult> {\n return {\n success: true,\n manualSteps: [\n 'In Cursor Settings > Models:',\n ' 1. Disable \"Override OpenAI Base URL (when using key)\"',\n ' 2. Clear the base URL field',\n ' 3. Restart Cursor',\n ],\n }\n },\n}\n","/**\n * Generic OpenAI-compatible connector.\n *\n * Catch-all for any tool that speaks the OpenAI API format and reads\n * OPENAI_BASE_URL or OPENAI_API_BASE. This covers tools like:\n * - Aider, Continue, Cline, Copilot alternatives\n * - Custom scripts using the OpenAI SDK\n * - Any tool that respects OPENAI_BASE_URL\n *\n * Protocol: OpenAI Chat Completions (POST /v1/chat/completions)\n * Auth: Authorization: Bearer header\n * Setup: Shell profile export — fully automatic\n */\n\nimport type { Connector, ConnectorInfo, ConnectorStatus, SetupResult, TeardownResult } from './types.js'\n\nconst ENV_VAR = 'OPENAI_BASE_URL'\n\nconst INFO: ConnectorInfo = {\n id: 'openai-compatible',\n label: 'Other / OpenAI-compatible',\n description: 'Any tool that reads OPENAI_BASE_URL',\n protocol: 'openai-chat',\n automatable: true,\n}\n\nfunction getCurrentBaseUrl(): string | undefined {\n return process.env[ENV_VAR] || undefined\n}\n\nexport const openaiCompatibleConnector: Connector = {\n info: INFO,\n\n async detect(): Promise<ConnectorStatus> {\n const currentUrl = getCurrentBaseUrl()\n const configured = currentUrl?.includes('127.0.0.1') ?? false\n\n return {\n installed: true, // Generic — always \"available\"\n configured,\n detail: configured\n ? `OPENAI_BASE_URL → ${currentUrl}`\n : 'OPENAI_BASE_URL not set to Liminal',\n }\n },\n\n getShellExports(port: number): string[] {\n return [`export ${ENV_VAR}=http://127.0.0.1:${port}/v1`]\n },\n\n async setup(port: number): Promise<SetupResult> {\n const exports = this.getShellExports(port)\n\n return {\n success: true,\n shellExports: exports,\n postSetupInstructions: [\n 'Any tool that reads OPENAI_BASE_URL will route through Liminal.',\n 'Make sure to source your shell profile or restart your terminal.',\n '',\n 'If your tool uses a different env var (e.g., OPENAI_API_BASE),',\n `set it to: http://127.0.0.1:${port}/v1`,\n ],\n }\n },\n\n async teardown(): Promise<TeardownResult> {\n return {\n success: true,\n manualSteps: [\n `Remove the line \\`export ${ENV_VAR}=...\\` from your shell profile (~/.zshrc or ~/.bashrc).`,\n 'Restart your terminal or run: unset OPENAI_BASE_URL',\n ],\n }\n },\n}\n","/**\n * Connector registry — maps tool IDs to their connector implementations.\n */\n\nimport { claudeCodeConnector } from './claude-code.js'\nimport { codexConnector } from './codex.js'\nimport { cursorConnector } from './cursor.js'\nimport { openaiCompatibleConnector } from './openai-compatible.js'\nimport type { Connector, ConnectorId } from './types.js'\n\n/** All registered connectors in display order */\nexport const CONNECTORS: readonly Connector[] = [\n claudeCodeConnector,\n codexConnector,\n cursorConnector,\n openaiCompatibleConnector,\n]\n\n/** Lookup a connector by its tool ID */\nexport function getConnector(id: ConnectorId): Connector {\n const connector = CONNECTORS.find((c) => c.info.id === id)\n if (!connector) {\n throw new Error(`Unknown connector: ${id}`)\n }\n return connector\n}\n\n/** Get connectors for a list of tool IDs */\nexport function getConnectors(ids: ConnectorId[]): Connector[] {\n return ids.map(getConnector)\n}\n\n/** Detect which tools are installed on this system */\nexport async function detectInstalledTools(): Promise<Map<ConnectorId, Connector>> {\n const results = await Promise.all(\n CONNECTORS.map(async (c) => {\n const status = await c.detect()\n return { connector: c, status }\n }),\n )\n\n const installed = new Map<ConnectorId, Connector>()\n for (const { connector, status } of results) {\n if (status.installed) {\n installed.set(connector.info.id, connector)\n }\n }\n\n return installed\n}\n\n// Re-export types for convenience\nexport type { Connector, ConnectorId, ConnectorInfo, ConnectorStatus, SetupResult, TeardownResult } from './types.js'\n","import { saveConfig, ensureDirectories } from '../config/loader.js'\nimport { DEFAULTS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\nimport {\n detectShellProfile,\n appendToShellProfile,\n lineExistsInFile,\n} from '../config/shell.js'\nimport { printBanner } from '../version.js'\nimport { multiSelectPrompt, selectPrompt } from '../ui/prompts.js'\nimport { runAuthFlow } from './login.js'\nimport { CONNECTORS, getConnectors } from '../connectors/index.js'\nimport type { ConnectorId } from '../connectors/types.js'\nimport type { Tool } from '../types.js'\n\n// ─── ANSI helpers ────────────────────────────────────────────────────\nconst BOLD = '\\x1b[1m'\nconst DIM = '\\x1b[2m'\nconst CYAN = '\\x1b[36m'\nconst GREEN = '\\x1b[32m'\nconst YELLOW = '\\x1b[33m'\nconst RESET = '\\x1b[0m'\n\nexport async function initCommand(): Promise<void> {\n printBanner()\n console.log(' Welcome to Liminal -- Your Transparency & Context Partner')\n console.log()\n console.log(\" Let's start evolving.\")\n console.log()\n\n // ── 1. Authenticate ───────────────────────────────────────────\n const apiKey = await runAuthFlow()\n console.log()\n\n // ── 2. Port (use default, configurable via `liminal config --set port=XXXX`) ──\n const port = DEFAULTS.port\n\n // ── 3. Tool detection ─────────────────────────────────────────\n console.log(` ${BOLD}Detecting installed tools...${RESET}`)\n console.log()\n const detectionResults = await Promise.all(\n CONNECTORS.map(async (c) => {\n const status = await c.detect()\n return { connector: c, status }\n }),\n )\n\n for (const { connector, status } of detectionResults) {\n const icon = status.installed ? `${GREEN}✓${RESET}` : `${DIM}·${RESET}`\n console.log(` ${icon} ${connector.info.label} ${DIM}${status.detail}${RESET}`)\n }\n console.log()\n\n // ── 4. Tool selection ─────────────────────────────────────────\n const toolOptions = CONNECTORS.map((c) => {\n const detected = detectionResults.find((r) => r.connector.info.id === c.info.id)\n const installed = detected?.status.installed ?? false\n\n let description = c.info.description\n if (!installed) description += ` ${DIM}(not detected)${RESET}`\n if (!c.info.automatable) description += ` ${DIM}(manual setup)${RESET}`\n\n return {\n label: c.info.label,\n value: c.info.id as ConnectorId,\n description,\n default: c.info.id === 'claude-code' && installed,\n }\n })\n\n const toolsResult = await multiSelectPrompt<ConnectorId>({\n message: 'Which AI tools will you use with Liminal?',\n options: toolOptions,\n })\n const selectedIds: ConnectorId[] = toolsResult ?? ['claude-code']\n\n console.log()\n\n // ── 5. Response learning ──────────────────────────────────────\n const learnResult = await selectPrompt<boolean>({\n message: 'Learn from LLM responses?',\n options: [\n { label: 'Yes', value: true, description: 'Improve compression over time' },\n { label: 'No', value: false, description: 'Skip response learning' },\n ],\n defaultIndex: 0,\n })\n const learnFromResponses = learnResult ?? true\n\n console.log()\n\n // ── 6. Save config ────────────────────────────────────────────\n ensureDirectories()\n saveConfig({\n apiKey,\n apiBaseUrl: DEFAULTS.apiBaseUrl,\n upstreamBaseUrl: DEFAULTS.upstreamBaseUrl,\n anthropicUpstreamUrl: DEFAULTS.anthropicUpstreamUrl,\n port,\n learnFromResponses,\n tools: selectedIds as Tool[],\n compressionThreshold: DEFAULTS.compressionThreshold,\n compressRoles: DEFAULTS.compressRoles,\n latencyBudgetMs: DEFAULTS.latencyBudgetMs,\n enabled: DEFAULTS.enabled,\n })\n\n console.log(` ${GREEN}✓${RESET} Configuration saved to ${DIM}${CONFIG_FILE}${RESET}`)\n console.log()\n\n // ── 7. Per-connector setup ────────────────────────────────────\n // Each selected tool gets its own visible setup section so the user\n // can see exactly what's being configured for every tool they chose.\n\n const connectors = getConnectors(selectedIds)\n const allShellExports: string[] = []\n const profile = detectShellProfile()\n\n console.log(` ${BOLD}Configuring ${connectors.length} tool${connectors.length > 1 ? 's' : ''}...${RESET}`)\n\n for (const connector of connectors) {\n const result = await connector.setup(port)\n const protocol = connector.info.protocol === 'anthropic-messages'\n ? 'Anthropic Messages API'\n : connector.info.protocol === 'openai-responses'\n ? 'Responses API'\n : 'Chat Completions API'\n\n console.log()\n console.log(` ${CYAN}── ${connector.info.label} ${RESET}${DIM}(${protocol})${RESET}`)\n\n if (connector.info.automatable && result.shellExports.length > 0) {\n // Automatable: show the env var(s) being set\n for (const line of result.shellExports) {\n console.log(` ${GREEN}✓${RESET} ${line}`)\n }\n allShellExports.push(...result.shellExports)\n }\n\n // Show all setup instructions for this connector\n for (const line of result.postSetupInstructions) {\n if (line === '') {\n console.log()\n } else {\n // Skip generic \"source your shell\" messages — we handle that globally below\n if (line.includes('source your shell profile') || line.includes('restart your terminal')) continue\n if (line.includes('will automatically route through Liminal')) {\n console.log(` ${DIM}${line}${RESET}`)\n } else if (line.startsWith(' ')) {\n // Indented instructions (e.g., Cursor numbered steps)\n console.log(` ${line}`)\n } else {\n console.log(` ${line}`)\n }\n }\n }\n\n // Show manual setup badge for non-automatable connectors\n if (!connector.info.automatable) {\n console.log(` ${YELLOW}⚠ Requires manual configuration (see steps above)${RESET}`)\n }\n }\n\n // ── 8. Shell auto-configuration ───────────────────────────────\n // Deduplicate (codex + openai-compatible both set OPENAI_BASE_URL)\n const uniqueExports = [...new Set(allShellExports)]\n\n if (uniqueExports.length > 0 && profile) {\n const allExist = uniqueExports.every((line) => lineExistsInFile(profile.path, line))\n\n console.log()\n if (allExist) {\n console.log(` ${GREEN}✓${RESET} Shell already configured in ${profile.name}`)\n } else {\n const autoResult = await selectPrompt<boolean>({\n message: `Add proxy exports to ${profile.name}?`,\n options: [\n { label: 'Yes', value: true, description: 'Automatic shell configuration' },\n { label: 'No', value: false, description: \"I'll set it up manually\" },\n ],\n defaultIndex: 0,\n })\n\n if (autoResult === true) {\n const added = appendToShellProfile(profile, uniqueExports)\n if (added.length > 0) {\n console.log()\n console.log(` ${GREEN}✓${RESET} Added to ${profile.name}`)\n console.log()\n console.log(` Run ${BOLD}source ${profile.name}${RESET} or restart your terminal.`)\n }\n } else {\n console.log()\n console.log(' Add these to your shell profile:')\n console.log()\n for (const line of uniqueExports) {\n console.log(` ${CYAN}${line}${RESET}`)\n }\n }\n }\n } else if (uniqueExports.length > 0) {\n // No shell profile detected\n console.log()\n console.log(' Add these to your shell profile:')\n console.log()\n for (const line of uniqueExports) {\n console.log(` ${CYAN}${line}${RESET}`)\n }\n }\n\n // ── 9. Done ───────────────────────────────────────────────────\n console.log()\n console.log(` ${BOLD}Setup complete!${RESET}`)\n console.log()\n console.log(' Next step:')\n console.log(` ${BOLD}liminal start${RESET}`)\n console.log()\n}\n","import { saveConfig, isConfigured } from '../config/loader.js'\n\nexport async function logoutCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log(' Not currently logged in.')\n return\n }\n\n saveConfig({ apiKey: '' })\n console.log(' Logged out.')\n console.log(' Run \\x1b[1mliminal login\\x1b[0m to reconnect.')\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressConversation, type ConversationCompressOptions } from '../rsc/message-compressor.js'\nimport { analyzeConversation } from '../rsc/conversation-analyzer.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeSSEResponse } from './streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionRequest, ResolvedConfig } from '../types.js'\nimport { formatTiersLog, formatSavedLog, formatDegradeLog, formatResponseLog } from '../terminology.js'\nimport type { Logger } from './handler.js'\nimport type { Semaphore } from '../rsc/semaphore.js'\nimport type { LatencyMonitor } from '../rsc/latency-monitor.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\n/**\n * Extract the bearer token from the Authorization header.\n * This is the user's LLM API key — used to forward to the upstream LLM.\n */\nfunction extractBearerToken(req: http.IncomingMessage): string | null {\n const auth = req.headers.authorization\n if (!auth || !auth.startsWith('Bearer ')) return null\n return auth.slice(7)\n}\n\nexport async function handleChatCompletions(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n semaphore: Semaphore,\n latencyMonitor: LatencyMonitor,\n sessionKey: string,\n): Promise<void> {\n const request = body as ChatCompletionRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendJSON(res, 400, {\n error: { message: 'messages is required and must be an array', type: 'invalid_request_error' },\n })\n return\n }\n\n // Extract LLM API key from the incoming request\n const llmApiKey = extractBearerToken(req)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n // Compress messages (or passthrough if circuit is open / disabled)\n let messages = request.messages\n let anyCompressed = false\n let totalTokensSaved = 0\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n const compressStart = Date.now()\n try {\n const compressRoles = new Set(config.compressRoles)\n\n const plan = analyzeConversation(request.messages, {\n hotFraction: config.hotFraction,\n coldFraction: config.coldFraction,\n aggregateThreshold: config.aggregateThreshold,\n compressRoles,\n compressToolResults: config.compressToolResults,\n })\n\n if (plan.shouldCompress) {\n logger.log(formatTiersLog(plan.hotCount, plan.warmCount, plan.coldCount, plan.totalEligibleTokens))\n }\n\n const result = await compressConversation(\n pipeline.pipeline,\n pipeline.session,\n plan,\n {\n compressToolResults: config.compressToolResults,\n logFn: (msg) => logger.log(msg),\n semaphore,\n semaphoreTimeoutMs: config.concurrencyTimeoutMs,\n },\n )\n messages = result.messages\n anyCompressed = result.anyCompressed\n totalTokensSaved = result.totalTokensSaved\n\n const latencyMs = Date.now() - compressStart\n const alert = latencyMonitor.record(sessionKey, latencyMs)\n if (alert) {\n logger.log(`[LATENCY] ${alert.type.toUpperCase()}: ${alert.message}`)\n }\n\n if (result.totalTokensSaved > 0) {\n logger.log(formatSavedLog(result.totalTokensSaved, latencyMs))\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log(formatDegradeLog())\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n // Fall through with original messages\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.upstreamBaseUrl}/v1/chat/completions`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n 'Authorization': `Bearer ${llmApiKey}`,\n 'Content-Type': 'application/json',\n }\n\n // Forward streaming preference\n if (request.stream) {\n upstreamHeaders['Accept'] = 'text/event-stream'\n }\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n logger.log(formatResponseLog(request.model, totalTokensSaved, true))\n await pipeSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n totalTokensSaved,\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n logger.log(formatResponseLog(request.model, totalTokensSaved))\n\n // Adjust usage to reflect pre-compression token count\n let finalBody = responseBody\n if (totalTokensSaved > 0) {\n try {\n const parsed = JSON.parse(responseBody)\n if (parsed?.usage?.prompt_tokens != null) {\n parsed.usage.prompt_tokens += totalTokensSaved\n if (parsed.usage.total_tokens != null) {\n parsed.usage.total_tokens += totalTokensSaved\n }\n finalBody = JSON.stringify(parsed)\n logger.log(`[TOKENS] Adjusted prompt_tokens by +${totalTokensSaved}`)\n }\n } catch {\n // Pass through unmodified on parse error\n }\n }\n\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(finalBody)\n\n // Trigger learning from response (fire-and-forget, uses original body)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const content = parsed?.choices?.[0]?.message?.content\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream LLM: ${message}`, type: 'server_error' },\n })\n }\n }\n}\n","import type { CompressionPipeline, Session } from '@cognisos/rsc-sdk'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport type { ChatCompletionMessage, ContentPart } from '../types.js'\nimport { segmentContent } from './content-segmenter.js'\nimport type { ConversationPlan } from './conversation-analyzer.js'\nimport type { Semaphore } from './semaphore.js'\n\nexport interface CompressedMessagesResult {\n messages: ChatCompletionMessage[]\n anyCompressed: boolean\n totalTokensSaved: number\n}\n\n/** Content block types that must never be modified. */\nconst PASSTHROUGH_BLOCK_TYPES = new Set(['thinking', 'tool_use', 'image'])\n\n/**\n * Sanitize text returned from RSC decompress to remove characters that\n * would break JSON serialization (lone surrogates, control chars except\n * newlines/tabs). This prevents \"Invalid character\" errors on upstream fetch.\n */\nfunction sanitizeCompressedText(text: string): string {\n // eslint-disable-next-line no-control-regex\n return text.replace(/[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]/g, '')\n}\n\ntype RecordFn = (compressed: boolean, saved: number) => void\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Legacy per-message compression (kept for backward compatibility).\n * Callers should prefer compressConversation() for tier-aware compression.\n */\nexport async function compressMessages(\n messages: ChatCompletionMessage[],\n pipeline: CompressionPipeline,\n session: Session,\n compressRoles: Set<string>,\n): Promise<CompressedMessagesResult> {\n let anyCompressed = false\n let totalTokensSaved = 0\n\n const compressed = await Promise.all(\n messages.map(async (msg) => {\n if (!compressRoles.has(msg.role)) return msg\n return compressMessage(msg, pipeline, session, (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n })\n }),\n )\n\n return { messages: compressed, anyCompressed, totalTokensSaved }\n}\n\n/**\n * Tier-aware conversation compression with per-message text batching.\n *\n * - HOT messages pass through verbatim (zero latency).\n * - WARM and COLD messages have all eligible text extracted, concatenated,\n * and compressed in a single API call per message. This avoids many\n * sub-threshold skips when messages contain multiple small blocks.\n * - If the plan says shouldCompress=false, everything passes through.\n */\nexport interface ConversationCompressOptions {\n compressToolResults: boolean\n /** Optional callback for block-level diagnostic logging */\n logFn?: (msg: string) => void\n /** Optional semaphore to limit concurrent RSC API calls across sessions */\n semaphore?: Semaphore\n /** Timeout for semaphore acquire (ms). Defaults to 15000. */\n semaphoreTimeoutMs?: number\n}\n\nexport async function compressConversation(\n pipeline: CompressionPipeline,\n session: Session,\n plan: ConversationPlan,\n options: ConversationCompressOptions = { compressToolResults: true },\n): Promise<CompressedMessagesResult> {\n // Fast path: aggregate threshold not met\n if (!plan.shouldCompress) {\n return {\n messages: plan.messages.map((tm) => tm.message),\n anyCompressed: false,\n totalTokensSaved: 0,\n }\n }\n\n let anyCompressed = false\n let totalTokensSaved = 0\n\n const record: RecordFn = (c, saved) => {\n anyCompressed = anyCompressed || c\n totalTokensSaved += saved\n }\n\n const log = options.logFn\n const compressed = await Promise.all(\n plan.messages.map(async (tm) => {\n const role = tm.message.role\n const blockTypes = Array.isArray(tm.message.content)\n ? (tm.message.content as ContentPart[]).map((b) => b.type).join(',')\n : 'string'\n\n // HOT: always verbatim\n if (tm.tier === 'hot') {\n log?.(`[BLOCK] #${tm.index} ${role} [${blockTypes}] → HOT (verbatim)`)\n return tm.message\n }\n\n // WARM / COLD with no eligible tokens: skip\n if (tm.eligibleTokens === 0) {\n log?.(`[BLOCK] #${tm.index} ${role} [${blockTypes}] → ${tm.tier.toUpperCase()} (0 eligible tok, skip)`)\n return tm.message\n }\n\n log?.(`[BLOCK] #${tm.index} ${role} [${blockTypes}] → ${tm.tier.toUpperCase()} (${tm.eligibleTokens} eligible tok, batch compressing)`)\n return batchCompressMessage(tm.message, pipeline, session, record, options)\n }),\n )\n\n return { messages: compressed, anyCompressed, totalTokensSaved }\n}\n\n// ---------------------------------------------------------------------------\n// Batch compression\n// ---------------------------------------------------------------------------\n\n/**\n * Extract all text from a tool_result block's content.\n * Returns null if no compressible text is found.\n */\nfunction extractToolResultText(part: ContentPart): string | null {\n if (typeof part.content === 'string' && part.content.trim()) {\n return part.content\n }\n if (Array.isArray(part.content)) {\n const texts = (part.content as ContentPart[])\n .filter((inner) => inner.type === 'text' && typeof inner.text === 'string' && (inner.text as string).trim())\n .map((inner) => inner.text as string)\n return texts.length > 0 ? texts.join('\\n') : null\n }\n return null\n}\n\n/**\n * Batch-compress all eligible text from a message into a single API call.\n *\n * Instead of compressing each text/tool_result block individually (which\n * results in many sub-threshold skips for small blocks), this:\n * 1. Extracts all eligible text from the message's content blocks\n * 2. Concatenates into a single string\n * 3. Makes ONE compressForLLM() call\n * 4. Places the compressed result as a text block, clears text from\n * batched blocks while preserving structure (tool_use_id pairing)\n */\nasync function batchCompressMessage(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: RecordFn,\n options: ConversationCompressOptions = { compressToolResults: true },\n): Promise<ChatCompletionMessage> {\n // String content: compress directly (already one block)\n if (typeof msg.content === 'string') {\n return compressStringContent(msg, pipeline, session, record, options.semaphore, options.semaphoreTimeoutMs)\n }\n\n if (!Array.isArray(msg.content)) return msg\n\n const parts = msg.content as ContentPart[]\n\n // Collect all eligible text and track which parts contributed\n const textSegments: string[] = []\n const batchedIndices = new Set<number>()\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i]\n if (PASSTHROUGH_BLOCK_TYPES.has(part.type)) continue\n\n if (part.type === 'text' && typeof part.text === 'string' && part.text.trim()) {\n textSegments.push(part.text)\n batchedIndices.add(i)\n }\n\n if (part.type === 'tool_result' && options.compressToolResults) {\n const extracted = extractToolResultText(part)\n if (extracted) {\n textSegments.push(extracted)\n batchedIndices.add(i)\n }\n }\n }\n\n // Nothing to compress\n if (textSegments.length === 0) return msg\n\n // Concatenate all eligible text into one batch\n const batchText = textSegments.join('\\n\\n')\n\n try {\n const compressed = await compressTextWithSegmentation(batchText, pipeline, session, record, options.semaphore, options.semaphoreTimeoutMs)\n\n // Rebuild content array in-place to preserve block ordering.\n // The Anthropic API requires tool_result blocks to appear in the\n // same position (immediately after the corresponding tool_use\n // message). We MUST NOT prepend, append, remove, or reorder blocks.\n //\n // Strategy: put the compressed batch into the first eligible block,\n // clear text in remaining batched blocks, keep everything else as-is.\n // Build the output content array in-place.\n // - First eligible block gets the full compressed batch text.\n // - Remaining batched text blocks are REMOVED (API rejects empty text blocks).\n // - Remaining batched tool_result blocks keep structure with cleared content\n // (tool_use_id pairing must be preserved).\n // - Non-batched blocks (passthrough, non-eligible) are kept as-is.\n const newParts: ContentPart[] = []\n let isFirstEligible = true\n\n for (let i = 0; i < parts.length; i++) {\n if (!batchedIndices.has(i)) {\n // Not batched — keep as-is\n newParts.push(parts[i])\n continue\n }\n\n if (isFirstEligible) {\n // First eligible block gets the compressed text\n if (parts[i].type === 'text') {\n newParts.push({ ...parts[i], text: compressed })\n } else if (parts[i].type === 'tool_result') {\n newParts.push({ ...parts[i], content: compressed })\n }\n isFirstEligible = false\n } else {\n // Remaining batched blocks:\n // - text blocks: drop entirely (API rejects empty text blocks)\n // - tool_result: keep with empty content (preserves tool_use_id pairing)\n if (parts[i].type === 'tool_result') {\n newParts.push({ ...parts[i], content: '' })\n }\n // text blocks are simply not pushed — removed from the array\n }\n }\n\n return { ...msg, content: newParts }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return msg\n }\n}\n\n// ---------------------------------------------------------------------------\n// Per-block helpers (used by legacy compressMessages path)\n// ---------------------------------------------------------------------------\n\n/**\n * Compress a single message's content, handling both string and array forms.\n */\nasync function compressMessage(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: RecordFn,\n options: ConversationCompressOptions = { compressToolResults: true },\n): Promise<ChatCompletionMessage> {\n if (typeof msg.content === 'string') {\n return compressStringContent(msg, pipeline, session, record)\n }\n\n if (Array.isArray(msg.content)) {\n return compressArrayContent(msg, pipeline, session, record, options)\n }\n\n return msg\n}\n\n/**\n * Compress plain-string message content with code-block segmentation.\n */\nasync function compressStringContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: RecordFn,\n semaphore?: Semaphore,\n semaphoreTimeoutMs?: number,\n): Promise<ChatCompletionMessage> {\n const text = msg.content as string\n try {\n const compressed = await compressTextWithSegmentation(text, pipeline, session, record, semaphore, semaphoreTimeoutMs)\n return { ...msg, content: compressed }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return msg\n }\n}\n\n/**\n * Compress array content blocks (text, tool_result). Skips thinking, tool_use, image.\n * Used by the legacy compressMessages() path.\n */\nasync function compressArrayContent(\n msg: ChatCompletionMessage,\n pipeline: CompressionPipeline,\n session: Session,\n record: RecordFn,\n options: ConversationCompressOptions = { compressToolResults: true },\n): Promise<ChatCompletionMessage> {\n const parts = msg.content as ContentPart[]\n\n const compressedParts = await Promise.all(\n parts.map(async (part) => {\n // Skip blocks that must not be modified\n if (PASSTHROUGH_BLOCK_TYPES.has(part.type)) return part\n\n // text block\n if (part.type === 'text' && typeof part.text === 'string') {\n try {\n const compressed = await compressTextWithSegmentation(part.text, pipeline, session, record)\n return { ...part, text: compressed }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return part\n }\n }\n\n // tool_result block — compress if enabled\n if (part.type === 'tool_result' && options.compressToolResults) {\n return compressToolResult(part, pipeline, session, record)\n }\n\n // Unknown block type or disabled tool_result — pass through\n return part\n }),\n )\n\n return { ...msg, content: compressedParts }\n}\n\n/**\n * Compress text content within a tool_result block.\n * tool_result.content can be a plain string or an array of content blocks.\n * Used by the legacy compressMessages() path.\n */\nasync function compressToolResult(\n part: ContentPart,\n pipeline: CompressionPipeline,\n session: Session,\n record: RecordFn,\n): Promise<ContentPart> {\n const content = part.content\n\n // String content\n if (typeof content === 'string') {\n try {\n const compressed = await compressTextWithSegmentation(content, pipeline, session, record)\n return { ...part, content: compressed }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return part\n }\n }\n\n // Nested content blocks (e.g. [{type:\"text\", text:\"...\"}])\n if (Array.isArray(content)) {\n try {\n const compressedInner = await Promise.all(\n (content as ContentPart[]).map(async (inner) => {\n if (inner.type === 'text' && typeof inner.text === 'string') {\n try {\n const compressed = await compressTextWithSegmentation(inner.text, pipeline, session, record)\n return { ...inner, text: compressed }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) throw err\n session.recordFailure()\n return inner\n }\n }\n return inner\n }),\n )\n return { ...part, content: compressedInner }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n session.recordFailure()\n throw err\n }\n session.recordFailure()\n return part\n }\n }\n\n return part\n}\n\n/**\n * Compress a text string, preserving code blocks verbatim.\n * When a semaphore is provided, each compressForLLM() call acquires a permit\n * first — this limits concurrent RSC API calls across all sessions.\n */\nasync function compressTextWithSegmentation(\n text: string,\n pipeline: CompressionPipeline,\n session: Session,\n record: RecordFn,\n semaphore?: Semaphore,\n semaphoreTimeoutMs?: number,\n): Promise<string> {\n const segments = segmentContent(text)\n const hasCode = segments.some((s) => s.type === 'code')\n\n if (!hasCode) {\n if (semaphore) await semaphore.acquire(semaphoreTimeoutMs)\n try {\n const result = await pipeline.compressForLLM(text)\n session.recordCompression(result.metrics)\n const saved = Math.max(0, result.metrics.tokensSaved)\n record(!result.metrics.skipped, saved)\n return sanitizeCompressedText(result.text)\n } finally {\n if (semaphore) semaphore.release()\n }\n }\n\n const parts = await Promise.all(\n segments.map(async (seg) => {\n if (seg.type === 'code') return seg.text\n if (seg.text.trim().length === 0) return seg.text\n if (semaphore) await semaphore.acquire(semaphoreTimeoutMs)\n try {\n const result = await pipeline.compressForLLM(seg.text)\n session.recordCompression(result.metrics)\n const saved = Math.max(0, result.metrics.tokensSaved)\n record(!result.metrics.skipped, saved)\n return sanitizeCompressedText(result.text)\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) throw err\n session.recordFailure()\n return seg.text\n } finally {\n if (semaphore) semaphore.release()\n }\n }),\n )\n return parts.join('')\n}\n","/**\n * Content segmenter — splits mixed text into code and prose segments.\n * Code segments (fenced blocks, indented blocks) pass through compression\n * unchanged to avoid destructive normalization (casefold, punct strip, lemmatize).\n */\n\nexport interface ContentSegment {\n type: 'prose' | 'code'\n text: string\n}\n\n/**\n * Segment text content into code and prose blocks.\n *\n * Detection rules:\n * 1. Fenced code blocks: ``` or ~~~ (with optional language tag) through closing fence\n * 2. Indented code blocks: 4+ space or tab-indented contiguous lines\n * 3. Everything else → prose\n *\n * Round-trip invariant: segments.map(s => s.text).join('') === input\n */\nexport function segmentContent(text: string): ContentSegment[] {\n if (text.length === 0) return [{ type: 'prose', text: '' }]\n\n const segments: ContentSegment[] = []\n const lines = text.split('\\n')\n let i = 0\n let proseBuf: string[] = []\n\n function flushProse(): void {\n if (proseBuf.length > 0) {\n segments.push({ type: 'prose', text: proseBuf.join('\\n') })\n proseBuf = []\n }\n }\n\n while (i < lines.length) {\n const line = lines[i]\n\n // Check for fenced code block opening\n const fenceMatch = matchFenceOpen(line)\n if (fenceMatch) {\n // Before flushing prose, add the newline that separated prose from this fence\n if (proseBuf.length > 0) {\n // The newline before this line belongs to the prose segment\n flushProse()\n // Add the newline separator between prose and code\n segments[segments.length - 1].text += '\\n'\n }\n\n const codeBuf: string[] = [line]\n i++\n\n // Scan until closing fence of same type and length\n let closed = false\n while (i < lines.length) {\n codeBuf.push(lines[i])\n if (matchFenceClose(lines[i], fenceMatch.char, fenceMatch.length)) {\n closed = true\n i++\n break\n }\n i++\n }\n\n // Add trailing newline if not at end of input\n let codeText = codeBuf.join('\\n')\n if (i < lines.length) {\n codeText += '\\n'\n }\n\n segments.push({ type: 'code', text: codeText })\n continue\n }\n\n // Check for indented code block (4+ spaces or tab)\n if (isIndentedCodeLine(line)) {\n if (proseBuf.length > 0) {\n flushProse()\n segments[segments.length - 1].text += '\\n'\n }\n\n const codeBuf: string[] = [line]\n i++\n\n // Consume contiguous indented lines (allow blank lines within)\n while (i < lines.length) {\n if (isIndentedCodeLine(lines[i])) {\n codeBuf.push(lines[i])\n i++\n } else if (lines[i].trim() === '' && i + 1 < lines.length && isIndentedCodeLine(lines[i + 1])) {\n // Blank line between indented lines — still part of code block\n codeBuf.push(lines[i])\n i++\n } else {\n break\n }\n }\n\n let codeText = codeBuf.join('\\n')\n if (i < lines.length) {\n codeText += '\\n'\n }\n\n segments.push({ type: 'code', text: codeText })\n continue\n }\n\n // Regular prose line\n if (proseBuf.length > 0) {\n proseBuf.push(line)\n } else {\n proseBuf.push(line)\n }\n i++\n }\n\n // Flush remaining prose\n if (proseBuf.length > 0) {\n flushProse()\n }\n\n // Ensure at least one segment\n if (segments.length === 0) {\n return [{ type: 'prose', text }]\n }\n\n return segments\n}\n\ninterface FenceInfo {\n char: string\n length: number\n}\n\nfunction matchFenceOpen(line: string): FenceInfo | null {\n // Match ``` or ~~~ with optional language tag, allowing leading whitespace (0-3 spaces)\n const match = line.match(/^( {0,3})((`{3,})|~{3,})(.*)$/)\n if (!match) return null\n\n const fenceStr = match[2]\n const char = fenceStr[0]\n\n // Backtick fences: info string must not contain backticks\n if (char === '`' && match[4] && match[4].includes('`')) return null\n\n return { char, length: fenceStr.length }\n}\n\nfunction matchFenceClose(line: string, char: string, minLength: number): boolean {\n const match = line.match(/^( {0,3})((`{3,})|(~{3,}))\\s*$/)\n if (!match) return false\n const fenceStr = match[2]\n return fenceStr[0] === char && fenceStr.length >= minLength\n}\n\nfunction isIndentedCodeLine(line: string): boolean {\n // 4+ spaces or starts with tab (and not blank)\n return (line.startsWith(' ') || line.startsWith('\\t')) && line.trim().length > 0\n}\n","import type { ChatCompletionMessage, ContentPart } from '../types.js'\n\nexport type MessageTier = 'hot' | 'warm' | 'cold'\n\nexport interface TieredMessage {\n index: number\n message: ChatCompletionMessage\n tier: MessageTier\n eligibleTokens: number\n}\n\nexport interface ConversationPlan {\n messages: TieredMessage[]\n totalEligibleTokens: number\n shouldCompress: boolean\n hotCount: number\n warmCount: number\n coldCount: number\n}\n\nexport interface TierConfig {\n hotFraction: number\n coldFraction: number\n aggregateThreshold: number\n compressRoles: Set<string>\n compressToolResults: boolean\n}\n\n/**\n * Content block types that should never be compressed.\n * tool_use contains structured JSON input; thinking contains reasoning chains.\n */\nconst SKIP_BLOCK_TYPES = new Set(['thinking', 'tool_use', 'image'])\n\n/**\n * Estimate token count for a string using the 4-chars-per-token heuristic.\n */\nfunction estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n}\n\n/**\n * Estimate eligible (compressible) tokens in a single content block.\n */\nfunction estimateBlockTokens(block: ContentPart, compressToolResults: boolean): number {\n if (SKIP_BLOCK_TYPES.has(block.type)) return 0\n\n // text block\n if (block.type === 'text' && typeof block.text === 'string') {\n return estimateTokens(block.text)\n }\n\n // tool_result block — content can be string or nested blocks\n if (block.type === 'tool_result' && compressToolResults) {\n if (typeof block.content === 'string') {\n return estimateTokens(block.content)\n }\n if (Array.isArray(block.content)) {\n return (block.content as ContentPart[]).reduce(\n (sum, inner) => sum + estimateBlockTokens(inner, compressToolResults),\n 0,\n )\n }\n }\n\n return 0\n}\n\n/**\n * Estimate eligible tokens in a message's content.\n */\nfunction estimateMessageTokens(msg: ChatCompletionMessage, config: TierConfig): number {\n if (!config.compressRoles.has(msg.role)) return 0\n\n if (typeof msg.content === 'string') {\n return estimateTokens(msg.content)\n }\n\n if (Array.isArray(msg.content)) {\n return (msg.content as ContentPart[]).reduce(\n (sum, part) => sum + estimateBlockTokens(part, config.compressToolResults),\n 0,\n )\n }\n\n return 0\n}\n\n/**\n * Assign a tier to each message based on its position in the conversation.\n *\n * Messages are ordered oldest-first (index 0 = oldest). The last `hotFraction`\n * of messages are HOT (verbatim), the first `coldFraction` are COLD, and\n * everything in between is WARM.\n *\n * For short conversations (< 5 messages), all messages are HOT to avoid\n * compressing context before there's enough to matter.\n */\nexport function analyzeConversation(\n messages: ChatCompletionMessage[],\n config: TierConfig,\n): ConversationPlan {\n const n = messages.length\n\n // Short conversations: everything is hot, skip analysis\n if (n < 5) {\n const tiered: TieredMessage[] = messages.map((msg, i) => ({\n index: i,\n message: msg,\n tier: 'hot' as MessageTier,\n eligibleTokens: estimateMessageTokens(msg, config),\n }))\n return {\n messages: tiered,\n totalEligibleTokens: 0,\n shouldCompress: false,\n hotCount: n,\n warmCount: 0,\n coldCount: 0,\n }\n }\n\n // Compute tier boundaries (message indices)\n const coldEnd = Math.floor(n * config.coldFraction)\n const hotStart = n - Math.floor(n * config.hotFraction)\n\n let totalEligibleTokens = 0\n let hotCount = 0\n let warmCount = 0\n let coldCount = 0\n\n const tiered: TieredMessage[] = messages.map((msg, i) => {\n let tier: MessageTier\n if (i >= hotStart) {\n tier = 'hot'\n hotCount++\n } else if (i < coldEnd) {\n tier = 'cold'\n coldCount++\n } else {\n tier = 'warm'\n warmCount++\n }\n\n const eligibleTokens = estimateMessageTokens(msg, config)\n\n // Only WARM and COLD messages contribute to compression budget\n if (tier !== 'hot') {\n totalEligibleTokens += eligibleTokens\n }\n\n return { index: i, message: msg, tier, eligibleTokens }\n })\n\n return {\n messages: tiered,\n totalEligibleTokens,\n shouldCompress: totalEligibleTokens >= config.aggregateThreshold,\n hotCount,\n warmCount,\n coldCount,\n }\n}\n","import type { CompressionPipeline } from '@cognisos/rsc-sdk'\n\n/**\n * Creates a buffer that accumulates streamed response text and triggers\n * background learning when the stream completes.\n */\nexport function createStreamLearningBuffer(pipeline: CompressionPipeline) {\n let buffer = ''\n\n return {\n /** Append a text delta from an SSE chunk */\n append(text: string): void {\n buffer += text\n },\n\n /** Flush the buffer — triggers fire-and-forget learning */\n flush(): void {\n if (buffer.length > 0) {\n pipeline.triggerLearning(buffer)\n buffer = ''\n }\n },\n\n /** Get current buffer contents (for testing) */\n getBuffer(): string {\n return buffer\n },\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an SSE response from an upstream LLM to the client,\n * parsing content deltas for the learning buffer.\n *\n * When totalTokensSaved > 0, intercepts the final usage chunk to adjust\n * prompt_tokens and total_tokens to reflect the pre-compression token count.\n *\n * Writes each chunk immediately — zero buffering, zero added latency\n * (except for the single usage chunk which may get rewritten).\n */\nexport async function pipeSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n totalTokensSaved = 0,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n const needsAdjustment = totalTokensSaved > 0\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Fast path: no token adjustment needed\n if (!needsAdjustment) {\n clientRes.write(chunk)\n\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const json = JSON.parse(line.slice(6))\n const content = json?.choices?.[0]?.delta?.content\n if (typeof content === 'string') {\n onContentDelta(content)\n }\n } catch {\n // Malformed SSE data — ignore for learning\n }\n }\n }\n continue\n }\n\n // Slow path: check each data line for usage to adjust\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n let adjusted = false\n const outputLines: string[] = []\n\n for (const line of lines) {\n if (line.startsWith('data: ') && line !== 'data: [DONE]') {\n try {\n const json = JSON.parse(line.slice(6))\n\n // Check for usage in this chunk (OpenAI sends it in the final chunk)\n if (json?.usage?.prompt_tokens != null) {\n json.usage.prompt_tokens += totalTokensSaved\n if (json.usage.total_tokens != null) {\n json.usage.total_tokens += totalTokensSaved\n }\n outputLines.push(`data: ${JSON.stringify(json)}`)\n adjusted = true\n } else {\n outputLines.push(line)\n }\n\n // Learning: extract content deltas\n const content = json?.choices?.[0]?.delta?.content\n if (typeof content === 'string') {\n onContentDelta(content)\n }\n } catch {\n outputLines.push(line)\n }\n } else {\n outputLines.push(line)\n }\n }\n\n if (adjusted) {\n const reconstructed = outputLines.join('\\n') + '\\n'\n clientRes.write(reconstructed)\n } else {\n clientRes.write(chunk)\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","/**\n * User-facing terminology for CLI log output.\n *\n * Mirrors web/src/lib/terminology.ts — kept in sync manually\n * since web and CLI are separate packages with no shared dependency.\n *\n * Source of truth: GitHub issue #55\n */\n\n// ── Memory tier labels ────────────────────────────────────────────\n\nexport const TIER_LABELS = {\n HOT: 'Active',\n WARM: 'Recent',\n COLD: 'Archived',\n} as const\n\n// ── Log tag formatting helpers ────────────────────────────────────\n\nexport function formatTiersLog(hot: number, warm: number, cold: number, eligibleTokens: number): string {\n return `[MEMORY] ${TIER_LABELS.HOT}:${hot} ${TIER_LABELS.WARM}:${warm} ${TIER_LABELS.COLD}:${cold} · ${eligibleTokens} tokens eligible`\n}\n\nexport function formatSavedLog(tokensSaved: number, latencyMs: number): string {\n return `[SAVED] ${tokensSaved} tokens (${latencyMs}ms)`\n}\n\nexport function formatDegradeLog(): string {\n return '[STATUS] Connection degraded — passing through directly'\n}\n\nexport function formatResponseLog(model: string, tokensSaved: number, streaming = false): string {\n return `[RESPONSE] ${streaming ? 'Streaming ' : ''}${model} response → client (saved:${tokensSaved}tok)`\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressConversation, type ConversationCompressOptions } from '../rsc/message-compressor.js'\nimport { analyzeConversation } from '../rsc/conversation-analyzer.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeAnthropicSSEResponse } from './anthropic-streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionMessage, ResolvedConfig } from '../types.js'\nimport type { AnthropicMessagesRequest, AnthropicMessage, AnthropicContentBlock } from '../types/anthropic.js'\nimport { formatTiersLog, formatSavedLog, formatDegradeLog, formatResponseLog } from '../terminology.js'\nimport type { Logger } from './handler.js'\nimport type { Semaphore } from '../rsc/semaphore.js'\nimport type { LatencyMonitor } from '../rsc/latency-monitor.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta, x-liminal-session')\n}\n\nfunction sendAnthropicError(res: http.ServerResponse, status: number, type: string, message: string): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({ type: 'error', error: { type, message } }))\n}\n\n/**\n * Extract auth headers from incoming request.\n * Supports both x-api-key (API users) and Authorization: Bearer (subscription/OAuth users).\n */\nfunction extractAuthHeaders(req: http.IncomingMessage): Record<string, string> {\n const headers: Record<string, string> = {}\n\n const xApiKey = req.headers['x-api-key']\n if (typeof xApiKey === 'string' && xApiKey.length > 0) {\n headers['x-api-key'] = xApiKey\n }\n\n const auth = req.headers['authorization']\n if (typeof auth === 'string' && auth.length > 0) {\n headers['Authorization'] = auth\n }\n\n return headers\n}\n\n/**\n * Convert Anthropic messages to ChatCompletionMessage[] for the compressor.\n * The structures are compatible — this is a thin adapter.\n */\nfunction convertAnthropicToCompressible(messages: AnthropicMessage[]): ChatCompletionMessage[] {\n return messages.map((msg) => ({\n role: msg.role,\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\n/**\n * Convert compressed ChatCompletionMessage[] back to Anthropic format.\n */\nfunction convertCompressedToAnthropic(messages: ChatCompletionMessage[]): AnthropicMessage[] {\n return messages.map((msg) => ({\n role: msg.role as 'user' | 'assistant',\n content: msg.content as string | AnthropicContentBlock[],\n }))\n}\n\nexport async function handleAnthropicMessages(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n semaphore: Semaphore,\n latencyMonitor: LatencyMonitor,\n sessionKey: string,\n): Promise<void> {\n const request = body as AnthropicMessagesRequest\n\n // Validate required fields\n if (!request.messages || !Array.isArray(request.messages)) {\n sendAnthropicError(res, 400, 'invalid_request_error', 'messages is required and must be an array')\n return\n }\n\n if (typeof request.max_tokens !== 'number') {\n sendAnthropicError(res, 400, 'invalid_request_error', 'max_tokens is required')\n return\n }\n\n // Extract auth headers (x-api-key for API users, Authorization for subscription/OAuth)\n const authHeaders = extractAuthHeaders(req)\n if (Object.keys(authHeaders).length === 0) {\n sendAnthropicError(res, 401, 'authentication_error', 'Authentication required (x-api-key or Authorization header)')\n return\n }\n\n // Analyze conversation and compress by tier\n let messages = request.messages\n let anyCompressed = false\n let totalTokensSaved = 0\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n const compressStart = Date.now()\n try {\n const compressRoles = new Set(config.compressRoles)\n const compressible = convertAnthropicToCompressible(request.messages)\n\n const plan = analyzeConversation(compressible, {\n hotFraction: config.hotFraction,\n coldFraction: config.coldFraction,\n aggregateThreshold: config.aggregateThreshold,\n compressRoles,\n compressToolResults: config.compressToolResults,\n })\n\n if (plan.shouldCompress) {\n logger.log(formatTiersLog(plan.hotCount, plan.warmCount, plan.coldCount, plan.totalEligibleTokens))\n }\n\n const result = await compressConversation(\n pipeline.pipeline,\n pipeline.session,\n plan,\n {\n compressToolResults: config.compressToolResults,\n logFn: (msg) => logger.log(msg),\n semaphore,\n semaphoreTimeoutMs: config.concurrencyTimeoutMs,\n },\n )\n messages = convertCompressedToAnthropic(result.messages)\n anyCompressed = result.anyCompressed\n totalTokensSaved = result.totalTokensSaved\n\n const latencyMs = Date.now() - compressStart\n const alert = latencyMonitor.record(sessionKey, latencyMs)\n if (alert) {\n logger.log(`[LATENCY] ${alert.type.toUpperCase()}: ${alert.message}`)\n }\n\n if (result.totalTokensSaved > 0) {\n logger.log(formatSavedLog(result.totalTokensSaved, latencyMs))\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log(formatDegradeLog())\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n messages = request.messages\n }\n }\n\n // Build upstream request\n const upstreamUrl = `${config.anthropicUpstreamUrl}/v1/messages`\n const upstreamBody = { ...request, messages }\n\n const upstreamHeaders: Record<string, string> = {\n ...authHeaders,\n 'anthropic-version': (req.headers['anthropic-version'] as string) || '2023-06-01',\n 'Content-Type': 'application/json',\n }\n\n // Forward anthropic-beta header if present\n const betaHeader = req.headers['anthropic-beta']\n if (typeof betaHeader === 'string') {\n upstreamHeaders['anthropic-beta'] = betaHeader\n }\n\n // Log request details for debugging\n const authTypes = Object.keys(authHeaders).join(', ') || 'none'\n logger.log(`[ANTHROPIC] ${request.model} → ${upstreamUrl} (auth: ${authTypes})`)\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n logger.log(`[ANTHROPIC] Upstream error ${upstreamResponse.status}: ${errorBody.slice(0, 500)}`)\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // Streaming response\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n logger.log(formatResponseLog(request.model, totalTokensSaved, true))\n await pipeAnthropicSSEResponse(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n totalTokensSaved,\n )\n return\n }\n\n // Non-streaming response\n const responseBody = await upstreamResponse.text()\n logger.log(formatResponseLog(request.model, totalTokensSaved))\n\n // Adjust usage.input_tokens to reflect pre-compression token count\n let finalBody = responseBody\n if (totalTokensSaved > 0) {\n try {\n const parsed = JSON.parse(responseBody)\n if (parsed?.usage?.input_tokens != null) {\n parsed.usage.input_tokens += totalTokensSaved\n finalBody = JSON.stringify(parsed)\n logger.log(`[TOKENS] Adjusted input_tokens by +${totalTokensSaved}`)\n }\n } catch {\n // Pass through unmodified on parse error\n }\n }\n\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(finalBody)\n\n // Trigger learning from response (fire-and-forget, uses original body)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody)\n const textBlocks = parsed?.content?.filter(\n (b: AnthropicContentBlock) => b.type === 'text' && typeof b.text === 'string',\n )\n const content = textBlocks?.map((b: AnthropicContentBlock) => b.text).join('')\n if (typeof content === 'string' && content.length > 0) {\n pipeline.pipeline.triggerLearning(content)\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendAnthropicError(res, 502, 'api_error', `Failed to reach upstream: ${message}`)\n }\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Adjust a `message_start` SSE data line to restore pre-compression input_tokens.\n * Returns the adjusted line if modified, or null if no adjustment was made.\n */\nfunction adjustMessageStartLine(dataLine: string, tokensSaved: number): string | null {\n try {\n const json = JSON.parse(dataLine.slice(6)) // strip \"data: \"\n if (json?.message?.usage?.input_tokens != null) {\n json.message.usage.input_tokens += tokensSaved\n return `data: ${JSON.stringify(json)}`\n }\n } catch {\n // Malformed JSON — don't adjust\n }\n return null\n}\n\n/**\n * Pipe an Anthropic SSE response from the upstream to the client,\n * parsing content_block_delta events for the learning buffer.\n *\n * Anthropic SSE format:\n * event: content_block_delta\n * data: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"Hello\"}}\n *\n * When totalTokensSaved > 0, intercepts the message_start event to adjust\n * usage.input_tokens to reflect the pre-compression token count.\n *\n * Writes each chunk immediately — zero buffering, zero added latency\n * (except for the single message_start chunk which gets rewritten).\n */\nexport async function pipeAnthropicSSEResponse(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n totalTokensSaved = 0,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n let currentEvent = ''\n let usageAdjusted = false\n const needsAdjustment = totalTokensSaved > 0\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Fast path: if no adjustment needed (or already done), write immediately\n if (!needsAdjustment || usageAdjusted) {\n clientRes.write(chunk)\n\n // Still parse for learning\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n } else if (line.startsWith('data: ') && currentEvent === 'content_block_delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (json?.delta?.type === 'text_delta' && typeof json.delta.text === 'string') {\n onContentDelta(json.delta.text)\n }\n } catch {\n // Malformed data — ignore for learning\n }\n }\n }\n continue\n }\n\n // Slow path: need to check for message_start to adjust usage\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n let adjusted = false\n const outputLines: string[] = []\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n outputLines.push(line)\n } else if (line.startsWith('data: ') && currentEvent === 'message_start' && !usageAdjusted) {\n const adjustedLine = adjustMessageStartLine(line, totalTokensSaved)\n if (adjustedLine) {\n outputLines.push(adjustedLine)\n usageAdjusted = true\n adjusted = true\n } else {\n outputLines.push(line)\n }\n } else {\n outputLines.push(line)\n\n // Learning: extract content deltas\n if (line.startsWith('data: ') && currentEvent === 'content_block_delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (json?.delta?.type === 'text_delta' && typeof json.delta.text === 'string') {\n onContentDelta(json.delta.text)\n }\n } catch {\n // Malformed data — ignore for learning\n }\n }\n }\n }\n\n if (adjusted) {\n // Reconstruct the chunk from adjusted lines + remaining buffer\n const reconstructed = outputLines.join('\\n') + '\\n' + (lineBuf ? '' : '')\n clientRes.write(reconstructed)\n } else {\n // No adjustment made in this chunk — write original\n clientRes.write(chunk)\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport { RSCCircuitOpenError } from '@cognisos/rsc-sdk'\nimport { compressMessages } from '../rsc/message-compressor.js'\nimport { createStreamLearningBuffer } from '../rsc/learning.js'\nimport { pipeResponsesSSE } from './responses-streaming.js'\nimport type { RSCPipelineWrapper } from '../rsc/pipeline.js'\nimport type { ChatCompletionMessage, ResolvedConfig } from '../types.js'\nimport { formatSavedLog, formatDegradeLog, formatResponseLog } from '../terminology.js'\nimport type { Logger } from './handler.js'\nimport type { Semaphore } from '../rsc/semaphore.js'\nimport type { LatencyMonitor } from '../rsc/latency-monitor.js'\nimport type {\n ResponsesRequest,\n ResponsesInputItem,\n ResponsesMessageItem,\n ResponsesInputContent,\n ResponsesInputTextContent,\n ResponsesResponse,\n ResponsesOutputItem,\n ResponsesOutputMessage,\n} from '../types/responses.js'\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction extractBearerToken(req: http.IncomingMessage): string | null {\n const auth = req.headers.authorization\n if (!auth || !auth.startsWith('Bearer ')) return null\n return auth.slice(7)\n}\n\n// ─── Input conversion ───────────────────────────────────────────────\n// Convert Responses API input items to ChatCompletionMessage[] for the\n// shared message compressor. Only message items with text content are\n// compressible — function call outputs, item references, images, and\n// files pass through unchanged.\n\nfunction isMessageItem(item: ResponsesInputItem): item is ResponsesMessageItem {\n return item.type === 'message'\n}\n\nfunction inputToCompressibleMessages(input: string | ResponsesInputItem[]): ChatCompletionMessage[] {\n // Simple string input\n if (typeof input === 'string') {\n return [{ role: 'user', content: input }]\n }\n\n const messages: ChatCompletionMessage[] = []\n\n for (const item of input) {\n if (!isMessageItem(item)) continue\n\n if (typeof item.content === 'string') {\n // Map 'developer' role → 'system' for the compressor\n const role = item.role === 'developer' ? 'system' : item.role\n messages.push({ role, content: item.content })\n } else if (Array.isArray(item.content)) {\n // Content array — extract text parts, preserve structure\n const role = item.role === 'developer' ? 'system' : item.role\n const parts = item.content.map((c: ResponsesInputContent) => {\n if (c.type === 'input_text') {\n return { type: 'text' as const, text: (c as ResponsesInputTextContent).text }\n }\n // Images and files pass through as non-text parts\n return c as unknown as { type: string; [key: string]: unknown }\n })\n messages.push({ role, content: parts })\n }\n }\n\n return messages\n}\n\n// ─── Apply compressed messages back to input ────────────────────────\n// After compression, we need to write the compressed text back into the\n// original Responses API input structure, preserving non-message items,\n// images, file references, etc.\n\nfunction applyCompressedToInput(\n originalInput: string | ResponsesInputItem[],\n compressedMessages: ChatCompletionMessage[],\n): string | ResponsesInputItem[] {\n // Simple string input — return compressed string directly\n if (typeof originalInput === 'string') {\n const first = compressedMessages[0]\n if (first && typeof first.content === 'string') {\n return first.content\n }\n return originalInput\n }\n\n // Array input — walk through and replace message items\n let msgIdx = 0\n const result: ResponsesInputItem[] = []\n\n for (const item of originalInput) {\n if (!isMessageItem(item)) {\n // Non-message items (function_call_output, item_reference, etc.) pass through\n result.push(item)\n continue\n }\n\n const compressed = compressedMessages[msgIdx]\n msgIdx++\n\n if (!compressed) {\n result.push(item)\n continue\n }\n\n if (typeof compressed.content === 'string') {\n result.push({\n ...item,\n content: compressed.content,\n } as ResponsesMessageItem)\n } else if (Array.isArray(compressed.content)) {\n // Convert back to Responses API content format\n const content: ResponsesInputContent[] = compressed.content.map((part) => {\n if (part.type === 'text' && 'text' in part) {\n return { type: 'input_text' as const, text: part.text as string }\n }\n return part as unknown as ResponsesInputContent\n })\n result.push({\n ...item,\n content,\n } as ResponsesMessageItem)\n } else {\n result.push(item)\n }\n }\n\n return result\n}\n\n// ─── Extract text from response output for learning ─────────────────\n\nfunction extractOutputText(output: ResponsesOutputItem[]): string {\n const texts: string[] = []\n for (const item of output) {\n if (item.type === 'message') {\n const msg = item as ResponsesOutputMessage\n for (const block of msg.content) {\n if (block.type === 'output_text' && typeof block.text === 'string') {\n texts.push(block.text)\n }\n }\n }\n }\n return texts.join('')\n}\n\n// ─── Main handler ───────────────────────────────────────────────────\n\nexport async function handleResponses(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n body: unknown,\n pipeline: RSCPipelineWrapper,\n config: ResolvedConfig,\n logger: Logger,\n semaphore: Semaphore,\n latencyMonitor: LatencyMonitor,\n sessionKey: string,\n): Promise<void> {\n const request = body as ResponsesRequest\n\n // Validate required fields\n if (request.input === undefined || request.input === null) {\n sendJSON(res, 400, {\n error: { message: 'input is required', type: 'invalid_request_error' },\n })\n return\n }\n\n // Extract LLM API key\n const llmApiKey = extractBearerToken(req)\n if (!llmApiKey) {\n sendJSON(res, 401, {\n error: { message: 'Authorization header with Bearer token is required', type: 'authentication_error' },\n })\n return\n }\n\n // ── Compress input ────────────────────────────────────────────\n let compressedInput = request.input\n let anyCompressed = false\n let totalTokensSaved = 0\n\n if (config.enabled && !pipeline.isCircuitOpen()) {\n const compressStart = Date.now()\n try {\n const compressRoles = new Set(config.compressRoles)\n const compressible = inputToCompressibleMessages(request.input)\n\n if (compressible.length > 0) {\n const result = await compressMessages(\n compressible,\n pipeline.pipeline,\n pipeline.session,\n compressRoles,\n )\n\n compressedInput = applyCompressedToInput(request.input, result.messages)\n anyCompressed = result.anyCompressed\n totalTokensSaved = result.totalTokensSaved\n\n const latencyMs = Date.now() - compressStart\n const alert = latencyMonitor.record(sessionKey, latencyMs)\n if (alert) {\n logger.log(`[LATENCY] ${alert.type.toUpperCase()}: ${alert.message}`)\n }\n\n if (result.totalTokensSaved > 0) {\n logger.log(formatSavedLog(result.totalTokensSaved, latencyMs))\n }\n }\n } catch (err) {\n if (err instanceof RSCCircuitOpenError) {\n logger.log(formatDegradeLog())\n } else {\n logger.log(`[ERROR] Compression failed: ${err instanceof Error ? err.message : String(err)}`)\n }\n compressedInput = request.input\n }\n }\n\n // ── Build upstream request ────────────────────────────────────\n const upstreamUrl = `${config.upstreamBaseUrl}/v1/responses`\n const upstreamBody = { ...request, input: compressedInput }\n\n const upstreamHeaders: Record<string, string> = {\n 'Authorization': `Bearer ${llmApiKey}`,\n 'Content-Type': 'application/json',\n }\n\n if (request.stream) {\n upstreamHeaders['Accept'] = 'text/event-stream'\n }\n\n logger.log(`[RESPONSES] ${request.model} → ${upstreamUrl}`)\n\n try {\n const upstreamResponse = await fetch(upstreamUrl, {\n method: 'POST',\n headers: upstreamHeaders,\n body: JSON.stringify(upstreamBody),\n })\n\n // Handle upstream errors\n if (!upstreamResponse.ok) {\n const errorBody = await upstreamResponse.text()\n logger.log(`[RESPONSES] Upstream error ${upstreamResponse.status}: ${errorBody.slice(0, 500)}`)\n setCORSHeaders(res)\n res.writeHead(upstreamResponse.status, {\n 'Content-Type': upstreamResponse.headers.get('Content-Type') || 'application/json',\n })\n res.end(errorBody)\n return\n }\n\n // ── Streaming response ────────────────────────────────────\n if (request.stream && upstreamResponse.body) {\n const learningBuffer = anyCompressed\n ? createStreamLearningBuffer(pipeline.pipeline)\n : null\n\n logger.log(formatResponseLog(request.model, totalTokensSaved, true))\n await pipeResponsesSSE(\n upstreamResponse,\n res,\n (text) => learningBuffer?.append(text),\n () => learningBuffer?.flush(),\n totalTokensSaved,\n )\n return\n }\n\n // ── Non-streaming response ────────────────────────────────\n const responseBody = await upstreamResponse.text()\n logger.log(formatResponseLog(request.model, totalTokensSaved))\n\n // Adjust usage to reflect pre-compression token count\n let finalBody = responseBody\n if (totalTokensSaved > 0) {\n try {\n const parsed = JSON.parse(responseBody) as ResponsesResponse\n if (parsed?.usage?.input_tokens != null) {\n parsed.usage.input_tokens += totalTokensSaved\n if (parsed.usage.total_tokens != null) {\n parsed.usage.total_tokens += totalTokensSaved\n }\n finalBody = JSON.stringify(parsed)\n logger.log(`[TOKENS] Adjusted input_tokens by +${totalTokensSaved}`)\n }\n } catch {\n // Pass through unmodified on parse error\n }\n }\n\n setCORSHeaders(res)\n res.writeHead(200, { 'Content-Type': 'application/json' })\n res.end(finalBody)\n\n // Trigger learning from response (fire-and-forget)\n if (anyCompressed) {\n try {\n const parsed = JSON.parse(responseBody) as ResponsesResponse\n if (parsed?.output) {\n const text = extractOutputText(parsed.output)\n if (text.length > 0) {\n pipeline.pipeline.triggerLearning(text)\n }\n }\n } catch {\n // Ignore learning parse errors\n }\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Upstream request failed: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 502, {\n error: { message: `Failed to reach upstream LLM: ${message}`, type: 'server_error' },\n })\n }\n }\n}\n","import * as http from 'node:http'\n\n/**\n * Pipe an OpenAI Responses API SSE stream from upstream to the client.\n *\n * Responses API SSE format differs from Chat Completions:\n * - Each chunk has both `event:` and `data:` lines\n * - Text deltas arrive as `response.output_text.delta` events\n * - Usage is reported in the `response.completed` event\n * - Stream ends with `data: [DONE]`\n *\n * When totalTokensSaved > 0, adjusts usage.input_tokens in the\n * `response.completed` event to reflect pre-compression token count.\n *\n * Writes each chunk immediately — zero buffering, zero added latency\n * (except for the single response.completed chunk which may get rewritten).\n */\nexport async function pipeResponsesSSE(\n upstreamResponse: Response,\n clientRes: http.ServerResponse,\n onContentDelta: (text: string) => void,\n onComplete: () => void,\n totalTokensSaved = 0,\n): Promise<void> {\n clientRes.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n 'Access-Control-Allow-Origin': '*',\n })\n\n const reader = upstreamResponse.body!.getReader()\n const decoder = new TextDecoder()\n let lineBuf = ''\n let currentEvent = ''\n let usageAdjusted = false\n const needsAdjustment = totalTokensSaved > 0\n\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n\n const chunk = decoder.decode(value, { stream: true })\n\n // Fast path: no adjustment needed (or already done), write immediately\n if (!needsAdjustment || usageAdjusted) {\n clientRes.write(chunk)\n\n // Still parse for learning\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n } else if (line.startsWith('data: ') && currentEvent === 'response.output_text.delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (typeof json?.delta === 'string') {\n onContentDelta(json.delta)\n }\n } catch {\n // Malformed data — ignore for learning\n }\n }\n }\n continue\n }\n\n // Slow path: need to check for response.completed to adjust usage\n lineBuf += chunk\n const lines = lineBuf.split('\\n')\n lineBuf = lines.pop() || ''\n\n let adjusted = false\n const outputLines: string[] = []\n\n for (const line of lines) {\n if (line.startsWith('event: ')) {\n currentEvent = line.slice(7).trim()\n outputLines.push(line)\n } else if (\n line.startsWith('data: ') &&\n currentEvent === 'response.completed' &&\n !usageAdjusted\n ) {\n // Adjust usage in the response.completed event\n try {\n const json = JSON.parse(line.slice(6))\n if (json?.response?.usage?.input_tokens != null) {\n json.response.usage.input_tokens += totalTokensSaved\n if (json.response.usage.total_tokens != null) {\n json.response.usage.total_tokens += totalTokensSaved\n }\n outputLines.push(`data: ${JSON.stringify(json)}`)\n usageAdjusted = true\n adjusted = true\n } else {\n outputLines.push(line)\n }\n } catch {\n outputLines.push(line)\n }\n } else {\n outputLines.push(line)\n\n // Learning: extract text deltas\n if (line.startsWith('data: ') && currentEvent === 'response.output_text.delta') {\n try {\n const json = JSON.parse(line.slice(6))\n if (typeof json?.delta === 'string') {\n onContentDelta(json.delta)\n }\n } catch {\n // Malformed data — ignore for learning\n }\n }\n }\n }\n\n if (adjusted) {\n const reconstructed = outputLines.join('\\n') + '\\n'\n clientRes.write(reconstructed)\n } else {\n clientRes.write(chunk)\n }\n }\n } finally {\n clientRes.end()\n onComplete()\n }\n}\n","import * as http from 'node:http'\nimport * as crypto from 'node:crypto'\n\nexport interface SessionKey {\n connector: 'claude-code' | 'cursor' | 'codex' | 'openai-compatible' | 'unknown'\n windowHash: string\n raw: string\n}\n\nexport function identifySession(req: http.IncomingMessage, pathname: string): SessionKey {\n const connector = detectConnector(req, pathname)\n const windowHash = deriveWindowHash(req)\n return { connector, windowHash, raw: `${connector}:${windowHash}` }\n}\n\n// ─── Connector detection ──────────────────────────────────────────────\n\nfunction detectConnector(\n req: http.IncomingMessage,\n pathname: string,\n): SessionKey['connector'] {\n if (req.headers['x-api-key'] || req.headers['anthropic-version']) {\n return 'claude-code'\n }\n if (pathname.startsWith('/v1/responses') || pathname.startsWith('/responses')) {\n return 'codex'\n }\n const ua = req.headers['user-agent'] ?? ''\n if (/cursor/i.test(ua)) {\n return 'cursor'\n }\n return 'openai-compatible'\n}\n\n// ─── Window hash derivation ───────────────────────────────────────────\n\nfunction deriveWindowHash(req: http.IncomingMessage): string {\n // Explicit session header takes priority\n const liminalSession = req.headers['x-liminal-session']\n if (typeof liminalSession === 'string' && liminalSession.length > 0) {\n return liminalSession\n }\n\n // Extract credential from x-api-key or Authorization bearer token\n const credential = extractCredential(req)\n if (!credential) return 'anonymous'\n\n return crypto.createHash('sha256').update(credential).digest('hex').slice(0, 8)\n}\n\nfunction extractCredential(req: http.IncomingMessage): string | null {\n const apiKey = req.headers['x-api-key']\n if (typeof apiKey === 'string' && apiKey.length > 0) return apiKey\n\n const auth = req.headers['authorization']\n if (typeof auth === 'string') {\n const match = auth.match(/^Bearer\\s+(.+)$/i)\n if (match) return match[1]\n }\n\n return null\n}\n","import * as http from 'node:http'\nimport { handleChatCompletions } from './completions.js'\nimport { handleAnthropicMessages } from './messages.js'\nimport { handleResponses } from './responses.js'\nimport { identifySession } from './session-identity.js'\nimport type { SessionManager } from '../rsc/session-manager.js'\nimport type { Semaphore } from '../rsc/semaphore.js'\nimport type { LatencyMonitor } from '../rsc/latency-monitor.js'\nimport type { ResolvedConfig } from '../types.js'\n\nexport interface Logger {\n log(message: string): void\n}\n\n/** Dependencies injected into the request handler. */\nexport interface HandlerDeps {\n sessions: SessionManager\n semaphore: Semaphore\n latencyMonitor: LatencyMonitor\n config: ResolvedConfig\n logger: Logger\n}\n\nfunction setCORSHeaders(res: http.ServerResponse): void {\n res.setHeader('Access-Control-Allow-Origin', '*')\n res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE, PATCH')\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, x-api-key, anthropic-version, anthropic-beta, anthropic-dangerous-direct-browser-access, x-liminal-session')\n res.setHeader('Access-Control-Max-Age', '86400')\n}\n\nfunction sendJSON(res: http.ServerResponse, status: number, body: unknown): void {\n setCORSHeaders(res)\n res.writeHead(status, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify(body))\n}\n\nfunction readBody(req: http.IncomingMessage): Promise<Buffer> {\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)))\n req.on('error', reject)\n })\n}\n\n// ─── Upstream detection ──────────────────────────────────────────────\n\ntype UpstreamTarget = 'anthropic' | 'openai'\n\nfunction detectUpstream(req: http.IncomingMessage, url: string): UpstreamTarget {\n if (req.headers['x-api-key']) return 'anthropic'\n if (req.headers['anthropic-version']) return 'anthropic'\n if (url.startsWith('/v1/messages') || url.startsWith('/messages')) return 'anthropic'\n return 'anthropic'\n}\n\nfunction getUpstreamBaseUrl(target: UpstreamTarget, config: ResolvedConfig): string {\n return target === 'anthropic'\n ? config.anthropicUpstreamUrl\n : config.upstreamBaseUrl\n}\n\n// ─── Header forwarding ──────────────────────────────────────────────\n\nconst HOP_BY_HOP = new Set([\n 'host', 'connection', 'keep-alive', 'transfer-encoding',\n 'te', 'trailer', 'upgrade', 'proxy-authorization', 'proxy-authenticate',\n])\n\nfunction buildUpstreamHeaders(req: http.IncomingMessage): Record<string, string> {\n const headers: Record<string, string> = {}\n\n for (const [key, value] of Object.entries(req.headers)) {\n if (HOP_BY_HOP.has(key)) continue\n if (value === undefined) continue\n headers[key] = Array.isArray(value) ? value.join(', ') : value\n }\n\n return headers\n}\n\n// ─── Adaptive passthrough ────────────────────────────────────────────\n\nasync function passthroughToUpstream(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n fullUrl: string,\n config: ResolvedConfig,\n logger: Logger,\n): Promise<void> {\n const target = detectUpstream(req, fullUrl)\n const upstreamBase = getUpstreamBaseUrl(target, config)\n const upstreamUrl = `${upstreamBase}${fullUrl}`\n const method = req.method?.toUpperCase() ?? 'GET'\n\n logger.log(`[PASSTHROUGH] ${method} ${fullUrl} → ${target} (${upstreamUrl})`)\n\n const headers = buildUpstreamHeaders(req)\n\n try {\n const hasBody = method !== 'GET' && method !== 'HEAD'\n const body = hasBody ? await readBody(req) : undefined\n\n const upstreamRes = await fetch(upstreamUrl, {\n method,\n headers,\n body,\n })\n\n const contentType = upstreamRes.headers.get('Content-Type') || 'application/json'\n const isStreaming = contentType.includes('text/event-stream')\n\n if (isStreaming && upstreamRes.body) {\n setCORSHeaders(res)\n res.writeHead(upstreamRes.status, {\n 'Content-Type': contentType,\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n })\n\n const reader = upstreamRes.body.getReader()\n try {\n while (true) {\n const { done, value } = await reader.read()\n if (done) break\n res.write(value)\n }\n } finally {\n res.end()\n }\n } else {\n const responseBody = await upstreamRes.arrayBuffer()\n setCORSHeaders(res)\n\n const responseHeaders: Record<string, string> = { 'Content-Type': contentType }\n const reqId = upstreamRes.headers.get('request-id')\n if (reqId) responseHeaders['request-id'] = reqId\n\n res.writeHead(upstreamRes.status, responseHeaders)\n res.end(Buffer.from(responseBody))\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Passthrough to ${target} failed: ${message}`)\n if (!res.headersSent) {\n setCORSHeaders(res)\n res.writeHead(502, { 'Content-Type': 'application/json' })\n res.end(JSON.stringify({\n type: 'error',\n error: { type: 'api_error', message: `Liminal proxy: failed to reach ${target} upstream: ${message}` },\n }))\n }\n }\n}\n\nexport function createRequestHandler(\n deps: HandlerDeps,\n): (req: http.IncomingMessage, res: http.ServerResponse) => void {\n const { sessions, semaphore, latencyMonitor, config, logger } = deps\n const startTime = Date.now()\n\n return async (req, res) => {\n try {\n const method = req.method?.toUpperCase() ?? ''\n const fullUrl = req.url ?? ''\n const url = fullUrl.split('?')[0]\n\n const authType = req.headers['x-api-key'] ? 'x-api-key' : req.headers['authorization'] ? 'bearer' : 'none'\n logger.log(`[REQUEST] ${method} ${fullUrl} (auth: ${authType})`)\n\n // CORS preflight\n if (method === 'OPTIONS') {\n setCORSHeaders(res)\n res.writeHead(204)\n res.end()\n return\n }\n\n // Health check — expanded with per-session data\n if (method === 'GET' && (url === '/health' || url === '/')) {\n const sessionSummaries = sessions.getAllSummaries()\n sendJSON(res, 200, {\n status: 'ok',\n version: config.rscApiKey ? 'connected' : 'no-api-key',\n uptime_ms: Date.now() - startTime,\n concurrency: {\n active_sessions: sessions.activeCount,\n semaphore_available: semaphore.available,\n semaphore_waiting: semaphore.waiting,\n max_concurrent_rsc_calls: config.concurrencyLimit,\n },\n latency: {\n global_p95_ms: latencyMonitor.getGlobalP95(),\n },\n sessions: sessionSummaries.map(s => ({\n session_key: s.key,\n connector: s.connector,\n circuit_state: s.circuitState,\n tokens_processed: s.tokensProcessed,\n tokens_saved: s.tokensSaved,\n calls_total: s.totalCalls,\n calls_compressed: s.compressedCalls,\n calls_failed: s.failedCalls,\n p95_latency_ms: latencyMonitor.getSessionP95(s.key),\n last_active_ago_ms: Date.now() - s.lastAccessedAt,\n })),\n })\n return\n }\n\n // ── Identify session and resolve pipeline ────────────────────\n const sessionKey = identifySession(req, url)\n const pipeline = sessions.getOrCreate(sessionKey)\n\n // ── Compression routes ───────────────────────────────────────\n\n if (method === 'POST' && (url === '/v1/chat/completions' || url === '/chat/completions')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body.toString('utf-8'))\n } catch {\n sendJSON(res, 400, {\n error: { message: 'Invalid JSON body', type: 'invalid_request_error' },\n })\n return\n }\n\n await handleChatCompletions(req, res, parsed, pipeline, config, logger, semaphore, latencyMonitor, sessionKey.raw)\n return\n }\n\n if (method === 'POST' && (url === '/v1/responses' || url === '/responses')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body.toString('utf-8'))\n } catch {\n sendJSON(res, 400, {\n error: { message: 'Invalid JSON body', type: 'invalid_request_error' },\n })\n return\n }\n\n await handleResponses(req, res, parsed, pipeline, config, logger, semaphore, latencyMonitor, sessionKey.raw)\n return\n }\n\n if (method === 'POST' && (url === '/v1/messages' || url === '/messages')) {\n const body = await readBody(req)\n let parsed: unknown\n try {\n parsed = JSON.parse(body.toString('utf-8'))\n } catch {\n sendJSON(res, 400, {\n type: 'error',\n error: { type: 'invalid_request_error', message: 'Invalid JSON body' },\n })\n return\n }\n\n await handleAnthropicMessages(req, res, parsed, pipeline, config, logger, semaphore, latencyMonitor, sessionKey.raw)\n return\n }\n\n // ── Adaptive passthrough ─────────────────────────────────────\n await passthroughToUpstream(req, res, fullUrl, config, logger)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[ERROR] Proxy handler error: ${message}`)\n if (!res.headersSent) {\n sendJSON(res, 500, {\n error: { message: 'Internal proxy error', type: 'server_error' },\n })\n }\n }\n }\n}\n","import * as http from 'node:http'\nimport * as net from 'node:net'\n\nconst MAX_PORT_RETRIES = 5\n\nexport type ConnectHandler = (\n req: http.IncomingMessage,\n socket: net.Socket,\n head: Buffer,\n) => void\n\nexport class ProxyServer {\n private server: http.Server | null = null\n private activePort: number | null = null\n private readonly requestedPort: number\n private readonly handler: (req: http.IncomingMessage, res: http.ServerResponse) => void\n private readonly connectHandler: ConnectHandler | null\n\n constructor(\n port: number,\n handler: (req: http.IncomingMessage, res: http.ServerResponse) => void,\n connectHandler?: ConnectHandler,\n ) {\n this.requestedPort = port\n this.handler = handler\n this.connectHandler = connectHandler ?? null\n }\n\n async start(): Promise<number> {\n let lastError: Error | null = null\n\n for (let attempt = 0; attempt < MAX_PORT_RETRIES; attempt++) {\n const port = this.requestedPort + attempt\n try {\n await this.listen(port)\n this.activePort = port\n return port\n } catch (err) {\n lastError = err instanceof Error ? err : new Error(String(err))\n if ((err as NodeJS.ErrnoException).code !== 'EADDRINUSE') {\n throw lastError\n }\n }\n }\n\n throw lastError ?? new Error(`All ports ${this.requestedPort}-${this.requestedPort + MAX_PORT_RETRIES - 1} in use`)\n }\n\n private listen(port: number): Promise<void> {\n return new Promise((resolve, reject) => {\n const server = http.createServer(this.handler)\n\n // Wire up CONNECT handler for forward proxy mode (Cursor MITM)\n if (this.connectHandler) {\n server.on('connect', this.connectHandler)\n }\n\n server.on('error', reject)\n server.listen(port, '127.0.0.1', () => {\n server.removeListener('error', reject)\n this.server = server\n resolve()\n })\n })\n }\n\n async stop(): Promise<void> {\n if (!this.server) return\n return new Promise((resolve) => {\n this.server!.close(() => {\n this.server = null\n this.activePort = null\n resolve()\n })\n })\n }\n\n isRunning(): boolean {\n return this.server !== null && this.server.listening\n }\n\n getPort(): number | null {\n return this.activePort\n }\n\n /** Expose internal HTTP server for MITM bridge socket injection */\n getHttpServer(): http.Server | null {\n return this.server\n }\n}\n","import { appendFileSync, statSync, renameSync, mkdirSync, existsSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { LOG_FILE, LOG_DIR } from '../config/paths.js'\nimport type { Logger } from '../proxy/handler.js'\n\nconst MAX_LOG_SIZE = 10 * 1024 * 1024 // 10 MB\nconst MAX_BACKUPS = 2\n\nexport class FileLogger implements Logger {\n private readonly logFile: string\n private readonly mirrorStdout: boolean\n\n constructor(options?: { logFile?: string; mirrorStdout?: boolean }) {\n this.logFile = options?.logFile ?? LOG_FILE\n this.mirrorStdout = options?.mirrorStdout ?? false\n\n // Ensure log directory exists\n const logDir = dirname(this.logFile)\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true })\n }\n }\n\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n const line = `[${timestamp}] ${message}\\n`\n\n try {\n appendFileSync(this.logFile, line)\n } catch {\n // If log write fails, try stdout as fallback\n process.stderr.write(`[LOG-WRITE-FAILED] ${line}`)\n }\n\n if (this.mirrorStdout) {\n process.stdout.write(line)\n }\n\n this.rotateIfNeeded()\n }\n\n private rotateIfNeeded(): void {\n try {\n const stats = statSync(this.logFile)\n if (stats.size <= MAX_LOG_SIZE) return\n\n // Rotate: liminal.log -> liminal.log.1 -> liminal.log.2 (drop oldest)\n for (let i = MAX_BACKUPS - 1; i >= 1; i--) {\n const from = `${this.logFile}.${i}`\n const to = `${this.logFile}.${i + 1}`\n if (existsSync(from)) renameSync(from, to)\n }\n renameSync(this.logFile, `${this.logFile}.1`)\n } catch {\n // Rotation failure is non-fatal\n }\n }\n\n getLogFile(): string {\n return this.logFile\n }\n}\n\n/**\n * A simple logger that only writes to stdout (for use during init or when log file isn't available).\n */\nexport class ConsoleLogger implements Logger {\n log(message: string): void {\n const timestamp = new Date().toISOString().slice(11, 23)\n process.stdout.write(`[${timestamp}] ${message}\\n`)\n }\n}\n","import type { SessionKey } from '../proxy/session-identity.js'\nimport { RSCPipelineWrapper } from './pipeline.js'\nimport type { PipelineConfig } from './pipeline.js'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface SessionManagerConfig {\n pipelineConfig: PipelineConfig\n maxSessions: number\n sessionTtlMs: number\n onSessionCreated?: (key: string, pipeline: RSCPipelineWrapper) => void\n onSessionEvicted?: (key: string) => void\n}\n\nexport interface SessionHealthEntry {\n key: string\n connector: string\n circuitState: string\n tokensProcessed: number\n tokensSaved: number\n totalCalls: number\n compressedCalls: number\n failedCalls: number\n lastAccessedAt: number\n}\n\ninterface ManagedSession {\n pipeline: RSCPipelineWrapper\n lastAccessedAt: number\n requestCount: number\n connector: string\n}\n\n// ---------------------------------------------------------------------------\n// Defaults\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_MAX_SESSIONS = 10\nconst DEFAULT_SESSION_TTL_MS = 30 * 60 * 1000 // 30 minutes\nconst EVICTION_INTERVAL_MS = 60_000 // 60 seconds\n\n// ---------------------------------------------------------------------------\n// SessionManager\n// ---------------------------------------------------------------------------\n\nexport class SessionManager {\n private readonly sessions = new Map<string, ManagedSession>()\n private readonly config: Required<Pick<SessionManagerConfig, 'maxSessions' | 'sessionTtlMs'>> &\n SessionManagerConfig\n private evictionTimer: ReturnType<typeof setInterval> | null = null\n\n constructor(config: SessionManagerConfig) {\n this.config = {\n ...config,\n maxSessions: config.maxSessions ?? DEFAULT_MAX_SESSIONS,\n sessionTtlMs: config.sessionTtlMs ?? DEFAULT_SESSION_TTL_MS,\n }\n\n this.evictionTimer = setInterval(() => this.evictStale(), EVICTION_INTERVAL_MS)\n // Allow the process to exit even if the timer is still running\n if (this.evictionTimer.unref) {\n this.evictionTimer.unref()\n }\n }\n\n // ── Public API ──────────────────────────────────────────────────────\n\n getOrCreate(key: SessionKey): RSCPipelineWrapper {\n const existing = this.sessions.get(key.raw)\n if (existing) {\n existing.lastAccessedAt = Date.now()\n existing.requestCount++\n return existing.pipeline\n }\n\n // At capacity — evict least-recently-used\n if (this.sessions.size >= this.config.maxSessions) {\n this.evictLRU()\n }\n\n const pipeline = new RSCPipelineWrapper({\n ...this.config.pipelineConfig,\n sessionId: key.raw,\n })\n\n this.sessions.set(key.raw, {\n pipeline,\n lastAccessedAt: Date.now(),\n requestCount: 1,\n connector: key.connector,\n })\n\n this.config.onSessionCreated?.(key.raw, pipeline)\n return pipeline\n }\n\n getAllSummaries(): SessionHealthEntry[] {\n const entries: SessionHealthEntry[] = []\n for (const [key, managed] of this.sessions) {\n entries.push(this.buildHealthEntry(key, managed))\n }\n return entries\n }\n\n getSessionSummary(key: string): SessionHealthEntry | null {\n const managed = this.sessions.get(key)\n if (!managed) return null\n return this.buildHealthEntry(key, managed)\n }\n\n get activeCount(): number {\n return this.sessions.size\n }\n\n shutdown(): void {\n if (this.evictionTimer !== null) {\n clearInterval(this.evictionTimer)\n this.evictionTimer = null\n }\n this.sessions.clear()\n }\n\n // ── Internals ───────────────────────────────────────────────────────\n\n private buildHealthEntry(key: string, managed: ManagedSession): SessionHealthEntry {\n const summary = managed.pipeline.getSessionSummary()\n return {\n key,\n connector: managed.connector,\n circuitState: managed.pipeline.getCircuitState(),\n tokensProcessed: summary.tokensProcessed,\n tokensSaved: summary.tokensSaved,\n totalCalls: summary.totalCalls,\n compressedCalls: summary.compressedCalls,\n failedCalls: summary.failedCalls,\n lastAccessedAt: managed.lastAccessedAt,\n }\n }\n\n private evictStale(): void {\n const now = Date.now()\n const cutoff = now - this.config.sessionTtlMs\n\n for (const [key, managed] of this.sessions) {\n if (managed.lastAccessedAt < cutoff) {\n this.sessions.delete(key)\n this.config.onSessionEvicted?.(key)\n }\n }\n }\n\n private evictLRU(): void {\n let oldestKey: string | null = null\n let oldestTime = Infinity\n\n for (const [key, managed] of this.sessions) {\n if (managed.lastAccessedAt < oldestTime) {\n oldestTime = managed.lastAccessedAt\n oldestKey = key\n }\n }\n\n if (oldestKey !== null) {\n this.sessions.delete(oldestKey)\n this.config.onSessionEvicted?.(oldestKey)\n }\n }\n}\n","export class SemaphoreTimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Semaphore acquire timed out after ${timeoutMs}ms`)\n this.name = 'SemaphoreTimeoutError'\n }\n}\n\ninterface Waiter {\n resolve: () => void\n reject: (err: Error) => void\n}\n\nexport class Semaphore {\n private permits: number\n private readonly queue: Waiter[] = []\n\n constructor(maxPermits: number) {\n if (maxPermits < 1) throw new RangeError('maxPermits must be >= 1')\n this.permits = maxPermits\n }\n\n get available(): number {\n return this.permits\n }\n\n get waiting(): number {\n return this.queue.length\n }\n\n acquire(timeoutMs?: number): Promise<void> {\n if (this.permits > 0) {\n this.permits--\n return Promise.resolve()\n }\n\n return new Promise<void>((resolve, reject) => {\n const waiter: Waiter = { resolve, reject }\n this.queue.push(waiter)\n\n if (timeoutMs !== undefined && timeoutMs >= 0) {\n const timer = setTimeout(() => {\n const idx = this.queue.indexOf(waiter)\n if (idx !== -1) {\n this.queue.splice(idx, 1)\n reject(new SemaphoreTimeoutError(timeoutMs))\n }\n }, timeoutMs)\n\n const originalResolve = waiter.resolve\n waiter.resolve = () => {\n clearTimeout(timer)\n originalResolve()\n }\n }\n })\n }\n\n release(): void {\n const next = this.queue.shift()\n if (next) {\n next.resolve()\n } else {\n this.permits++\n }\n }\n}\n","export interface LatencyAlert {\n type: 'warning' | 'critical'\n message: string\n sessionKey: string\n p95Ms: number\n thresholdMs: number\n activeSessions: number\n suggestion: string\n}\n\nexport interface LatencyMonitorConfig {\n warningThresholdMs: number\n criticalThresholdMs: number\n windowSize: number\n}\n\nconst DEFAULT_CONFIG: LatencyMonitorConfig = {\n warningThresholdMs: 4000,\n criticalThresholdMs: 8000,\n windowSize: 50,\n}\n\nclass CircularBuffer {\n private readonly buffer: number[]\n private index = 0\n private count = 0\n private readonly capacity: number\n\n constructor(capacity: number) {\n this.capacity = capacity\n this.buffer = new Array<number>(capacity)\n }\n\n push(value: number): void {\n this.buffer[this.index] = value\n this.index = (this.index + 1) % this.capacity\n if (this.count < this.capacity) {\n this.count++\n }\n }\n\n getValues(): number[] {\n if (this.count < this.capacity) {\n return this.buffer.slice(0, this.count)\n }\n return [...this.buffer.slice(this.index), ...this.buffer.slice(0, this.index)]\n }\n\n get size(): number {\n return this.count\n }\n}\n\nfunction calculateP95(values: number[]): number | null {\n if (values.length === 0) return null\n const sorted = [...values].sort((a, b) => a - b)\n const idx = Math.floor(sorted.length * 0.95)\n return sorted[Math.min(idx, sorted.length - 1)]\n}\n\nexport class LatencyMonitor {\n private readonly config: LatencyMonitorConfig\n private readonly sessionWindows = new Map<string, CircularBuffer>()\n private readonly globalWindow: CircularBuffer\n private readonly callbacks: Array<(alert: LatencyAlert) => void> = []\n\n constructor(config?: Partial<LatencyMonitorConfig>) {\n this.config = { ...DEFAULT_CONFIG, ...config }\n this.globalWindow = new CircularBuffer(this.config.windowSize * 4)\n }\n\n record(sessionKey: string, latencyMs: number): LatencyAlert | null {\n let sessionBuf = this.sessionWindows.get(sessionKey)\n if (!sessionBuf) {\n sessionBuf = new CircularBuffer(this.config.windowSize)\n this.sessionWindows.set(sessionKey, sessionBuf)\n }\n sessionBuf.push(latencyMs)\n this.globalWindow.push(latencyMs)\n\n const globalP95 = calculateP95(this.globalWindow.getValues())\n if (globalP95 === null) return null\n\n let alert: LatencyAlert | null = null\n\n if (globalP95 >= this.config.criticalThresholdMs) {\n alert = {\n type: 'critical',\n message: `Global p95 latency ${globalP95.toFixed(0)}ms exceeds critical threshold ${this.config.criticalThresholdMs}ms`,\n sessionKey,\n p95Ms: globalP95,\n thresholdMs: this.config.criticalThresholdMs,\n activeSessions: this.sessionWindows.size,\n suggestion: 'Reduce active sessions or increase latency budget',\n }\n } else if (globalP95 >= this.config.warningThresholdMs) {\n alert = {\n type: 'warning',\n message: `Global p95 latency ${globalP95.toFixed(0)}ms exceeds warning threshold ${this.config.warningThresholdMs}ms`,\n sessionKey,\n p95Ms: globalP95,\n thresholdMs: this.config.warningThresholdMs,\n activeSessions: this.sessionWindows.size,\n suggestion: 'Consider reducing active sessions',\n }\n }\n\n if (alert) {\n for (const cb of this.callbacks) {\n cb(alert)\n }\n }\n\n return alert\n }\n\n getSessionP95(sessionKey: string): number | null {\n const buf = this.sessionWindows.get(sessionKey)\n if (!buf) return null\n return calculateP95(buf.getValues())\n }\n\n getGlobalP95(): number | null {\n return calculateP95(this.globalWindow.getValues())\n }\n\n onAlert(cb: (alert: LatencyAlert) => void): void {\n this.callbacks.push(cb)\n }\n\n get sessionCount(): number {\n return this.sessionWindows.size\n }\n}\n","/**\n * HTTP CONNECT handler for forward proxy mode.\n *\n * When Cursor is launched with --proxy-server=http://127.0.0.1:PORT,\n * it sends CONNECT requests for HTTPS destinations. This handler:\n *\n * 1. Parses the CONNECT host:port request\n * 2. Checks the allowlist — is this an LLM API host?\n * 3. If YES: responds 200 and hands off to MITM interceptor (Phase 3+4)\n * 4. If NO: opens a plain TCP tunnel to the destination (passthrough)\n *\n * The CONNECT event is emitted by Node's http.Server separately from\n * the normal 'request' event, so this is wired up independently.\n */\n\nimport * as net from 'node:net'\nimport type * as http from 'node:http'\nimport { shouldIntercept } from './allowlist.js'\n\nexport interface ConnectLogger {\n log(message: string): void\n}\n\nexport type MitmHandler = (\n clientSocket: net.Socket,\n hostname: string,\n port: number,\n) => void\n\nexport interface ConnectHandlerOptions {\n logger: ConnectLogger\n /** Called for allowlisted hosts that should be MITM-intercepted. */\n onIntercept?: MitmHandler\n}\n\n/**\n * Create a handler for the http.Server 'connect' event.\n *\n * Usage:\n * server.on('connect', createConnectHandler({ logger }))\n */\nexport function createConnectHandler(\n options: ConnectHandlerOptions,\n): (req: http.IncomingMessage, clientSocket: net.Socket, head: Buffer) => void {\n const { logger, onIntercept } = options\n\n return (req: http.IncomingMessage, clientSocket: net.Socket, head: Buffer) => {\n const target = req.url ?? ''\n const [hostname, portStr] = parseConnectTarget(target)\n const port = parseInt(portStr, 10) || 443\n\n if (!hostname) {\n logger.log(`[CONNECT] Invalid target: ${target}`)\n clientSocket.write('HTTP/1.1 400 Bad Request\\r\\n\\r\\n')\n clientSocket.destroy()\n return\n }\n\n if (shouldIntercept(hostname) && onIntercept) {\n // Allowlisted host — MITM intercept\n logger.log(`[CONNECT] ${hostname}:${port} → intercept`)\n\n // Tell the client the tunnel is established\n clientSocket.write('HTTP/1.1 200 Connection Established\\r\\n\\r\\n')\n\n // Hand off to the MITM handler (Phase 3+4)\n // Pass any data that arrived with the CONNECT request\n if (head.length > 0) {\n clientSocket.unshift(head)\n }\n\n onIntercept(clientSocket, hostname, port)\n } else {\n // Non-allowlisted host — plain TCP tunnel passthrough\n logger.log(`[TUNNEL] ${hostname}:${port} → passthrough`)\n\n const upstreamSocket = net.connect(port, hostname, () => {\n clientSocket.write('HTTP/1.1 200 Connection Established\\r\\n\\r\\n')\n\n // Forward any data that arrived with the CONNECT request\n if (head.length > 0) {\n upstreamSocket.write(head)\n }\n\n // Bidirectional pipe\n clientSocket.pipe(upstreamSocket)\n upstreamSocket.pipe(clientSocket)\n })\n\n // Error handling\n upstreamSocket.on('error', (err) => {\n logger.log(`[TUNNEL] ${hostname}:${port} upstream error: ${err.message}`)\n clientSocket.write('HTTP/1.1 502 Bad Gateway\\r\\n\\r\\n')\n clientSocket.destroy()\n })\n\n clientSocket.on('error', (err) => {\n logger.log(`[TUNNEL] ${hostname}:${port} client error: ${err.message}`)\n upstreamSocket.destroy()\n })\n\n // Cleanup on close\n clientSocket.on('close', () => upstreamSocket.destroy())\n upstreamSocket.on('close', () => clientSocket.destroy())\n }\n }\n}\n\n/**\n * Parse \"host:port\" from CONNECT target.\n * Returns [hostname, port] or ['', ''] on failure.\n */\nfunction parseConnectTarget(target: string): [string, string] {\n const colonIdx = target.lastIndexOf(':')\n if (colonIdx === -1) return [target, '443']\n return [target.slice(0, colonIdx), target.slice(colonIdx + 1)]\n}\n","/**\n * MITM interception allowlist.\n *\n * Only hosts in this list get TLS-intercepted for compression.\n * Everything else passes through as a plain TCP tunnel.\n */\n\nconst MITM_HOSTS = new Set([\n 'api.openai.com',\n 'api.anthropic.com',\n 'generativelanguage.googleapis.com',\n])\n\n/**\n * Check if a hostname should be MITM-intercepted for compression.\n */\nexport function shouldIntercept(hostname: string): boolean {\n return MITM_HOSTS.has(hostname)\n}\n\n/**\n * Get the list of intercepted hosts (for status display).\n */\nexport function getInterceptedHosts(): string[] {\n return [...MITM_HOSTS]\n}\n","/**\n * CA certificate generation and management.\n *\n * Generates a self-signed CA key pair for TLS MITM interception.\n * The CA cert is installed in the system trust store so that Cursor\n * (via --proxy-server) accepts dynamically generated host certs.\n *\n * Storage: ~/.liminal/ca.pem + ca-key.pem (mode 0o600)\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { LIMINAL_DIR } from '../config/paths.js'\nimport forge from 'node-forge'\n\nexport const CA_CERT_PATH = join(LIMINAL_DIR, 'ca.pem')\nexport const CA_KEY_PATH = join(LIMINAL_DIR, 'ca-key.pem')\n\n// ─── Generation ──────────────────────────────────────────────────────\n\n/**\n * Generate a new self-signed CA certificate and private key.\n * Returns { cert, key } as PEM strings.\n */\nexport function generateCA(): { certPem: string; keyPem: string } {\n const keys = forge.pki.rsa.generateKeyPair(2048)\n\n const cert = forge.pki.createCertificate()\n cert.publicKey = keys.publicKey\n cert.serialNumber = generateSerialNumber()\n\n // Valid from now, for 5 years\n cert.validity.notBefore = new Date()\n cert.validity.notAfter = new Date()\n cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 5)\n\n const attrs = [\n { name: 'commonName', value: 'Liminal Proxy CA' },\n { name: 'organizationName', value: 'Liminal (Cognisos)' },\n { shortName: 'OU', value: 'Local Development' },\n ]\n cert.setSubject(attrs)\n cert.setIssuer(attrs) // Self-signed\n\n cert.setExtensions([\n { name: 'basicConstraints', cA: true, critical: true },\n { name: 'keyUsage', keyCertSign: true, cRLSign: true, critical: true },\n {\n name: 'subjectKeyIdentifier',\n },\n ])\n\n // Self-sign with SHA-256\n cert.sign(keys.privateKey, forge.md.sha256.create())\n\n return {\n certPem: forge.pki.certificateToPem(cert),\n keyPem: forge.pki.privateKeyToPem(keys.privateKey),\n }\n}\n\n// ─── Persistence ─────────────────────────────────────────────────────\n\n/**\n * Generate and save CA cert + key to ~/.liminal/.\n * Overwrites existing files.\n */\nexport function generateAndSaveCA(): { certPem: string; keyPem: string } {\n if (!existsSync(LIMINAL_DIR)) {\n mkdirSync(LIMINAL_DIR, { recursive: true, mode: 0o700 })\n }\n\n const { certPem, keyPem } = generateCA()\n\n writeFileSync(CA_CERT_PATH, certPem, { encoding: 'utf-8', mode: 0o644 })\n writeFileSync(CA_KEY_PATH, keyPem, { encoding: 'utf-8', mode: 0o600 })\n\n return { certPem, keyPem }\n}\n\n/**\n * Load existing CA cert and key from disk.\n * Returns null if either file is missing.\n */\nexport function loadCA(): { certPem: string; keyPem: string } | null {\n if (!existsSync(CA_CERT_PATH) || !existsSync(CA_KEY_PATH)) {\n return null\n }\n\n return {\n certPem: readFileSync(CA_CERT_PATH, 'utf-8'),\n keyPem: readFileSync(CA_KEY_PATH, 'utf-8'),\n }\n}\n\n/**\n * Load or generate CA. Prefers existing, generates if missing.\n */\nexport function ensureCA(): { certPem: string; keyPem: string } {\n const existing = loadCA()\n if (existing) return existing\n return generateAndSaveCA()\n}\n\n/**\n * Check if CA certificate files exist.\n */\nexport function hasCA(): boolean {\n return existsSync(CA_CERT_PATH) && existsSync(CA_KEY_PATH)\n}\n\n/**\n * Delete CA cert and key files.\n */\nexport function removeCA(): void {\n if (existsSync(CA_CERT_PATH)) unlinkSync(CA_CERT_PATH)\n if (existsSync(CA_KEY_PATH)) unlinkSync(CA_KEY_PATH)\n}\n\n/**\n * Parse CA cert PEM and return readable info.\n */\nexport function getCAInfo(): { commonName: string; validFrom: Date; validTo: Date; fingerprint: string } | null {\n const ca = loadCA()\n if (!ca) return null\n\n const cert = forge.pki.certificateFromPem(ca.certPem)\n const cn = cert.subject.getField('CN')\n\n // SHA-256 fingerprint\n const der = forge.asn1.toDer(forge.pki.certificateToAsn1(cert)).getBytes()\n const md = forge.md.sha256.create()\n md.update(der)\n const fingerprint = md.digest().toHex().match(/.{2}/g)!.join(':').toUpperCase()\n\n return {\n commonName: cn ? cn.value : 'Unknown',\n validFrom: cert.validity.notBefore,\n validTo: cert.validity.notAfter,\n fingerprint,\n }\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────\n\nfunction generateSerialNumber(): string {\n // Random 16-byte serial number as hex string\n const bytes = forge.random.getBytesSync(16)\n return forge.util.bytesToHex(bytes)\n}\n","/**\n * Platform-specific CA certificate trust management.\n *\n * Installs/removes the Liminal CA from the system trust store\n * so that Cursor (and other Electron apps) accept our dynamic certs.\n */\n\nimport { execSync } from 'node:child_process'\nimport { existsSync, copyFileSync, unlinkSync } from 'node:fs'\nimport { CA_CERT_PATH } from './ca.js'\n\nexport interface TrustResult {\n success: boolean\n message: string\n requiresSudo: boolean\n}\n\n// ─── Install ─────────────────────────────────────────────────────────\n\nexport function installCA(): TrustResult {\n if (!existsSync(CA_CERT_PATH)) {\n return { success: false, message: 'CA certificate not found. Run \"liminal init\" first.', requiresSudo: false }\n }\n\n const platform = process.platform\n\n if (platform === 'darwin') return installMacOS()\n if (platform === 'linux') return installLinux()\n if (platform === 'win32') return installWindows()\n\n return { success: false, message: `Unsupported platform: ${platform}`, requiresSudo: false }\n}\n\n// ─── Remove ──────────────────────────────────────────────────────────\n\nexport function removeCA(): TrustResult {\n const platform = process.platform\n\n if (platform === 'darwin') return removeMacOS()\n if (platform === 'linux') return removeLinux()\n if (platform === 'win32') return removeWindows()\n\n return { success: false, message: `Unsupported platform: ${platform}`, requiresSudo: false }\n}\n\n// ─── Check ───────────────────────────────────────────────────────────\n\nexport function isCATrusted(): boolean {\n const platform = process.platform\n\n if (platform === 'darwin') return isTrustedMacOS()\n if (platform === 'linux') return isTrustedLinux()\n if (platform === 'win32') return isTrustedWindows()\n\n return false\n}\n\n// ─── macOS ───────────────────────────────────────────────────────────\n\nconst MACOS_LABEL = 'Liminal Proxy CA'\n\nfunction installMacOS(): TrustResult {\n try {\n // Add to login keychain and mark as trusted for SSL\n execSync(\n `security add-trusted-cert -r trustRoot -k ~/Library/Keychains/login.keychain-db \"${CA_CERT_PATH}\"`,\n { stdio: 'pipe' },\n )\n return { success: true, message: 'CA installed in login keychain (trusted for SSL)', requiresSudo: false }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('authorization') || msg.includes('permission')) {\n return {\n success: false,\n message: 'Keychain access denied. You may need to unlock your keychain or run with sudo.',\n requiresSudo: true,\n }\n }\n return { success: false, message: `Failed to install CA: ${msg}`, requiresSudo: false }\n }\n}\n\nfunction removeMacOS(): TrustResult {\n try {\n execSync(\n `security delete-certificate -c \"${MACOS_LABEL}\" ~/Library/Keychains/login.keychain-db`,\n { stdio: 'pipe' },\n )\n return { success: true, message: 'CA removed from login keychain', requiresSudo: false }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('could not be found')) {\n return { success: true, message: 'CA was not in keychain (already removed)', requiresSudo: false }\n }\n return { success: false, message: `Failed to remove CA: ${msg}`, requiresSudo: false }\n }\n}\n\nfunction isTrustedMacOS(): boolean {\n try {\n const out = execSync(\n `security find-certificate -c \"${MACOS_LABEL}\" ~/Library/Keychains/login.keychain-db`,\n { stdio: 'pipe', encoding: 'utf-8' },\n )\n return out.includes(MACOS_LABEL)\n } catch {\n return false\n }\n}\n\n// ─── Linux ───────────────────────────────────────────────────────────\n\nconst LINUX_CERT_PATH = '/usr/local/share/ca-certificates/liminal-proxy-ca.crt'\n\nfunction installLinux(): TrustResult {\n try {\n copyFileSync(CA_CERT_PATH, LINUX_CERT_PATH)\n execSync('update-ca-certificates', { stdio: 'pipe' })\n return { success: true, message: 'CA installed in system trust store', requiresSudo: true }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n if (msg.includes('EACCES') || msg.includes('permission')) {\n return {\n success: false,\n message: `Permission denied. Run with sudo:\\n sudo liminal trust-ca`,\n requiresSudo: true,\n }\n }\n return { success: false, message: `Failed to install CA: ${msg}`, requiresSudo: true }\n }\n}\n\nfunction removeLinux(): TrustResult {\n try {\n if (existsSync(LINUX_CERT_PATH)) {\n unlinkSync(LINUX_CERT_PATH)\n execSync('update-ca-certificates --fresh', { stdio: 'pipe' })\n }\n return { success: true, message: 'CA removed from system trust store', requiresSudo: true }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return { success: false, message: `Failed to remove CA: ${msg}`, requiresSudo: true }\n }\n}\n\nfunction isTrustedLinux(): boolean {\n return existsSync(LINUX_CERT_PATH)\n}\n\n// ─── Windows ─────────────────────────────────────────────────────────\n\nfunction installWindows(): TrustResult {\n try {\n execSync(`certutil -addstore -user -f \"ROOT\" \"${CA_CERT_PATH}\"`, { stdio: 'pipe' })\n return { success: true, message: 'CA installed in user certificate store', requiresSudo: false }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return { success: false, message: `Failed to install CA: ${msg}`, requiresSudo: false }\n }\n}\n\nfunction removeWindows(): TrustResult {\n try {\n execSync(`certutil -delstore -user \"ROOT\" \"${MACOS_LABEL}\"`, { stdio: 'pipe' })\n return { success: true, message: 'CA removed from user certificate store', requiresSudo: false }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n return { success: false, message: `Failed to remove CA: ${msg}`, requiresSudo: false }\n }\n}\n\nfunction isTrustedWindows(): boolean {\n try {\n const out = execSync(`certutil -verifystore -user \"ROOT\" \"${MACOS_LABEL}\"`, {\n stdio: 'pipe',\n encoding: 'utf-8',\n })\n return out.includes('Liminal')\n } catch {\n return false\n }\n}\n","/**\n * TLS MITM bridge for intercepting HTTPS LLM API calls.\n *\n * When a CONNECT request arrives for an allowlisted host (e.g. api.openai.com),\n * this bridge:\n *\n * 1. Generates a dynamic TLS certificate for the hostname (signed by our CA)\n * 2. Wraps the client socket in a TLS server socket using that cert\n * 3. Injects the decrypted TLS socket into the existing HTTP server\n * 4. Our normal request handler processes it — compression, forwarding, etc.\n *\n * The client (Cursor) sees a valid certificate chain:\n * Cursor → [our dynamic cert for api.openai.com] → [our CA cert in trust store]\n *\n * The upstream sees a normal HTTPS request from our proxy.\n */\n\nimport * as tls from 'node:tls'\nimport * as net from 'node:net'\nimport type * as http from 'node:http'\nimport { CertGenerator } from './cert-generator.js'\nimport type { MitmHandler, ConnectLogger } from './connect-handler.js'\n\nexport interface MitmBridgeOptions {\n /** The HTTP server to inject decrypted connections into */\n httpServer: http.Server\n /** CA certificate PEM */\n caCertPem: string\n /** CA private key PEM */\n caKeyPem: string\n /** Logger for MITM events */\n logger: ConnectLogger\n}\n\n/**\n * Create a MITM handler that can be passed to createConnectHandler's onIntercept.\n *\n * When called, it wraps the client socket in TLS (presenting a cert for the\n * target hostname), then injects it into the HTTP server so our existing\n * request handlers process it transparently.\n */\nexport function createMitmBridge(options: MitmBridgeOptions): MitmHandler {\n const { httpServer, caCertPem, caKeyPem, logger } = options\n const certGen = new CertGenerator(caCertPem, caKeyPem)\n\n return (clientSocket: net.Socket, hostname: string, _port: number) => {\n try {\n // Generate (or retrieve cached) cert for this hostname\n const { certPem, keyPem } = certGen.getCert(hostname)\n\n // Create a TLS server socket wrapping the client connection\n const tlsSocket = new tls.TLSSocket(clientSocket, {\n isServer: true,\n key: keyPem,\n cert: certPem,\n })\n\n tlsSocket.on('error', (err) => {\n logger.log(`[MITM] TLS error for ${hostname}: ${err.message}`)\n tlsSocket.destroy()\n })\n\n // Inject the decrypted socket into our HTTP server.\n // The server's 'request' event handler will fire with the\n // decrypted HTTP request — our compression pipeline takes over.\n httpServer.emit('connection', tlsSocket)\n\n logger.log(`[MITM] TLS bridge established for ${hostname} (cert cache: ${certGen.cacheSize})`)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n logger.log(`[MITM] Failed to establish bridge for ${hostname}: ${message}`)\n clientSocket.destroy()\n }\n }\n}\n","/**\n * Dynamic TLS certificate generation for MITM interception.\n *\n * When Cursor connects to api.openai.com through our proxy, we need\n * to present a certificate for api.openai.com signed by our CA.\n * This module generates those certificates on-the-fly and caches them.\n */\n\nimport forge from 'node-forge'\n\nexport interface CertPair {\n certPem: string\n keyPem: string\n}\n\ninterface CacheEntry {\n cert: CertPair\n expiresAt: number\n}\n\nconst CERT_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\nconst MAX_CACHE_SIZE = 50\n\nexport class CertGenerator {\n private readonly caCert: forge.pki.Certificate\n private readonly caKey: forge.pki.rsa.PrivateKey\n private readonly cache = new Map<string, CacheEntry>()\n\n constructor(caCertPem: string, caKeyPem: string) {\n this.caCert = forge.pki.certificateFromPem(caCertPem)\n this.caKey = forge.pki.privateKeyFromPem(caKeyPem)\n }\n\n /**\n * Get or generate a TLS certificate for the given hostname.\n * Certificates are cached for 24 hours.\n */\n getCert(hostname: string): CertPair {\n const now = Date.now()\n\n // Check cache\n const cached = this.cache.get(hostname)\n if (cached && cached.expiresAt > now) {\n return cached.cert\n }\n\n // Generate new cert\n const cert = this.generate(hostname)\n\n // Evict oldest if at capacity\n if (this.cache.size >= MAX_CACHE_SIZE) {\n const oldest = this.cache.keys().next().value\n if (oldest) this.cache.delete(oldest)\n }\n\n this.cache.set(hostname, { cert, expiresAt: now + CERT_TTL_MS })\n return cert\n }\n\n get cacheSize(): number {\n return this.cache.size\n }\n\n private generate(hostname: string): CertPair {\n const keys = forge.pki.rsa.generateKeyPair(2048)\n\n const cert = forge.pki.createCertificate()\n cert.publicKey = keys.publicKey\n cert.serialNumber = randomSerial()\n\n // Valid from 1 day ago (clock skew tolerance) to 24 hours from now\n cert.validity.notBefore = new Date(Date.now() - 24 * 60 * 60 * 1000)\n cert.validity.notAfter = new Date(Date.now() + 24 * 60 * 60 * 1000)\n\n cert.setSubject([\n { name: 'commonName', value: hostname },\n { name: 'organizationName', value: 'Liminal Proxy (local)' },\n ])\n\n // Issuer is our CA\n cert.setIssuer(this.caCert.subject.attributes)\n\n cert.setExtensions([\n { name: 'basicConstraints', cA: false },\n {\n name: 'keyUsage',\n digitalSignature: true,\n keyEncipherment: true,\n critical: true,\n },\n {\n name: 'extKeyUsage',\n serverAuth: true,\n },\n {\n name: 'subjectAltName',\n altNames: [{ type: 2, value: hostname }], // DNS name\n },\n ])\n\n // Sign with our CA's private key\n cert.sign(this.caKey, forge.md.sha256.create())\n\n return {\n certPem: forge.pki.certificateToPem(cert),\n keyPem: forge.pki.privateKeyToPem(keys.privateKey),\n }\n }\n}\n\nfunction randomSerial(): string {\n return forge.util.bytesToHex(forge.random.getBytesSync(16))\n}\n","import { readFileSync, writeFileSync, unlinkSync, existsSync } from 'node:fs'\nimport { fork } from 'node:child_process'\nimport { fileURLToPath } from 'node:url'\nimport { PID_FILE } from '../config/paths.js'\nimport type { ProxyServer } from '../proxy/server.js'\nimport type { Logger } from '../proxy/handler.js'\n\n/**\n * Write the current process PID to ~/.liminal/liminal.pid.\n */\nexport function writePidFile(pid: number): void {\n writeFileSync(PID_FILE, String(pid), 'utf-8')\n}\n\n/**\n * Read PID from ~/.liminal/liminal.pid. Returns null if file doesn't exist.\n */\nexport function readPidFile(): number | null {\n if (!existsSync(PID_FILE)) return null\n try {\n const content = readFileSync(PID_FILE, 'utf-8').trim()\n const pid = parseInt(content, 10)\n return isNaN(pid) ? null : pid\n } catch {\n return null\n }\n}\n\n/**\n * Remove the PID file.\n */\nexport function removePidFile(): void {\n try {\n if (existsSync(PID_FILE)) unlinkSync(PID_FILE)\n } catch {\n // Ignore — file may already be gone\n }\n}\n\n/**\n * Check if a process with the given PID is alive.\n */\nexport function isProcessAlive(pid: number): boolean {\n try {\n process.kill(pid, 0)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Check if the Liminal daemon is currently running.\n * Cleans up stale PID files automatically.\n */\nexport function isDaemonRunning(): { running: boolean; pid?: number } {\n const pid = readPidFile()\n if (pid === null) return { running: false }\n\n if (isProcessAlive(pid)) {\n return { running: true, pid }\n }\n\n // Stale PID file — process is dead\n removePidFile()\n return { running: false }\n}\n\n/**\n * Set up signal handlers for graceful shutdown.\n */\nexport function setupSignalHandlers(server: ProxyServer, logger: Logger): void {\n const shutdown = async (signal: string) => {\n logger.log(`[DAEMON] Received ${signal}, shutting down...`)\n try {\n await server.stop()\n } catch {\n // Best-effort server stop\n }\n removePidFile()\n logger.log('[DAEMON] Stopped.')\n process.exit(0)\n }\n\n process.on('SIGTERM', () => shutdown('SIGTERM'))\n process.on('SIGINT', () => shutdown('SIGINT'))\n\n process.on('uncaughtException', (err) => {\n logger.log(`[FATAL] Uncaught exception: ${err.message}`)\n removePidFile()\n process.exit(1)\n })\n\n process.on('unhandledRejection', (reason) => {\n const message = reason instanceof Error ? reason.message : String(reason)\n logger.log(`[FATAL] Unhandled rejection: ${message}`)\n removePidFile()\n process.exit(1)\n })\n}\n\n/**\n * Fork a detached child process to run the daemon in the background.\n * Returns the child PID.\n */\nexport function forkDaemon(binPath: string, extraArgs: string[] = []): number {\n const child = fork(binPath, ['start', '--_forked', ...extraArgs], {\n detached: true,\n stdio: 'ignore',\n })\n\n child.unref()\n return child.pid!\n}\n\n/**\n * Resolve the bin.ts/bin.js entry point path from import.meta.url.\n */\nexport function resolveBinPath(importMetaUrl: string): string {\n return fileURLToPath(importMetaUrl)\n}\n\n/**\n * Sleep for a given number of milliseconds.\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { loadConfig, applyOverrides, isConfigured } from '../config/loader.js'\nimport { createRequestHandler } from '../proxy/handler.js'\nimport type { HandlerDeps } from '../proxy/handler.js'\nimport { ProxyServer } from '../proxy/server.js'\nimport { FileLogger } from '../daemon/logger.js'\nimport { SessionManager } from '../rsc/session-manager.js'\nimport { Semaphore } from '../rsc/semaphore.js'\nimport { LatencyMonitor } from '../rsc/latency-monitor.js'\nimport { createConnectHandler } from '../tls/connect-handler.js'\nimport { hasCA, loadCA } from '../tls/ca.js'\nimport { isCATrusted } from '../tls/trust.js'\nimport { createMitmBridge } from '../tls/mitm-bridge.js'\nimport {\n isDaemonRunning,\n writePidFile,\n setupSignalHandlers,\n forkDaemon,\n resolveBinPath,\n} from '../daemon/lifecycle.js'\nimport type { ResolvedConfig, Tool } from '../types.js'\nimport { printBanner } from '../version.js'\n\nexport async function startCommand(flags: Map<string, string | true>): Promise<void> {\n const isDaemon = flags.has('d') || flags.has('daemon')\n const isForked = flags.has('_forked')\n\n // Check if already running (skip for forked processes — parent already checked)\n if (!isForked) {\n const state = isDaemonRunning()\n if (state.running) {\n console.error(`Liminal daemon is already running (PID ${state.pid}).`)\n console.error('Use \"liminal stop\" first, or \"liminal status\" to check.')\n process.exit(1)\n }\n }\n\n // Check config\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n\n // Load and apply config\n let config = loadConfig()\n const portOverride = flags.get('port')\n const upstreamOverride = flags.get('upstream')\n config = applyOverrides(config, {\n ...(typeof portOverride === 'string' ? { port: parseInt(portOverride, 10) } : {}),\n ...(typeof upstreamOverride === 'string' ? { upstreamBaseUrl: upstreamOverride } : {}),\n })\n\n // Background mode: fork and exit parent\n if (isDaemon && !isForked) {\n const extraArgs: string[] = []\n if (portOverride) extraArgs.push('--port', String(portOverride))\n if (upstreamOverride) extraArgs.push('--upstream', String(upstreamOverride))\n\n const binPath = resolveBinPath(import.meta.url)\n const childPid = forkDaemon(binPath, extraArgs)\n\n console.log(`Liminal daemon started in background (PID ${childPid})`)\n console.log(`Proxy: http://127.0.0.1:${config.port}/v1`)\n console.log('Logs: ~/.liminal/logs/liminal.log')\n process.exit(0)\n }\n\n // Foreground mode: run the server in this process\n const isForeground = !isDaemon || isForked\n const logger = new FileLogger({ mirrorStdout: isForeground && !isForked })\n\n // Build the resolved config for the proxy\n const resolvedConfig: ResolvedConfig = {\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n proxyPort: config.port,\n compressionThreshold: config.compressionThreshold,\n aggregateThreshold: config.aggregateThreshold,\n hotFraction: config.hotFraction,\n coldFraction: config.coldFraction,\n compressRoles: config.compressRoles,\n compressToolResults: config.compressToolResults,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n upstreamBaseUrl: config.upstreamBaseUrl,\n anthropicUpstreamUrl: config.anthropicUpstreamUrl,\n enabled: config.enabled,\n tools: config.tools as Tool[],\n concurrencyLimit: config.concurrencyLimit,\n concurrencyTimeoutMs: config.concurrencyTimeoutMs,\n maxSessions: config.maxSessions,\n sessionTtlMs: config.sessionTtlMs,\n latencyWarningMs: config.latencyWarningMs,\n latencyCriticalMs: config.latencyCriticalMs,\n }\n\n // Create multi-session infrastructure\n const semaphore = new Semaphore(resolvedConfig.concurrencyLimit)\n const latencyMonitor = new LatencyMonitor({\n warningThresholdMs: resolvedConfig.latencyWarningMs,\n criticalThresholdMs: resolvedConfig.latencyCriticalMs,\n })\n\n // Wire up pipeline events for each new session\n function wireSessionEvents(key: string, pipeline: import('../rsc/pipeline.js').RSCPipelineWrapper): void {\n pipeline.events.on('compression', (event) => {\n if (event.tokensSaved > 0) {\n logger.log(`[LIMINAL] [${key}] Compressed: ${event.tokensSaved} tokens saved (${event.ratio.toFixed(3)} ratio)`)\n }\n })\n pipeline.events.on('compression_skipped', (event) => {\n const detail = event.reason === 'latency_budget'\n ? `${event.reason} (${event.estimatedTokens}tok, budget:${event.budgetMs}ms, elapsed:${event.elapsedMs}ms)`\n : event.reason === 'below_threshold'\n ? `${event.reason} (${event.estimatedTokens}tok < ${config.compressionThreshold}tok threshold)`\n : `${event.reason} (${event.estimatedTokens}tok)`\n logger.log(`[LIMINAL] [${key}] Skipped: ${detail}`)\n })\n pipeline.events.on('error', (event) => {\n logger.log(`[LIMINAL] [${key}] Error: ${event.error.message}`)\n })\n pipeline.events.on('degradation', (event) => {\n logger.log(`[LIMINAL] [${key}] Circuit ${event.circuitState}: ${event.reason}`)\n })\n }\n\n const sessions = new SessionManager({\n pipelineConfig: {\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n compressionThreshold: config.compressionThreshold,\n learnFromResponses: config.learnFromResponses,\n latencyBudgetMs: config.latencyBudgetMs || undefined,\n },\n maxSessions: resolvedConfig.maxSessions,\n sessionTtlMs: resolvedConfig.sessionTtlMs,\n onSessionCreated: (key, pipeline) => {\n logger.log(`[SESSION] Created: ${key}`)\n wireSessionEvents(key, pipeline)\n },\n onSessionEvicted: (key) => {\n logger.log(`[SESSION] Evicted: ${key} (idle)`)\n },\n })\n\n latencyMonitor.onAlert((alert) => {\n logger.log(`[LATENCY] ${alert.type.toUpperCase()}: ${alert.message} (${alert.activeSessions} sessions) — ${alert.suggestion}`)\n })\n\n // Create server with optional CONNECT handler for Cursor MITM\n const deps: HandlerDeps = { sessions, semaphore, latencyMonitor, config: resolvedConfig, logger }\n const handler = createRequestHandler(deps)\n\n // MITM intercept handler — set after server starts (needs http.Server ref)\n let mitmHandler: ((socket: import('node:net').Socket, hostname: string, port: number) => void) | undefined\n\n const connectHandler = createConnectHandler({\n logger,\n onIntercept: (socket, hostname, port) => {\n if (mitmHandler) {\n mitmHandler(socket, hostname, port)\n } else {\n logger.log(`[MITM] No bridge available for ${hostname} — falling back to passthrough`)\n }\n },\n })\n\n const server = new ProxyServer(config.port, handler, connectHandler)\n\n // Setup graceful shutdown\n setupSignalHandlers(server, logger)\n\n // Start listening\n try {\n const actualPort = await server.start()\n writePidFile(process.pid)\n\n logger.log(`[DAEMON] Liminal proxy started on http://127.0.0.1:${actualPort}`)\n logger.log(`[DAEMON] Upstream (OpenAI): ${config.upstreamBaseUrl}`)\n logger.log(`[DAEMON] Upstream (Anthropic): ${config.anthropicUpstreamUrl}`)\n logger.log(`[DAEMON] Liminal API: ${config.apiBaseUrl}`)\n logger.log(`[DAEMON] PID: ${process.pid}`)\n logger.log(`[DAEMON] Max sessions: ${resolvedConfig.maxSessions}, Concurrency limit: ${resolvedConfig.concurrencyLimit}`)\n\n // Wire MITM bridge if CA is available and trusted\n const caReady = hasCA() && isCATrusted()\n if (caReady) {\n const httpServer = server.getHttpServer()\n const ca = loadCA()\n if (httpServer && ca) {\n mitmHandler = createMitmBridge({\n httpServer,\n caCertPem: ca.certPem,\n caKeyPem: ca.keyPem,\n logger,\n })\n logger.log('[MITM] TLS bridge active — intercepting LLM API calls')\n }\n }\n\n // Log MITM proxy status\n logger.log(`[DAEMON] CONNECT handler: active | MITM: ${caReady ? 'ready (CA trusted)' : 'passthrough only (run liminal trust-ca)'}`)\n\n if (isForeground && !isForked) {\n printBanner()\n console.log(` Liminal proxy running on http://127.0.0.1:${actualPort}/v1`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log(` Max sessions: ${resolvedConfig.maxSessions} | Concurrency: ${resolvedConfig.concurrencyLimit}`)\n if (caReady) {\n console.log(' MITM: active (Cursor interception ready)')\n }\n console.log()\n console.log(' Point your AI tool\\'s base URL here. Press Ctrl+C to stop.')\n console.log()\n }\n\n // Check RSC API health on startup using a temporary probe pipeline\n const { RSCPipelineWrapper } = await import('../rsc/pipeline.js')\n const probe = new RSCPipelineWrapper({\n rscApiKey: config.apiKey,\n rscBaseUrl: config.apiBaseUrl,\n compressionThreshold: config.compressionThreshold,\n learnFromResponses: false,\n })\n const healthy = await probe.healthCheck()\n if (healthy) {\n logger.log('[DAEMON] Liminal API health check: OK')\n } else {\n logger.log('[DAEMON] Liminal API health check: FAILED (will retry on first request)')\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Failed to start proxy: ${message}`)\n process.exit(1)\n }\n}\n","import {\n isDaemonRunning,\n readPidFile,\n removePidFile,\n isProcessAlive,\n sleep,\n} from '../daemon/lifecycle.js'\n\nexport async function stopCommand(): Promise<void> {\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running.')\n return\n }\n\n const pid = state.pid\n console.log(`Stopping Liminal daemon (PID ${pid})...`)\n\n // Send SIGTERM for graceful shutdown\n try {\n process.kill(pid, 'SIGTERM')\n } catch {\n // Process may have already exited\n removePidFile()\n console.log('Liminal daemon stopped.')\n return\n }\n\n // Poll for up to 5 seconds\n for (let i = 0; i < 25; i++) {\n await sleep(200)\n if (!isProcessAlive(pid)) {\n removePidFile()\n console.log(`Liminal daemon stopped (PID ${pid}).`)\n return\n }\n }\n\n // Force kill after timeout\n try {\n process.kill(pid, 'SIGKILL')\n } catch {\n // Already dead\n }\n\n removePidFile()\n console.log(`Liminal daemon force-killed (PID ${pid}).`)\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\ninterface SessionInfo {\n session_key: string\n connector: string\n circuit_state: string\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_failed: number\n p95_latency_ms: number | null\n last_active_ago_ms: number\n}\n\ninterface HealthResponse {\n status: string\n version: string\n uptime_ms: number\n concurrency: {\n active_sessions: number\n semaphore_available: number\n semaphore_waiting: number\n max_concurrent_rsc_calls: number\n }\n latency: {\n global_p95_ms: number | null\n }\n sessions: SessionInfo[]\n}\n\nexport async function statusCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal: not configured')\n console.log('Run \"liminal init\" to set up.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal Daemon: stopped')\n console.log('Run \"liminal start\" to start the proxy.')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n // Try to reach the daemon's /health endpoint\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as HealthResponse\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log(`Status: ${data.status} (${data.version})`)\n console.log(`Uptime: ${uptime}`)\n console.log()\n\n // Concurrency\n const c = data.concurrency\n console.log(`Sessions: ${c.active_sessions} active (max ${config.maxSessions})`)\n console.log(`Semaphore: ${c.semaphore_available}/${c.max_concurrent_rsc_calls} available` +\n (c.semaphore_waiting > 0 ? ` (${c.semaphore_waiting} waiting)` : ''))\n\n // Global latency\n const globalP95 = data.latency.global_p95_ms\n if (globalP95 !== null) {\n const latencyFlag = globalP95 >= config.latencyCriticalMs ? ' CRITICAL'\n : globalP95 >= config.latencyWarningMs ? ' WARNING'\n : ''\n console.log(`Latency: p95 ${globalP95.toFixed(0)}ms${latencyFlag}`)\n }\n\n // Per-session details\n if (data.sessions.length > 0) {\n console.log()\n console.log('─── Sessions ───')\n for (const s of data.sessions) {\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n const activeAgo = formatUptime(s.last_active_ago_ms)\n const p95 = s.p95_latency_ms !== null ? `${s.p95_latency_ms.toFixed(0)}ms` : '-'\n\n console.log()\n console.log(` ${s.connector} [${s.session_key}]`)\n console.log(` Circuit: ${s.circuit_state}`)\n console.log(` Tokens: ${s.tokens_processed.toLocaleString()} processed, ${s.tokens_saved.toLocaleString()} saved (${savingsPercent}%)`)\n console.log(` Calls: ${s.calls_total} total (${s.calls_compressed} compressed, ${s.calls_failed} failed)`)\n console.log(` Latency: p95 ${p95}`)\n console.log(` Active: ${activeAgo} ago`)\n }\n } else {\n console.log()\n console.log('No active sessions.')\n }\n } catch {\n // Can't reach the daemon, but PID is alive — might still be starting\n console.log(`Liminal Daemon: running (PID ${state.pid}, port ${port})`)\n console.log('Status: unknown (could not reach /health)')\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { isDaemonRunning } from '../daemon/lifecycle.js'\nimport { loadConfig, isConfigured } from '../config/loader.js'\n\nexport async function summaryCommand(): Promise<void> {\n if (!isConfigured()) {\n console.log('Liminal is not configured. Run \"liminal init\" first.')\n return\n }\n\n const state = isDaemonRunning()\n\n if (!state.running || !state.pid) {\n console.log('Liminal daemon is not running. Start it with \"liminal start\".')\n return\n }\n\n const config = loadConfig()\n const port = config.port\n\n try {\n const res = await fetch(`http://127.0.0.1:${port}/health`, {\n signal: AbortSignal.timeout(3000),\n })\n const data = await res.json() as {\n circuit_state: string\n session_id: string\n uptime_ms: number\n session?: {\n tokens_processed: number\n tokens_saved: number\n calls_total: number\n calls_compressed: number\n calls_skipped: number\n calls_failed: number\n patterns_learned: number\n estimated_cost_saved_usd: number\n }\n }\n\n const uptime = formatUptime(data.uptime_ms)\n\n console.log()\n console.log(` Session: ${data.session_id}`)\n console.log(` Uptime: ${uptime}`)\n console.log()\n\n if (data.session) {\n const s = data.session\n const savingsPercent = s.tokens_processed > 0\n ? ((s.tokens_saved / s.tokens_processed) * 100).toFixed(1)\n : '0.0'\n const compressionRate = s.calls_total > 0\n ? ((s.calls_compressed / s.calls_total) * 100).toFixed(0)\n : '0'\n\n console.log(' Compression:')\n console.log(` Tokens processed: ${s.tokens_processed.toLocaleString()}`)\n console.log(` Tokens saved: ${s.tokens_saved.toLocaleString()} (${savingsPercent}%)`)\n console.log(` Compression rate: ${compressionRate}% of calls compressed`)\n console.log(` Patterns learned: ${s.patterns_learned.toLocaleString()}`)\n console.log()\n console.log(' Calls:')\n console.log(` Total: ${s.calls_total}`)\n console.log(` Compressed: ${s.calls_compressed}`)\n console.log(` Skipped: ${s.calls_skipped}`)\n console.log(` Failed: ${s.calls_failed}`)\n console.log()\n console.log(' Cost Savings:')\n console.log(` Estimated: $${s.estimated_cost_saved_usd.toFixed(4)} USD`)\n console.log()\n } else {\n console.log(' No session data available yet.')\n console.log()\n }\n\n console.log(` Circuit: ${data.circuit_state}`)\n console.log(` API: ${config.apiBaseUrl}`)\n console.log(` Upstream: ${config.upstreamBaseUrl}`)\n console.log()\n } catch {\n console.error('Could not reach the Liminal daemon. Is it running?')\n console.error(`Tried http://127.0.0.1:${port}/health`)\n process.exit(1)\n }\n}\n\nfunction formatUptime(ms: number): string {\n const seconds = Math.floor(ms / 1000)\n const minutes = Math.floor(seconds / 60)\n const hours = Math.floor(minutes / 60)\n const days = Math.floor(hours / 24)\n\n if (days > 0) return `${days}d ${hours % 24}h ${minutes % 60}m`\n if (hours > 0) return `${hours}h ${minutes % 60}m`\n if (minutes > 0) return `${minutes}m ${seconds % 60}s`\n return `${seconds}s`\n}\n","import { loadConfig, saveConfig, isConfigured, maskApiKey } from '../config/loader.js'\nimport { CONFIGURABLE_KEYS } from '../config/schema.js'\nimport { CONFIG_FILE } from '../config/paths.js'\n\nexport async function configCommand(flags: Map<string, string | true>): Promise<void> {\n const getKey = flags.get('get')\n const setKv = flags.get('set')\n\n // rsc config --get <key>\n if (typeof getKey === 'string') {\n if (!isConfigured()) {\n console.error('Liminal is not configured. Run \"liminal init\" first.')\n process.exit(1)\n }\n const config = loadConfig()\n const value = (config as unknown as Record<string, unknown>)[getKey]\n if (value === undefined) {\n console.error(`Unknown config key: ${getKey}`)\n process.exit(1)\n }\n console.log(getKey === 'apiKey' ? maskApiKey(String(value)) : String(value))\n return\n }\n\n // rsc config --set <key>=<value>\n if (typeof setKv === 'string') {\n const eqIdx = setKv.indexOf('=')\n if (eqIdx === -1) {\n console.error('Usage: liminal config --set key=value')\n process.exit(1)\n }\n const key = setKv.slice(0, eqIdx)\n const rawValue = setKv.slice(eqIdx + 1)\n\n if (!CONFIGURABLE_KEYS.has(key) && key !== 'apiKey') {\n console.error(`Unknown or non-configurable key: ${key}`)\n console.error(`Configurable keys: ${[...CONFIGURABLE_KEYS].join(', ')}`)\n process.exit(1)\n }\n\n // Parse value based on key type\n let parsedValue: unknown = rawValue\n if (key === 'port' || key === 'compressionThreshold' || key === 'latencyBudgetMs') {\n parsedValue = parseInt(rawValue, 10)\n if (isNaN(parsedValue as number)) {\n console.error(`Invalid number for ${key}: ${rawValue}`)\n process.exit(1)\n }\n } else if (key === 'learnFromResponses' || key === 'enabled') {\n parsedValue = rawValue === 'true' || rawValue === '1'\n } else if (key === 'compressRoles') {\n parsedValue = rawValue.split(',').map((s) => s.trim())\n }\n\n saveConfig({ [key]: parsedValue })\n console.log(`Set ${key} = ${key === 'apiKey' ? maskApiKey(rawValue) : rawValue}`)\n return\n }\n\n // rsc config (no flags) — show all\n if (!isConfigured()) {\n console.log(`Liminal is not configured. Run \"liminal init\" first.`)\n console.log(`Config file: ${CONFIG_FILE}`)\n return\n }\n\n const config = loadConfig()\n console.log()\n console.log(` Config: ${CONFIG_FILE}`)\n console.log()\n console.log(` apiKey: ${maskApiKey(config.apiKey)}`)\n console.log(` apiBaseUrl: ${config.apiBaseUrl}`)\n console.log(` upstreamBaseUrl: ${config.upstreamBaseUrl}`)\n console.log(` anthropicUpstreamUrl: ${config.anthropicUpstreamUrl}`)\n console.log(` tools: ${config.tools.length > 0 ? config.tools.join(', ') : '(none)'}`)\n console.log(` port: ${config.port}`)\n console.log(` compressionThreshold: ${config.compressionThreshold}`)\n console.log(` compressRoles: ${config.compressRoles.join(', ')}`)\n console.log(` learnFromResponses: ${config.learnFromResponses}`)\n console.log(` latencyBudgetMs: ${config.latencyBudgetMs || 'auto'}`)\n console.log(` enabled: ${config.enabled}`)\n console.log()\n}\n","import { readFileSync, existsSync, statSync, createReadStream } from 'node:fs'\nimport { watchFile, unwatchFile } from 'node:fs'\nimport { LOG_FILE } from '../config/paths.js'\n\nexport async function logsCommand(flags: Map<string, string | true>): Promise<void> {\n const follow = flags.has('follow') || flags.has('f')\n const linesFlag = flags.get('lines') ?? flags.get('n')\n const lines = typeof linesFlag === 'string' ? parseInt(linesFlag, 10) : 50\n\n if (!existsSync(LOG_FILE)) {\n console.log('No log file found. Start the daemon with \"liminal start\" to generate logs.')\n return\n }\n\n // Read and display last N lines\n const content = readFileSync(LOG_FILE, 'utf-8')\n const allLines = content.split('\\n')\n const tail = allLines.slice(-lines - 1) // -1 to account for trailing newline\n process.stdout.write(tail.join('\\n'))\n\n if (!follow) return\n\n // Follow mode: watch for changes and stream new content\n let lastSize = statSync(LOG_FILE).size\n\n watchFile(LOG_FILE, { interval: 500 }, (curr) => {\n if (curr.size > lastSize) {\n const stream = createReadStream(LOG_FILE, { start: lastSize, encoding: 'utf-8' })\n stream.on('data', (chunk) => process.stdout.write(chunk as string))\n stream.on('end', () => { lastSize = curr.size })\n } else if (curr.size < lastSize) {\n // File was rotated — read from beginning\n lastSize = 0\n }\n })\n\n // Keep the process alive and handle Ctrl+C\n process.on('SIGINT', () => {\n unwatchFile(LOG_FILE)\n process.exit(0)\n })\n\n // Block forever\n await new Promise(() => {})\n}\n","import { existsSync, rmSync, readFileSync } from 'node:fs'\nimport {\n detectShellProfile,\n removeLiminalFromShellProfile,\n findLiminalExportsInProfile,\n} from '../config/shell.js'\nimport { LIMINAL_DIR, CONFIG_FILE } from '../config/paths.js'\nimport { isDaemonRunning, removePidFile, isProcessAlive, sleep } from '../daemon/lifecycle.js'\nimport { CONNECTORS, getConnectors } from '../connectors/index.js'\nimport { selectPrompt } from '../ui/prompts.js'\nimport type { ConnectorId } from '../connectors/types.js'\n\n// ─── ANSI helpers ────────────────────────────────────────────────────\nconst BOLD = '\\x1b[1m'\nconst DIM = '\\x1b[2m'\nconst CYAN = '\\x1b[36m'\nconst GREEN = '\\x1b[32m'\nconst YELLOW = '\\x1b[33m'\nconst RED = '\\x1b[31m'\nconst RESET = '\\x1b[0m'\n\n/**\n * Load the list of configured tools from ~/.liminal/config.json.\n */\nfunction loadConfiguredTools(): ConnectorId[] {\n if (!existsSync(CONFIG_FILE)) return []\n try {\n const raw = readFileSync(CONFIG_FILE, 'utf-8')\n const config = JSON.parse(raw)\n if (Array.isArray(config.tools)) return config.tools as ConnectorId[]\n } catch {\n // Corrupted config — treat as empty\n }\n return []\n}\n\nexport async function uninstallCommand(): Promise<void> {\n console.log()\n console.log(` ${BOLD}Liminal Uninstall${RESET}`)\n console.log()\n\n // ── 1. Confirm ────────────────────────────────────────────────\n const confirm = await selectPrompt<boolean>({\n message: 'Remove Liminal configuration and restore tool settings?',\n options: [\n { label: 'Yes', value: true, description: 'Undo all Liminal setup' },\n { label: 'No', value: false, description: 'Cancel' },\n ],\n defaultIndex: 1, // Default to No for safety\n })\n\n if (confirm !== true) {\n console.log()\n console.log(' Cancelled.')\n console.log()\n return\n }\n\n console.log()\n\n // ── 2. Stop daemon if running ─────────────────────────────────\n const state = isDaemonRunning()\n if (state.running && state.pid) {\n console.log(` Stopping Liminal daemon (PID ${state.pid})...`)\n try {\n process.kill(state.pid, 'SIGTERM')\n // Wait up to 3 seconds for graceful shutdown\n for (let i = 0; i < 15; i++) {\n await sleep(200)\n if (!isProcessAlive(state.pid)) break\n }\n if (isProcessAlive(state.pid)) {\n process.kill(state.pid, 'SIGKILL')\n }\n } catch {\n // Already dead\n }\n removePidFile()\n console.log(` ${GREEN}✓${RESET} Daemon stopped`)\n } else {\n console.log(` ${DIM}·${RESET} Daemon not running`)\n }\n\n // ── 3. Remove shell profile exports ───────────────────────────\n const profile = detectShellProfile()\n if (profile) {\n const existing = findLiminalExportsInProfile(profile)\n if (existing.length > 0) {\n const removed = removeLiminalFromShellProfile(profile)\n if (removed.length > 0) {\n console.log(` ${GREEN}✓${RESET} Removed ${removed.length} line${removed.length > 1 ? 's' : ''} from ${profile.name}:`)\n for (const line of removed) {\n const trimmed = line.trim()\n if (trimmed && trimmed !== '# Liminal — route AI tools through compression proxy') {\n console.log(` ${DIM}${trimmed}${RESET}`)\n }\n }\n }\n } else {\n console.log(` ${DIM}·${RESET} No Liminal exports found in ${profile.name}`)\n }\n }\n\n // ── 4. Run connector-specific teardown ────────────────────────\n const configuredTools = loadConfiguredTools()\n const allTools = configuredTools.length > 0 ? configuredTools : CONNECTORS.map((c) => c.info.id)\n const connectors = getConnectors(allTools)\n\n const manualSteps: Array<{ label: string; steps: string[] }> = []\n\n for (const connector of connectors) {\n const result = await connector.teardown()\n if (result.manualSteps.length > 0 && !connector.info.automatable) {\n manualSteps.push({\n label: connector.info.label,\n steps: result.manualSteps,\n })\n }\n }\n\n if (manualSteps.length > 0) {\n console.log()\n console.log(` ${YELLOW}Manual steps needed:${RESET}`)\n for (const { label, steps } of manualSteps) {\n console.log()\n console.log(` ${BOLD}${label}:${RESET}`)\n for (const step of steps) {\n console.log(` ${step}`)\n }\n }\n }\n\n // ── 5. Optionally remove ~/.liminal/ ──────────────────────────\n if (existsSync(LIMINAL_DIR)) {\n console.log()\n const removeData = await selectPrompt<boolean>({\n message: 'Remove ~/.liminal/ directory? (config, logs, PID file)',\n options: [\n { label: 'Yes', value: true, description: 'Delete all Liminal data' },\n { label: 'No', value: false, description: 'Keep config and logs' },\n ],\n defaultIndex: 1, // Default to keep\n })\n\n if (removeData === true) {\n rmSync(LIMINAL_DIR, { recursive: true, force: true })\n console.log(` ${GREEN}✓${RESET} Removed ~/.liminal/`)\n } else {\n console.log(` ${DIM}·${RESET} Kept ~/.liminal/`)\n }\n }\n\n // ── 6. Summary ────────────────────────────────────────────────\n console.log()\n console.log(` ${GREEN}Liminal has been uninstalled.${RESET}`)\n console.log()\n console.log(` ${DIM}Your AI tools will connect directly to their APIs.${RESET}`)\n console.log(` ${DIM}Restart your terminal for shell changes to take effect.${RESET}`)\n\n if (manualSteps.length > 0) {\n console.log(` ${YELLOW}Don't forget the manual steps above for ${manualSteps.map((s) => s.label).join(', ')}.${RESET}`)\n }\n\n console.log()\n console.log(` ${DIM}To reinstall: npx @cognisos/liminal init${RESET}`)\n console.log()\n}\n","import { hasCA, ensureCA, getCAInfo, CA_CERT_PATH } from '../tls/ca.js'\nimport { installCA, isCATrusted } from '../tls/trust.js'\nimport { printBanner } from '../version.js'\n\nexport async function trustCACommand(): Promise<void> {\n printBanner()\n\n // Check if already trusted\n if (isCATrusted()) {\n console.log(' Liminal CA is already trusted.')\n const info = getCAInfo()\n if (info) {\n console.log(` Fingerprint: ${info.fingerprint}`)\n console.log(` Valid until: ${info.validTo.toLocaleDateString()}`)\n }\n return\n }\n\n // Ensure CA exists\n if (!hasCA()) {\n console.log(' Generating CA certificate...')\n ensureCA()\n console.log(' Created ~/.liminal/ca.pem')\n console.log()\n }\n\n // Explain what this does\n console.log(' Installing Liminal CA certificate')\n console.log()\n console.log(' This allows Liminal to transparently compress LLM API')\n console.log(' traffic from Cursor and other Electron-based editors.')\n console.log()\n console.log(' The certificate is scoped to your user account and only')\n console.log(' used by the local Liminal proxy on 127.0.0.1.')\n console.log()\n console.log(` Certificate: ${CA_CERT_PATH}`)\n console.log()\n\n // Install\n const result = installCA()\n\n if (result.success) {\n console.log(` ${result.message}`)\n console.log()\n const info = getCAInfo()\n if (info) {\n console.log(` Fingerprint: ${info.fingerprint}`)\n console.log(` Valid until: ${info.validTo.toLocaleDateString()}`)\n }\n console.log()\n console.log(' You can now use Liminal with Cursor:')\n console.log(' liminal start')\n console.log(' cursor --proxy-server=http://127.0.0.1:3141 --disable-http2')\n } else {\n console.error(` Failed: ${result.message}`)\n if (result.requiresSudo) {\n console.log()\n console.log(' Try running with elevated permissions:')\n console.log(' sudo liminal trust-ca')\n }\n process.exit(1)\n }\n}\n","import { removeCA as removeCAFiles, hasCA } from '../tls/ca.js'\nimport { removeCA as untrustCA, isCATrusted } from '../tls/trust.js'\nimport { printBanner } from '../version.js'\n\nexport async function untrustCACommand(): Promise<void> {\n printBanner()\n\n if (!hasCA() && !isCATrusted()) {\n console.log(' No Liminal CA found (nothing to remove).')\n return\n }\n\n // Remove from trust store first\n if (isCATrusted()) {\n console.log(' Removing CA from system trust store...')\n const result = untrustCA()\n\n if (result.success) {\n console.log(` ${result.message}`)\n } else {\n console.error(` ${result.message}`)\n if (result.requiresSudo) {\n console.log()\n console.log(' Try running with elevated permissions:')\n console.log(' sudo liminal untrust-ca')\n }\n process.exit(1)\n }\n }\n\n // Remove cert files\n if (hasCA()) {\n console.log(' Removing CA certificate files...')\n removeCAFiles()\n console.log(' Removed ~/.liminal/ca.pem and ca-key.pem')\n }\n\n console.log()\n console.log(' Liminal CA fully removed.')\n console.log(' Cursor MITM interception is no longer available.')\n}\n","import { VERSION } from './version.js'\nimport { initCommand } from './commands/init.js'\nimport { loginCommand } from './commands/login.js'\nimport { logoutCommand } from './commands/logout.js'\nimport { startCommand } from './commands/start.js'\nimport { stopCommand } from './commands/stop.js'\nimport { statusCommand } from './commands/status.js'\nimport { summaryCommand } from './commands/summary.js'\nimport { configCommand } from './commands/config.js'\nimport { logsCommand } from './commands/logs.js'\nimport { uninstallCommand } from './commands/uninstall.js'\nimport { trustCACommand } from './commands/trust-ca.js'\nimport { untrustCACommand } from './commands/untrust-ca.js'\n\nconst USAGE = `\n liminal v${VERSION} — Transparent LLM context compression proxy\n\n Usage:\n liminal init Set up Liminal (login, config)\n liminal login Log in or create an account\n liminal logout Log out of your account\n liminal start [-d] [--port PORT] Start the compression proxy\n liminal stop Stop the running proxy\n liminal status Show proxy health and stats\n liminal summary Detailed session metrics\n liminal config [--set k=v] [--get k] View or edit configuration\n liminal logs [--follow] [--lines N] View proxy logs\n liminal trust-ca Install CA cert (for Cursor MITM)\n liminal untrust-ca Remove CA cert\n liminal uninstall Remove Liminal configuration\n\n Options:\n -h, --help Show this help message\n -v, --version Show version number\n\n Getting started:\n 1. liminal init # Log in + select tools\n 2. liminal start # Start the proxy\n 3. Connect your AI tools:\n Claude Code: export ANTHROPIC_BASE_URL=http://localhost:3141\n Codex: export OPENAI_BASE_URL=http://localhost:3141/v1\n Cursor: liminal trust-ca && cursor --proxy-server=http://localhost:3141\n`\n\nfunction parseArgs(argv: string[]): { command: string; flags: Map<string, string | true> } {\n const command = argv[2] ?? ''\n const flags = new Map<string, string | true>()\n\n for (let i = 3; i < argv.length; i++) {\n const arg = argv[i]\n if (arg.startsWith('--')) {\n const key = arg.slice(2)\n // Check if next arg is a value (not another flag)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n } else if (arg.startsWith('-') && arg.length === 2) {\n const key = arg.slice(1)\n if (i + 1 < argv.length && !argv[i + 1].startsWith('-')) {\n flags.set(key, argv[i + 1])\n i++\n } else {\n flags.set(key, true)\n }\n }\n }\n\n return { command, flags }\n}\n\nasync function main(): Promise<void> {\n const { command, flags } = parseArgs(process.argv)\n\n // Global flags — handle --help and --version as both commands and flags\n if (flags.has('h') || flags.has('help') || command === 'help' || command === '--help' || command === '-h') {\n console.log(USAGE)\n process.exit(0)\n }\n\n if (flags.has('v') || flags.has('version') || command === 'version' || command === '--version' || command === '-v') {\n console.log(VERSION)\n process.exit(0)\n }\n\n try {\n switch (command) {\n case 'init':\n await initCommand()\n break\n\n case 'login':\n await loginCommand()\n break\n\n case 'logout':\n await logoutCommand()\n break\n\n case 'start':\n await startCommand(flags)\n break\n\n case 'stop':\n await stopCommand()\n break\n\n case 'status':\n await statusCommand()\n break\n\n case 'summary':\n await summaryCommand()\n break\n\n case 'config':\n await configCommand(flags)\n break\n\n case 'logs':\n await logsCommand(flags)\n break\n\n case 'trust-ca':\n await trustCACommand()\n break\n\n case 'untrust-ca':\n await untrustCACommand()\n break\n\n case 'uninstall':\n await uninstallCommand()\n break\n\n case '':\n console.log(USAGE)\n process.exit(0)\n break\n\n default:\n console.error(`Unknown command: ${command}`)\n console.log(USAGE)\n process.exit(1)\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n console.error(`Error: ${message}`)\n process.exit(1)\n }\n}\n\nmain()\n"],"mappings":"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","names":["existsSync","readFileSync","writeFileSync","join","homedir","stdin","stdout","execSync","existsSync","readFileSync","join","homedir","ENV_VAR","INFO","getCurrentBaseUrl","existsSync","join","homedir","INFO","ENV_VAR","INFO","getCurrentBaseUrl","RSCCircuitOpenError","tiered","lines","RSCCircuitOpenError","RSCCircuitOpenError","lines","setCORSHeaders","RSCCircuitOpenError","RSCCircuitOpenError","lines","setCORSHeaders","sendJSON","extractBearerToken","RSCCircuitOpenError","setCORSHeaders","sendJSON","appendFileSync","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","appendFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","join","join","existsSync","mkdirSync","writeFileSync","readFileSync","execSync","existsSync","unlinkSync","existsSync","removeCA","execSync","unlinkSync","forge","readFileSync","writeFileSync","unlinkSync","existsSync","writeFileSync","existsSync","readFileSync","unlinkSync","RSCPipelineWrapper","formatUptime","config","readFileSync","existsSync","statSync","existsSync","readFileSync","statSync","existsSync","readFileSync","BOLD","DIM","GREEN","YELLOW","RESET","existsSync","readFileSync","BOLD","GREEN","DIM","YELLOW","removeCA"]}