cc-wiretap 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -883,7 +883,7 @@ function createUIServer(options) {
|
|
|
883
883
|
}
|
|
884
884
|
|
|
885
885
|
// src/index.ts
|
|
886
|
-
var VERSION = "1.0.
|
|
886
|
+
var VERSION = "1.0.5";
|
|
887
887
|
var BANNER = `
|
|
888
888
|
${chalk7.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557")}
|
|
889
889
|
${chalk7.cyan("\u2551")} ${chalk7.cyan("\u2551")}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/ca.ts","../src/proxy.ts","../src/interceptor.ts","../src/parser.ts","../src/websocket.ts","../src/setup-server.ts","../src/ui-server.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { loadOrGenerateCA, getCAPath } from \"./ca.js\";\nimport { createProxy } from \"./proxy.js\";\nimport { WiretapWebSocketServer } from \"./websocket.js\";\nimport { createSetupServer, getSetupCommand } from \"./setup-server.js\";\nimport { createUIServer } from \"./ui-server.js\";\n\nconst VERSION = \"1.0.4\";\n\nconst BANNER = `\n${chalk.cyan(\"╔════════════════════════════════════════════════════════════╗\")}\n${chalk.cyan(\"║\")} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"║\")} ${chalk.bold.white(\"CC Wiretap\")} ${chalk.gray(\"v\" + VERSION)} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"║\")} ${chalk.gray(\"HTTP/HTTPS proxy for Claude Code traffic inspection\")} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"║\")} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"╚════════════════════════════════════════════════════════════╝\")}\n`;\n\ninterface CLIOptions {\n port: string;\n wsPort: string;\n uiPort: string;\n quiet: boolean;\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"cc-wiretap\")\n .description(\n \"HTTP/HTTPS proxy for intercepting and visualizing Claude Code traffic\",\n )\n .version(VERSION)\n .option(\"-p, --port <port>\", \"Proxy server port\", \"8080\")\n .option(\"-w, --ws-port <port>\", \"WebSocket server port for UI\", \"8081\")\n .option(\"-u, --ui-port <port>\", \"UI dashboard server port\", \"3000\")\n .option(\"-q, --quiet\", \"Suppress banner and verbose output\", false)\n .action(async (options: CLIOptions) => {\n if (!options.quiet) {\n console.log(BANNER);\n }\n\n const proxyPort = parseInt(options.port, 10);\n const wsPort = parseInt(options.wsPort, 10);\n const uiPort = parseInt(options.uiPort, 10);\n\n try {\n // Load or generate CA certificate\n const ca = await loadOrGenerateCA();\n\n // Start WebSocket server\n const wsServer = new WiretapWebSocketServer({ port: wsPort });\n console.log(\n chalk.green(\"✓\"),\n `WebSocket server started on port ${chalk.cyan(wsPort)}`,\n );\n\n // Start proxy server\n const proxy = await createProxy({\n port: proxyPort,\n ca,\n wsServer,\n });\n\n // Start setup server (for terminal eval command)\n const setupServer = createSetupServer(proxyPort);\n\n // Start UI server (serves bundled dashboard)\n const uiServer = createUIServer({ port: uiPort });\n\n console.log();\n console.log(chalk.white(\"Ready to intercept Claude API traffic.\"));\n console.log();\n\n // Highlight the easy setup command\n console.log(\n chalk.yellow.bold(\"Quick setup - run this in any terminal:\"),\n );\n console.log();\n console.log(chalk.yellow(\"=>\"), chalk.cyan.bold(getSetupCommand()));\n console.log();\n console.log(chalk.gray(\"Or manually:\"));\n console.log();\n console.log(chalk.gray(` NODE_EXTRA_CA_CERTS=\"${getCAPath()}\" \\\\`));\n console.log(\n chalk.gray(` HTTPS_PROXY=http://localhost:${proxyPort} \\\\`),\n );\n console.log(chalk.gray(\" claude\"));\n console.log();\n console.log(\n chalk.yellow(\"=>\"),\n chalk.yellow.bold(\"UI:\"),\n chalk.cyan(`http://localhost:${uiPort}`),\n );\n console.log();\n console.log(chalk.gray(\"─\".repeat(60)));\n console.log();\n\n // Handle shutdown\n const shutdown = async () => {\n console.log();\n console.log(chalk.yellow(\"Shutting down...\"));\n await proxy.stop();\n await wsServer.close();\n setupServer.close();\n uiServer?.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n } catch (error) {\n console.error(chalk.red(\"✗\"), \"Failed to start:\", error);\n process.exit(1);\n }\n });\n\n program.parse();\n}\n\nmain().catch((error) => {\n console.error(chalk.red(\"Fatal error:\"), error);\n process.exit(1);\n});\n\nexport { loadOrGenerateCA, getCAPath } from \"./ca.js\";\nexport { createProxy } from \"./proxy.js\";\nexport { WiretapWebSocketServer } from \"./websocket.js\";\nexport { ClaudeInterceptor, CLAUDE_API_HOSTS } from \"./interceptor.js\";\nexport {\n SSEStreamParser,\n parseSSEChunk,\n reconstructResponseFromEvents,\n} from \"./parser.js\";\nexport { createSetupServer, getSetupCommand } from \"./setup-server.js\";\nexport { createUIServer } from \"./ui-server.js\";\nexport * from \"./types.js\";\n","import { homedir } from 'os';\nimport { join } from 'path';\nimport { mkdir, readFile, writeFile, access, constants } from 'fs/promises';\nimport { generateCACertificate } from 'mockttp';\nimport chalk from 'chalk';\n\nconst CA_DIR = join(homedir(), '.cc-wiretap');\nconst CA_CERT_PATH = join(CA_DIR, 'ca.pem');\nconst CA_KEY_PATH = join(CA_DIR, 'ca-key.pem');\n\nexport interface CAConfig {\n certPath: string;\n keyPath: string;\n cert: string;\n key: string;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureCADirectory(): Promise<void> {\n try {\n await mkdir(CA_DIR, { recursive: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw error;\n }\n }\n}\n\nexport async function loadOrGenerateCA(): Promise<CAConfig> {\n await ensureCADirectory();\n\n const certExists = await fileExists(CA_CERT_PATH);\n const keyExists = await fileExists(CA_KEY_PATH);\n\n if (certExists && keyExists) {\n console.log(chalk.green('✓'), 'Using existing CA certificate from', chalk.cyan(CA_DIR));\n const cert = await readFile(CA_CERT_PATH, 'utf-8');\n const key = await readFile(CA_KEY_PATH, 'utf-8');\n return {\n certPath: CA_CERT_PATH,\n keyPath: CA_KEY_PATH,\n cert,\n key,\n };\n }\n\n console.log(chalk.yellow('⚙'), 'Generating new CA certificate...');\n\n const { cert, key } = await generateCACertificate({\n commonName: 'CC Wiretap CA',\n organizationName: 'CC Wiretap',\n });\n\n await writeFile(CA_CERT_PATH, cert);\n await writeFile(CA_KEY_PATH, key);\n\n console.log(chalk.green('✓'), 'CA certificate generated at', chalk.cyan(CA_DIR));\n console.log();\n console.log(chalk.yellow('To trust the CA certificate, run:'));\n console.log();\n console.log(chalk.gray(' # macOS:'));\n console.log(chalk.white(` sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain \"${CA_CERT_PATH}\"`));\n console.log();\n console.log(chalk.gray(' # Linux (Debian/Ubuntu):'));\n console.log(chalk.white(` sudo cp \"${CA_CERT_PATH}\" /usr/local/share/ca-certificates/cc-wiretap.crt`));\n console.log(chalk.white(' sudo update-ca-certificates'));\n console.log();\n console.log(chalk.gray(' # For Node.js/Claude Code, use:'));\n console.log(chalk.white(` NODE_EXTRA_CA_CERTS=\"${CA_CERT_PATH}\"`));\n console.log();\n\n return {\n certPath: CA_CERT_PATH,\n keyPath: CA_KEY_PATH,\n cert,\n key,\n };\n}\n\nexport function getCAPath(): string {\n return CA_CERT_PATH;\n}\n\nexport function getCADir(): string {\n return CA_DIR;\n}\n","import * as mockttp from 'mockttp';\nimport chalk from 'chalk';\nimport { gunzipSync, brotliDecompressSync } from 'zlib';\nimport type { CAConfig } from './ca.js';\nimport { ClaudeInterceptor, CLAUDE_API_HOSTS } from './interceptor.js';\nimport type { WiretapWebSocketServer } from './websocket.js';\n\nfunction decompressBody(buffer: Buffer, contentEncoding: string | undefined): string {\n if (!buffer.length) return '';\n\n try {\n if (contentEncoding === 'gzip') {\n return gunzipSync(buffer).toString('utf-8');\n }\n if (contentEncoding === 'br') {\n return brotliDecompressSync(buffer).toString('utf-8');\n }\n } catch {\n // If decompression fails, try as plain text\n }\n\n return buffer.toString('utf-8');\n}\n\nfunction isAnthropicHost(url: string): boolean {\n try {\n const host = new URL(url).host;\n return CLAUDE_API_HOSTS.some((h) => host.includes(h));\n } catch {\n return false;\n }\n}\n\nexport interface ProxyOptions {\n port: number;\n ca: CAConfig;\n wsServer: WiretapWebSocketServer;\n}\n\nexport interface ProxyServer {\n server: mockttp.Mockttp;\n interceptor: ClaudeInterceptor;\n stop: () => Promise<void>;\n}\n\nexport async function createProxy(options: ProxyOptions): Promise<ProxyServer> {\n const { port, ca, wsServer } = options;\n\n const server = mockttp.getLocal({\n https: {\n cert: ca.cert,\n key: ca.key,\n },\n });\n\n const interceptor = new ClaudeInterceptor(wsServer);\n\n // Track request IDs for matching requests to responses (only for Anthropic requests)\n const requestIds = new Map<string, string>();\n\n // All requests pass through, but only Anthropic API requests are intercepted\n await server\n .forAnyRequest()\n .thenPassThrough({\n beforeRequest: async (request) => {\n // Quick check - skip non-Anthropic hosts immediately\n if (!isAnthropicHost(request.url)) {\n return {};\n }\n\n const requestId = await interceptor.handleRequest(request);\n if (requestId) {\n requestIds.set(request.id, requestId);\n }\n return {};\n },\n beforeResponse: async (response) => {\n // Only process if we have a tracked request ID (i.e., it was an Anthropic request)\n const requestId = requestIds.get(response.id);\n if (!requestId) {\n return {};\n }\n\n await interceptor.handleResponseStart(requestId, response.statusCode, response.headers as Record<string, string>);\n\n // Check if this is a streaming response\n const contentType = response.headers['content-type'] || '';\n const isStreaming = contentType.includes('text/event-stream');\n\n if (isStreaming) {\n const bodyBuffer = response.body.buffer;\n if (bodyBuffer.length > 0) {\n const bodyText = bodyBuffer.toString('utf-8');\n interceptor.handleResponseChunk(requestId, bodyText);\n }\n await interceptor.handleResponseComplete(requestId);\n } else {\n const bodyBuffer = response.body.buffer;\n const contentEncoding = response.headers['content-encoding'] as string | undefined;\n const bodyText = decompressBody(bodyBuffer, contentEncoding);\n interceptor.handleNonStreamingResponse(requestId, response.statusCode, bodyText);\n }\n\n requestIds.delete(response.id);\n return {};\n },\n });\n\n await server.start(port);\n\n console.log(chalk.green('✓'), `Proxy server started on port ${chalk.cyan(port)}`);\n console.log(chalk.gray(' Intercepting:'), CLAUDE_API_HOSTS.join(', '));\n console.log(chalk.gray(' All other traffic: transparent passthrough'));\n\n return {\n server,\n interceptor,\n stop: async () => {\n await server.stop();\n console.log(chalk.gray('○'), 'Proxy server stopped');\n },\n };\n}\n","import type { CompletedRequest } from 'mockttp';\nimport { randomUUID } from 'crypto';\nimport chalk from 'chalk';\nimport type {\n ClaudeRequest,\n ClaudeResponse,\n InterceptedRequest,\n} from './types.js';\nimport { SSEStreamParser, reconstructResponseFromEvents } from './parser.js';\nimport type { WiretapWebSocketServer } from './websocket.js';\n\nexport const CLAUDE_API_HOSTS = [\n 'api.anthropic.com',\n 'api.claude.ai',\n];\n\nconst CLAUDE_MESSAGES_PATH = '/v1/messages';\n\nexport class ClaudeInterceptor {\n private wsServer: WiretapWebSocketServer;\n private activeRequests: Map<string, {\n request: InterceptedRequest;\n parser: SSEStreamParser;\n }> = new Map();\n\n constructor(wsServer: WiretapWebSocketServer) {\n this.wsServer = wsServer;\n }\n\n isClaudeRequest(request: CompletedRequest): boolean {\n const host = request.headers.host || new URL(request.url).host;\n const path = new URL(request.url).pathname;\n\n return (\n CLAUDE_API_HOSTS.some((h) => host.includes(h)) &&\n path.includes(CLAUDE_MESSAGES_PATH) &&\n request.method === 'POST'\n );\n }\n\n async handleRequest(request: CompletedRequest): Promise<string | null> {\n if (!this.isClaudeRequest(request)) {\n return null;\n }\n\n const requestId = randomUUID();\n const timestamp = Date.now();\n\n // Parse request body\n let requestBody: ClaudeRequest | undefined;\n try {\n const bodyBuffer = request.body.buffer;\n if (bodyBuffer.length > 0) {\n const bodyText = bodyBuffer.toString('utf-8');\n requestBody = JSON.parse(bodyText) as ClaudeRequest;\n }\n } catch (error) {\n console.error(chalk.yellow('⚠'), 'Failed to parse request body:', error);\n }\n\n // Create intercepted request\n const intercepted: InterceptedRequest = {\n id: requestId,\n timestamp,\n method: request.method,\n url: request.url,\n requestHeaders: this.headersToRecord(request.headers),\n requestBody,\n sseEvents: [],\n };\n\n // Store active request\n this.activeRequests.set(requestId, {\n request: intercepted,\n parser: new SSEStreamParser(),\n });\n\n // Add to store and broadcast\n this.wsServer.addRequest(intercepted);\n\n this.wsServer.broadcast({\n type: 'request_start',\n requestId,\n timestamp,\n method: request.method,\n url: request.url,\n headers: intercepted.requestHeaders,\n });\n\n if (requestBody) {\n this.wsServer.broadcast({\n type: 'request_body',\n requestId,\n body: requestBody,\n });\n\n // Log request info\n const model = requestBody.model || 'unknown';\n const messageCount = requestBody.messages?.length || 0;\n const hasTools = requestBody.tools && requestBody.tools.length > 0;\n const isStreaming = requestBody.stream === true;\n\n console.log(\n chalk.cyan('→'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n chalk.green(model),\n `${messageCount} messages`,\n hasTools ? chalk.yellow(`+ ${requestBody.tools!.length} tools`) : '',\n isStreaming ? chalk.magenta('streaming') : ''\n );\n }\n\n return requestId;\n }\n\n async handleResponseStart(\n requestId: string,\n statusCode: number,\n headers: Record<string, string>\n ): Promise<void> {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n const timestamp = Date.now();\n active.request.responseStartTime = timestamp;\n active.request.statusCode = statusCode;\n active.request.responseHeaders = headers;\n\n this.wsServer.broadcast({\n type: 'response_start',\n requestId,\n timestamp,\n statusCode,\n headers,\n });\n }\n\n handleResponseChunk(requestId: string, chunk: Buffer | string): void {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n const data = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n const events = active.parser.feed(data);\n\n for (const event of events) {\n active.request.sseEvents.push(event);\n this.wsServer.broadcast({\n type: 'response_chunk',\n requestId,\n event,\n });\n\n // Log streaming progress for text deltas\n if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {\n process.stdout.write(chalk.gray('.'));\n }\n }\n }\n\n async handleResponseComplete(requestId: string): Promise<void> {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n // Flush any remaining data\n const remainingEvents = active.parser.flush();\n for (const event of remainingEvents) {\n active.request.sseEvents.push(event);\n this.wsServer.broadcast({\n type: 'response_chunk',\n requestId,\n event,\n });\n }\n\n // Reconstruct full response\n const response = reconstructResponseFromEvents(active.request.sseEvents);\n const timestamp = Date.now();\n const durationMs = timestamp - active.request.timestamp;\n\n active.request.response = response || undefined;\n active.request.durationMs = durationMs;\n\n if (response) {\n this.wsServer.broadcast({\n type: 'response_complete',\n requestId,\n timestamp,\n response,\n durationMs,\n });\n\n // Log completion\n console.log(); // New line after streaming dots\n console.log(\n chalk.green('✓'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n `${response.usage.input_tokens} in / ${response.usage.output_tokens} out`,\n chalk.gray(`(${durationMs}ms)`),\n response.stop_reason === 'tool_use' ? chalk.yellow('→ tool_use') : ''\n );\n }\n\n // Cleanup\n this.activeRequests.delete(requestId);\n }\n\n handleResponseError(requestId: string, error: Error): void {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n active.request.error = error.message;\n\n this.wsServer.broadcast({\n type: 'error',\n requestId,\n error: error.message,\n timestamp: Date.now(),\n });\n\n console.log(\n chalk.red('✗'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n error.message\n );\n\n this.activeRequests.delete(requestId);\n }\n\n handleNonStreamingResponse(\n requestId: string,\n _statusCode: number,\n bodyText: string\n ): void {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n try {\n if (bodyText) {\n const claudeResponse = JSON.parse(bodyText) as ClaudeResponse;\n const timestamp = Date.now();\n const durationMs = timestamp - active.request.timestamp;\n\n active.request.response = claudeResponse;\n active.request.durationMs = durationMs;\n\n this.wsServer.broadcast({\n type: 'response_complete',\n requestId,\n timestamp,\n response: claudeResponse,\n durationMs,\n });\n\n if (claudeResponse.type === 'message') {\n console.log(\n chalk.green('✓'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n `${claudeResponse.usage.input_tokens} in / ${claudeResponse.usage.output_tokens} out`,\n chalk.gray(`(${durationMs}ms)`),\n claudeResponse.stop_reason === 'tool_use' ? chalk.yellow('→ tool_use') : ''\n );\n } else if (claudeResponse.type === 'error') {\n console.log(\n chalk.yellow('⚠'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n chalk.red(claudeResponse.error.message),\n chalk.gray(`(${durationMs}ms)`)\n );\n }\n }\n } catch (error) {\n console.error(chalk.yellow('⚠'), 'Failed to parse response body:', error);\n }\n\n this.activeRequests.delete(requestId);\n }\n\n private headersToRecord(headers: Record<string, string | string[] | undefined>): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) {\n result[key] = Array.isArray(value) ? value.join(', ') : value;\n }\n }\n return result;\n }\n\n getActiveRequestCount(): number {\n return this.activeRequests.size;\n }\n}\n","import type {\n SSEEvent,\n ClaudeMessageResponse,\n ClaudeContent,\n TextContent,\n ToolUseContent,\n TokenUsage,\n ContentBlockStartEvent,\n ContentBlockDeltaEvent,\n MessageStartEvent,\n MessageDeltaEvent,\n} from './types.js';\n\n/**\n * Parses a raw SSE data string into an SSEEvent\n */\nexport function parseSSELine(line: string): SSEEvent | null {\n if (!line.startsWith('data: ')) {\n return null;\n }\n\n const jsonStr = line.slice(6).trim();\n if (!jsonStr || jsonStr === '[DONE]') {\n return null;\n }\n\n try {\n return JSON.parse(jsonStr) as SSEEvent;\n } catch {\n return null;\n }\n}\n\n/**\n * Parses a complete SSE stream chunk (may contain multiple events)\n */\nexport function parseSSEChunk(chunk: string): SSEEvent[] {\n const events: SSEEvent[] = [];\n const lines = chunk.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data: ')) {\n const event = parseSSELine(trimmed);\n if (event) {\n events.push(event);\n }\n }\n }\n\n return events;\n}\n\n/**\n * SSE Stream Parser class for handling streaming data\n */\nexport class SSEStreamParser {\n private buffer = '';\n private events: SSEEvent[] = [];\n\n /**\n * Feed data to the parser\n */\n feed(data: string): SSEEvent[] {\n this.buffer += data;\n const newEvents: SSEEvent[] = [];\n\n // Split on double newlines (SSE event separator)\n const parts = this.buffer.split('\\n\\n');\n\n // Keep the last part in the buffer (might be incomplete)\n this.buffer = parts.pop() || '';\n\n for (const part of parts) {\n const lines = part.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data: ')) {\n const event = parseSSELine(trimmed);\n if (event) {\n newEvents.push(event);\n this.events.push(event);\n }\n }\n }\n }\n\n return newEvents;\n }\n\n /**\n * Flush any remaining buffered data\n */\n flush(): SSEEvent[] {\n if (!this.buffer.trim()) {\n return [];\n }\n\n const events = parseSSEChunk(this.buffer);\n this.events.push(...events);\n this.buffer = '';\n return events;\n }\n\n /**\n * Get all parsed events\n */\n getAllEvents(): SSEEvent[] {\n return [...this.events];\n }\n\n /**\n * Reset the parser\n */\n reset(): void {\n this.buffer = '';\n this.events = [];\n }\n}\n\n/**\n * Reconstructs a complete ClaudeMessageResponse from SSE events.\n * Streaming responses are always message responses (errors are non-streaming).\n */\nexport function reconstructResponseFromEvents(events: SSEEvent[]): ClaudeMessageResponse | null {\n let messageStart: MessageStartEvent | null = null;\n let messageDelta: MessageDeltaEvent | null = null;\n const contentBlocks: Map<number, { type: string; content: Partial<ClaudeContent> }> = new Map();\n const textDeltas: Map<number, string[]> = new Map();\n const jsonDeltas: Map<number, string[]> = new Map();\n\n for (const event of events) {\n switch (event.type) {\n case 'message_start':\n messageStart = event;\n break;\n\n case 'content_block_start': {\n const startEvent = event as ContentBlockStartEvent;\n contentBlocks.set(startEvent.index, {\n type: startEvent.content_block.type,\n content: { ...startEvent.content_block },\n });\n if (startEvent.content_block.type === 'text') {\n textDeltas.set(startEvent.index, []);\n } else if (startEvent.content_block.type === 'tool_use') {\n jsonDeltas.set(startEvent.index, []);\n }\n break;\n }\n\n case 'content_block_delta': {\n const deltaEvent = event as ContentBlockDeltaEvent;\n if (deltaEvent.delta.type === 'text_delta') {\n const deltas = textDeltas.get(deltaEvent.index) || [];\n deltas.push(deltaEvent.delta.text);\n textDeltas.set(deltaEvent.index, deltas);\n } else if (deltaEvent.delta.type === 'input_json_delta') {\n const deltas = jsonDeltas.get(deltaEvent.index) || [];\n deltas.push(deltaEvent.delta.partial_json);\n jsonDeltas.set(deltaEvent.index, deltas);\n }\n break;\n }\n\n case 'message_delta':\n messageDelta = event;\n break;\n }\n }\n\n if (!messageStart) {\n return null;\n }\n\n // Build content array\n const content: ClaudeContent[] = [];\n const sortedIndices = Array.from(contentBlocks.keys()).sort((a, b) => a - b);\n\n for (const index of sortedIndices) {\n const block = contentBlocks.get(index)!;\n\n if (block.type === 'text') {\n const text = (textDeltas.get(index) || []).join('');\n content.push({\n type: 'text',\n text,\n } as TextContent);\n } else if (block.type === 'tool_use') {\n const jsonStr = (jsonDeltas.get(index) || []).join('');\n let input: Record<string, unknown> = {};\n try {\n input = jsonStr ? JSON.parse(jsonStr) : {};\n } catch {\n // Keep empty object if parsing fails\n }\n content.push({\n type: 'tool_use',\n id: (block.content as ToolUseContent).id || '',\n name: (block.content as ToolUseContent).name || '',\n input,\n } as ToolUseContent);\n }\n }\n\n // Calculate total usage\n const usage: TokenUsage = {\n input_tokens: messageStart.message.usage.input_tokens,\n output_tokens: messageDelta?.usage.output_tokens || messageStart.message.usage.output_tokens,\n cache_creation_input_tokens: messageStart.message.usage.cache_creation_input_tokens,\n cache_read_input_tokens: messageStart.message.usage.cache_read_input_tokens,\n };\n\n return {\n id: messageStart.message.id,\n type: 'message',\n role: 'assistant',\n content,\n model: messageStart.message.model,\n stop_reason: messageDelta?.delta.stop_reason || null,\n stop_sequence: messageDelta?.delta.stop_sequence || null,\n usage,\n };\n}\n\n/**\n * Extracts text content from SSE events (useful for live preview)\n */\nexport function extractTextFromEvents(events: SSEEvent[]): string {\n const textParts: string[] = [];\n\n for (const event of events) {\n if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {\n textParts.push(event.delta.text);\n }\n }\n\n return textParts.join('');\n}\n\n/**\n * Extracts tool calls from SSE events\n */\nexport function extractToolCallsFromEvents(events: SSEEvent[]): ToolUseContent[] {\n const tools: Map<number, { id: string; name: string; jsonParts: string[] }> = new Map();\n\n for (const event of events) {\n if (event.type === 'content_block_start' && event.content_block.type === 'tool_use') {\n tools.set(event.index, {\n id: event.content_block.id,\n name: event.content_block.name,\n jsonParts: [],\n });\n } else if (\n event.type === 'content_block_delta' &&\n event.delta.type === 'input_json_delta'\n ) {\n const tool = tools.get(event.index);\n if (tool) {\n tool.jsonParts.push(event.delta.partial_json);\n }\n }\n }\n\n return Array.from(tools.values()).map((tool) => {\n let input: Record<string, unknown> = {};\n try {\n const jsonStr = tool.jsonParts.join('');\n input = jsonStr ? JSON.parse(jsonStr) : {};\n } catch {\n // Keep empty object\n }\n return {\n type: 'tool_use' as const,\n id: tool.id,\n name: tool.name,\n input,\n };\n });\n}\n","import { WebSocketServer, WebSocket } from 'ws';\nimport type { Server } from 'http';\nimport type { WSMessage, InterceptedRequest } from './types.js';\nimport chalk from 'chalk';\n\nexport interface WiretapWebSocketServerOptions {\n port?: number;\n server?: Server;\n}\n\nexport class WiretapWebSocketServer {\n private wss: WebSocketServer;\n private clients: Set<WebSocket> = new Set();\n private requests: Map<string, InterceptedRequest> = new Map();\n\n constructor(options: WiretapWebSocketServerOptions = {}) {\n if (options.server) {\n this.wss = new WebSocketServer({ server: options.server });\n } else {\n this.wss = new WebSocketServer({ port: options.port || 8081 });\n }\n\n this.wss.on('connection', (ws, req) => {\n const clientIp = req.socket.remoteAddress || 'unknown';\n console.log(chalk.blue('⬤'), `UI client connected from ${clientIp}`);\n this.clients.add(ws);\n\n // Send current state to new client\n this.sendCurrentState(ws);\n\n ws.on('message', (data) => {\n try {\n const message = JSON.parse(data.toString());\n if (message.type === 'clear_all') {\n console.log(chalk.yellow('⟲'), 'Clearing all requests');\n this.requests.clear();\n this.broadcast({ type: 'clear_all' });\n }\n } catch (error) {\n console.error(chalk.red('✗'), `Failed to parse client message: ${error}`);\n }\n });\n\n ws.on('close', () => {\n console.log(chalk.gray('○'), `UI client disconnected from ${clientIp}`);\n this.clients.delete(ws);\n });\n\n ws.on('error', (error) => {\n console.error(chalk.red('✗'), `WebSocket error: ${error.message}`);\n this.clients.delete(ws);\n });\n });\n\n this.wss.on('error', (error) => {\n console.error(chalk.red('✗'), `WebSocket server error: ${error.message}`);\n });\n }\n\n private sendCurrentState(ws: WebSocket): void {\n // Send all existing requests in a single message for fast initial load\n if (this.requests.size > 0) {\n this.sendToClient(ws, {\n type: 'history_sync',\n requests: Array.from(this.requests.values()),\n });\n }\n }\n\n private sendToClient(ws: WebSocket, message: WSMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n }\n\n broadcast(message: WSMessage): void {\n const data = JSON.stringify(message);\n for (const client of this.clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data);\n }\n }\n }\n\n // Request management\n\n addRequest(request: InterceptedRequest): void {\n this.requests.set(request.id, request);\n }\n\n getRequest(requestId: string): InterceptedRequest | undefined {\n return this.requests.get(requestId);\n }\n\n // Stats\n\n getClientCount(): number {\n return this.clients.size;\n }\n\n getRequestCount(): number {\n return this.requests.size;\n }\n\n // Lifecycle\n\n close(): Promise<void> {\n return new Promise((resolve, reject) => {\n for (const client of this.clients) {\n client.close();\n }\n this.clients.clear();\n\n this.wss.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n }\n\n getPort(): number | undefined {\n const address = this.wss.address();\n if (address && typeof address === 'object') {\n return address.port;\n }\n return undefined;\n }\n}\n","import { createServer, type Server } from 'http';\nimport { getCAPath } from './ca.js';\nimport chalk from 'chalk';\n\nconst SETUP_PORT = 8082;\n\nfunction generateSetupScript(proxyPort: number): string {\n const caPath = getCAPath();\n\n return `#!/bin/bash\n# CC Wiretap - Terminal Setup Script\n# This script configures your terminal session to route traffic through the proxy\n\n# Proxy settings (for most HTTP clients)\nexport HTTP_PROXY=\"http://localhost:${proxyPort}\"\nexport HTTPS_PROXY=\"http://localhost:${proxyPort}\"\nexport http_proxy=\"http://localhost:${proxyPort}\"\nexport https_proxy=\"http://localhost:${proxyPort}\"\n\n# Node.js CA certificate\nexport NODE_EXTRA_CA_CERTS=\"${caPath}\"\n\n# Python/OpenSSL CA certificates\nexport SSL_CERT_FILE=\"${caPath}\"\nexport REQUESTS_CA_BUNDLE=\"${caPath}\"\n\n# curl CA certificate\nexport CURL_CA_BUNDLE=\"${caPath}\"\n\n# Ruby CA certificate\nexport SSL_CERT_DIR=\"\"\n\n# Git CA certificate (for HTTPS remotes)\nexport GIT_SSL_CAINFO=\"${caPath}\"\n\n# AWS CLI\nexport AWS_CA_BUNDLE=\"${caPath}\"\n\n# Disable proxy for localhost (prevents loops)\nexport NO_PROXY=\"localhost,127.0.0.1,::1\"\nexport no_proxy=\"localhost,127.0.0.1,::1\"\n\n# Visual indicator that proxy is active\nexport WIRETAP_ACTIVE=\"1\"\n\n# Update PS1 to show proxy is active (optional - uncomment if desired)\n# export PS1=\"[wiretap] $PS1\"\n\necho \"\"\necho \" ✓ CC Wiretap proxy configured for this terminal\"\necho \"\"\necho \" Proxy: http://localhost:${proxyPort}\"\necho \" CA: ${caPath}\"\necho \"\"\necho \" All HTTP/HTTPS traffic from this terminal will be intercepted.\"\necho \" Run 'unset-wiretap' to disable.\"\necho \"\"\n\n# Create unset function\nunset-wiretap() {\n unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy\n unset NODE_EXTRA_CA_CERTS SSL_CERT_FILE REQUESTS_CA_BUNDLE\n unset CURL_CA_BUNDLE SSL_CERT_DIR GIT_SSL_CAINFO AWS_CA_BUNDLE\n unset NO_PROXY no_proxy WIRETAP_ACTIVE\n echo \"✓ Wiretap proxy disabled for this terminal\"\n}\nexport -f unset-wiretap 2>/dev/null || true\n`;\n}\n\nfunction generateFishScript(proxyPort: number): string {\n const caPath = getCAPath();\n\n return `# CC Wiretap - Fish Shell Setup Script\n\nset -gx HTTP_PROXY \"http://localhost:${proxyPort}\"\nset -gx HTTPS_PROXY \"http://localhost:${proxyPort}\"\nset -gx http_proxy \"http://localhost:${proxyPort}\"\nset -gx https_proxy \"http://localhost:${proxyPort}\"\nset -gx NODE_EXTRA_CA_CERTS \"${caPath}\"\nset -gx SSL_CERT_FILE \"${caPath}\"\nset -gx REQUESTS_CA_BUNDLE \"${caPath}\"\nset -gx CURL_CA_BUNDLE \"${caPath}\"\nset -gx GIT_SSL_CAINFO \"${caPath}\"\nset -gx AWS_CA_BUNDLE \"${caPath}\"\nset -gx NO_PROXY \"localhost,127.0.0.1,::1\"\nset -gx no_proxy \"localhost,127.0.0.1,::1\"\nset -gx WIRETAP_ACTIVE \"1\"\n\necho \"\"\necho \" ✓ CC Wiretap proxy configured for this terminal\"\necho \"\"\necho \" Proxy: http://localhost:${proxyPort}\"\necho \" CA: ${caPath}\"\necho \"\"\n\nfunction unset-wiretap\n set -e HTTP_PROXY HTTPS_PROXY http_proxy https_proxy\n set -e NODE_EXTRA_CA_CERTS SSL_CERT_FILE REQUESTS_CA_BUNDLE\n set -e CURL_CA_BUNDLE GIT_SSL_CAINFO AWS_CA_BUNDLE\n set -e NO_PROXY no_proxy WIRETAP_ACTIVE\n echo \"✓ Wiretap proxy disabled\"\nend\n`;\n}\n\nexport function createSetupServer(proxyPort: number): Server {\n const server = createServer((req, res) => {\n const url = new URL(req.url || '/', `http://localhost:${SETUP_PORT}`);\n\n // CORS headers for browser access\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET');\n\n if (url.pathname === '/' || url.pathname === '/setup') {\n // Detect shell from query param or User-Agent\n const shell = url.searchParams.get('shell') || 'bash';\n\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n\n if (shell === 'fish') {\n res.end(generateFishScript(proxyPort));\n } else {\n res.end(generateSetupScript(proxyPort));\n }\n } else if (url.pathname === '/status') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({\n active: true,\n proxyPort,\n caPath: getCAPath(),\n }));\n } else {\n res.statusCode = 404;\n res.end('Not found');\n }\n });\n\n server.listen(SETUP_PORT, () => {\n console.log(chalk.green('✓'), `Setup server started on port ${chalk.cyan(SETUP_PORT)}`);\n });\n\n return server;\n}\n\nexport function getSetupCommand(): string {\n return `eval \"$(curl -s http://localhost:${SETUP_PORT}/setup)\"`;\n}\n\nexport function getSetupPort(): number {\n return SETUP_PORT;\n}\n","import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'http';\nimport { createReadStream, existsSync, statSync } from 'fs';\nimport { join, extname } from 'path';\nimport { fileURLToPath } from 'url';\nimport chalk from 'chalk';\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url));\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject',\n};\n\nfunction getUIDistPath(): string {\n // In production build, UI is at dist/ui relative to this file\n // After tsup build, this file is at dist/index.js, so ui is at dist/ui\n return join(__dirname, 'ui');\n}\n\nfunction serveFile(res: ServerResponse, filePath: string): void {\n const ext = extname(filePath).toLowerCase();\n const contentType = MIME_TYPES[ext] || 'application/octet-stream';\n\n res.setHeader('Content-Type', contentType);\n res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n\n const stream = createReadStream(filePath);\n stream.pipe(res);\n stream.on('error', () => {\n res.statusCode = 500;\n res.end('Internal Server Error');\n });\n}\n\nfunction handleRequest(req: IncomingMessage, res: ServerResponse, uiPath: string): void {\n const url = new URL(req.url || '/', 'http://localhost');\n let pathname = url.pathname;\n\n // Remove leading slash and decode\n let relativePath = decodeURIComponent(pathname.slice(1));\n\n // Default to index.html\n if (relativePath === '' || relativePath === '/') {\n relativePath = 'index.html';\n }\n\n const filePath = join(uiPath, relativePath);\n\n // Security: prevent directory traversal\n if (!filePath.startsWith(uiPath)) {\n res.statusCode = 403;\n res.end('Forbidden');\n return;\n }\n\n // Check if file exists\n if (existsSync(filePath) && statSync(filePath).isFile()) {\n serveFile(res, filePath);\n return;\n }\n\n // For SPA routing: serve index.html for non-file requests\n const indexPath = join(uiPath, 'index.html');\n if (existsSync(indexPath)) {\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache');\n createReadStream(indexPath).pipe(res);\n return;\n }\n\n res.statusCode = 404;\n res.end('Not Found');\n}\n\nexport interface UIServerOptions {\n port: number;\n}\n\nexport function createUIServer(options: UIServerOptions): Server | null {\n const { port } = options;\n const uiPath = getUIDistPath();\n\n // Check if UI is bundled\n if (!existsSync(uiPath) || !existsSync(join(uiPath, 'index.html'))) {\n console.log(chalk.yellow('!'), 'UI not bundled. Run in dev mode or build first.');\n return null;\n }\n\n const server = createServer((req, res) => {\n // CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET');\n\n handleRequest(req, res, uiPath);\n });\n\n server.listen(port, () => {\n console.log(chalk.green('✓'), `UI server started on port ${chalk.cyan(port)}`);\n });\n\n return server;\n}\n\nexport function getUIPath(): string {\n return getUIDistPath();\n}\n"],"mappings":"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","names":["chalk","cert","key","chalk","chalk","chalk","chalk","chalk","chalk","createServer","join","chalk","__dirname","chalk"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/ca.ts","../src/proxy.ts","../src/interceptor.ts","../src/parser.ts","../src/websocket.ts","../src/setup-server.ts","../src/ui-server.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { loadOrGenerateCA, getCAPath } from \"./ca.js\";\nimport { createProxy } from \"./proxy.js\";\nimport { WiretapWebSocketServer } from \"./websocket.js\";\nimport { createSetupServer, getSetupCommand } from \"./setup-server.js\";\nimport { createUIServer } from \"./ui-server.js\";\n\nconst VERSION = \"1.0.5\";\n\nconst BANNER = `\n${chalk.cyan(\"╔════════════════════════════════════════════════════════════╗\")}\n${chalk.cyan(\"║\")} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"║\")} ${chalk.bold.white(\"CC Wiretap\")} ${chalk.gray(\"v\" + VERSION)} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"║\")} ${chalk.gray(\"HTTP/HTTPS proxy for Claude Code traffic inspection\")} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"║\")} ${chalk.cyan(\"║\")}\n${chalk.cyan(\"╚════════════════════════════════════════════════════════════╝\")}\n`;\n\ninterface CLIOptions {\n port: string;\n wsPort: string;\n uiPort: string;\n quiet: boolean;\n}\n\nasync function main() {\n const program = new Command();\n\n program\n .name(\"cc-wiretap\")\n .description(\n \"HTTP/HTTPS proxy for intercepting and visualizing Claude Code traffic\",\n )\n .version(VERSION)\n .option(\"-p, --port <port>\", \"Proxy server port\", \"8080\")\n .option(\"-w, --ws-port <port>\", \"WebSocket server port for UI\", \"8081\")\n .option(\"-u, --ui-port <port>\", \"UI dashboard server port\", \"3000\")\n .option(\"-q, --quiet\", \"Suppress banner and verbose output\", false)\n .action(async (options: CLIOptions) => {\n if (!options.quiet) {\n console.log(BANNER);\n }\n\n const proxyPort = parseInt(options.port, 10);\n const wsPort = parseInt(options.wsPort, 10);\n const uiPort = parseInt(options.uiPort, 10);\n\n try {\n // Load or generate CA certificate\n const ca = await loadOrGenerateCA();\n\n // Start WebSocket server\n const wsServer = new WiretapWebSocketServer({ port: wsPort });\n console.log(\n chalk.green(\"✓\"),\n `WebSocket server started on port ${chalk.cyan(wsPort)}`,\n );\n\n // Start proxy server\n const proxy = await createProxy({\n port: proxyPort,\n ca,\n wsServer,\n });\n\n // Start setup server (for terminal eval command)\n const setupServer = createSetupServer(proxyPort);\n\n // Start UI server (serves bundled dashboard)\n const uiServer = createUIServer({ port: uiPort });\n\n console.log();\n console.log(chalk.white(\"Ready to intercept Claude API traffic.\"));\n console.log();\n\n // Highlight the easy setup command\n console.log(\n chalk.yellow.bold(\"Quick setup - run this in any terminal:\"),\n );\n console.log();\n console.log(chalk.yellow(\"=>\"), chalk.cyan.bold(getSetupCommand()));\n console.log();\n console.log(chalk.gray(\"Or manually:\"));\n console.log();\n console.log(chalk.gray(` NODE_EXTRA_CA_CERTS=\"${getCAPath()}\" \\\\`));\n console.log(\n chalk.gray(` HTTPS_PROXY=http://localhost:${proxyPort} \\\\`),\n );\n console.log(chalk.gray(\" claude\"));\n console.log();\n console.log(\n chalk.yellow(\"=>\"),\n chalk.yellow.bold(\"UI:\"),\n chalk.cyan(`http://localhost:${uiPort}`),\n );\n console.log();\n console.log(chalk.gray(\"─\".repeat(60)));\n console.log();\n\n // Handle shutdown\n const shutdown = async () => {\n console.log();\n console.log(chalk.yellow(\"Shutting down...\"));\n await proxy.stop();\n await wsServer.close();\n setupServer.close();\n uiServer?.close();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n } catch (error) {\n console.error(chalk.red(\"✗\"), \"Failed to start:\", error);\n process.exit(1);\n }\n });\n\n program.parse();\n}\n\nmain().catch((error) => {\n console.error(chalk.red(\"Fatal error:\"), error);\n process.exit(1);\n});\n\nexport { loadOrGenerateCA, getCAPath } from \"./ca.js\";\nexport { createProxy } from \"./proxy.js\";\nexport { WiretapWebSocketServer } from \"./websocket.js\";\nexport { ClaudeInterceptor, CLAUDE_API_HOSTS } from \"./interceptor.js\";\nexport {\n SSEStreamParser,\n parseSSEChunk,\n reconstructResponseFromEvents,\n} from \"./parser.js\";\nexport { createSetupServer, getSetupCommand } from \"./setup-server.js\";\nexport { createUIServer } from \"./ui-server.js\";\nexport * from \"./types.js\";\n","import { homedir } from 'os';\nimport { join } from 'path';\nimport { mkdir, readFile, writeFile, access, constants } from 'fs/promises';\nimport { generateCACertificate } from 'mockttp';\nimport chalk from 'chalk';\n\nconst CA_DIR = join(homedir(), '.cc-wiretap');\nconst CA_CERT_PATH = join(CA_DIR, 'ca.pem');\nconst CA_KEY_PATH = join(CA_DIR, 'ca-key.pem');\n\nexport interface CAConfig {\n certPath: string;\n keyPath: string;\n cert: string;\n key: string;\n}\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function ensureCADirectory(): Promise<void> {\n try {\n await mkdir(CA_DIR, { recursive: true });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') {\n throw error;\n }\n }\n}\n\nexport async function loadOrGenerateCA(): Promise<CAConfig> {\n await ensureCADirectory();\n\n const certExists = await fileExists(CA_CERT_PATH);\n const keyExists = await fileExists(CA_KEY_PATH);\n\n if (certExists && keyExists) {\n console.log(chalk.green('✓'), 'Using existing CA certificate from', chalk.cyan(CA_DIR));\n const cert = await readFile(CA_CERT_PATH, 'utf-8');\n const key = await readFile(CA_KEY_PATH, 'utf-8');\n return {\n certPath: CA_CERT_PATH,\n keyPath: CA_KEY_PATH,\n cert,\n key,\n };\n }\n\n console.log(chalk.yellow('⚙'), 'Generating new CA certificate...');\n\n const { cert, key } = await generateCACertificate({\n commonName: 'CC Wiretap CA',\n organizationName: 'CC Wiretap',\n });\n\n await writeFile(CA_CERT_PATH, cert);\n await writeFile(CA_KEY_PATH, key);\n\n console.log(chalk.green('✓'), 'CA certificate generated at', chalk.cyan(CA_DIR));\n console.log();\n console.log(chalk.yellow('To trust the CA certificate, run:'));\n console.log();\n console.log(chalk.gray(' # macOS:'));\n console.log(chalk.white(` sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain \"${CA_CERT_PATH}\"`));\n console.log();\n console.log(chalk.gray(' # Linux (Debian/Ubuntu):'));\n console.log(chalk.white(` sudo cp \"${CA_CERT_PATH}\" /usr/local/share/ca-certificates/cc-wiretap.crt`));\n console.log(chalk.white(' sudo update-ca-certificates'));\n console.log();\n console.log(chalk.gray(' # For Node.js/Claude Code, use:'));\n console.log(chalk.white(` NODE_EXTRA_CA_CERTS=\"${CA_CERT_PATH}\"`));\n console.log();\n\n return {\n certPath: CA_CERT_PATH,\n keyPath: CA_KEY_PATH,\n cert,\n key,\n };\n}\n\nexport function getCAPath(): string {\n return CA_CERT_PATH;\n}\n\nexport function getCADir(): string {\n return CA_DIR;\n}\n","import * as mockttp from 'mockttp';\nimport chalk from 'chalk';\nimport { gunzipSync, brotliDecompressSync } from 'zlib';\nimport type { CAConfig } from './ca.js';\nimport { ClaudeInterceptor, CLAUDE_API_HOSTS } from './interceptor.js';\nimport type { WiretapWebSocketServer } from './websocket.js';\n\nfunction decompressBody(buffer: Buffer, contentEncoding: string | undefined): string {\n if (!buffer.length) return '';\n\n try {\n if (contentEncoding === 'gzip') {\n return gunzipSync(buffer).toString('utf-8');\n }\n if (contentEncoding === 'br') {\n return brotliDecompressSync(buffer).toString('utf-8');\n }\n } catch {\n // If decompression fails, try as plain text\n }\n\n return buffer.toString('utf-8');\n}\n\nfunction isAnthropicHost(url: string): boolean {\n try {\n const host = new URL(url).host;\n return CLAUDE_API_HOSTS.some((h) => host.includes(h));\n } catch {\n return false;\n }\n}\n\nexport interface ProxyOptions {\n port: number;\n ca: CAConfig;\n wsServer: WiretapWebSocketServer;\n}\n\nexport interface ProxyServer {\n server: mockttp.Mockttp;\n interceptor: ClaudeInterceptor;\n stop: () => Promise<void>;\n}\n\nexport async function createProxy(options: ProxyOptions): Promise<ProxyServer> {\n const { port, ca, wsServer } = options;\n\n const server = mockttp.getLocal({\n https: {\n cert: ca.cert,\n key: ca.key,\n },\n });\n\n const interceptor = new ClaudeInterceptor(wsServer);\n\n // Track request IDs for matching requests to responses (only for Anthropic requests)\n const requestIds = new Map<string, string>();\n\n // All requests pass through, but only Anthropic API requests are intercepted\n await server\n .forAnyRequest()\n .thenPassThrough({\n beforeRequest: async (request) => {\n // Quick check - skip non-Anthropic hosts immediately\n if (!isAnthropicHost(request.url)) {\n return {};\n }\n\n const requestId = await interceptor.handleRequest(request);\n if (requestId) {\n requestIds.set(request.id, requestId);\n }\n return {};\n },\n beforeResponse: async (response) => {\n // Only process if we have a tracked request ID (i.e., it was an Anthropic request)\n const requestId = requestIds.get(response.id);\n if (!requestId) {\n return {};\n }\n\n await interceptor.handleResponseStart(requestId, response.statusCode, response.headers as Record<string, string>);\n\n // Check if this is a streaming response\n const contentType = response.headers['content-type'] || '';\n const isStreaming = contentType.includes('text/event-stream');\n\n if (isStreaming) {\n const bodyBuffer = response.body.buffer;\n if (bodyBuffer.length > 0) {\n const bodyText = bodyBuffer.toString('utf-8');\n interceptor.handleResponseChunk(requestId, bodyText);\n }\n await interceptor.handleResponseComplete(requestId);\n } else {\n const bodyBuffer = response.body.buffer;\n const contentEncoding = response.headers['content-encoding'] as string | undefined;\n const bodyText = decompressBody(bodyBuffer, contentEncoding);\n interceptor.handleNonStreamingResponse(requestId, response.statusCode, bodyText);\n }\n\n requestIds.delete(response.id);\n return {};\n },\n });\n\n await server.start(port);\n\n console.log(chalk.green('✓'), `Proxy server started on port ${chalk.cyan(port)}`);\n console.log(chalk.gray(' Intercepting:'), CLAUDE_API_HOSTS.join(', '));\n console.log(chalk.gray(' All other traffic: transparent passthrough'));\n\n return {\n server,\n interceptor,\n stop: async () => {\n await server.stop();\n console.log(chalk.gray('○'), 'Proxy server stopped');\n },\n };\n}\n","import type { CompletedRequest } from 'mockttp';\nimport { randomUUID } from 'crypto';\nimport chalk from 'chalk';\nimport type {\n ClaudeRequest,\n ClaudeResponse,\n InterceptedRequest,\n} from './types.js';\nimport { SSEStreamParser, reconstructResponseFromEvents } from './parser.js';\nimport type { WiretapWebSocketServer } from './websocket.js';\n\nexport const CLAUDE_API_HOSTS = [\n 'api.anthropic.com',\n 'api.claude.ai',\n];\n\nconst CLAUDE_MESSAGES_PATH = '/v1/messages';\n\nexport class ClaudeInterceptor {\n private wsServer: WiretapWebSocketServer;\n private activeRequests: Map<string, {\n request: InterceptedRequest;\n parser: SSEStreamParser;\n }> = new Map();\n\n constructor(wsServer: WiretapWebSocketServer) {\n this.wsServer = wsServer;\n }\n\n isClaudeRequest(request: CompletedRequest): boolean {\n const host = request.headers.host || new URL(request.url).host;\n const path = new URL(request.url).pathname;\n\n return (\n CLAUDE_API_HOSTS.some((h) => host.includes(h)) &&\n path.includes(CLAUDE_MESSAGES_PATH) &&\n request.method === 'POST'\n );\n }\n\n async handleRequest(request: CompletedRequest): Promise<string | null> {\n if (!this.isClaudeRequest(request)) {\n return null;\n }\n\n const requestId = randomUUID();\n const timestamp = Date.now();\n\n // Parse request body\n let requestBody: ClaudeRequest | undefined;\n try {\n const bodyBuffer = request.body.buffer;\n if (bodyBuffer.length > 0) {\n const bodyText = bodyBuffer.toString('utf-8');\n requestBody = JSON.parse(bodyText) as ClaudeRequest;\n }\n } catch (error) {\n console.error(chalk.yellow('⚠'), 'Failed to parse request body:', error);\n }\n\n // Create intercepted request\n const intercepted: InterceptedRequest = {\n id: requestId,\n timestamp,\n method: request.method,\n url: request.url,\n requestHeaders: this.headersToRecord(request.headers),\n requestBody,\n sseEvents: [],\n };\n\n // Store active request\n this.activeRequests.set(requestId, {\n request: intercepted,\n parser: new SSEStreamParser(),\n });\n\n // Add to store and broadcast\n this.wsServer.addRequest(intercepted);\n\n this.wsServer.broadcast({\n type: 'request_start',\n requestId,\n timestamp,\n method: request.method,\n url: request.url,\n headers: intercepted.requestHeaders,\n });\n\n if (requestBody) {\n this.wsServer.broadcast({\n type: 'request_body',\n requestId,\n body: requestBody,\n });\n\n // Log request info\n const model = requestBody.model || 'unknown';\n const messageCount = requestBody.messages?.length || 0;\n const hasTools = requestBody.tools && requestBody.tools.length > 0;\n const isStreaming = requestBody.stream === true;\n\n console.log(\n chalk.cyan('→'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n chalk.green(model),\n `${messageCount} messages`,\n hasTools ? chalk.yellow(`+ ${requestBody.tools!.length} tools`) : '',\n isStreaming ? chalk.magenta('streaming') : ''\n );\n }\n\n return requestId;\n }\n\n async handleResponseStart(\n requestId: string,\n statusCode: number,\n headers: Record<string, string>\n ): Promise<void> {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n const timestamp = Date.now();\n active.request.responseStartTime = timestamp;\n active.request.statusCode = statusCode;\n active.request.responseHeaders = headers;\n\n this.wsServer.broadcast({\n type: 'response_start',\n requestId,\n timestamp,\n statusCode,\n headers,\n });\n }\n\n handleResponseChunk(requestId: string, chunk: Buffer | string): void {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n const data = typeof chunk === 'string' ? chunk : chunk.toString('utf-8');\n const events = active.parser.feed(data);\n\n for (const event of events) {\n active.request.sseEvents.push(event);\n this.wsServer.broadcast({\n type: 'response_chunk',\n requestId,\n event,\n });\n\n // Log streaming progress for text deltas\n if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {\n process.stdout.write(chalk.gray('.'));\n }\n }\n }\n\n async handleResponseComplete(requestId: string): Promise<void> {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n // Flush any remaining data\n const remainingEvents = active.parser.flush();\n for (const event of remainingEvents) {\n active.request.sseEvents.push(event);\n this.wsServer.broadcast({\n type: 'response_chunk',\n requestId,\n event,\n });\n }\n\n // Reconstruct full response\n const response = reconstructResponseFromEvents(active.request.sseEvents);\n const timestamp = Date.now();\n const durationMs = timestamp - active.request.timestamp;\n\n active.request.response = response || undefined;\n active.request.durationMs = durationMs;\n\n if (response) {\n this.wsServer.broadcast({\n type: 'response_complete',\n requestId,\n timestamp,\n response,\n durationMs,\n });\n\n // Log completion\n console.log(); // New line after streaming dots\n console.log(\n chalk.green('✓'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n `${response.usage.input_tokens} in / ${response.usage.output_tokens} out`,\n chalk.gray(`(${durationMs}ms)`),\n response.stop_reason === 'tool_use' ? chalk.yellow('→ tool_use') : ''\n );\n }\n\n // Cleanup\n this.activeRequests.delete(requestId);\n }\n\n handleResponseError(requestId: string, error: Error): void {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n active.request.error = error.message;\n\n this.wsServer.broadcast({\n type: 'error',\n requestId,\n error: error.message,\n timestamp: Date.now(),\n });\n\n console.log(\n chalk.red('✗'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n error.message\n );\n\n this.activeRequests.delete(requestId);\n }\n\n handleNonStreamingResponse(\n requestId: string,\n _statusCode: number,\n bodyText: string\n ): void {\n const active = this.activeRequests.get(requestId);\n if (!active) {\n return;\n }\n\n try {\n if (bodyText) {\n const claudeResponse = JSON.parse(bodyText) as ClaudeResponse;\n const timestamp = Date.now();\n const durationMs = timestamp - active.request.timestamp;\n\n active.request.response = claudeResponse;\n active.request.durationMs = durationMs;\n\n this.wsServer.broadcast({\n type: 'response_complete',\n requestId,\n timestamp,\n response: claudeResponse,\n durationMs,\n });\n\n if (claudeResponse.type === 'message') {\n console.log(\n chalk.green('✓'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n `${claudeResponse.usage.input_tokens} in / ${claudeResponse.usage.output_tokens} out`,\n chalk.gray(`(${durationMs}ms)`),\n claudeResponse.stop_reason === 'tool_use' ? chalk.yellow('→ tool_use') : ''\n );\n } else if (claudeResponse.type === 'error') {\n console.log(\n chalk.yellow('⚠'),\n chalk.white(`[${requestId.slice(0, 8)}]`),\n chalk.red(claudeResponse.error.message),\n chalk.gray(`(${durationMs}ms)`)\n );\n }\n }\n } catch (error) {\n console.error(chalk.yellow('⚠'), 'Failed to parse response body:', error);\n }\n\n this.activeRequests.delete(requestId);\n }\n\n private headersToRecord(headers: Record<string, string | string[] | undefined>): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [key, value] of Object.entries(headers)) {\n if (value !== undefined) {\n result[key] = Array.isArray(value) ? value.join(', ') : value;\n }\n }\n return result;\n }\n\n getActiveRequestCount(): number {\n return this.activeRequests.size;\n }\n}\n","import type {\n SSEEvent,\n ClaudeMessageResponse,\n ClaudeContent,\n TextContent,\n ToolUseContent,\n TokenUsage,\n ContentBlockStartEvent,\n ContentBlockDeltaEvent,\n MessageStartEvent,\n MessageDeltaEvent,\n} from './types.js';\n\n/**\n * Parses a raw SSE data string into an SSEEvent\n */\nexport function parseSSELine(line: string): SSEEvent | null {\n if (!line.startsWith('data: ')) {\n return null;\n }\n\n const jsonStr = line.slice(6).trim();\n if (!jsonStr || jsonStr === '[DONE]') {\n return null;\n }\n\n try {\n return JSON.parse(jsonStr) as SSEEvent;\n } catch {\n return null;\n }\n}\n\n/**\n * Parses a complete SSE stream chunk (may contain multiple events)\n */\nexport function parseSSEChunk(chunk: string): SSEEvent[] {\n const events: SSEEvent[] = [];\n const lines = chunk.split('\\n');\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data: ')) {\n const event = parseSSELine(trimmed);\n if (event) {\n events.push(event);\n }\n }\n }\n\n return events;\n}\n\n/**\n * SSE Stream Parser class for handling streaming data\n */\nexport class SSEStreamParser {\n private buffer = '';\n private events: SSEEvent[] = [];\n\n /**\n * Feed data to the parser\n */\n feed(data: string): SSEEvent[] {\n this.buffer += data;\n const newEvents: SSEEvent[] = [];\n\n // Split on double newlines (SSE event separator)\n const parts = this.buffer.split('\\n\\n');\n\n // Keep the last part in the buffer (might be incomplete)\n this.buffer = parts.pop() || '';\n\n for (const part of parts) {\n const lines = part.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.startsWith('data: ')) {\n const event = parseSSELine(trimmed);\n if (event) {\n newEvents.push(event);\n this.events.push(event);\n }\n }\n }\n }\n\n return newEvents;\n }\n\n /**\n * Flush any remaining buffered data\n */\n flush(): SSEEvent[] {\n if (!this.buffer.trim()) {\n return [];\n }\n\n const events = parseSSEChunk(this.buffer);\n this.events.push(...events);\n this.buffer = '';\n return events;\n }\n\n /**\n * Get all parsed events\n */\n getAllEvents(): SSEEvent[] {\n return [...this.events];\n }\n\n /**\n * Reset the parser\n */\n reset(): void {\n this.buffer = '';\n this.events = [];\n }\n}\n\n/**\n * Reconstructs a complete ClaudeMessageResponse from SSE events.\n * Streaming responses are always message responses (errors are non-streaming).\n */\nexport function reconstructResponseFromEvents(events: SSEEvent[]): ClaudeMessageResponse | null {\n let messageStart: MessageStartEvent | null = null;\n let messageDelta: MessageDeltaEvent | null = null;\n const contentBlocks: Map<number, { type: string; content: Partial<ClaudeContent> }> = new Map();\n const textDeltas: Map<number, string[]> = new Map();\n const jsonDeltas: Map<number, string[]> = new Map();\n\n for (const event of events) {\n switch (event.type) {\n case 'message_start':\n messageStart = event;\n break;\n\n case 'content_block_start': {\n const startEvent = event as ContentBlockStartEvent;\n contentBlocks.set(startEvent.index, {\n type: startEvent.content_block.type,\n content: { ...startEvent.content_block },\n });\n if (startEvent.content_block.type === 'text') {\n textDeltas.set(startEvent.index, []);\n } else if (startEvent.content_block.type === 'tool_use') {\n jsonDeltas.set(startEvent.index, []);\n }\n break;\n }\n\n case 'content_block_delta': {\n const deltaEvent = event as ContentBlockDeltaEvent;\n if (deltaEvent.delta.type === 'text_delta') {\n const deltas = textDeltas.get(deltaEvent.index) || [];\n deltas.push(deltaEvent.delta.text);\n textDeltas.set(deltaEvent.index, deltas);\n } else if (deltaEvent.delta.type === 'input_json_delta') {\n const deltas = jsonDeltas.get(deltaEvent.index) || [];\n deltas.push(deltaEvent.delta.partial_json);\n jsonDeltas.set(deltaEvent.index, deltas);\n }\n break;\n }\n\n case 'message_delta':\n messageDelta = event;\n break;\n }\n }\n\n if (!messageStart) {\n return null;\n }\n\n // Build content array\n const content: ClaudeContent[] = [];\n const sortedIndices = Array.from(contentBlocks.keys()).sort((a, b) => a - b);\n\n for (const index of sortedIndices) {\n const block = contentBlocks.get(index)!;\n\n if (block.type === 'text') {\n const text = (textDeltas.get(index) || []).join('');\n content.push({\n type: 'text',\n text,\n } as TextContent);\n } else if (block.type === 'tool_use') {\n const jsonStr = (jsonDeltas.get(index) || []).join('');\n let input: Record<string, unknown> = {};\n try {\n input = jsonStr ? JSON.parse(jsonStr) : {};\n } catch {\n // Keep empty object if parsing fails\n }\n content.push({\n type: 'tool_use',\n id: (block.content as ToolUseContent).id || '',\n name: (block.content as ToolUseContent).name || '',\n input,\n } as ToolUseContent);\n }\n }\n\n // Calculate total usage\n const usage: TokenUsage = {\n input_tokens: messageStart.message.usage.input_tokens,\n output_tokens: messageDelta?.usage.output_tokens || messageStart.message.usage.output_tokens,\n cache_creation_input_tokens: messageStart.message.usage.cache_creation_input_tokens,\n cache_read_input_tokens: messageStart.message.usage.cache_read_input_tokens,\n };\n\n return {\n id: messageStart.message.id,\n type: 'message',\n role: 'assistant',\n content,\n model: messageStart.message.model,\n stop_reason: messageDelta?.delta.stop_reason || null,\n stop_sequence: messageDelta?.delta.stop_sequence || null,\n usage,\n };\n}\n\n/**\n * Extracts text content from SSE events (useful for live preview)\n */\nexport function extractTextFromEvents(events: SSEEvent[]): string {\n const textParts: string[] = [];\n\n for (const event of events) {\n if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {\n textParts.push(event.delta.text);\n }\n }\n\n return textParts.join('');\n}\n\n/**\n * Extracts tool calls from SSE events\n */\nexport function extractToolCallsFromEvents(events: SSEEvent[]): ToolUseContent[] {\n const tools: Map<number, { id: string; name: string; jsonParts: string[] }> = new Map();\n\n for (const event of events) {\n if (event.type === 'content_block_start' && event.content_block.type === 'tool_use') {\n tools.set(event.index, {\n id: event.content_block.id,\n name: event.content_block.name,\n jsonParts: [],\n });\n } else if (\n event.type === 'content_block_delta' &&\n event.delta.type === 'input_json_delta'\n ) {\n const tool = tools.get(event.index);\n if (tool) {\n tool.jsonParts.push(event.delta.partial_json);\n }\n }\n }\n\n return Array.from(tools.values()).map((tool) => {\n let input: Record<string, unknown> = {};\n try {\n const jsonStr = tool.jsonParts.join('');\n input = jsonStr ? JSON.parse(jsonStr) : {};\n } catch {\n // Keep empty object\n }\n return {\n type: 'tool_use' as const,\n id: tool.id,\n name: tool.name,\n input,\n };\n });\n}\n","import { WebSocketServer, WebSocket } from 'ws';\nimport type { Server } from 'http';\nimport type { WSMessage, InterceptedRequest } from './types.js';\nimport chalk from 'chalk';\n\nexport interface WiretapWebSocketServerOptions {\n port?: number;\n server?: Server;\n}\n\nexport class WiretapWebSocketServer {\n private wss: WebSocketServer;\n private clients: Set<WebSocket> = new Set();\n private requests: Map<string, InterceptedRequest> = new Map();\n\n constructor(options: WiretapWebSocketServerOptions = {}) {\n if (options.server) {\n this.wss = new WebSocketServer({ server: options.server });\n } else {\n this.wss = new WebSocketServer({ port: options.port || 8081 });\n }\n\n this.wss.on('connection', (ws, req) => {\n const clientIp = req.socket.remoteAddress || 'unknown';\n console.log(chalk.blue('⬤'), `UI client connected from ${clientIp}`);\n this.clients.add(ws);\n\n // Send current state to new client\n this.sendCurrentState(ws);\n\n ws.on('message', (data) => {\n try {\n const message = JSON.parse(data.toString());\n if (message.type === 'clear_all') {\n console.log(chalk.yellow('⟲'), 'Clearing all requests');\n this.requests.clear();\n this.broadcast({ type: 'clear_all' });\n }\n } catch (error) {\n console.error(chalk.red('✗'), `Failed to parse client message: ${error}`);\n }\n });\n\n ws.on('close', () => {\n console.log(chalk.gray('○'), `UI client disconnected from ${clientIp}`);\n this.clients.delete(ws);\n });\n\n ws.on('error', (error) => {\n console.error(chalk.red('✗'), `WebSocket error: ${error.message}`);\n this.clients.delete(ws);\n });\n });\n\n this.wss.on('error', (error) => {\n console.error(chalk.red('✗'), `WebSocket server error: ${error.message}`);\n });\n }\n\n private sendCurrentState(ws: WebSocket): void {\n // Send all existing requests in a single message for fast initial load\n if (this.requests.size > 0) {\n this.sendToClient(ws, {\n type: 'history_sync',\n requests: Array.from(this.requests.values()),\n });\n }\n }\n\n private sendToClient(ws: WebSocket, message: WSMessage): void {\n if (ws.readyState === WebSocket.OPEN) {\n ws.send(JSON.stringify(message));\n }\n }\n\n broadcast(message: WSMessage): void {\n const data = JSON.stringify(message);\n for (const client of this.clients) {\n if (client.readyState === WebSocket.OPEN) {\n client.send(data);\n }\n }\n }\n\n // Request management\n\n addRequest(request: InterceptedRequest): void {\n this.requests.set(request.id, request);\n }\n\n getRequest(requestId: string): InterceptedRequest | undefined {\n return this.requests.get(requestId);\n }\n\n // Stats\n\n getClientCount(): number {\n return this.clients.size;\n }\n\n getRequestCount(): number {\n return this.requests.size;\n }\n\n // Lifecycle\n\n close(): Promise<void> {\n return new Promise((resolve, reject) => {\n for (const client of this.clients) {\n client.close();\n }\n this.clients.clear();\n\n this.wss.close((err) => {\n if (err) {\n reject(err);\n } else {\n resolve();\n }\n });\n });\n }\n\n getPort(): number | undefined {\n const address = this.wss.address();\n if (address && typeof address === 'object') {\n return address.port;\n }\n return undefined;\n }\n}\n","import { createServer, type Server } from 'http';\nimport { getCAPath } from './ca.js';\nimport chalk from 'chalk';\n\nconst SETUP_PORT = 8082;\n\nfunction generateSetupScript(proxyPort: number): string {\n const caPath = getCAPath();\n\n return `#!/bin/bash\n# CC Wiretap - Terminal Setup Script\n# This script configures your terminal session to route traffic through the proxy\n\n# Proxy settings (for most HTTP clients)\nexport HTTP_PROXY=\"http://localhost:${proxyPort}\"\nexport HTTPS_PROXY=\"http://localhost:${proxyPort}\"\nexport http_proxy=\"http://localhost:${proxyPort}\"\nexport https_proxy=\"http://localhost:${proxyPort}\"\n\n# Node.js CA certificate\nexport NODE_EXTRA_CA_CERTS=\"${caPath}\"\n\n# Python/OpenSSL CA certificates\nexport SSL_CERT_FILE=\"${caPath}\"\nexport REQUESTS_CA_BUNDLE=\"${caPath}\"\n\n# curl CA certificate\nexport CURL_CA_BUNDLE=\"${caPath}\"\n\n# Ruby CA certificate\nexport SSL_CERT_DIR=\"\"\n\n# Git CA certificate (for HTTPS remotes)\nexport GIT_SSL_CAINFO=\"${caPath}\"\n\n# AWS CLI\nexport AWS_CA_BUNDLE=\"${caPath}\"\n\n# Disable proxy for localhost (prevents loops)\nexport NO_PROXY=\"localhost,127.0.0.1,::1\"\nexport no_proxy=\"localhost,127.0.0.1,::1\"\n\n# Visual indicator that proxy is active\nexport WIRETAP_ACTIVE=\"1\"\n\n# Update PS1 to show proxy is active (optional - uncomment if desired)\n# export PS1=\"[wiretap] $PS1\"\n\necho \"\"\necho \" ✓ CC Wiretap proxy configured for this terminal\"\necho \"\"\necho \" Proxy: http://localhost:${proxyPort}\"\necho \" CA: ${caPath}\"\necho \"\"\necho \" All HTTP/HTTPS traffic from this terminal will be intercepted.\"\necho \" Run 'unset-wiretap' to disable.\"\necho \"\"\n\n# Create unset function\nunset-wiretap() {\n unset HTTP_PROXY HTTPS_PROXY http_proxy https_proxy\n unset NODE_EXTRA_CA_CERTS SSL_CERT_FILE REQUESTS_CA_BUNDLE\n unset CURL_CA_BUNDLE SSL_CERT_DIR GIT_SSL_CAINFO AWS_CA_BUNDLE\n unset NO_PROXY no_proxy WIRETAP_ACTIVE\n echo \"✓ Wiretap proxy disabled for this terminal\"\n}\nexport -f unset-wiretap 2>/dev/null || true\n`;\n}\n\nfunction generateFishScript(proxyPort: number): string {\n const caPath = getCAPath();\n\n return `# CC Wiretap - Fish Shell Setup Script\n\nset -gx HTTP_PROXY \"http://localhost:${proxyPort}\"\nset -gx HTTPS_PROXY \"http://localhost:${proxyPort}\"\nset -gx http_proxy \"http://localhost:${proxyPort}\"\nset -gx https_proxy \"http://localhost:${proxyPort}\"\nset -gx NODE_EXTRA_CA_CERTS \"${caPath}\"\nset -gx SSL_CERT_FILE \"${caPath}\"\nset -gx REQUESTS_CA_BUNDLE \"${caPath}\"\nset -gx CURL_CA_BUNDLE \"${caPath}\"\nset -gx GIT_SSL_CAINFO \"${caPath}\"\nset -gx AWS_CA_BUNDLE \"${caPath}\"\nset -gx NO_PROXY \"localhost,127.0.0.1,::1\"\nset -gx no_proxy \"localhost,127.0.0.1,::1\"\nset -gx WIRETAP_ACTIVE \"1\"\n\necho \"\"\necho \" ✓ CC Wiretap proxy configured for this terminal\"\necho \"\"\necho \" Proxy: http://localhost:${proxyPort}\"\necho \" CA: ${caPath}\"\necho \"\"\n\nfunction unset-wiretap\n set -e HTTP_PROXY HTTPS_PROXY http_proxy https_proxy\n set -e NODE_EXTRA_CA_CERTS SSL_CERT_FILE REQUESTS_CA_BUNDLE\n set -e CURL_CA_BUNDLE GIT_SSL_CAINFO AWS_CA_BUNDLE\n set -e NO_PROXY no_proxy WIRETAP_ACTIVE\n echo \"✓ Wiretap proxy disabled\"\nend\n`;\n}\n\nexport function createSetupServer(proxyPort: number): Server {\n const server = createServer((req, res) => {\n const url = new URL(req.url || '/', `http://localhost:${SETUP_PORT}`);\n\n // CORS headers for browser access\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET');\n\n if (url.pathname === '/' || url.pathname === '/setup') {\n // Detect shell from query param or User-Agent\n const shell = url.searchParams.get('shell') || 'bash';\n\n res.setHeader('Content-Type', 'text/plain; charset=utf-8');\n\n if (shell === 'fish') {\n res.end(generateFishScript(proxyPort));\n } else {\n res.end(generateSetupScript(proxyPort));\n }\n } else if (url.pathname === '/status') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({\n active: true,\n proxyPort,\n caPath: getCAPath(),\n }));\n } else {\n res.statusCode = 404;\n res.end('Not found');\n }\n });\n\n server.listen(SETUP_PORT, () => {\n console.log(chalk.green('✓'), `Setup server started on port ${chalk.cyan(SETUP_PORT)}`);\n });\n\n return server;\n}\n\nexport function getSetupCommand(): string {\n return `eval \"$(curl -s http://localhost:${SETUP_PORT}/setup)\"`;\n}\n\nexport function getSetupPort(): number {\n return SETUP_PORT;\n}\n","import { createServer, type Server, type IncomingMessage, type ServerResponse } from 'http';\nimport { createReadStream, existsSync, statSync } from 'fs';\nimport { join, extname } from 'path';\nimport { fileURLToPath } from 'url';\nimport chalk from 'chalk';\n\nconst __dirname = fileURLToPath(new URL('.', import.meta.url));\n\nconst MIME_TYPES: Record<string, string> = {\n '.html': 'text/html; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject',\n};\n\nfunction getUIDistPath(): string {\n // In production build, UI is at dist/ui relative to this file\n // After tsup build, this file is at dist/index.js, so ui is at dist/ui\n return join(__dirname, 'ui');\n}\n\nfunction serveFile(res: ServerResponse, filePath: string): void {\n const ext = extname(filePath).toLowerCase();\n const contentType = MIME_TYPES[ext] || 'application/octet-stream';\n\n res.setHeader('Content-Type', contentType);\n res.setHeader('Cache-Control', 'public, max-age=31536000, immutable');\n\n const stream = createReadStream(filePath);\n stream.pipe(res);\n stream.on('error', () => {\n res.statusCode = 500;\n res.end('Internal Server Error');\n });\n}\n\nfunction handleRequest(req: IncomingMessage, res: ServerResponse, uiPath: string): void {\n const url = new URL(req.url || '/', 'http://localhost');\n let pathname = url.pathname;\n\n // Remove leading slash and decode\n let relativePath = decodeURIComponent(pathname.slice(1));\n\n // Default to index.html\n if (relativePath === '' || relativePath === '/') {\n relativePath = 'index.html';\n }\n\n const filePath = join(uiPath, relativePath);\n\n // Security: prevent directory traversal\n if (!filePath.startsWith(uiPath)) {\n res.statusCode = 403;\n res.end('Forbidden');\n return;\n }\n\n // Check if file exists\n if (existsSync(filePath) && statSync(filePath).isFile()) {\n serveFile(res, filePath);\n return;\n }\n\n // For SPA routing: serve index.html for non-file requests\n const indexPath = join(uiPath, 'index.html');\n if (existsSync(indexPath)) {\n res.setHeader('Content-Type', 'text/html; charset=utf-8');\n res.setHeader('Cache-Control', 'no-cache');\n createReadStream(indexPath).pipe(res);\n return;\n }\n\n res.statusCode = 404;\n res.end('Not Found');\n}\n\nexport interface UIServerOptions {\n port: number;\n}\n\nexport function createUIServer(options: UIServerOptions): Server | null {\n const { port } = options;\n const uiPath = getUIDistPath();\n\n // Check if UI is bundled\n if (!existsSync(uiPath) || !existsSync(join(uiPath, 'index.html'))) {\n console.log(chalk.yellow('!'), 'UI not bundled. Run in dev mode or build first.');\n return null;\n }\n\n const server = createServer((req, res) => {\n // CORS headers\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET');\n\n handleRequest(req, res, uiPath);\n });\n\n server.listen(port, () => {\n console.log(chalk.green('✓'), `UI server started on port ${chalk.cyan(port)}`);\n });\n\n return server;\n}\n\nexport function getUIPath(): string {\n return getUIDistPath();\n}\n"],"mappings":"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","names":["chalk","cert","key","chalk","chalk","chalk","chalk","chalk","chalk","createServer","join","chalk","__dirname","chalk"]}
|