@tumnel/codex 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/cli.js +181 -24
- package/dist/cli.js.map +1 -1
- package/dist/index.js +161 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/codex-adapter.ts","../src/codex-sessions.ts","../src/safe-json.ts","../../protocol/src/index.ts","../src/identity.ts","../src/client.ts","../src/config.ts","../src/local-server.ts","../src/cli.ts"],"sourcesContent":["import { Codex } from '@openai/codex-sdk'\nimport { createCodexAdapter, type CodexAdapterOptions } from './codex-adapter.js'\nimport { CodexSessionStore } from './codex-sessions.js'\nimport { TumnelBridgeClient } from './client.js'\nimport { resolveConfig, type TumnelCodexConfig } from './config.js'\nimport { loadOrCreateIdentity } from './identity.js'\nimport { startPairingServer } from './local-server.js'\n\nexport type CodexConnectorOptions = {\n config?: Record<string, unknown>\n environment?: NodeJS.ProcessEnv\n codex?: Codex\n sessionsDir?: string\n log?: CodexAdapterOptions['log']\n}\n\nexport type CodexConnector = {\n bridge: TumnelBridgeClient\n pairingServer: Awaited<ReturnType<typeof startPairingServer>>\n stop: () => Promise<void>\n}\n\nexport async function createCodexConnector(options: CodexConnectorOptions = {}): Promise<CodexConnector> {\n const config = resolveConfig(options.config, options.environment)\n const identity = await loadOrCreateIdentity(config.identityPath)\n const codex = options.codex ?? new Codex()\n const sessions = new CodexSessionStore(options.sessionsDir)\n const adapter = createCodexAdapter({ codex, config, sessions, log: options.log })\n const bridge = new TumnelBridgeClient({\n relayUrl: config.relayUrl,\n identity,\n adapter,\n })\n const pairingServer = await startPairingServer({\n identity,\n port: config.localPort,\n relayUrl: config.relayUrl,\n appOrigins: config.appOrigins,\n log: (level, message, fields) => adapter.log(level, message, fields),\n })\n\n bridge.start()\n\n return {\n bridge,\n pairingServer,\n stop: async () => {\n await bridge.stop()\n await pairingServer?.stop()\n },\n }\n}\n\nexport { createCodexAdapter, resolveConfig, CodexSessionStore, TumnelBridgeClient }\nexport type { TumnelCodexConfig }\nexport type { ConnectorAdapter, ConnectorLogLevel } from './connector-adapter.js'\nexport type { DeviceIdentity } from './identity.js'","import type { Codex, Input, Thread, ThreadEvent, ThreadItem } from '@openai/codex-sdk'\nimport type { BridgeMethod, JsonValue } from '@openbridge/protocol'\nimport { z } from 'zod'\nimport {\n createMessageId,\n createSessionId,\n projectId,\n type CodexSessionRecord,\n type CodexSessionStore,\n type DiscoveredSession,\n type MessagePart,\n type MessageRecord,\n} from './codex-sessions.js'\nimport type { TumnelCodexConfig } from './config.js'\nimport type { ConnectorAdapter, ConnectorLogLevel } from './connector-adapter.js'\nimport { toSafeJson } from './safe-json.js'\n\nconst directorySchema = z.string().min(1).max(4096).optional()\nconst emptyParamsSchema = z.object({}).strict()\n// OpenCode uses an empty directory to explicitly request the global catalog.\n// Keep that meaning for Codex instead of rejecting the request at the adapter boundary.\nconst projectListSchema = z.object({ directory: z.string().max(4096).optional() }).strict()\nconst sessionListSchema = z.object({ directory: directorySchema }).strict()\nconst sessionCreateSchema = z\n .object({\n directory: directorySchema,\n parentID: z.string().min(1).max(256).optional(),\n title: z.string().min(1).max(512).optional(),\n })\n .strict()\nconst sessionForkSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n messageID: z.string().min(1).max(256).optional(),\n title: z.string().min(1).max(512).optional(),\n })\n .strict()\nconst sessionDeleteSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n })\n .strict()\nconst sessionStatusSchema = z.object({ directory: directorySchema }).strict()\nconst sessionMessagesSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n limit: z.number().int().positive().max(1000).optional(),\n })\n .strict()\nconst textPartSchema = z\n .object({\n type: z.literal('text'),\n text: z.string().max(1_000_000),\n })\n .strict()\nconst filePartSchema = z\n .object({\n type: z.literal('file'),\n mime: z.string().min(1).max(256),\n filename: z.string().min(1).max(1024).optional(),\n url: z.string().min(1).max(8_000_000),\n })\n .strict()\nconst sessionPromptSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n messageID: z.string().min(1).max(256).optional(),\n model: z\n .object({\n providerID: z.string().min(1).max(128),\n modelID: z.string().min(1).max(256),\n })\n .strict()\n .optional(),\n agent: z.string().min(1).max(128).optional(),\n variant: z.string().min(1).max(128).optional(),\n noReply: z.boolean().optional(),\n system: z.string().max(100_000).optional(),\n tools: z.record(z.string().min(1).max(128), z.boolean()).optional(),\n parts: z.array(z.union([textPartSchema, filePartSchema])).min(1).max(100),\n })\n .strict()\nconst sessionAbortSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n })\n .strict()\nconst permissionReplySchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n permissionId: z.string().min(1).max(256),\n directory: directorySchema,\n response: z.enum(['once', 'always', 'reject']),\n })\n .strict()\nconst providerListSchema = z.object({ directory: directorySchema }).strict()\nconst agentListSchema = z.object({ directory: directorySchema }).strict()\nconst permissionListSchema = z\n .object({\n directory: directorySchema,\n sessionId: z.string().min(1).max(256).optional(),\n })\n .strict()\nconst questionListSchema = z\n .object({\n directory: directorySchema,\n sessionId: z.string().min(1).max(256).optional(),\n })\n .strict()\nconst questionReplySchema = z\n .object({\n requestId: z.string().min(1).max(256),\n directory: directorySchema,\n answers: z\n .array(z.array(z.string().trim().min(1).max(8_000)).min(1).max(32))\n .min(1)\n .max(32),\n })\n .strict()\nconst questionRejectSchema = z\n .object({\n requestId: z.string().min(1).max(256),\n directory: directorySchema,\n })\n .strict()\n\ntype PromptPart = z.infer<typeof textPartSchema> | z.infer<typeof filePartSchema>\nexport type { PromptPart }\n\ntype AdapterEvent = {\n directory: string\n payload: { type: string; properties: Record<string, unknown> }\n}\n\nclass EventBus {\n private readonly queue: AdapterEvent[] = []\n private wake: (() => void) | null = null\n\n push(event: AdapterEvent): void {\n this.queue.push(event)\n this.wake?.()\n this.wake = null\n }\n\n async *stream(signal: AbortSignal): AsyncIterable<JsonValue> {\n while (!signal.aborted) {\n const next = this.queue.shift()\n if (next !== undefined) {\n yield toSafeJson(next)\n continue\n }\n await new Promise<void>((resolve) => {\n const done = () => {\n signal.removeEventListener('abort', done)\n this.wake = null\n resolve()\n }\n signal.addEventListener('abort', done, { once: true })\n this.wake = done\n })\n }\n }\n}\n\nfunction errorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : 'Codex request failed'\n return message.slice(0, 512)\n}\n\nexport function sessionView(record: CodexSessionRecord): Record<string, unknown> {\n return {\n id: record.id,\n projectID: record.projectID,\n directory: record.directory,\n title: record.title,\n version: record.version,\n time: { created: record.created, updated: record.updated },\n }\n}\n\nexport function discoveredSessionView(session: DiscoveredSession): Record<string, unknown> {\n return {\n id: session.id,\n projectID: projectId(session.directory),\n directory: session.directory,\n title: session.title,\n version: session.version,\n time: { created: session.created, updated: session.updated },\n }\n}\n\nexport function buildUserMessage(\n record: CodexSessionRecord,\n parts: PromptPart[],\n now = Date.now(),\n): MessageRecord {\n const info = {\n id: createMessageId(record),\n sessionID: record.id,\n role: 'user' as const,\n time: { created: now },\n }\n const messageParts: MessagePart[] = []\n for (const [index, part] of parts.entries()) {\n if (part.type === 'text') {\n messageParts.push({\n id: `${info.id}_${index}`,\n sessionID: record.id,\n messageID: info.id,\n type: 'text',\n text: part.text,\n })\n } else {\n const file: MessagePart = {\n id: `${info.id}_${index}`,\n sessionID: record.id,\n messageID: info.id,\n type: 'file',\n mime: part.mime,\n url: part.url,\n }\n if (part.filename) file.filename = part.filename\n messageParts.push(file)\n }\n }\n return { info, parts: messageParts }\n}\n\nexport function createAssistantMessage(\n record: CodexSessionRecord,\n now = Date.now(),\n): MessageRecord {\n const info = {\n id: createMessageId(record),\n sessionID: record.id,\n role: 'assistant' as const,\n time: { created: now },\n }\n return { info, parts: [] }\n}\n\nfunction activeAssistantMessage(record: CodexSessionRecord): MessageRecord | null {\n const last = record.messages[record.messages.length - 1]\n return last && last.info.role === 'assistant' ? last : null\n}\n\nfunction upsertStreamedPart(\n message: MessageRecord,\n part: MessagePart,\n lifecycle: 'started' | 'updated' | 'completed',\n now = Date.now(),\n): MessagePart {\n const index = message.parts.findIndex((existing) => existing.id === part.id)\n const existing = index === -1 ? undefined : message.parts[index]\n\n // The Codex SDK emits complete item snapshots, not text deltas. Preserve one\n // canonical part per item id and mark reasoning completion explicitly so the\n // UI does not leave an old \"Thinking\" block in a streaming state.\n if (part.type === 'reasoning') {\n const previousTime = existing?.time && typeof existing.time === 'object'\n ? existing.time as Record<string, unknown>\n : null\n const started = typeof previousTime?.start === 'number' ? previousTime.start : now\n part.time = lifecycle === 'completed'\n ? { start: started, end: now }\n : { start: started }\n }\n\n if (index === -1) message.parts.push(part)\n else message.parts[index] = part\n return part\n}\n\nexport function itemPart(record: CodexSessionRecord, item: ThreadItem): MessagePart | null {\n const message = activeAssistantMessage(record)\n if (!message) return null\n\n const base = {\n id: item.id,\n sessionID: record.id,\n messageID: message.info.id,\n }\n\n switch (item.type) {\n case 'agent_message':\n return { ...base, type: 'text', text: item.text }\n case 'reasoning':\n return { ...base, type: 'reasoning', text: item.text }\n case 'command_execution':\n return {\n ...base,\n type: 'tool',\n tool: 'bash',\n state: {\n status: item.status === 'in_progress' ? 'running'\n : item.status === 'failed' ? 'error'\n : 'completed',\n title: item.command.slice(0, 512),\n input: { command: item.command },\n ...(item.aggregated_output ? { output: item.aggregated_output } : {}),\n },\n }\n case 'file_change':\n return {\n ...base,\n type: 'tool',\n tool: 'edit',\n state: {\n status: item.status === 'failed' ? 'error' : 'completed',\n title: item.changes.length === 1\n ? `Edited ${item.changes[0].path}`\n : `Edited ${item.changes.length} files`,\n input: { changes: item.changes },\n },\n }\n case 'mcp_tool_call':\n return {\n ...base,\n type: 'tool',\n tool: item.tool,\n state: {\n status: item.status === 'in_progress' ? 'running'\n : item.status === 'failed' ? 'error'\n : 'completed',\n title: `${item.server}:${item.tool}`,\n input: { arguments: item.arguments },\n ...(item.error ? { error: item.error.message } : {}),\n },\n }\n case 'web_search':\n return {\n ...base,\n type: 'tool',\n tool: 'web_search',\n state: {\n status: 'completed',\n title: 'Web search',\n input: { query: item.query },\n },\n }\n case 'todo_list': {\n const completed = item.items.filter((todo) => todo.completed).length\n return {\n ...base,\n type: 'tool',\n tool: 'todo_list',\n state: {\n status: completed === item.items.length\n ? 'completed'\n : 'running',\n title: item.items.length > 0\n ? `Tasks ${completed}/${item.items.length}`\n : 'Tasks',\n input: { items: item.items },\n },\n }\n }\n case 'error':\n return {\n ...base,\n type: 'tool',\n tool: 'codex_error',\n state: {\n status: 'error',\n title: 'Codex error',\n input: {},\n error: item.message,\n },\n }\n }\n}\n\nexport function toUserInput(parts: PromptPart[]): Input {\n const input: Input = []\n for (const part of parts) {\n if (part.type === 'text' && typeof part.text === 'string' && part.text.length) {\n input.push({ type: 'text', text: part.text })\n } else if (part.type === 'file' && typeof part.url === 'string') {\n const path = part.url.replace(/^file:\\/\\//, '')\n if (path) input.push({ type: 'local_image', path })\n }\n }\n return input\n}\n\nexport type CodexAdapterOptions = {\n codex: Codex\n config: TumnelCodexConfig\n sessions: CodexSessionStore\n log?: (level: ConnectorLogLevel, message: string, extra?: Record<string, JsonValue>) => Promise<void> | void\n}\n\nfunction threadOptions(config: TumnelCodexConfig, directory: string, model?: string) {\n return {\n workingDirectory: directory,\n model: model ?? config.model,\n sandboxMode: config.sandboxMode,\n approvalPolicy: config.approvalPolicy,\n modelReasoningEffort: config.modelReasoningEffort,\n webSearchMode: config.webSearchMode,\n skipGitRepoCheck: config.skipGitRepoCheck,\n networkAccessEnabled: config.networkAccess,\n }\n}\n\nfunction ensureThread(\n codex: Codex,\n record: CodexSessionRecord,\n config: TumnelCodexConfig,\n model?: string,\n): Thread {\n const selectedModel = model ?? record.model ?? config.model\n if (record.thread && record.model === selectedModel) return record.thread\n record.model = selectedModel\n if (record.codexThreadId) {\n record.thread = codex.resumeThread(\n record.codexThreadId,\n threadOptions(config, record.directory, selectedModel),\n )\n } else {\n record.thread = codex.startThread(threadOptions(config, record.directory, selectedModel))\n }\n return record.thread\n}\n\nexport function createCodexAdapter(options: CodexAdapterOptions): ConnectorAdapter {\n const { codex, config, sessions } = options\n const bus = new EventBus()\n const log: NonNullable<CodexAdapterOptions['log']> = options.log ?? (async () => undefined)\n const controllers = new WeakMap<CodexSessionRecord, AbortController>()\n\n const emit = (\n type: string,\n directory: string,\n properties: Record<string, unknown>,\n ): void => {\n bus.push({ directory, payload: { type, properties } })\n }\n\n const finishRun = (record: CodexSessionRecord, controller: AbortController): void => {\n controllers.delete(record)\n record.busy = false\n record.updated = Date.now()\n emit('session.updated', record.directory, { info: sessionView(record) })\n if (!record.failed) {\n emit('session.status', record.directory, { sessionID: record.id, status: { type: 'idle' } })\n }\n emit('session.idle', record.directory, { sessionID: record.id })\n void log('info', 'Codex turn finished', { sessionId: record.id })\n }\n\n const handleThreadEvent = (record: CodexSessionRecord, event: ThreadEvent): void => {\n switch (event.type) {\n case 'thread.started':\n record.codexThreadId = event.thread_id\n return\n case 'turn.completed': {\n const message = activeAssistantMessage(record)\n if (message) {\n message.info.time.completed = Date.now()\n emit('message.updated', record.directory, { info: message.info })\n }\n void log('info', 'Codex turn completed', {\n sessionId: record.id,\n inputTokens: event.usage.input_tokens,\n outputTokens: event.usage.output_tokens,\n })\n return\n }\n case 'turn.failed':\n record.failed = true\n emit('session.error', record.directory, { sessionID: record.id, message: event.error.message })\n return\n case 'item.started':\n case 'item.updated':\n case 'item.completed': {\n let message = activeAssistantMessage(record)\n if (!message) {\n message = createAssistantMessage(record)\n record.messages.push(message)\n emit('message.updated', record.directory, { info: message.info })\n }\n const part = itemPart(record, event.item)\n if (!part) return\n const lifecycle = event.type === 'item.started'\n ? 'started'\n : event.type === 'item.updated'\n ? 'updated'\n : 'completed'\n emit('message.part.updated', record.directory, {\n part: upsertStreamedPart(message, part, lifecycle),\n })\n return\n }\n case 'error':\n record.failed = true\n emit('session.error', record.directory, { sessionID: record.id, message: event.message })\n return\n }\n }\n\n const startRun = (record: CodexSessionRecord, input: Input, model?: string): void => {\n if (record.busy) throw new Error('Codex session is already running a turn')\n record.busy = true\n record.failed = false\n const controller = new AbortController()\n controllers.set(record, controller)\n const thread = ensureThread(codex, record, config, model)\n\n emit('session.status', record.directory, { sessionID: record.id, status: { type: 'busy' } })\n void log('info', 'Codex turn started', { sessionId: record.id })\n\n void (async () => {\n try {\n const { events } = await thread.runStreamed(input, { signal: controller.signal })\n for await (const event of events) handleThreadEvent(record, event)\n } catch (error) {\n if (!controller.signal.aborted) {\n record.failed = true\n emit('session.error', record.directory, {\n sessionID: record.id,\n message: errorMessage(error),\n })\n void log('warn', 'Codex turn failed', { sessionId: record.id, reason: errorMessage(error) })\n }\n } finally {\n finishRun(record, controller)\n }\n })()\n }\n\n return {\n async invoke(method, rawParams) {\n switch (method) {\n case 'device.health': {\n emptyParamsSchema.parse(rawParams)\n return {\n healthy: true,\n connector: 'codex',\n version: '0.1.0',\n model: config.model ?? null,\n }\n }\n case 'project.list': {\n const params = projectListSchema.parse(rawParams)\n const directory = params.directory || undefined\n const records = sessions.list(directory)\n const discovered = await sessions.discoverAll(directory)\n const directories = new Map<string, number>()\n for (const record of records) {\n const existing = directories.get(record.directory)\n if (existing === undefined || record.created < existing) {\n directories.set(record.directory, record.created)\n }\n }\n for (const session of discovered) {\n const existing = directories.get(session.directory)\n if (existing === undefined || session.created < existing) {\n directories.set(session.directory, session.created)\n }\n }\n return [...directories.entries()].map(([worktree, created]) => ({\n id: projectId(worktree),\n worktree,\n time: { created },\n }))\n }\n case 'session.list': {\n const params = sessionListSchema.parse(rawParams)\n const discovered = params.directory\n ? await sessions.discover(params.directory)\n : await sessions.discover()\n const views = [\n ...sessions.list(params.directory).map(sessionView),\n ...discovered.map(discoveredSessionView),\n ]\n return views.map(toSafeJson)\n }\n case 'session.create': {\n const params = sessionCreateSchema.parse(rawParams)\n if (!params.directory) throw new Error('session.create requires a directory')\n const record = sessions.create({\n id: createSessionId(),\n directory: params.directory,\n title: params.title,\n version: '0.1.0',\n model: config.model,\n })\n return toSafeJson(sessionView(record))\n }\n case 'session.fork':\n throw new Error('session.fork is not supported by the Codex connector')\n case 'session.delete': {\n const params = sessionDeleteSchema.parse(rawParams)\n const record = sessions.get(params.sessionId)\n if (record) {\n emit('session.deleted', record.directory, { info: sessionView(record) })\n sessions.remove(record.id)\n }\n return true\n }\n case 'session.status': {\n const params = sessionStatusSchema.parse(rawParams)\n const statuses: Record<string, { type: 'idle' | 'busy' | 'error' }> = {}\n for (const record of sessions.list(params.directory)) {\n statuses[record.id] = {\n type: record.busy ? 'busy' : record.failed ? 'error' : 'idle',\n }\n }\n return statuses\n }\n case 'session.messages': {\n const params = sessionMessagesSchema.parse(rawParams)\n const record = sessions.get(params.sessionId)\n if (!record) {\n const history = await sessions.loadHistory(params.sessionId, params.directory)\n if (!history) return []\n const messages = params.limit\n ? history.messages.slice(-params.limit)\n : history.messages\n return toSafeJson(messages)\n }\n const messages = params.limit ? record.messages.slice(-params.limit) : record.messages\n return toSafeJson(messages.map((message) => ({ info: message.info, parts: message.parts })))\n }\n case 'session.prompt': {\n const params = sessionPromptSchema.parse(rawParams)\n const selectedModel = params.model\n ? params.model.providerID === 'codex'\n ? params.model.modelID\n : (() => {\n throw new Error(`Codex does not support provider ${params.model?.providerID}`)\n })()\n : undefined\n let record = sessions.get(params.sessionId)\n if (!record) {\n const discovered = await sessions.discover(params.directory)\n const session = discovered.find((item) => item.id === params.sessionId)\n if (!session) throw new Error(`Unknown Codex session ${params.sessionId}`)\n const history = await sessions.loadHistory(session.id, session.directory)\n record = sessions.create({\n id: params.sessionId,\n directory: session.directory,\n title: history?.title ?? session.title,\n version: session.version,\n codexThreadId: session.id,\n model: selectedModel ?? config.model,\n messages: history?.messages,\n })\n }\n const userMessage = buildUserMessage(record, params.parts)\n record.messages.push(userMessage)\n emit('message.updated', record.directory, { info: userMessage.info })\n startRun(record, toUserInput(params.parts), selectedModel)\n return { accepted: true }\n }\n case 'session.abort': {\n const params = sessionAbortSchema.parse(rawParams)\n const record = sessions.get(params.sessionId)\n const controller = record ? controllers.get(record) : undefined\n controller?.abort()\n return { accepted: true }\n }\n case 'provider.list': {\n providerListSchema.parse(rawParams)\n if (!config.model) return toSafeJson({ default: {}, providers: [] })\n return toSafeJson({\n default: { codex: config.model },\n providers: [\n {\n id: 'codex',\n name: 'Codex',\n models: [\n {\n id: config.model,\n name: config.model,\n attachment: false,\n reasoning: true,\n toolCall: true,\n status: 'active',\n variants: [],\n },\n ],\n },\n ],\n })\n }\n case 'agent.list': {\n agentListSchema.parse(rawParams)\n return []\n }\n case 'permission.list': {\n permissionListSchema.parse(rawParams)\n return []\n }\n case 'permission.reply': {\n permissionReplySchema.parse(rawParams)\n return true\n }\n case 'question.list': {\n questionListSchema.parse(rawParams)\n return []\n }\n case 'question.reply': {\n questionReplySchema.parse(rawParams)\n throw new Error('The Codex connector does not support interactive questions')\n }\n case 'question.reject': {\n questionRejectSchema.parse(rawParams)\n throw new Error('The Codex connector does not support interactive questions')\n }\n case 'event.subscribe': {\n emptyParamsSchema.parse(rawParams)\n return { subscribed: true }\n }\n }\n },\n\n async *events(signal) {\n yield* bus.stream(signal)\n },\n\n async log(level, message, extra) {\n await log(level, message, extra)\n },\n }\n}\n","import { createHash, randomBytes } from 'node:crypto'\nimport { createReadStream } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { readFile, readdir, stat } from 'node:fs/promises'\nimport { z } from 'zod'\nimport type { Thread } from '@openai/codex-sdk'\n\nexport type MessagePart = Record<string, unknown> & {\n id: string\n sessionID: string\n messageID: string\n type: string\n}\n\nexport type MessageInfo = {\n id: string\n sessionID: string\n role: 'user' | 'assistant'\n time: { created: number; completed?: number }\n}\n\nexport type MessageRecord = {\n info: MessageInfo\n parts: MessagePart[]\n}\n\nexport type CodexSessionRecord = {\n id: string\n projectID: string\n directory: string\n title: string\n version: string\n created: number\n updated: number\n thread: Thread | null\n codexThreadId: string | null\n model?: string\n busy: boolean\n failed: boolean\n messages: MessageRecord[]\n messageIndex: number\n}\n\nexport type DiscoveredSession = {\n id: string\n directory: string\n version: string\n created: number\n updated: number\n title: string\n rolloutPath: string\n}\n\ntype RolloutJson = {\n timestamp?: unknown\n type?: unknown\n payload?: unknown\n}\n\ntype RolloutPayload = Record<string, unknown> & { type?: unknown }\n\nconst sessionMetaSchema = z.object({\n type: z.literal('session_meta'),\n payload: z\n .object({\n session_id: z.string().min(1).optional(),\n id: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n timestamp: z.string().optional(),\n cli_version: z.string().min(1).optional(),\n })\n .passthrough(),\n})\n\nexport function defaultSessionsDir(environment: NodeJS.ProcessEnv = process.env): string {\n const root = environment.CODEX_HOME ?? join(homedir(), '.codex')\n return join(root, 'sessions')\n}\n\nexport function projectId(directory: string): string {\n const hash = createHash('sha256').update(directory.toLowerCase()).digest('base64url').slice(0, 12)\n return `project_${hash}`\n}\n\nexport function createSessionId(): string {\n return `codex_${randomBytes(9).toString('base64url')}`\n}\n\nexport function createMessageId(record: CodexSessionRecord): string {\n record.messageIndex += 1\n return `message_${record.messageIndex}`\n}\n\nasync function readFirstLine(path: string): Promise<string | null> {\n return new Promise((resolve) => {\n const stream = createReadStream(path, { encoding: 'utf8', highWaterMark: 64 * 1024 })\n let buffer = ''\n stream.on('data', (chunk: string) => {\n buffer += chunk\n const newline = buffer.indexOf('\\n')\n if (newline !== -1) {\n stream.destroy()\n resolve(buffer.slice(0, newline))\n return\n }\n if (buffer.length > 512 * 1024) {\n stream.destroy()\n resolve(buffer)\n return\n }\n })\n stream.on('error', () => resolve(null))\n stream.on('end', () => resolve(buffer.length ? buffer : null))\n })\n}\n\nasync function readRolloutTitle(path: string, fallback: string): Promise<string> {\n let source: string\n try {\n source = await readFile(path, 'utf8')\n } catch {\n return fallback\n }\n\n let title = fallback\n for (const line of source.split(/\\r?\\n/)) {\n if (!line.trim()) continue\n try {\n const outer = JSON.parse(line) as RolloutJson\n const payload = asRecord(outer.payload)\n if (stringValue(payload?.type) !== 'thread_name_updated') continue\n title = stringValue(payload?.thread_name) ?? title\n } catch {\n // A partially written rollout should not prevent the rest of the catalog loading.\n }\n }\n return title\n}\n\nasync function walkRollouts(dir: string): Promise<string[]> {\n let entries\n try {\n entries = await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n\n const results: string[] = []\n for (const entry of entries) {\n const path = join(dir, entry.name)\n if (entry.isDirectory()) results.push(...(await walkRollouts(path)))\n else if (entry.isFile() && entry.name.endsWith('.jsonl')) results.push(path)\n }\n return results\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null\n}\n\nfunction stringValue(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\nfunction timestampValue(value: unknown, fallback: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const parsed = Date.parse(value)\n if (Number.isFinite(parsed)) return parsed\n }\n return fallback\n}\n\nfunction textFromValue(value: unknown): string | null {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n const text = value\n .map((item) => textFromValue(item))\n .filter((item): item is string => item !== null)\n .join('')\n return text || null\n }\n const record = asRecord(value)\n if (!record) return null\n for (const key of ['text', 'message', 'content', 'output_text']) {\n const text = textFromValue(record[key])\n if (text !== null) return text\n }\n return null\n}\n\nfunction parseJsonValue(value: unknown): unknown {\n if (typeof value !== 'string') return value\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\nfunction historyMessageId(sessionId: string, index: number): string {\n return `history_${sessionId}_${index}`\n}\n\nfunction historyPartId(sessionId: string, index: number, partIndex: number): string {\n return `history_${sessionId}_${index}_${partIndex}`\n}\n\nfunction createHistoryMessage(\n sessionId: string,\n index: number,\n role: MessageInfo['role'],\n created: number,\n): MessageRecord {\n return {\n info: {\n id: historyMessageId(sessionId, index),\n sessionID: sessionId,\n role,\n time: { created, completed: role === 'assistant' ? created : undefined },\n },\n parts: [],\n }\n}\n\nfunction addHistoryText(\n message: MessageRecord,\n sessionId: string,\n partIndex: number,\n type: 'text' | 'reasoning',\n text: string,\n): void {\n if (!text.trim()) return\n message.parts.push({\n id: historyPartId(sessionId, Number(message.info.id.split('_').at(-1) ?? 0), partIndex),\n sessionID: sessionId,\n messageID: message.info.id,\n type,\n text,\n })\n}\n\nfunction localFileUrl(value: unknown): string | null {\n const path = stringValue(value)\n if (!path) return null\n return path.startsWith('file://') ? path : `file://${path}`\n}\n\nexport type RolloutHistory = {\n messages: MessageRecord[]\n title: string\n updated: number\n}\n\n/**\n * Rebuilds the user-visible portion of a Codex rollout. Codex stores internal\n * context messages in the same JSONL file, so only the public user/agent/tool\n * events are translated into the bridge message shape.\n */\nexport async function readRolloutHistory(\n path: string,\n sessionId: string,\n): Promise<RolloutHistory> {\n let source: string\n let updated = 0\n try {\n source = await readFile(path, 'utf8')\n updated = (await stat(path)).mtimeMs\n } catch {\n return { messages: [], title: '(untitled session)', updated }\n }\n\n const messages: MessageRecord[] = []\n const toolParts = new Map<string, MessagePart>()\n let title = '(untitled session)'\n let messageIndex = 0\n let lastAssistant: MessageRecord | null = null\n\n const ensureAssistant = (created: number): MessageRecord => {\n if (lastAssistant) return lastAssistant\n const message = createHistoryMessage(sessionId, messageIndex++, 'assistant', created)\n messages.push(message)\n lastAssistant = message\n return message\n }\n\n for (const line of source.split(/\\r?\\n/)) {\n if (!line.trim()) continue\n let outer: RolloutJson\n try {\n outer = JSON.parse(line) as RolloutJson\n } catch {\n continue\n }\n const payload = asRecord(outer.payload)\n if (!payload) continue\n const type = stringValue(payload.type)\n const created = timestampValue(outer.timestamp, updated || Date.now())\n\n if (type === 'user_message') {\n const text = stringValue(payload.message)\n const message = createHistoryMessage(sessionId, messageIndex++, 'user', created)\n if (text) addHistoryText(message, sessionId, 0, 'text', text)\n const localImages = Array.isArray(payload.local_images) ? payload.local_images : []\n for (const [index, image] of localImages.entries()) {\n const url = localFileUrl(image)\n if (!url) continue\n message.parts.push({\n id: historyPartId(sessionId, Number(message.info.id.split('_').at(-1) ?? 0), index + 1),\n sessionID: sessionId,\n messageID: message.info.id,\n type: 'file',\n url,\n })\n }\n if (message.parts.length) messages.push(message)\n lastAssistant = null\n continue\n }\n\n if (type === 'agent_message') {\n const text = stringValue(payload.message)\n if (!text) continue\n const message = createHistoryMessage(sessionId, messageIndex++, 'assistant', created)\n addHistoryText(message, sessionId, Number(message.info.id.split('_').at(-1) ?? 0), 'text', text)\n messages.push(message)\n lastAssistant = message\n continue\n }\n\n if (type === 'reasoning') {\n const text = textFromValue(payload.summary) ?? textFromValue(payload.content)\n if (!text) continue\n const message = ensureAssistant(created)\n addHistoryText(message, sessionId, message.parts.length, 'reasoning', text)\n continue\n }\n\n if (type === 'thread_name_updated') {\n title = stringValue(payload.thread_name) ?? title\n continue\n }\n\n if (type === 'function_call' || type === 'custom_tool_call') {\n const message = ensureAssistant(created)\n const callId = stringValue(payload.call_id) ?? `${sessionId}:${message.parts.length}`\n const name = stringValue(payload.name) ?? (type === 'function_call' ? 'function' : 'tool')\n const input = parseJsonValue(payload.arguments ?? payload.input)\n const part: MessagePart = {\n id: `history_${callId}`,\n sessionID: sessionId,\n messageID: message.info.id,\n type: 'tool',\n tool: name,\n state: {\n status: 'running',\n title: name,\n input: { arguments: input },\n },\n }\n message.parts.push(part)\n toolParts.set(callId, part)\n continue\n }\n\n if (type === 'function_call_output' || type === 'custom_tool_call_output') {\n const callId = stringValue(payload.call_id)\n if (!callId) continue\n const part = toolParts.get(callId)\n if (!part) continue\n const state = asRecord(part.state) ?? {}\n part.state = {\n ...state,\n status: 'completed',\n output: payload.output ?? payload.result ?? null,\n }\n continue\n }\n\n if (type === 'exec_command_end') {\n const callId = stringValue(payload.call_id)\n const part = callId ? toolParts.get(callId) : undefined\n if (!part) continue\n const state = asRecord(part.state) ?? {}\n part.state = {\n ...state,\n status: payload.exit_code === 0 ? 'completed' : 'error',\n ...(payload.aggregated_output !== undefined\n ? { output: payload.aggregated_output }\n : {}),\n }\n }\n }\n\n for (const message of messages) {\n if (message.info.role === 'assistant') {\n message.info.time.completed ??= updated || message.info.time.created\n }\n }\n return { messages, title, updated }\n}\n\nexport async function discoverSessions(sessionsDir: string): Promise<DiscoveredSession[]> {\n const rollouts = await walkRollouts(sessionsDir)\n const sessions: DiscoveredSession[] = []\n\n for (const path of rollouts) {\n const line = await readFirstLine(path)\n if (!line) continue\n\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch {\n continue\n }\n const result = sessionMetaSchema.safeParse(parsed)\n if (!result.success) continue\n const meta = result.data.payload\n const id = meta.session_id ?? meta.id\n if (!id || !meta.cwd) continue\n\n const created = meta.timestamp ? Date.parse(meta.timestamp) : NaN\n let mtime = created\n try {\n const info = await stat(path)\n mtime = info.mtimeMs\n } catch {\n mtime = Number.isFinite(created) ? created : 0\n }\n\n sessions.push({\n id,\n directory: meta.cwd,\n version: meta.cli_version ?? 'unknown',\n created: Number.isFinite(created) ? created : mtime,\n updated: mtime,\n title: await readRolloutTitle(path, '(untitled session)'),\n rolloutPath: path,\n })\n }\n\n return sessions\n}\n\nexport class CodexSessionStore {\n private readonly records = new Map<string, CodexSessionRecord>()\n private readonly discoveryCache: { at: number; byDirectory: Map<string, DiscoveredSession[]> } = {\n at: 0,\n byDirectory: new Map(),\n }\n\n constructor(readonly sessionsDir: string = defaultSessionsDir()) {}\n\n create(input: {\n id: string\n directory: string\n title?: string\n version: string\n thread?: Thread | null\n codexThreadId?: string | null\n model?: string\n messages?: MessageRecord[]\n }): CodexSessionRecord {\n const now = Date.now()\n const record: CodexSessionRecord = {\n id: input.id,\n projectID: projectId(input.directory),\n directory: input.directory,\n title: input.title ?? '(untitled session)',\n version: input.version,\n created: now,\n updated: now,\n thread: input.thread ?? null,\n codexThreadId: input.codexThreadId ?? null,\n model: input.model,\n busy: false,\n failed: false,\n messages: input.messages ?? [],\n messageIndex: input.messages?.length ?? 0,\n }\n this.records.set(record.id, record)\n return record\n }\n\n get(id: string): CodexSessionRecord | undefined {\n return this.records.get(id)\n }\n\n has(id: string): boolean {\n return this.records.has(id)\n }\n\n list(directory?: string): CodexSessionRecord[] {\n const all = [...this.records.values()]\n return directory ? all.filter((record) => samePath(record.directory, directory)) : all\n }\n\n remove(id: string): boolean {\n return this.records.delete(id)\n }\n\n touch(id: string): void {\n const record = this.records.get(id)\n if (record) record.updated = Date.now()\n }\n\n private async refreshDiscovery(): Promise<void> {\n const now = Date.now()\n if (this.discoveryCache.at !== 0 && now - this.discoveryCache.at <= 30_000) return\n const discovered = await discoverSessions(this.sessionsDir)\n const byDirectory = new Map<string, DiscoveredSession[]>()\n for (const session of discovered) {\n const list = byDirectory.get(session.directory) ?? []\n list.push(session)\n byDirectory.set(session.directory, list)\n }\n this.discoveryCache.at = now\n this.discoveryCache.byDirectory = byDirectory\n }\n\n async discoverAll(directory?: string): Promise<DiscoveredSession[]> {\n await this.refreshDiscovery()\n return directory\n ? [...this.discoveryCache.byDirectory.entries()]\n .filter(([dir]) => samePath(dir, directory))\n .flatMap(([, sessions]) => sessions)\n : [...this.discoveryCache.byDirectory.values()].flat()\n }\n\n async discover(directory?: string): Promise<DiscoveredSession[]> {\n const matching = await this.discoverAll(directory)\n\n const liveThreadIds = new Set(\n [...this.records.values()]\n .map((record) => record.codexThreadId)\n .filter((id): id is string => Boolean(id)),\n )\n return matching.filter((session) => !liveThreadIds.has(session.id))\n }\n\n async loadHistory(sessionId: string, directory?: string): Promise<RolloutHistory | null> {\n const discovered = (await this.discoverAll(directory)).find((session) => session.id === sessionId)\n if (!discovered) return null\n return readRolloutHistory(discovered.rolloutPath, discovered.id)\n }\n\n directories(): string[] {\n const directories = new Set(this.list().map((record) => record.directory))\n for (const session of this.discoveryCache.byDirectory.values()) {\n for (const record of session) directories.add(record.directory)\n }\n return [...directories]\n }\n}\n\nfunction samePath(left: string, right: string): boolean {\n if (process.platform === 'win32') return left.toLowerCase() === right.toLowerCase()\n return left === right\n}\n","import type { JsonValue } from '@openbridge/protocol'\n\nconst sensitiveKey = /(?:api[-_]?key|access[-_]?token|refresh[-_]?token|authorization|credential|password|private[-_]?key|secret)/i\n\nexport function toSafeJson(value: unknown): JsonValue {\n return visit(value, new WeakSet<object>(), 0)\n}\n\nfunction visit(value: unknown, seen: WeakSet<object>, depth: number): JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value\n if (typeof value === 'number') return Number.isFinite(value) ? value : String(value)\n if (typeof value === 'bigint') return value.toString()\n if (typeof value === 'undefined' || typeof value === 'function' || typeof value === 'symbol') {\n return null\n }\n if (depth >= 30) return '[Maximum depth reached]'\n if (value instanceof Date) return value.toISOString()\n if (value instanceof Error) {\n return { name: value.name, message: value.message }\n }\n if (ArrayBuffer.isView(value)) {\n return `[${value.constructor.name} omitted]`\n }\n if (value instanceof ArrayBuffer) return '[ArrayBuffer omitted]'\n if (typeof value !== 'object') return String(value)\n if (seen.has(value)) return '[Circular]'\n\n seen.add(value)\n\n if (Array.isArray(value)) {\n const result = value.map((entry) => visit(entry, seen, depth + 1))\n seen.delete(value)\n return result\n }\n\n const result: Record<string, JsonValue> = {}\n for (const [key, entry] of Object.entries(value)) {\n if (sensitiveKey.test(key)) {\n result[key] = '[REDACTED]'\n continue\n }\n if (typeof entry === 'undefined' || typeof entry === 'function' || typeof entry === 'symbol') continue\n result[key] = visit(entry, seen, depth + 1)\n }\n\n seen.delete(value)\n return result\n}\n","import { z } from 'zod'\n\nexport const BRIDGE_PROTOCOL_VERSION = 1 as const\n\nexport const bridgeRoleSchema = z.enum(['device', 'browser'])\nexport type BridgeRole = z.infer<typeof bridgeRoleSchema>\n\nexport const deviceIdSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[a-zA-Z0-9._:-]+$/, 'Device ID contains unsupported characters')\n\nexport const clientIdSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[a-zA-Z0-9._:-]+$/, 'Client ID contains unsupported characters')\n\nexport const base64UrlSchema = z\n .string()\n .min(16)\n .max(512)\n .regex(/^[A-Za-z0-9_-]+$/, 'Value must use unpadded base64url encoding')\n\nexport const deviceAuthProofSchema = z\n .object({\n deviceId: deviceIdSchema,\n publicKey: z.string().min(32).max(512),\n timestamp: z.number().int().positive(),\n nonce: base64UrlSchema.max(128),\n signature: base64UrlSchema,\n })\n .strict()\n\nexport const pairingClientSchema = z\n .object({\n clientId: clientIdSchema,\n label: z.string().trim().min(1).max(80).optional(),\n })\n .strict()\n\nexport const pairingStartRequestSchema = z\n .object({\n proof: deviceAuthProofSchema,\n client: pairingClientSchema,\n })\n .strict()\n\nexport const pairingHostStartRequestSchema = pairingClientSchema\n\nexport const pairingClaimRequestSchema = z\n .object({\n ticket: base64UrlSchema.max(128),\n client: pairingClientSchema,\n })\n .strict()\n\nexport const pairingStartResponseSchema = z\n .object({\n deviceId: deviceIdSchema,\n pairingId: base64UrlSchema.max(128),\n pairUrl: z.string().url(),\n expiresAt: z.number().int().positive(),\n deviceOnline: z.boolean(),\n })\n .strict()\n\nexport const pairingClaimResponseSchema = z\n .object({\n deviceId: deviceIdSchema,\n authorized: z.literal(true),\n })\n .strict()\n\nexport const pairingRevokeRequestSchema = z\n .object({\n clientId: clientIdSchema,\n })\n .strict()\n\nexport const pairingRevokeResponseSchema = z\n .object({\n revoked: z.literal(true),\n })\n .strict()\n\nexport const pairedDeviceSchema = z\n .object({\n clientId: clientIdSchema,\n label: z.string().nullable(),\n online: z.boolean(),\n pairedAt: z.number().int().positive(),\n })\n .strict()\n\nexport const pairedDevicesResponseSchema = z\n .object({\n devices: z.array(pairedDeviceSchema),\n })\n .strict()\n\nexport type DeviceAuthProof = z.infer<typeof deviceAuthProofSchema>\nexport type PairingClient = z.infer<typeof pairingClientSchema>\nexport type PairingStartRequest = z.infer<typeof pairingStartRequestSchema>\nexport type PairingHostStartRequest = z.infer<typeof pairingHostStartRequestSchema>\nexport type PairingClaimRequest = z.infer<typeof pairingClaimRequestSchema>\nexport type PairingStartResponse = z.infer<typeof pairingStartResponseSchema>\nexport type PairingClaimResponse = z.infer<typeof pairingClaimResponseSchema>\nexport type PairingRevokeRequest = z.infer<typeof pairingRevokeRequestSchema>\nexport type PairingRevokeResponse = z.infer<typeof pairingRevokeResponseSchema>\nexport type PairedDevice = z.infer<typeof pairedDeviceSchema>\nexport type PairedDevicesResponse = z.infer<typeof pairedDevicesResponseSchema>\n\nexport const bridgeConnectionSchema = z.object({\n role: bridgeRoleSchema,\n clientId: clientIdSchema,\n})\n\nexport const bridgeMethodSchema = z.enum([\n 'device.health',\n 'project.list',\n 'session.list',\n 'session.create',\n 'session.fork',\n 'session.delete',\n 'session.status',\n 'session.messages',\n 'session.prompt',\n 'session.abort',\n 'provider.list',\n 'agent.list',\n 'permission.list',\n 'permission.reply',\n 'question.list',\n 'question.reply',\n 'question.reject',\n 'event.subscribe',\n])\nexport type BridgeMethod = z.infer<typeof bridgeMethodSchema>\n\nexport type JsonValue =\n | null\n | boolean\n | number\n | string\n | JsonValue[]\n | { [key: string]: JsonValue }\n\nexport const jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n z.null(),\n z.boolean(),\n z.number(),\n z.string(),\n z.array(jsonValueSchema),\n z.record(z.string(), jsonValueSchema),\n ]),\n)\n\nconst messageBase = {\n version: z.literal(BRIDGE_PROTOCOL_VERSION),\n}\n\nexport const bridgeHelloSchema = z\n .object({\n ...messageBase,\n type: z.literal('device.hello'),\n clientId: clientIdSchema,\n agentVersion: z.string().min(1).max(64),\n connectorId: z.string().min(1).max(64).default('opencode'),\n })\n .strict()\n\nexport const bridgeRequestSchema = z\n .object({\n ...messageBase,\n type: z.literal('request'),\n id: z.string().min(1).max(128),\n connectorId: z.string().min(1).max(64).optional(),\n method: bridgeMethodSchema,\n params: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeErrorSchema = z\n .object({\n code: z.enum([\n 'INVALID_MESSAGE',\n 'ROLE_NOT_ALLOWED',\n 'DEVICE_OFFLINE',\n 'REQUEST_NOT_FOUND',\n 'DUPLICATE_REQUEST',\n 'SESSION_BUSY',\n 'INTERNAL_ERROR',\n ]),\n message: z.string().min(1).max(512),\n })\n .strict()\n\nexport const bridgeSuccessResponseSchema = z\n .object({\n ...messageBase,\n type: z.literal('response'),\n id: z.string().min(1).max(128),\n ok: z.literal(true),\n result: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeFailureResponseSchema = z\n .object({\n ...messageBase,\n type: z.literal('response'),\n id: z.string().min(1).max(128),\n ok: z.literal(false),\n error: bridgeErrorSchema,\n })\n .strict()\n\nexport const bridgeResponseSchema = z.union([\n bridgeSuccessResponseSchema,\n bridgeFailureResponseSchema,\n])\n\nexport const bridgeEventSchema = z\n .object({\n ...messageBase,\n type: z.literal('event'),\n connectorId: z.string().min(1).max(64).optional(),\n event: z.string().min(1).max(128),\n payload: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeSystemSchema = z\n .object({\n ...messageBase,\n type: z.literal('system'),\n event: z.enum([\n 'connection.ready',\n 'presence.changed',\n 'pairing.claimed',\n 'protocol.error',\n ]),\n payload: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeMessageSchema = z.union([\n bridgeHelloSchema,\n bridgeRequestSchema,\n bridgeResponseSchema,\n bridgeEventSchema,\n bridgeSystemSchema,\n])\n\nexport type BridgeHello = z.infer<typeof bridgeHelloSchema>\nexport type BridgeRequest = z.infer<typeof bridgeRequestSchema>\nexport type BridgeResponse = z.infer<typeof bridgeResponseSchema>\nexport type BridgeEvent = z.infer<typeof bridgeEventSchema>\nexport type BridgeSystemMessage = z.infer<typeof bridgeSystemSchema>\nexport type BridgeMessage = z.infer<typeof bridgeMessageSchema>\nexport type BridgeError = z.infer<typeof bridgeErrorSchema>\n\nexport type BridgeParseResult =\n | { ok: true; message: BridgeMessage }\n | { ok: false; error: BridgeError }\n\nexport function parseBridgeMessage(value: string): BridgeParseResult {\n let parsed: unknown\n\n try {\n parsed = JSON.parse(value)\n } catch {\n return {\n ok: false,\n error: {\n code: 'INVALID_MESSAGE',\n message: 'Message must be valid JSON',\n },\n }\n }\n\n const result = bridgeMessageSchema.safeParse(parsed)\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: 'INVALID_MESSAGE',\n message: result.error.issues[0]?.message ?? 'Message does not match the bridge protocol',\n },\n }\n }\n\n return { ok: true, message: result.data }\n}\n\nexport function encodeBridgeMessage(message: BridgeMessage): string {\n return JSON.stringify(bridgeMessageSchema.parse(message))\n}\n","import {\n createHash,\n createPrivateKey,\n createPublicKey,\n generateKeyPairSync,\n randomBytes,\n sign,\n verify,\n} from 'node:crypto'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { mkdir, open, readFile } from 'node:fs/promises'\nimport { z } from 'zod'\nimport type { DeviceAuthProof } from '@openbridge/protocol'\n\nconst DEVICE_PROOF_PREFIX = 'tumnel-device-proof-v1'\n\nconst identitySchema = z\n .object({\n version: z.literal(1),\n deviceId: z.string().regex(/^device_[A-Za-z0-9_-]{32,64}$/),\n publicKey: z.string().min(1),\n privateKey: z.string().min(1),\n createdAt: z.string().datetime(),\n })\n .strict()\n\nexport type DeviceIdentity = z.infer<typeof identitySchema>\n\nexport function defaultIdentityPath(environment: NodeJS.ProcessEnv = process.env): string {\n const configRoot =\n environment.TUMNEL_CONFIG_DIR ??\n environment.XDG_CONFIG_HOME ??\n (process.platform === 'win32' && environment.USERPROFILE\n ? join(environment.USERPROFILE, '.config')\n : join(homedir(), '.config'))\n\n return join(configRoot, 'tumnel', 'identity.json')\n}\n\nfunction legacyIdentityPaths(environment: NodeJS.ProcessEnv = process.env): string[] {\n const configRoot =\n environment.TUMNEL_CONFIG_DIR ??\n environment.XDG_CONFIG_HOME ??\n (process.platform === 'win32' && environment.USERPROFILE\n ? join(environment.USERPROFILE, '.config')\n : join(homedir(), '.config'))\n // OpenCode is first so existing hosts keep their paired identity when\n // Codex is installed later on the same computer.\n return [\n join(configRoot, 'opencode', 'tumnel', 'identity.json'),\n join(configRoot, 'codex', 'tumnel', 'identity.json'),\n ]\n}\n\nfunction deviceIdFromPublicKey(publicKey: string): string {\n const fingerprint = createHash('sha256').update(Buffer.from(publicKey, 'base64')).digest('base64url')\n return `device_${fingerprint}`\n}\n\nfunction createIdentity(): DeviceIdentity {\n const pair = generateKeyPairSync('ed25519')\n const publicKey = pair.publicKey.export({ type: 'spki', format: 'der' }).toString('base64')\n const privateKey = pair.privateKey.export({ type: 'pkcs8', format: 'pem' }).toString()\n\n return {\n version: 1,\n deviceId: deviceIdFromPublicKey(publicKey),\n publicKey,\n privateKey,\n createdAt: new Date().toISOString(),\n }\n}\n\nfunction validateKeyPair(identity: DeviceIdentity): DeviceIdentity {\n if (deviceIdFromPublicKey(identity.publicKey) !== identity.deviceId) {\n throw new Error('Tumnel identity fingerprint does not match its public key')\n }\n\n const challenge = Buffer.from('tumnel-device-identity-v1')\n const signature = sign(null, challenge, createPrivateKey(identity.privateKey))\n const valid = verify(\n null,\n challenge,\n createPublicKey({ key: Buffer.from(identity.publicKey, 'base64'), format: 'der', type: 'spki' }),\n signature,\n )\n\n if (!valid) {\n throw new Error('Tumnel identity contains an invalid key pair')\n }\n\n return identity\n}\n\nasync function readIdentity(path: string): Promise<DeviceIdentity> {\n const contents = await readFile(path, 'utf8')\n return validateKeyPair(identitySchema.parse(JSON.parse(contents)))\n}\n\nasync function persistNewIdentity(path: string, identity: DeviceIdentity): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 })\n const handle = await open(path, 'wx', 0o600)\n\n try {\n await handle.writeFile(`${JSON.stringify(identity, null, 2)}\\n`, 'utf8')\n await handle.sync()\n } finally {\n await handle.close()\n }\n}\n\nexport async function loadOrCreateIdentity(\n path = defaultIdentityPath(),\n migrationSources = path === defaultIdentityPath() ? legacyIdentityPaths() : [],\n): Promise<DeviceIdentity> {\n try {\n return await readIdentity(path)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n\n if (migrationSources.length > 0) {\n for (const legacyPath of migrationSources) {\n try {\n const identity = await readIdentity(legacyPath)\n try {\n await persistNewIdentity(path, identity)\n return identity\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error\n return readIdentity(path)\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n }\n }\n\n const identity = createIdentity()\n\n try {\n await persistNewIdentity(path, identity)\n return identity\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error\n return readIdentity(path)\n }\n}\n\nexport function createDeviceProof(\n identity: DeviceIdentity,\n timestamp = Date.now(),\n nonce = randomBytes(24).toString('base64url'),\n): DeviceAuthProof {\n const message = `${DEVICE_PROOF_PREFIX}\\n${identity.deviceId}\\n${timestamp}\\n${nonce}`\n const signature = sign(null, Buffer.from(message), createPrivateKey(identity.privateKey))\n\n return {\n deviceId: identity.deviceId,\n publicKey: identity.publicKey,\n timestamp,\n nonce,\n signature: signature.toString('base64url'),\n }\n}\n","import {\n BRIDGE_PROTOCOL_VERSION,\n encodeBridgeMessage,\n parseBridgeMessage,\n type BridgeEvent,\n type BridgeHello,\n type BridgeRequest,\n type BridgeResponse,\n type DeviceAuthProof,\n type JsonValue,\n} from '@openbridge/protocol'\nimport { createDeviceProof, type DeviceIdentity } from './identity.js'\nimport type { ConnectorAdapter } from './connector-adapter.js'\n\nconst CONNECT_TIMEOUT_MS = 15_000\nconst STABLE_CONNECTION_MS = 30_000\nconst INITIAL_BACKOFF_MS = 500\nconst MAX_BACKOFF_MS = 30_000\n\nexport type BridgeConnectionState = 'idle' | 'connecting' | 'connected' | 'stopped'\n\nexport type TumnelBridgeClientOptions = {\n relayUrl: string\n identity: DeviceIdentity\n adapter: ConnectorAdapter\n webSocketFactory?: (url: string) => WebSocket\n random?: () => number\n proofFactory?: () => Promise<DeviceAuthProof> | DeviceAuthProof\n}\n\nfunction bridgeUrl(\n relayUrl: string,\n identity: DeviceIdentity,\n proof: DeviceAuthProof,\n): string {\n const url = new URL(relayUrl)\n if (url.protocol === 'http:') url.protocol = 'ws:'\n if (url.protocol === 'https:') url.protocol = 'wss:'\n if (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n throw new Error('TUMNEL_RELAY_URL must use http, https, ws, or wss')\n }\n\n const basePath = url.pathname.replace(/\\/$/, '')\n url.pathname = `${basePath}/api/bridge/${encodeURIComponent(identity.deviceId)}`\n url.search = ''\n url.searchParams.set('role', 'device')\n url.searchParams.set('clientId', identity.deviceId)\n url.searchParams.set('connectorId', 'codex')\n url.searchParams.set('publicKey', proof.publicKey)\n url.searchParams.set('timestamp', String(proof.timestamp))\n url.searchParams.set('nonce', proof.nonce)\n url.searchParams.set('signature', proof.signature)\n return url.toString()\n}\n\nfunction abortableDelay(milliseconds: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal.aborted) return resolve()\n const timeout = setTimeout(resolve, milliseconds)\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeout)\n resolve()\n },\n { once: true },\n )\n })\n}\n\nfunction eventName(payload: JsonValue): string {\n if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) return 'codex.event'\n if (typeof payload.type === 'string') return payload.type.slice(0, 128)\n const nested = payload.payload\n if (\n typeof nested === 'object' &&\n nested !== null &&\n !Array.isArray(nested) &&\n typeof nested.type === 'string'\n ) {\n return nested.type.slice(0, 128)\n }\n return 'codex.event'\n}\n\nasync function messageText(data: unknown): Promise<string | null> {\n if (typeof data === 'string') return data\n if (data instanceof Blob) return data.text()\n if (data instanceof ArrayBuffer) return Buffer.from(data).toString('utf8')\n if (ArrayBuffer.isView(data)) {\n return Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('utf8')\n }\n return null\n}\n\nfunction errorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : 'Codex request failed'\n return message.slice(0, 512)\n}\n\nexport class TumnelBridgeClient {\n private readonly relayUrl: string\n private readonly identity: DeviceIdentity\n private readonly adapter: ConnectorAdapter\n private readonly webSocketFactory: (url: string) => WebSocket\n private readonly random: () => number\n private readonly proofFactory: () => Promise<DeviceAuthProof> | DeviceAuthProof\n private readonly abortController = new AbortController()\n private connectionLoop?: Promise<void>\n private eventLoop?: Promise<void>\n private socket?: WebSocket\n private currentState: BridgeConnectionState = 'idle'\n\n constructor(options: TumnelBridgeClientOptions) {\n this.relayUrl = options.relayUrl\n this.identity = options.identity\n this.adapter = options.adapter\n this.webSocketFactory = options.webSocketFactory ?? ((url) => new WebSocket(url))\n this.random = options.random ?? Math.random\n this.proofFactory = options.proofFactory ?? (() => createDeviceProof(this.identity))\n }\n\n get state(): BridgeConnectionState {\n return this.currentState\n }\n\n get deviceId(): string {\n return this.identity.deviceId\n }\n\n start(): void {\n if (this.connectionLoop || this.abortController.signal.aborted) return\n this.connectionLoop = this.runConnectionLoop()\n this.eventLoop = this.runEventLoop()\n }\n\n async stop(): Promise<void> {\n if (this.currentState === 'stopped') return\n this.currentState = 'stopped'\n this.abortController.abort()\n this.socket?.close(1000, 'Connector disposed')\n await Promise.allSettled([this.connectionLoop, this.eventLoop])\n }\n\n private async runConnectionLoop(): Promise<void> {\n let attempt = 0\n\n while (!this.abortController.signal.aborted) {\n const startedAt = Date.now()\n try {\n await this.connectOnce()\n } catch (error) {\n await this.adapter.log('warn', 'Cloud relay connection failed', {\n reason: errorMessage(error),\n })\n }\n\n if (this.abortController.signal.aborted) break\n attempt = Date.now() - startedAt >= STABLE_CONNECTION_MS ? 0 : attempt + 1\n const exponential = Math.min(MAX_BACKOFF_MS, INITIAL_BACKOFF_MS * 2 ** Math.min(attempt, 10))\n const delay = Math.round(exponential * (0.75 + this.random() * 0.5))\n await this.adapter.log('info', 'Reconnecting to Cloud relay', {\n attempt,\n delayMs: delay,\n })\n await abortableDelay(delay, this.abortController.signal)\n }\n }\n\n private async connectOnce(): Promise<void> {\n this.currentState = 'connecting'\n const proof = await this.proofFactory()\n const socket = this.webSocketFactory(bridgeUrl(this.relayUrl, this.identity, proof))\n this.socket = socket\n\n return new Promise((resolve, reject) => {\n let opened = false\n const timeout = setTimeout(() => {\n socket.close(4000, 'Connection timeout')\n reject(new Error('Timed out connecting to Cloud relay'))\n }, CONNECT_TIMEOUT_MS)\n\n const abort = () => socket.close(1000, 'Connector disposed')\n this.abortController.signal.addEventListener('abort', abort, { once: true })\n\n socket.addEventListener('open', () => {\n opened = true\n clearTimeout(timeout)\n this.currentState = 'connected'\n const hello: BridgeHello = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'device.hello',\n clientId: this.identity.deviceId,\n agentVersion: '0.1.1',\n connectorId: 'codex',\n }\n socket.send(encodeBridgeMessage(hello))\n void this.adapter.log('info', 'Connected to Cloud relay', {\n deviceId: this.identity.deviceId,\n })\n })\n\n socket.addEventListener('message', (event) => {\n void this.handleMessage(socket, event.data)\n })\n\n socket.addEventListener('error', () => {\n if (!opened) {\n clearTimeout(timeout)\n reject(new Error('Cloud relay WebSocket error'))\n }\n })\n\n socket.addEventListener('close', (event) => {\n clearTimeout(timeout)\n this.abortController.signal.removeEventListener('abort', abort)\n if (this.socket === socket) this.socket = undefined\n if (!this.abortController.signal.aborted) this.currentState = 'idle'\n if (!this.abortController.signal.aborted) {\n void this.adapter.log('warn', 'Cloud relay disconnected', {\n code: event.code,\n reason: event.reason.slice(0, 256),\n wasClean: event.wasClean,\n })\n }\n if (opened) resolve()\n else reject(new Error('Cloud relay closed before connecting'))\n })\n })\n }\n\n private async handleMessage(socket: WebSocket, data: unknown): Promise<void> {\n const raw = await messageText(data)\n if (raw === 'pong' || raw === null) return\n const parsed = parseBridgeMessage(raw)\n\n if (!parsed.ok) {\n await this.adapter.log('warn', 'Ignored invalid Cloud relay message', {\n code: parsed.error.code,\n message: parsed.error.message,\n })\n return\n }\n if (parsed.message.type !== 'request') return\n await this.handleRequest(socket, parsed.message)\n }\n\n private async handleRequest(socket: WebSocket, request: BridgeRequest): Promise<void> {\n let response: BridgeResponse\n\n try {\n response = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'response',\n id: request.id,\n ok: true,\n result: await this.adapter.invoke(request.method, request.params),\n }\n } catch (error) {\n response = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'response',\n id: request.id,\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: errorMessage(error),\n },\n }\n }\n\n if (socket.readyState === WebSocket.OPEN) socket.send(encodeBridgeMessage(response))\n }\n\n private async runEventLoop(): Promise<void> {\n let attempt = 0\n\n while (!this.abortController.signal.aborted) {\n try {\n for await (const payload of this.adapter.events(this.abortController.signal)) {\n const event: BridgeEvent = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'event',\n event: eventName(payload),\n payload,\n }\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(encodeBridgeMessage(event))\n }\n }\n attempt = 0\n } catch (error) {\n if (this.abortController.signal.aborted) break\n attempt += 1\n await this.adapter.log('warn', 'Codex event stream disconnected', {\n reason: errorMessage(error),\n attempt,\n })\n const delay = Math.min(MAX_BACKOFF_MS, INITIAL_BACKOFF_MS * 2 ** Math.min(attempt, 10))\n await abortableDelay(delay, this.abortController.signal)\n }\n }\n }\n}\n","import { z } from 'zod'\nimport type { SandboxMode } from '@openai/codex-sdk'\nimport type { ApprovalMode, ModelReasoningEffort, WebSearchMode } from '@openai/codex-sdk'\n\nexport const DEFAULT_RELAY_URL = 'https://openbridge.jlfloressanchez01.workers.dev'\nexport const DEFAULT_LOCAL_PORT = 43817\nexport const DEFAULT_SANDBOX_MODE: SandboxMode = 'workspace-write'\nexport const DEFAULT_APPROVAL_POLICY: ApprovalMode = 'on-request'\n\nconst localPortSchema = z.number().int().min(1024).max(65535)\nconst sandboxModeSchema = z.enum(['read-only', 'workspace-write', 'danger-full-access'])\nconst approvalPolicySchema = z.enum(['never', 'on-request', 'on-failure', 'untrusted'])\nconst modelReasoningEffortSchema = z.enum(['minimal', 'low', 'medium', 'high', 'xhigh'])\nconst webSearchModeSchema = z.enum(['disabled', 'cached', 'live'])\n\nconst connectorOptionsSchema = z\n .object({\n relayUrl: z.string().url().optional(),\n identityPath: z.string().min(1).optional(),\n localPort: localPortSchema.optional(),\n appOrigins: z.array(z.string().url()).max(10).optional(),\n model: z.string().min(1).max(256).optional(),\n sandboxMode: sandboxModeSchema.optional(),\n approvalPolicy: approvalPolicySchema.optional(),\n modelReasoningEffort: modelReasoningEffortSchema.optional(),\n webSearchMode: webSearchModeSchema.optional(),\n skipGitRepoCheck: z.boolean().optional(),\n networkAccess: z.boolean().optional(),\n })\n .strict()\n\nexport type TumnelCodexOptions = z.infer<typeof connectorOptionsSchema>\n\nexport type TumnelCodexConfig = {\n relayUrl: string\n identityPath?: string\n localPort: number\n appOrigins: string[]\n model?: string\n sandboxMode: SandboxMode\n approvalPolicy: ApprovalMode\n modelReasoningEffort?: ModelReasoningEffort\n webSearchMode?: WebSearchMode\n skipGitRepoCheck: boolean\n networkAccess: boolean\n}\n\nfunction envBool(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined\n return value === '1' || value.toLowerCase() === 'true'\n}\n\nexport function resolveConfig(\n options: Record<string, unknown> | undefined,\n environment: NodeJS.ProcessEnv = process.env,\n): TumnelCodexConfig {\n const parsedOptions = connectorOptionsSchema.parse(options ?? {})\n const relayUrl = parsedOptions.relayUrl ?? environment.TUMNEL_RELAY_URL ?? DEFAULT_RELAY_URL\n const configuredOrigins = environment.TUMNEL_APP_ORIGIN\n ?.split(',')\n .map((origin) => origin.trim())\n .filter(Boolean)\n\n const sandboxMode = sandboxModeSchema.parse(\n parsedOptions.sandboxMode ?? environment.CODEX_SANDBOX ?? DEFAULT_SANDBOX_MODE,\n )\n const approvalPolicy = approvalPolicySchema.parse(\n parsedOptions.approvalPolicy ?? environment.CODEX_APPROVAL_POLICY ?? DEFAULT_APPROVAL_POLICY,\n )\n\n return {\n relayUrl,\n identityPath: parsedOptions.identityPath ?? environment.TUMNEL_IDENTITY_PATH,\n localPort: localPortSchema.parse(\n parsedOptions.localPort ??\n (environment.TUMNEL_LOCAL_PORT ? Number(environment.TUMNEL_LOCAL_PORT) : DEFAULT_LOCAL_PORT),\n ),\n appOrigins: parsedOptions.appOrigins ?? configuredOrigins ?? [],\n model: parsedOptions.model ?? environment.CODEX_MODEL,\n sandboxMode,\n approvalPolicy,\n modelReasoningEffort:\n parsedOptions.modelReasoningEffort ??\n (environment.CODEX_REASONING_EFFORT as ModelReasoningEffort | undefined),\n webSearchMode:\n parsedOptions.webSearchMode ??\n (environment.CODEX_WEB_SEARCH as WebSearchMode | undefined),\n skipGitRepoCheck:\n parsedOptions.skipGitRepoCheck ?? envBool(environment.CODEX_SKIP_GIT_REPO_CHECK) ?? false,\n networkAccess:\n parsedOptions.networkAccess ?? envBool(environment.CODEX_NETWORK_ACCESS) ?? false,\n }\n}\n","import { createServer, type Server } from 'node:http'\nimport { clientIdSchema, type JsonValue } from '@openbridge/protocol'\nimport type { DeviceIdentity } from './identity.js'\nimport { createDeviceProof } from './identity.js'\n\ntype PairingServerOptions = {\n identity: DeviceIdentity\n port: number\n relayUrl: string\n appOrigins: string[]\n log: (level: 'info' | 'warn', message: string, fields?: Record<string, JsonValue>) => Promise<void>\n}\n\nexport type PairingServer = {\n port: number\n stop: () => Promise<void>\n}\n\nfunction relayOrigin(relayUrl: string): string {\n const url = new URL(relayUrl)\n if (url.protocol === 'ws:') url.protocol = 'http:'\n if (url.protocol === 'wss:') url.protocol = 'https:'\n return url.origin\n}\n\nfunction closeServer(server: Server): Promise<void> {\n return new Promise((resolve) => server.close(() => resolve()))\n}\n\nexport async function startPairingServer(options: PairingServerOptions): Promise<PairingServer | null> {\n const allowedOrigins = new Set([\n relayOrigin(options.relayUrl),\n 'http://127.0.0.1:5173',\n 'http://localhost:5173',\n ...options.appOrigins,\n ])\n\n const server = createServer((request, response) => {\n const origin = request.headers.origin\n const expectedHosts = new Set([\n `127.0.0.1:${options.port}`,\n `localhost:${options.port}`,\n ])\n\n if (!expectedHosts.has(request.headers.host ?? '')) {\n response.writeHead(403, { 'Cache-Control': 'no-store' })\n response.end('Forbidden')\n return\n }\n\n const requestUrl = new URL(request.url ?? '/', `http://${request.headers.host}`)\n if (request.method === 'GET' && requestUrl.pathname === '/v1/health') {\n const body = JSON.stringify({ ready: true })\n response.writeHead(200, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'application/json; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body).toString(),\n })\n response.end(body)\n return\n }\n\n if (request.method === 'GET' && requestUrl.pathname === '/v1/connect') {\n const returnOrigin = requestUrl.searchParams.get('returnOrigin')\n const clientId = clientIdSchema.safeParse(requestUrl.searchParams.get('clientId'))\n if (!returnOrigin || !allowedOrigins.has(returnOrigin) || !clientId.success) {\n response.writeHead(400, { 'Cache-Control': 'no-store' })\n response.end('Invalid pairing handoff')\n return\n }\n\n const payload = Buffer.from(JSON.stringify({\n proof: createDeviceProof(options.identity),\n client: { clientId: clientId.data, label: 'Desktop browser' },\n })).toString('base64url')\n const redirect = new URL('/connect', returnOrigin)\n redirect.hash = new URLSearchParams({ payload }).toString()\n response.writeHead(302, {\n 'Cache-Control': 'no-store',\n 'Referrer-Policy': 'no-referrer',\n Location: redirect.toString(),\n })\n response.end()\n return\n }\n\n if (!origin || !allowedOrigins.has(origin)) {\n response.writeHead(403, { 'Cache-Control': 'no-store' })\n response.end('Forbidden')\n return\n }\n\n const corsHeaders: Record<string, string> = {\n 'Access-Control-Allow-Origin': origin,\n 'Access-Control-Allow-Methods': 'GET, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n 'Cache-Control': 'no-store',\n Vary: 'Origin',\n }\n if (request.headers['access-control-request-private-network'] === 'true') {\n corsHeaders['Access-Control-Allow-Private-Network'] = 'true'\n }\n\n if (request.method === 'OPTIONS') {\n response.writeHead(204, corsHeaders)\n response.end()\n return\n }\n\n if (request.method !== 'GET' || requestUrl.pathname !== '/v1/pairing-proof') {\n response.writeHead(404, corsHeaders)\n response.end('Not Found')\n return\n }\n\n const body = JSON.stringify({ proof: createDeviceProof(options.identity) })\n response.writeHead(200, {\n ...corsHeaders,\n 'Content-Type': 'application/json; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body).toString(),\n })\n response.end(body)\n })\n\n const listening = await new Promise<boolean>((resolve) => {\n const onError = (error: NodeJS.ErrnoException) => {\n server.removeListener('listening', onListening)\n void options.log('warn', 'Local pairing endpoint is unavailable', {\n port: options.port,\n reason: error.code ?? error.message,\n })\n resolve(false)\n }\n const onListening = () => {\n server.removeListener('error', onError)\n resolve(true)\n }\n server.once('error', onError)\n server.once('listening', onListening)\n server.listen(options.port, '127.0.0.1')\n })\n\n if (!listening) return null\n await options.log('info', 'Local pairing endpoint ready', { port: options.port })\n\n return {\n port: options.port,\n stop: () => closeServer(server),\n }\n}\n","#!/usr/bin/env node\n\nimport { createCodexConnector } from './index.js'\n\nconst printHelp = () => {\n console.log(`Tumnel connector for Codex\n\nUsage:\n tumnel-codex install [options]\n tumnel-codex connect [options]\n\nThe install command is the standard one-command setup for Codex. It prepares the\nTumnel identity and starts the connector. The connect command remains available\nas an explicit alias.\n\nOptions:\n --model <model> Codex model id (e.g. gpt-5-mini)\n --port <port> Local pairing endpoint port (default 43817)\n --relay-url <url> Tumnel relay URL (default: production relay)\n --sandbox <mode> Sandbox: read-only | workspace-write | danger-full-access\n --approval-policy <policy> Approval: never | on-request | on-failure | untrusted\n --version Print the connector version\n -h, --help Show this help\n\nEnvironment:\n TUMNEL_RELAY_URL, TUMNEL_APP_ORIGIN, TUMNEL_IDENTITY_PATH, TUMNEL_LOCAL_PORT,\n TUMNEL_CONFIG_DIR, CODEX_MODEL, CODEX_SANDBOX, CODEX_APPROVAL_POLICY,\n CODEX_REASONING_EFFORT, CODEX_WEB_SEARCH, CODEX_NETWORK_ACCESS,\n CODEX_SKIP_GIT_REPO_CHECK, CODEX_HOME\n\nThe connect command starts the Codex agent bridge and keeps it connected to the\nTumnel relay until interrupted. Pair from the Tumnel web app when it is online.`)\n}\n\nconst printVersion = async () => {\n const { version } = JSON.parse(\n await import('node:fs/promises').then(({ readFile }) =>\n readFile(new URL('../package.json', import.meta.url), 'utf8'),\n ),\n ) as { version: string }\n console.log(`@tumnel/codex ${version}`)\n}\n\nconst run = async () => {\n const command = process.argv[2] ?? 'install'\n\n if (command === '--help' || command === '-h' || command === 'help') {\n printHelp()\n return\n }\n\n if (command === '--version' || command === '-v') {\n printVersion()\n return\n }\n\n if (command !== 'install' && command !== 'connect' && !command.startsWith('-')) {\n throw new Error(`Unknown command: ${command}`)\n }\n\n const args = command === 'install' || command === 'connect'\n ? process.argv.slice(3)\n : process.argv.slice(2)\n\n if (args.includes('--help') || args.includes('-h')) {\n printHelp()\n return\n }\n\n const versionIndex = args.indexOf('--version')\n if (versionIndex !== -1) {\n await printVersion()\n return\n }\n\n const config: Record<string, unknown> = {}\n\n const flag = (name: string): void => {\n const index = args.indexOf(name)\n if (index === -1) return\n const value = args[index + 1]\n if (!value) throw new Error(`Missing value for ${name}`)\n const key = {\n '--model': 'model',\n '--port': 'localPort',\n '--relay-url': 'relayUrl',\n '--sandbox': 'sandboxMode',\n '--approval-policy': 'approvalPolicy',\n }[name] ?? name\n config[key] = name === '--port' ? Number(value) : value\n }\n\n flag('--model')\n flag('--port')\n flag('--relay-url')\n flag('--sandbox')\n flag('--approval-policy')\n\n if (command === 'install') {\n console.log('Tumnel Codex connector is installed and ready.')\n }\n\n const connector = await createCodexConnector({ config })\n const port = connector.pairingServer?.port\n\n console.log('Tumnel Codex connector started')\n console.log(` Device ID: ${connector.bridge.deviceId}`)\n if (port) console.log(` Pairing port: http://127.0.0.1:${port}`)\n console.log('Press Ctrl+C to stop.\\n')\n\n let stopping = false\n const stop = async () => {\n if (stopping) return\n stopping = true\n console.log('\\nStopping Tumnel Codex connector...')\n await connector.stop()\n process.exit(0)\n }\n process.on('SIGINT', () => void stop())\n process.on('SIGTERM', () => void stop())\n}\n\nrun().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error))\n process.exitCode = 1\n})\n"],"mappings":"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","names":["z","result","z","existing","messages","z","z","createHash","randomBytes","homedir","join","readFile","z","identity","errorMessage","z","body","readFile"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/codex-adapter.ts","../src/codex-sessions.ts","../src/safe-json.ts","../../protocol/src/index.ts","../src/identity.ts","../src/client.ts","../src/config.ts","../src/local-server.ts","../src/cli.ts"],"sourcesContent":["import { Codex } from '@openai/codex-sdk'\nimport { createCodexAdapter, type CodexAdapterOptions } from './codex-adapter.js'\nimport { CodexSessionStore } from './codex-sessions.js'\nimport { TumnelBridgeClient } from './client.js'\nimport { resolveConfig, type TumnelCodexConfig } from './config.js'\nimport { loadOrCreateIdentity } from './identity.js'\nimport { startPairingServer } from './local-server.js'\n\nexport type CodexConnectorOptions = {\n config?: Record<string, unknown>\n environment?: NodeJS.ProcessEnv\n codex?: Codex\n sessionsDir?: string\n log?: CodexAdapterOptions['log']\n}\n\nexport type CodexConnector = {\n bridge: TumnelBridgeClient\n pairingServer: Awaited<ReturnType<typeof startPairingServer>>\n stop: () => Promise<void>\n}\n\nexport async function createCodexConnector(options: CodexConnectorOptions = {}): Promise<CodexConnector> {\n const config = resolveConfig(options.config, options.environment)\n const identity = await loadOrCreateIdentity(config.identityPath)\n const codex = options.codex ?? new Codex()\n const sessions = new CodexSessionStore(options.sessionsDir)\n const adapter = createCodexAdapter({ codex, config, sessions, log: options.log })\n const bridge = new TumnelBridgeClient({\n relayUrl: config.relayUrl,\n identity,\n adapter,\n })\n const pairingServer = await startPairingServer({\n identity,\n port: config.localPort,\n relayUrl: config.relayUrl,\n appOrigins: config.appOrigins,\n log: (level, message, fields) => adapter.log(level, message, fields),\n })\n\n bridge.start()\n\n return {\n bridge,\n pairingServer,\n stop: async () => {\n await bridge.stop()\n await pairingServer?.stop()\n },\n }\n}\n\nexport { createCodexAdapter, resolveConfig, CodexSessionStore, TumnelBridgeClient }\nexport type { TumnelCodexConfig }\nexport type { ConnectorAdapter, ConnectorLogLevel } from './connector-adapter.js'\nexport type { DeviceIdentity } from './identity.js'","import type { Codex, Input, Thread, ThreadEvent, ThreadItem } from '@openai/codex-sdk'\nimport type { BridgeMethod, JsonValue } from '@openbridge/protocol'\nimport { z } from 'zod'\nimport {\n createMessageId,\n createSessionId,\n projectId,\n type CodexSessionRecord,\n type CodexSessionStore,\n type DiscoveredSession,\n type MessagePart,\n type MessageRecord,\n} from './codex-sessions.js'\nimport type { TumnelCodexConfig } from './config.js'\nimport type { ConnectorAdapter, ConnectorLogLevel } from './connector-adapter.js'\nimport { toSafeJson } from './safe-json.js'\n\nconst directorySchema = z.string().min(1).max(4096).optional()\nconst emptyParamsSchema = z.object({}).strict()\n// OpenCode uses an empty directory to explicitly request the global catalog.\n// Keep that meaning for Codex instead of rejecting the request at the adapter boundary.\nconst projectListSchema = z.object({ directory: z.string().max(4096).optional() }).strict()\nconst sessionListSchema = z.object({ directory: directorySchema }).strict()\nconst sessionCreateSchema = z\n .object({\n directory: directorySchema,\n parentID: z.string().min(1).max(256).optional(),\n title: z.string().min(1).max(512).optional(),\n })\n .strict()\nconst sessionForkSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n messageID: z.string().min(1).max(256).optional(),\n title: z.string().min(1).max(512).optional(),\n })\n .strict()\nconst sessionDeleteSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n })\n .strict()\nconst sessionStatusSchema = z.object({ directory: directorySchema }).strict()\nconst sessionMessagesSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n limit: z.number().int().positive().max(1000).optional(),\n })\n .strict()\nconst textPartSchema = z\n .object({\n type: z.literal('text'),\n text: z.string().max(1_000_000),\n })\n .strict()\nconst filePartSchema = z\n .object({\n type: z.literal('file'),\n mime: z.string().min(1).max(256),\n filename: z.string().min(1).max(1024).optional(),\n url: z.string().min(1).max(8_000_000),\n })\n .strict()\nconst sessionPromptSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n messageID: z.string().min(1).max(256).optional(),\n model: z\n .object({\n providerID: z.string().min(1).max(128),\n modelID: z.string().min(1).max(256),\n })\n .strict()\n .optional(),\n agent: z.string().min(1).max(128).optional(),\n variant: z.string().min(1).max(128).optional(),\n noReply: z.boolean().optional(),\n system: z.string().max(100_000).optional(),\n tools: z.record(z.string().min(1).max(128), z.boolean()).optional(),\n parts: z.array(z.union([textPartSchema, filePartSchema])).min(1).max(100),\n })\n .strict()\nconst sessionAbortSchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n directory: directorySchema,\n })\n .strict()\nconst permissionReplySchema = z\n .object({\n sessionId: z.string().min(1).max(256),\n permissionId: z.string().min(1).max(256),\n directory: directorySchema,\n response: z.enum(['once', 'always', 'reject']),\n })\n .strict()\nconst providerListSchema = z.object({ directory: directorySchema }).strict()\nconst agentListSchema = z.object({ directory: directorySchema }).strict()\nconst permissionListSchema = z\n .object({\n directory: directorySchema,\n sessionId: z.string().min(1).max(256).optional(),\n })\n .strict()\nconst questionListSchema = z\n .object({\n directory: directorySchema,\n sessionId: z.string().min(1).max(256).optional(),\n })\n .strict()\nconst questionReplySchema = z\n .object({\n requestId: z.string().min(1).max(256),\n directory: directorySchema,\n answers: z\n .array(z.array(z.string().trim().min(1).max(8_000)).min(1).max(32))\n .min(1)\n .max(32),\n })\n .strict()\nconst questionRejectSchema = z\n .object({\n requestId: z.string().min(1).max(256),\n directory: directorySchema,\n })\n .strict()\n\ntype PromptPart = z.infer<typeof textPartSchema> | z.infer<typeof filePartSchema>\nexport type { PromptPart }\n\ntype AdapterEvent = {\n directory: string\n payload: { type: string; properties: Record<string, unknown> }\n}\n\nclass EventBus {\n private readonly queue: AdapterEvent[] = []\n private wake: (() => void) | null = null\n\n push(event: AdapterEvent): void {\n this.queue.push(event)\n this.wake?.()\n this.wake = null\n }\n\n async *stream(signal: AbortSignal): AsyncIterable<JsonValue> {\n while (!signal.aborted) {\n const next = this.queue.shift()\n if (next !== undefined) {\n yield toSafeJson(next)\n continue\n }\n await new Promise<void>((resolve) => {\n const done = () => {\n signal.removeEventListener('abort', done)\n this.wake = null\n resolve()\n }\n signal.addEventListener('abort', done, { once: true })\n this.wake = done\n })\n }\n }\n}\n\nfunction errorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : 'Codex request failed'\n return message.slice(0, 512)\n}\n\nexport function sessionView(record: CodexSessionRecord): Record<string, unknown> {\n return {\n id: record.id,\n projectID: record.projectID,\n directory: record.directory,\n title: record.title,\n version: record.version,\n time: { created: record.created, updated: record.updated },\n }\n}\n\nexport function discoveredSessionView(session: DiscoveredSession): Record<string, unknown> {\n return {\n id: session.id,\n projectID: projectId(session.directory),\n directory: session.directory,\n title: session.title,\n version: session.version,\n time: { created: session.created, updated: session.updated },\n }\n}\n\nexport function buildUserMessage(\n record: CodexSessionRecord,\n parts: PromptPart[],\n now = Date.now(),\n): MessageRecord {\n const info = {\n id: createMessageId(record),\n sessionID: record.id,\n role: 'user' as const,\n time: { created: now },\n }\n const messageParts: MessagePart[] = []\n for (const [index, part] of parts.entries()) {\n if (part.type === 'text') {\n messageParts.push({\n id: `${info.id}_${index}`,\n sessionID: record.id,\n messageID: info.id,\n type: 'text',\n text: part.text,\n })\n } else {\n const file: MessagePart = {\n id: `${info.id}_${index}`,\n sessionID: record.id,\n messageID: info.id,\n type: 'file',\n mime: part.mime,\n url: part.url,\n }\n if (part.filename) file.filename = part.filename\n messageParts.push(file)\n }\n }\n return { info, parts: messageParts }\n}\n\nexport function createAssistantMessage(\n record: CodexSessionRecord,\n now = Date.now(),\n): MessageRecord {\n const info = {\n id: createMessageId(record),\n sessionID: record.id,\n role: 'assistant' as const,\n time: { created: now },\n }\n return { info, parts: [] }\n}\n\nfunction activeAssistantMessage(record: CodexSessionRecord): MessageRecord | null {\n const last = record.messages[record.messages.length - 1]\n return last && last.info.role === 'assistant' ? last : null\n}\n\nfunction upsertStreamedPart(\n message: MessageRecord,\n part: MessagePart,\n lifecycle: 'started' | 'updated' | 'completed',\n now = Date.now(),\n): MessagePart {\n const index = message.parts.findIndex((existing) => existing.id === part.id)\n const existing = index === -1 ? undefined : message.parts[index]\n\n // The Codex SDK emits complete item snapshots, not text deltas. Preserve one\n // canonical part per item id and mark reasoning completion explicitly so the\n // UI does not leave an old \"Thinking\" block in a streaming state.\n if (part.type === 'reasoning') {\n const previousTime = existing?.time && typeof existing.time === 'object'\n ? existing.time as Record<string, unknown>\n : null\n const started = typeof previousTime?.start === 'number' ? previousTime.start : now\n part.time = lifecycle === 'completed'\n ? { start: started, end: now }\n : { start: started }\n }\n\n if (index === -1) message.parts.push(part)\n else message.parts[index] = part\n return part\n}\n\nexport function itemPart(record: CodexSessionRecord, item: ThreadItem): MessagePart | null {\n const message = activeAssistantMessage(record)\n if (!message) return null\n\n const base = {\n id: item.id,\n sessionID: record.id,\n messageID: message.info.id,\n }\n\n switch (item.type) {\n case 'agent_message':\n return { ...base, type: 'text', text: item.text }\n case 'reasoning':\n return { ...base, type: 'reasoning', text: item.text }\n case 'command_execution':\n return {\n ...base,\n type: 'tool',\n tool: 'bash',\n state: {\n status: item.status === 'in_progress' ? 'running'\n : item.status === 'failed' ? 'error'\n : 'completed',\n title: item.command.slice(0, 512),\n input: { command: item.command },\n ...(item.aggregated_output ? { output: item.aggregated_output } : {}),\n },\n }\n case 'file_change':\n return {\n ...base,\n type: 'tool',\n tool: 'edit',\n state: {\n status: item.status === 'failed' ? 'error' : 'completed',\n title: item.changes.length === 1\n ? `Edited ${item.changes[0].path}`\n : `Edited ${item.changes.length} files`,\n input: { changes: item.changes },\n },\n }\n case 'mcp_tool_call':\n return {\n ...base,\n type: 'tool',\n tool: item.tool,\n state: {\n status: item.status === 'in_progress' ? 'running'\n : item.status === 'failed' ? 'error'\n : 'completed',\n title: `${item.server}:${item.tool}`,\n input: { arguments: item.arguments },\n ...(item.error ? { error: item.error.message } : {}),\n },\n }\n case 'web_search':\n return {\n ...base,\n type: 'tool',\n tool: 'web_search',\n state: {\n status: 'completed',\n title: 'Web search',\n input: { query: item.query },\n },\n }\n case 'todo_list': {\n const completed = item.items.filter((todo) => todo.completed).length\n return {\n ...base,\n type: 'tool',\n tool: 'todo_list',\n state: {\n status: completed === item.items.length\n ? 'completed'\n : 'running',\n title: item.items.length > 0\n ? `Tasks ${completed}/${item.items.length}`\n : 'Tasks',\n input: { items: item.items },\n },\n }\n }\n case 'error':\n return {\n ...base,\n type: 'tool',\n tool: 'codex_error',\n state: {\n status: 'error',\n title: 'Codex error',\n input: {},\n error: item.message,\n },\n }\n }\n}\n\nexport function toUserInput(parts: PromptPart[]): Input {\n const input: Input = []\n for (const part of parts) {\n if (part.type === 'text' && typeof part.text === 'string' && part.text.length) {\n input.push({ type: 'text', text: part.text })\n } else if (part.type === 'file' && typeof part.url === 'string') {\n const path = part.url.replace(/^file:\\/\\//, '')\n if (path) input.push({ type: 'local_image', path })\n }\n }\n return input\n}\n\nexport type CodexAdapterOptions = {\n codex: Codex\n config: TumnelCodexConfig\n sessions: CodexSessionStore\n log?: (level: ConnectorLogLevel, message: string, extra?: Record<string, JsonValue>) => Promise<void> | void\n}\n\nfunction threadOptions(config: TumnelCodexConfig, directory: string, model?: string) {\n return {\n workingDirectory: directory,\n model: model ?? config.model,\n sandboxMode: config.sandboxMode,\n approvalPolicy: config.approvalPolicy,\n modelReasoningEffort: config.modelReasoningEffort,\n webSearchMode: config.webSearchMode,\n skipGitRepoCheck: config.skipGitRepoCheck,\n networkAccessEnabled: config.networkAccess,\n }\n}\n\nfunction ensureThread(\n codex: Codex,\n record: CodexSessionRecord,\n config: TumnelCodexConfig,\n model?: string,\n): Thread {\n const selectedModel = model ?? record.model ?? config.model\n if (record.thread && record.model === selectedModel) return record.thread\n record.model = selectedModel\n const workingDirectory = record.workingDirectory ?? record.directory\n if (record.codexThreadId) {\n record.thread = codex.resumeThread(\n record.codexThreadId,\n threadOptions(config, workingDirectory, selectedModel),\n )\n } else {\n record.thread = codex.startThread(threadOptions(config, workingDirectory, selectedModel))\n }\n return record.thread\n}\n\nexport function createCodexAdapter(options: CodexAdapterOptions): ConnectorAdapter {\n const { codex, config, sessions } = options\n const bus = new EventBus()\n const log: NonNullable<CodexAdapterOptions['log']> = options.log ?? (async () => undefined)\n const controllers = new WeakMap<CodexSessionRecord, AbortController>()\n\n const emit = (\n type: string,\n directory: string,\n properties: Record<string, unknown>,\n ): void => {\n bus.push({ directory, payload: { type, properties } })\n }\n\n const finishRun = (record: CodexSessionRecord, controller: AbortController): void => {\n controllers.delete(record)\n record.busy = false\n record.updated = Date.now()\n emit('session.updated', record.directory, { info: sessionView(record) })\n if (!record.failed) {\n emit('session.status', record.directory, { sessionID: record.id, status: { type: 'idle' } })\n }\n emit('session.idle', record.directory, { sessionID: record.id })\n void log('info', 'Codex turn finished', { sessionId: record.id })\n }\n\n const handleThreadEvent = (record: CodexSessionRecord, event: ThreadEvent): void => {\n switch (event.type) {\n case 'thread.started':\n record.codexThreadId = event.thread_id\n return\n case 'turn.completed': {\n const message = activeAssistantMessage(record)\n if (message) {\n message.info.time.completed = Date.now()\n emit('message.updated', record.directory, { info: message.info })\n }\n void log('info', 'Codex turn completed', {\n sessionId: record.id,\n inputTokens: event.usage.input_tokens,\n outputTokens: event.usage.output_tokens,\n })\n return\n }\n case 'turn.failed':\n record.failed = true\n emit('session.error', record.directory, { sessionID: record.id, message: event.error.message })\n return\n case 'item.started':\n case 'item.updated':\n case 'item.completed': {\n let message = activeAssistantMessage(record)\n if (!message) {\n message = createAssistantMessage(record)\n record.messages.push(message)\n emit('message.updated', record.directory, { info: message.info })\n }\n const part = itemPart(record, event.item)\n if (!part) return\n const lifecycle = event.type === 'item.started'\n ? 'started'\n : event.type === 'item.updated'\n ? 'updated'\n : 'completed'\n emit('message.part.updated', record.directory, {\n part: upsertStreamedPart(message, part, lifecycle),\n })\n return\n }\n case 'error':\n record.failed = true\n emit('session.error', record.directory, { sessionID: record.id, message: event.message })\n return\n }\n }\n\n const startRun = (record: CodexSessionRecord, input: Input, model?: string): void => {\n if (record.busy) throw new Error('Codex session is already running a turn')\n record.busy = true\n record.failed = false\n const controller = new AbortController()\n controllers.set(record, controller)\n const thread = ensureThread(codex, record, config, model)\n\n emit('session.status', record.directory, { sessionID: record.id, status: { type: 'busy' } })\n void log('info', 'Codex turn started', { sessionId: record.id })\n\n void (async () => {\n try {\n const { events } = await thread.runStreamed(input, { signal: controller.signal })\n for await (const event of events) handleThreadEvent(record, event)\n } catch (error) {\n if (!controller.signal.aborted) {\n record.failed = true\n emit('session.error', record.directory, {\n sessionID: record.id,\n message: errorMessage(error),\n })\n void log('warn', 'Codex turn failed', { sessionId: record.id, reason: errorMessage(error) })\n }\n } finally {\n finishRun(record, controller)\n }\n })()\n }\n\n return {\n async invoke(method, rawParams) {\n switch (method) {\n case 'device.health': {\n emptyParamsSchema.parse(rawParams)\n return {\n healthy: true,\n connector: 'codex',\n version: '0.1.0',\n model: config.model ?? null,\n }\n }\n case 'project.list': {\n const params = projectListSchema.parse(rawParams)\n const directory = params.directory || undefined\n const catalogProjects = await sessions.discoverProjects(directory)\n const records = sessions.list(directory)\n const discovered = await sessions.discoverAll(directory)\n const directories = new Map<string, { created: number; name?: string; order: number }>()\n for (const project of catalogProjects) {\n directories.set(project.directory, {\n created: project.created,\n name: project.name,\n order: project.order,\n })\n }\n for (const record of records) {\n const existing = directories.get(record.directory)\n if (existing === undefined || record.created < existing.created) {\n directories.set(record.directory, {\n created: record.created,\n name: existing?.name,\n order: existing?.order ?? Number.MAX_SAFE_INTEGER,\n })\n }\n }\n for (const session of discovered) {\n const existing = directories.get(session.directory)\n if (existing === undefined || session.created < existing.created) {\n directories.set(session.directory, {\n created: session.created,\n name: existing?.name,\n order: existing?.order ?? Number.MAX_SAFE_INTEGER,\n })\n }\n }\n return [...directories.entries()]\n .sort(([, left], [, right]) => left.order - right.order || left.created - right.created)\n .map(([worktree, project]) => ({\n id: projectId(worktree),\n ...(project.name ? { name: project.name } : {}),\n worktree,\n time: { created: project.created },\n }))\n }\n case 'session.list': {\n const params = sessionListSchema.parse(rawParams)\n const discovered = params.directory\n ? await sessions.discover(params.directory)\n : await sessions.discover()\n const views = [\n ...sessions.list(params.directory).map(sessionView),\n ...discovered.map(discoveredSessionView),\n ]\n return views.map(toSafeJson)\n }\n case 'session.create': {\n const params = sessionCreateSchema.parse(rawParams)\n if (!params.directory) throw new Error('session.create requires a directory')\n const record = sessions.create({\n id: createSessionId(),\n directory: params.directory,\n title: params.title,\n version: '0.1.0',\n model: config.model,\n })\n return toSafeJson(sessionView(record))\n }\n case 'session.fork':\n throw new Error('session.fork is not supported by the Codex connector')\n case 'session.delete': {\n const params = sessionDeleteSchema.parse(rawParams)\n const record = sessions.get(params.sessionId)\n if (record) {\n emit('session.deleted', record.directory, { info: sessionView(record) })\n sessions.remove(record.id)\n }\n return true\n }\n case 'session.status': {\n const params = sessionStatusSchema.parse(rawParams)\n const statuses: Record<string, { type: 'idle' | 'busy' | 'error' }> = {}\n for (const record of sessions.list(params.directory)) {\n statuses[record.id] = {\n type: record.busy ? 'busy' : record.failed ? 'error' : 'idle',\n }\n }\n return statuses\n }\n case 'session.messages': {\n const params = sessionMessagesSchema.parse(rawParams)\n const record = sessions.get(params.sessionId)\n if (!record) {\n const history = await sessions.loadHistory(params.sessionId, params.directory)\n if (!history) return []\n const messages = params.limit\n ? history.messages.slice(-params.limit)\n : history.messages\n return toSafeJson(messages)\n }\n const messages = params.limit ? record.messages.slice(-params.limit) : record.messages\n return toSafeJson(messages.map((message) => ({ info: message.info, parts: message.parts })))\n }\n case 'session.prompt': {\n const params = sessionPromptSchema.parse(rawParams)\n const selectedModel = params.model\n ? params.model.providerID === 'codex'\n ? params.model.modelID\n : (() => {\n throw new Error(`Codex does not support provider ${params.model?.providerID}`)\n })()\n : undefined\n let record = sessions.get(params.sessionId)\n if (!record) {\n const discovered = await sessions.discover(params.directory)\n const session = discovered.find((item) => item.id === params.sessionId)\n if (!session) throw new Error(`Unknown Codex session ${params.sessionId}`)\n const history = await sessions.loadHistory(session.id, session.directory)\n record = sessions.create({\n id: params.sessionId,\n directory: session.directory,\n workingDirectory: session.workingDirectory,\n title: history?.title ?? session.title,\n version: session.version,\n codexThreadId: session.id,\n model: selectedModel ?? config.model,\n messages: history?.messages,\n })\n }\n const userMessage = buildUserMessage(record, params.parts)\n record.messages.push(userMessage)\n emit('message.updated', record.directory, { info: userMessage.info })\n startRun(record, toUserInput(params.parts), selectedModel)\n return { accepted: true }\n }\n case 'session.abort': {\n const params = sessionAbortSchema.parse(rawParams)\n const record = sessions.get(params.sessionId)\n const controller = record ? controllers.get(record) : undefined\n controller?.abort()\n return { accepted: true }\n }\n case 'provider.list': {\n providerListSchema.parse(rawParams)\n if (!config.model) return toSafeJson({ default: {}, providers: [] })\n return toSafeJson({\n default: { codex: config.model },\n providers: [\n {\n id: 'codex',\n name: 'Codex',\n models: [\n {\n id: config.model,\n name: config.model,\n attachment: false,\n reasoning: true,\n toolCall: true,\n status: 'active',\n variants: [],\n },\n ],\n },\n ],\n })\n }\n case 'agent.list': {\n agentListSchema.parse(rawParams)\n return []\n }\n case 'permission.list': {\n permissionListSchema.parse(rawParams)\n return []\n }\n case 'permission.reply': {\n permissionReplySchema.parse(rawParams)\n return true\n }\n case 'question.list': {\n questionListSchema.parse(rawParams)\n return []\n }\n case 'question.reply': {\n questionReplySchema.parse(rawParams)\n throw new Error('The Codex connector does not support interactive questions')\n }\n case 'question.reject': {\n questionRejectSchema.parse(rawParams)\n throw new Error('The Codex connector does not support interactive questions')\n }\n case 'event.subscribe': {\n emptyParamsSchema.parse(rawParams)\n return { subscribed: true }\n }\n }\n },\n\n async *events(signal) {\n yield* bus.stream(signal)\n },\n\n async log(level, message, extra) {\n await log(level, message, extra)\n },\n }\n}\n","import { createHash, randomBytes } from 'node:crypto'\nimport { createReadStream } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { readFile, readdir, stat } from 'node:fs/promises'\nimport { z } from 'zod'\nimport type { Thread } from '@openai/codex-sdk'\n\nexport type MessagePart = Record<string, unknown> & {\n id: string\n sessionID: string\n messageID: string\n type: string\n}\n\nexport type MessageInfo = {\n id: string\n sessionID: string\n role: 'user' | 'assistant'\n time: { created: number; completed?: number }\n}\n\nexport type MessageRecord = {\n info: MessageInfo\n parts: MessagePart[]\n}\n\nexport type CodexSessionRecord = {\n id: string\n projectID: string\n directory: string\n workingDirectory?: string\n title: string\n version: string\n created: number\n updated: number\n thread: Thread | null\n codexThreadId: string | null\n model?: string\n busy: boolean\n failed: boolean\n messages: MessageRecord[]\n messageIndex: number\n}\n\nexport type DiscoveredSession = {\n id: string\n directory: string\n workingDirectory?: string\n version: string\n created: number\n updated: number\n title: string\n rolloutPath: string\n}\n\nexport type DiscoveredProject = {\n id: string\n name?: string\n directory: string\n created: number\n updated: number\n order: number\n}\n\ntype RolloutJson = {\n timestamp?: unknown\n type?: unknown\n payload?: unknown\n}\n\ntype RolloutPayload = Record<string, unknown> & { type?: unknown }\n\nconst sessionMetaSchema = z.object({\n type: z.literal('session_meta'),\n payload: z\n .object({\n session_id: z.string().min(1).optional(),\n id: z.string().min(1).optional(),\n cwd: z.string().min(1).optional(),\n timestamp: z.string().optional(),\n cli_version: z.string().min(1).optional(),\n })\n .passthrough(),\n})\n\nexport function defaultSessionsDir(environment: NodeJS.ProcessEnv = process.env): string {\n return join(defaultCodexHome(environment), 'sessions')\n}\n\nexport function defaultCodexHome(environment: NodeJS.ProcessEnv = process.env): string {\n return environment.CODEX_HOME ?? join(homedir(), '.codex')\n}\n\nexport function projectId(directory: string): string {\n const hash = createHash('sha256').update(directory.toLowerCase()).digest('base64url').slice(0, 12)\n return `project_${hash}`\n}\n\nexport function createSessionId(): string {\n return `codex_${randomBytes(9).toString('base64url')}`\n}\n\nexport function createMessageId(record: CodexSessionRecord): string {\n record.messageIndex += 1\n return `message_${record.messageIndex}`\n}\n\nasync function readFirstLine(path: string): Promise<string | null> {\n return new Promise((resolve) => {\n const stream = createReadStream(path, { encoding: 'utf8', highWaterMark: 64 * 1024 })\n let buffer = ''\n stream.on('data', (chunk: string) => {\n buffer += chunk\n const newline = buffer.indexOf('\\n')\n if (newline !== -1) {\n stream.destroy()\n resolve(buffer.slice(0, newline))\n return\n }\n if (buffer.length > 512 * 1024) {\n stream.destroy()\n resolve(buffer)\n return\n }\n })\n stream.on('error', () => resolve(null))\n stream.on('end', () => resolve(buffer.length ? buffer : null))\n })\n}\n\nasync function readRolloutTitle(path: string, fallback: string): Promise<string> {\n let source: string\n try {\n source = await readFile(path, 'utf8')\n } catch {\n return fallback\n }\n\n let title = fallback\n for (const line of source.split(/\\r?\\n/)) {\n if (!line.trim()) continue\n try {\n const outer = JSON.parse(line) as RolloutJson\n const payload = asRecord(outer.payload)\n if (stringValue(payload?.type) !== 'thread_name_updated') continue\n title = stringValue(payload?.thread_name) ?? title\n } catch {\n // A partially written rollout should not prevent the rest of the catalog loading.\n }\n }\n return title\n}\n\ntype SessionIndexEntry = {\n thread_name?: string\n updated_at?: string\n}\n\nasync function readSessionIndex(path: string): Promise<Map<string, SessionIndexEntry>> {\n const result = new Map<string, SessionIndexEntry>()\n let source: string\n try {\n source = await readFile(path, 'utf8')\n } catch {\n return result\n }\n\n for (const line of source.split(/\\r?\\n/)) {\n if (!line.trim()) continue\n try {\n const value = JSON.parse(line) as Record<string, unknown>\n const id = stringValue(value.id)\n if (!id) continue\n result.set(id, {\n thread_name: stringValue(value.thread_name) ?? undefined,\n updated_at: stringValue(value.updated_at) ?? undefined,\n })\n } catch {\n // Ignore partially-written index entries.\n }\n }\n return result\n}\n\nasync function readGlobalProjects(path: string): Promise<DiscoveredProject[]> {\n let source: string\n try {\n source = await readFile(path, 'utf8')\n } catch {\n return []\n }\n\n try {\n const root = asRecord(JSON.parse(source))\n const projects = asRecord(root?.['local-projects'])\n const order = Array.isArray(root?.['project-order'])\n ? root?.['project-order'].filter((value): value is string => typeof value === 'string')\n : []\n const orderById = new Map(order.map((id, index) => [id, index]))\n const result: DiscoveredProject[] = []\n for (const [id, value] of Object.entries(projects ?? {})) {\n const project = asRecord(value)\n const name = stringValue(project?.name) ?? undefined\n const roots = Array.isArray(project?.rootPaths)\n ? project.rootPaths.filter((path): path is string => typeof path === 'string' && path.length > 0)\n : []\n if (!roots.length) continue\n const created = timestampValue(project?.createdAt, 0)\n const updated = timestampValue(project?.updatedAt, created)\n for (const directory of roots) {\n result.push({\n id,\n name,\n directory,\n created,\n updated,\n order: orderById.get(id) ?? Number.MAX_SAFE_INTEGER,\n })\n }\n }\n return result.sort((left, right) => left.order - right.order || left.created - right.created)\n } catch {\n return []\n }\n}\n\nasync function readGlobalSessionAssignments(path: string): Promise<Map<string, string>> {\n let source: string\n try {\n source = await readFile(path, 'utf8')\n } catch {\n return new Map()\n }\n try {\n const root = asRecord(JSON.parse(source))\n const assignments = asRecord(root?.['thread-project-assignments'])\n const result = new Map<string, string>()\n for (const [threadId, value] of Object.entries(assignments ?? {})) {\n const assignment = asRecord(value)\n const projectId = stringValue(assignment?.projectId)\n const projectKind = stringValue(assignment?.projectKind)\n if (projectId && (!projectKind || projectKind === 'local')) result.set(threadId, projectId)\n }\n return result\n } catch {\n return new Map()\n }\n}\n\nasync function walkRollouts(dir: string): Promise<string[]> {\n let entries\n try {\n entries = await readdir(dir, { withFileTypes: true })\n } catch {\n return []\n }\n\n const results: string[] = []\n for (const entry of entries) {\n const path = join(dir, entry.name)\n if (entry.isDirectory()) results.push(...(await walkRollouts(path)))\n else if (entry.isFile() && entry.name.endsWith('.jsonl')) results.push(path)\n }\n return results\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n ? value as Record<string, unknown>\n : null\n}\n\nfunction stringValue(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null\n}\n\nfunction timestampValue(value: unknown, fallback: number): number {\n if (typeof value === 'number' && Number.isFinite(value)) return value\n if (typeof value === 'string') {\n const parsed = Date.parse(value)\n if (Number.isFinite(parsed)) return parsed\n }\n return fallback\n}\n\nfunction textFromValue(value: unknown): string | null {\n if (typeof value === 'string') return value\n if (Array.isArray(value)) {\n const text = value\n .map((item) => textFromValue(item))\n .filter((item): item is string => item !== null)\n .join('')\n return text || null\n }\n const record = asRecord(value)\n if (!record) return null\n for (const key of ['text', 'message', 'content', 'output_text']) {\n const text = textFromValue(record[key])\n if (text !== null) return text\n }\n return null\n}\n\nfunction parseJsonValue(value: unknown): unknown {\n if (typeof value !== 'string') return value\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\nfunction historyMessageId(sessionId: string, index: number): string {\n return `history_${sessionId}_${index}`\n}\n\nfunction historyPartId(sessionId: string, index: number, partIndex: number): string {\n return `history_${sessionId}_${index}_${partIndex}`\n}\n\nfunction createHistoryMessage(\n sessionId: string,\n index: number,\n role: MessageInfo['role'],\n created: number,\n): MessageRecord {\n return {\n info: {\n id: historyMessageId(sessionId, index),\n sessionID: sessionId,\n role,\n time: { created, completed: role === 'assistant' ? created : undefined },\n },\n parts: [],\n }\n}\n\nfunction addHistoryText(\n message: MessageRecord,\n sessionId: string,\n partIndex: number,\n type: 'text' | 'reasoning',\n text: string,\n): void {\n if (!text.trim()) return\n message.parts.push({\n id: historyPartId(sessionId, Number(message.info.id.split('_').at(-1) ?? 0), partIndex),\n sessionID: sessionId,\n messageID: message.info.id,\n type,\n text,\n })\n}\n\nfunction localFileUrl(value: unknown): string | null {\n const path = stringValue(value)\n if (!path) return null\n return path.startsWith('file://') ? path : `file://${path}`\n}\n\nexport type RolloutHistory = {\n messages: MessageRecord[]\n title: string\n updated: number\n}\n\n/**\n * Rebuilds the user-visible portion of a Codex rollout. Codex stores internal\n * context messages in the same JSONL file, so only the public user/agent/tool\n * events are translated into the bridge message shape.\n */\nexport async function readRolloutHistory(\n path: string,\n sessionId: string,\n): Promise<RolloutHistory> {\n let source: string\n let updated = 0\n try {\n source = await readFile(path, 'utf8')\n updated = (await stat(path)).mtimeMs\n } catch {\n return { messages: [], title: '(untitled session)', updated }\n }\n\n const messages: MessageRecord[] = []\n const toolParts = new Map<string, MessagePart>()\n let title = '(untitled session)'\n let messageIndex = 0\n let lastAssistant: MessageRecord | null = null\n\n const ensureAssistant = (created: number): MessageRecord => {\n if (lastAssistant) return lastAssistant\n const message = createHistoryMessage(sessionId, messageIndex++, 'assistant', created)\n messages.push(message)\n lastAssistant = message\n return message\n }\n\n for (const line of source.split(/\\r?\\n/)) {\n if (!line.trim()) continue\n let outer: RolloutJson\n try {\n outer = JSON.parse(line) as RolloutJson\n } catch {\n continue\n }\n const payload = asRecord(outer.payload)\n if (!payload) continue\n const type = stringValue(payload.type)\n const created = timestampValue(outer.timestamp, updated || Date.now())\n\n if (type === 'user_message') {\n const text = stringValue(payload.message)\n const message = createHistoryMessage(sessionId, messageIndex++, 'user', created)\n if (text) addHistoryText(message, sessionId, 0, 'text', text)\n const localImages = Array.isArray(payload.local_images) ? payload.local_images : []\n for (const [index, image] of localImages.entries()) {\n const url = localFileUrl(image)\n if (!url) continue\n message.parts.push({\n id: historyPartId(sessionId, Number(message.info.id.split('_').at(-1) ?? 0), index + 1),\n sessionID: sessionId,\n messageID: message.info.id,\n type: 'file',\n url,\n })\n }\n if (message.parts.length) messages.push(message)\n lastAssistant = null\n continue\n }\n\n if (type === 'agent_message') {\n const text = stringValue(payload.message)\n if (!text) continue\n const message = createHistoryMessage(sessionId, messageIndex++, 'assistant', created)\n addHistoryText(message, sessionId, Number(message.info.id.split('_').at(-1) ?? 0), 'text', text)\n messages.push(message)\n lastAssistant = message\n continue\n }\n\n if (type === 'reasoning') {\n const text = textFromValue(payload.summary) ?? textFromValue(payload.content)\n if (!text) continue\n const message = ensureAssistant(created)\n addHistoryText(message, sessionId, message.parts.length, 'reasoning', text)\n continue\n }\n\n if (type === 'thread_name_updated') {\n title = stringValue(payload.thread_name) ?? title\n continue\n }\n\n if (type === 'function_call' || type === 'custom_tool_call') {\n const message = ensureAssistant(created)\n const callId = stringValue(payload.call_id) ?? `${sessionId}:${message.parts.length}`\n const name = stringValue(payload.name) ?? (type === 'function_call' ? 'function' : 'tool')\n const input = parseJsonValue(payload.arguments ?? payload.input)\n const part: MessagePart = {\n id: `history_${callId}`,\n sessionID: sessionId,\n messageID: message.info.id,\n type: 'tool',\n tool: name,\n state: {\n status: 'running',\n title: name,\n input: { arguments: input },\n },\n }\n message.parts.push(part)\n toolParts.set(callId, part)\n continue\n }\n\n if (type === 'function_call_output' || type === 'custom_tool_call_output') {\n const callId = stringValue(payload.call_id)\n if (!callId) continue\n const part = toolParts.get(callId)\n if (!part) continue\n const state = asRecord(part.state) ?? {}\n part.state = {\n ...state,\n status: 'completed',\n output: payload.output ?? payload.result ?? null,\n }\n continue\n }\n\n if (type === 'exec_command_end') {\n const callId = stringValue(payload.call_id)\n const part = callId ? toolParts.get(callId) : undefined\n if (!part) continue\n const state = asRecord(part.state) ?? {}\n part.state = {\n ...state,\n status: payload.exit_code === 0 ? 'completed' : 'error',\n ...(payload.aggregated_output !== undefined\n ? { output: payload.aggregated_output }\n : {}),\n }\n }\n }\n\n for (const message of messages) {\n if (message.info.role === 'assistant') {\n message.info.time.completed ??= updated || message.info.time.created\n }\n }\n return { messages, title, updated }\n}\n\nexport async function discoverSessions(\n sessionsDir: string,\n sessionIndexPath = join(dirname(sessionsDir), 'session_index.jsonl'),\n projectRootsById = new Map<string, string>(),\n projectAssignments = new Map<string, string>(),\n): Promise<DiscoveredSession[]> {\n const rollouts = await walkRollouts(sessionsDir)\n const index = await readSessionIndex(sessionIndexPath)\n const sessions: DiscoveredSession[] = []\n\n for (const path of rollouts) {\n const line = await readFirstLine(path)\n if (!line) continue\n\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch {\n continue\n }\n const result = sessionMetaSchema.safeParse(parsed)\n if (!result.success) continue\n const meta = result.data.payload\n const id = meta.session_id ?? meta.id\n if (!id) continue\n\n const workingDirectory = meta.cwd\n const assignedProjectId = projectAssignments.get(id)\n const directory = (assignedProjectId ? projectRootsById.get(assignedProjectId) : undefined) ?? workingDirectory\n if (!directory) continue\n\n const created = meta.timestamp ? Date.parse(meta.timestamp) : NaN\n let mtime = created\n try {\n const info = await stat(path)\n mtime = info.mtimeMs\n } catch {\n mtime = Number.isFinite(created) ? created : 0\n }\n\n const indexed = index.get(id)\n const indexedUpdated = indexed?.updated_at ? Date.parse(indexed.updated_at) : NaN\n sessions.push({\n id,\n directory,\n ...(workingDirectory && workingDirectory !== directory ? { workingDirectory } : {}),\n version: meta.cli_version ?? 'unknown',\n created: Number.isFinite(created) ? created : mtime,\n updated: Number.isFinite(indexedUpdated) ? Math.max(mtime, indexedUpdated) : mtime,\n title: await readRolloutTitle(path, indexed?.thread_name ?? '(untitled session)'),\n rolloutPath: path,\n })\n }\n\n return sessions\n}\n\nexport class CodexSessionStore {\n private readonly records = new Map<string, CodexSessionRecord>()\n private readonly discoveryCache: { at: number; byDirectory: Map<string, DiscoveredSession[]> } = {\n at: 0,\n byDirectory: new Map(),\n }\n\n private readonly projectCache: {\n at: number\n projects: DiscoveredProject[]\n rootsById: Map<string, string>\n assignments: Map<string, string>\n } = {\n at: 0,\n projects: [],\n rootsById: new Map(),\n assignments: new Map(),\n }\n\n constructor(readonly sessionsDir: string = defaultSessionsDir()) {}\n\n create(input: {\n id: string\n directory: string\n workingDirectory?: string\n title?: string\n version: string\n thread?: Thread | null\n codexThreadId?: string | null\n model?: string\n messages?: MessageRecord[]\n }): CodexSessionRecord {\n const now = Date.now()\n const record: CodexSessionRecord = {\n id: input.id,\n projectID: projectId(input.directory),\n directory: input.directory,\n workingDirectory: input.workingDirectory,\n title: input.title ?? '(untitled session)',\n version: input.version,\n created: now,\n updated: now,\n thread: input.thread ?? null,\n codexThreadId: input.codexThreadId ?? null,\n model: input.model,\n busy: false,\n failed: false,\n messages: input.messages ?? [],\n messageIndex: input.messages?.length ?? 0,\n }\n this.records.set(record.id, record)\n return record\n }\n\n get(id: string): CodexSessionRecord | undefined {\n return this.records.get(id)\n }\n\n has(id: string): boolean {\n return this.records.has(id)\n }\n\n list(directory?: string): CodexSessionRecord[] {\n const all = [...this.records.values()]\n return directory ? all.filter((record) => samePath(record.directory, directory)) : all\n }\n\n remove(id: string): boolean {\n return this.records.delete(id)\n }\n\n touch(id: string): void {\n const record = this.records.get(id)\n if (record) record.updated = Date.now()\n }\n\n private async refreshDiscovery(): Promise<void> {\n const now = Date.now()\n if (this.discoveryCache.at !== 0 && now - this.discoveryCache.at <= 30_000) return\n await this.refreshProjectCatalog(now)\n const discovered = await discoverSessions(\n this.sessionsDir,\n join(dirname(this.sessionsDir), 'session_index.jsonl'),\n this.projectCache.rootsById,\n this.projectCache.assignments,\n )\n const byDirectory = new Map<string, DiscoveredSession[]>()\n for (const session of discovered) {\n const list = byDirectory.get(session.directory) ?? []\n list.push(session)\n byDirectory.set(session.directory, list)\n }\n this.discoveryCache.at = now\n this.discoveryCache.byDirectory = byDirectory\n }\n\n async discoverAll(directory?: string): Promise<DiscoveredSession[]> {\n await this.refreshDiscovery()\n return directory\n ? [...this.discoveryCache.byDirectory.entries()]\n .filter(([dir]) => samePath(dir, directory))\n .flatMap(([, sessions]) => sessions)\n : [...this.discoveryCache.byDirectory.values()].flat()\n }\n\n async discoverProjects(directory?: string): Promise<DiscoveredProject[]> {\n const now = Date.now()\n await this.refreshProjectCatalog(now)\n return directory\n ? this.projectCache.projects.filter((project) => samePath(project.directory, directory))\n : [...this.projectCache.projects]\n }\n\n private async refreshProjectCatalog(now = Date.now()): Promise<void> {\n if (this.projectCache.at !== 0 && now - this.projectCache.at <= 30_000) return\n const globalStatePath = join(dirname(this.sessionsDir), '.codex-global-state.json')\n const projects = await readGlobalProjects(globalStatePath)\n const rootsById = new Map<string, string>()\n for (const project of projects) {\n if (!rootsById.has(project.id)) rootsById.set(project.id, project.directory)\n }\n this.projectCache.projects = projects\n this.projectCache.rootsById = rootsById\n this.projectCache.assignments = await readGlobalSessionAssignments(globalStatePath)\n this.projectCache.at = now\n }\n\n async discover(directory?: string): Promise<DiscoveredSession[]> {\n const matching = await this.discoverAll(directory)\n\n const liveThreadIds = new Set(\n [...this.records.values()]\n .map((record) => record.codexThreadId)\n .filter((id): id is string => Boolean(id)),\n )\n return matching.filter((session) => !liveThreadIds.has(session.id))\n }\n\n async loadHistory(sessionId: string, directory?: string): Promise<RolloutHistory | null> {\n const discovered = (await this.discoverAll(directory)).find((session) => session.id === sessionId)\n if (!discovered) return null\n return readRolloutHistory(discovered.rolloutPath, discovered.id)\n }\n\n directories(): string[] {\n const directories = new Set(this.list().map((record) => record.directory))\n for (const session of this.discoveryCache.byDirectory.values()) {\n for (const record of session) directories.add(record.directory)\n }\n return [...directories]\n }\n}\n\nfunction samePath(left: string, right: string): boolean {\n if (process.platform === 'win32') return left.toLowerCase() === right.toLowerCase()\n return left === right\n}\n","import type { JsonValue } from '@openbridge/protocol'\n\nconst sensitiveKey = /(?:api[-_]?key|access[-_]?token|refresh[-_]?token|authorization|credential|password|private[-_]?key|secret)/i\n\nexport function toSafeJson(value: unknown): JsonValue {\n return visit(value, new WeakSet<object>(), 0)\n}\n\nfunction visit(value: unknown, seen: WeakSet<object>, depth: number): JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value\n if (typeof value === 'number') return Number.isFinite(value) ? value : String(value)\n if (typeof value === 'bigint') return value.toString()\n if (typeof value === 'undefined' || typeof value === 'function' || typeof value === 'symbol') {\n return null\n }\n if (depth >= 30) return '[Maximum depth reached]'\n if (value instanceof Date) return value.toISOString()\n if (value instanceof Error) {\n return { name: value.name, message: value.message }\n }\n if (ArrayBuffer.isView(value)) {\n return `[${value.constructor.name} omitted]`\n }\n if (value instanceof ArrayBuffer) return '[ArrayBuffer omitted]'\n if (typeof value !== 'object') return String(value)\n if (seen.has(value)) return '[Circular]'\n\n seen.add(value)\n\n if (Array.isArray(value)) {\n const result = value.map((entry) => visit(entry, seen, depth + 1))\n seen.delete(value)\n return result\n }\n\n const result: Record<string, JsonValue> = {}\n for (const [key, entry] of Object.entries(value)) {\n if (sensitiveKey.test(key)) {\n result[key] = '[REDACTED]'\n continue\n }\n if (typeof entry === 'undefined' || typeof entry === 'function' || typeof entry === 'symbol') continue\n result[key] = visit(entry, seen, depth + 1)\n }\n\n seen.delete(value)\n return result\n}\n","import { z } from 'zod'\n\nexport const BRIDGE_PROTOCOL_VERSION = 1 as const\n\nexport const bridgeRoleSchema = z.enum(['device', 'browser'])\nexport type BridgeRole = z.infer<typeof bridgeRoleSchema>\n\nexport const deviceIdSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[a-zA-Z0-9._:-]+$/, 'Device ID contains unsupported characters')\n\nexport const clientIdSchema = z\n .string()\n .min(1)\n .max(128)\n .regex(/^[a-zA-Z0-9._:-]+$/, 'Client ID contains unsupported characters')\n\nexport const base64UrlSchema = z\n .string()\n .min(16)\n .max(512)\n .regex(/^[A-Za-z0-9_-]+$/, 'Value must use unpadded base64url encoding')\n\nexport const deviceAuthProofSchema = z\n .object({\n deviceId: deviceIdSchema,\n publicKey: z.string().min(32).max(512),\n timestamp: z.number().int().positive(),\n nonce: base64UrlSchema.max(128),\n signature: base64UrlSchema,\n })\n .strict()\n\nexport const pairingClientSchema = z\n .object({\n clientId: clientIdSchema,\n label: z.string().trim().min(1).max(80).optional(),\n })\n .strict()\n\nexport const pairingStartRequestSchema = z\n .object({\n proof: deviceAuthProofSchema,\n client: pairingClientSchema,\n })\n .strict()\n\nexport const pairingHostStartRequestSchema = pairingClientSchema\n\nexport const pairingClaimRequestSchema = z\n .object({\n ticket: base64UrlSchema.max(128),\n client: pairingClientSchema,\n })\n .strict()\n\nexport const pairingStartResponseSchema = z\n .object({\n deviceId: deviceIdSchema,\n pairingId: base64UrlSchema.max(128),\n pairUrl: z.string().url(),\n expiresAt: z.number().int().positive(),\n deviceOnline: z.boolean(),\n })\n .strict()\n\nexport const pairingClaimResponseSchema = z\n .object({\n deviceId: deviceIdSchema,\n authorized: z.literal(true),\n })\n .strict()\n\nexport const pairingRevokeRequestSchema = z\n .object({\n clientId: clientIdSchema,\n })\n .strict()\n\nexport const pairingRevokeResponseSchema = z\n .object({\n revoked: z.literal(true),\n })\n .strict()\n\nexport const pairedDeviceSchema = z\n .object({\n clientId: clientIdSchema,\n label: z.string().nullable(),\n online: z.boolean(),\n pairedAt: z.number().int().positive(),\n })\n .strict()\n\nexport const pairedDevicesResponseSchema = z\n .object({\n devices: z.array(pairedDeviceSchema),\n })\n .strict()\n\nexport type DeviceAuthProof = z.infer<typeof deviceAuthProofSchema>\nexport type PairingClient = z.infer<typeof pairingClientSchema>\nexport type PairingStartRequest = z.infer<typeof pairingStartRequestSchema>\nexport type PairingHostStartRequest = z.infer<typeof pairingHostStartRequestSchema>\nexport type PairingClaimRequest = z.infer<typeof pairingClaimRequestSchema>\nexport type PairingStartResponse = z.infer<typeof pairingStartResponseSchema>\nexport type PairingClaimResponse = z.infer<typeof pairingClaimResponseSchema>\nexport type PairingRevokeRequest = z.infer<typeof pairingRevokeRequestSchema>\nexport type PairingRevokeResponse = z.infer<typeof pairingRevokeResponseSchema>\nexport type PairedDevice = z.infer<typeof pairedDeviceSchema>\nexport type PairedDevicesResponse = z.infer<typeof pairedDevicesResponseSchema>\n\nexport const bridgeConnectionSchema = z.object({\n role: bridgeRoleSchema,\n clientId: clientIdSchema,\n})\n\nexport const bridgeMethodSchema = z.enum([\n 'device.health',\n 'project.list',\n 'session.list',\n 'session.create',\n 'session.fork',\n 'session.delete',\n 'session.status',\n 'session.messages',\n 'session.prompt',\n 'session.abort',\n 'provider.list',\n 'agent.list',\n 'permission.list',\n 'permission.reply',\n 'question.list',\n 'question.reply',\n 'question.reject',\n 'event.subscribe',\n])\nexport type BridgeMethod = z.infer<typeof bridgeMethodSchema>\n\nexport type JsonValue =\n | null\n | boolean\n | number\n | string\n | JsonValue[]\n | { [key: string]: JsonValue }\n\nexport const jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() =>\n z.union([\n z.null(),\n z.boolean(),\n z.number(),\n z.string(),\n z.array(jsonValueSchema),\n z.record(z.string(), jsonValueSchema),\n ]),\n)\n\nconst messageBase = {\n version: z.literal(BRIDGE_PROTOCOL_VERSION),\n}\n\nexport const bridgeHelloSchema = z\n .object({\n ...messageBase,\n type: z.literal('device.hello'),\n clientId: clientIdSchema,\n agentVersion: z.string().min(1).max(64),\n connectorId: z.string().min(1).max(64).default('opencode'),\n })\n .strict()\n\nexport const bridgeRequestSchema = z\n .object({\n ...messageBase,\n type: z.literal('request'),\n id: z.string().min(1).max(128),\n connectorId: z.string().min(1).max(64).optional(),\n method: bridgeMethodSchema,\n params: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeErrorSchema = z\n .object({\n code: z.enum([\n 'INVALID_MESSAGE',\n 'ROLE_NOT_ALLOWED',\n 'DEVICE_OFFLINE',\n 'REQUEST_NOT_FOUND',\n 'DUPLICATE_REQUEST',\n 'SESSION_BUSY',\n 'INTERNAL_ERROR',\n ]),\n message: z.string().min(1).max(512),\n })\n .strict()\n\nexport const bridgeSuccessResponseSchema = z\n .object({\n ...messageBase,\n type: z.literal('response'),\n id: z.string().min(1).max(128),\n ok: z.literal(true),\n result: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeFailureResponseSchema = z\n .object({\n ...messageBase,\n type: z.literal('response'),\n id: z.string().min(1).max(128),\n ok: z.literal(false),\n error: bridgeErrorSchema,\n })\n .strict()\n\nexport const bridgeResponseSchema = z.union([\n bridgeSuccessResponseSchema,\n bridgeFailureResponseSchema,\n])\n\nexport const bridgeEventSchema = z\n .object({\n ...messageBase,\n type: z.literal('event'),\n connectorId: z.string().min(1).max(64).optional(),\n event: z.string().min(1).max(128),\n payload: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeSystemSchema = z\n .object({\n ...messageBase,\n type: z.literal('system'),\n event: z.enum([\n 'connection.ready',\n 'presence.changed',\n 'pairing.claimed',\n 'protocol.error',\n ]),\n payload: jsonValueSchema,\n })\n .strict()\n\nexport const bridgeMessageSchema = z.union([\n bridgeHelloSchema,\n bridgeRequestSchema,\n bridgeResponseSchema,\n bridgeEventSchema,\n bridgeSystemSchema,\n])\n\nexport type BridgeHello = z.infer<typeof bridgeHelloSchema>\nexport type BridgeRequest = z.infer<typeof bridgeRequestSchema>\nexport type BridgeResponse = z.infer<typeof bridgeResponseSchema>\nexport type BridgeEvent = z.infer<typeof bridgeEventSchema>\nexport type BridgeSystemMessage = z.infer<typeof bridgeSystemSchema>\nexport type BridgeMessage = z.infer<typeof bridgeMessageSchema>\nexport type BridgeError = z.infer<typeof bridgeErrorSchema>\n\nexport type BridgeParseResult =\n | { ok: true; message: BridgeMessage }\n | { ok: false; error: BridgeError }\n\nexport function parseBridgeMessage(value: string): BridgeParseResult {\n let parsed: unknown\n\n try {\n parsed = JSON.parse(value)\n } catch {\n return {\n ok: false,\n error: {\n code: 'INVALID_MESSAGE',\n message: 'Message must be valid JSON',\n },\n }\n }\n\n const result = bridgeMessageSchema.safeParse(parsed)\n if (!result.success) {\n return {\n ok: false,\n error: {\n code: 'INVALID_MESSAGE',\n message: result.error.issues[0]?.message ?? 'Message does not match the bridge protocol',\n },\n }\n }\n\n return { ok: true, message: result.data }\n}\n\nexport function encodeBridgeMessage(message: BridgeMessage): string {\n return JSON.stringify(bridgeMessageSchema.parse(message))\n}\n","import {\n createHash,\n createPrivateKey,\n createPublicKey,\n generateKeyPairSync,\n randomBytes,\n sign,\n verify,\n} from 'node:crypto'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\nimport { mkdir, open, readFile } from 'node:fs/promises'\nimport { z } from 'zod'\nimport type { DeviceAuthProof } from '@openbridge/protocol'\n\nconst DEVICE_PROOF_PREFIX = 'tumnel-device-proof-v1'\n\nconst identitySchema = z\n .object({\n version: z.literal(1),\n deviceId: z.string().regex(/^device_[A-Za-z0-9_-]{32,64}$/),\n publicKey: z.string().min(1),\n privateKey: z.string().min(1),\n createdAt: z.string().datetime(),\n })\n .strict()\n\nexport type DeviceIdentity = z.infer<typeof identitySchema>\n\nexport function defaultIdentityPath(environment: NodeJS.ProcessEnv = process.env): string {\n const configRoot =\n environment.TUMNEL_CONFIG_DIR ??\n environment.XDG_CONFIG_HOME ??\n (process.platform === 'win32' && environment.USERPROFILE\n ? join(environment.USERPROFILE, '.config')\n : join(homedir(), '.config'))\n\n return join(configRoot, 'tumnel', 'identity.json')\n}\n\nfunction legacyIdentityPaths(environment: NodeJS.ProcessEnv = process.env): string[] {\n const configRoot =\n environment.TUMNEL_CONFIG_DIR ??\n environment.XDG_CONFIG_HOME ??\n (process.platform === 'win32' && environment.USERPROFILE\n ? join(environment.USERPROFILE, '.config')\n : join(homedir(), '.config'))\n // OpenCode is first so existing hosts keep their paired identity when\n // Codex is installed later on the same computer.\n return [\n join(configRoot, 'opencode', 'tumnel', 'identity.json'),\n join(configRoot, 'codex', 'tumnel', 'identity.json'),\n ]\n}\n\nfunction deviceIdFromPublicKey(publicKey: string): string {\n const fingerprint = createHash('sha256').update(Buffer.from(publicKey, 'base64')).digest('base64url')\n return `device_${fingerprint}`\n}\n\nfunction createIdentity(): DeviceIdentity {\n const pair = generateKeyPairSync('ed25519')\n const publicKey = pair.publicKey.export({ type: 'spki', format: 'der' }).toString('base64')\n const privateKey = pair.privateKey.export({ type: 'pkcs8', format: 'pem' }).toString()\n\n return {\n version: 1,\n deviceId: deviceIdFromPublicKey(publicKey),\n publicKey,\n privateKey,\n createdAt: new Date().toISOString(),\n }\n}\n\nfunction validateKeyPair(identity: DeviceIdentity): DeviceIdentity {\n if (deviceIdFromPublicKey(identity.publicKey) !== identity.deviceId) {\n throw new Error('Tumnel identity fingerprint does not match its public key')\n }\n\n const challenge = Buffer.from('tumnel-device-identity-v1')\n const signature = sign(null, challenge, createPrivateKey(identity.privateKey))\n const valid = verify(\n null,\n challenge,\n createPublicKey({ key: Buffer.from(identity.publicKey, 'base64'), format: 'der', type: 'spki' }),\n signature,\n )\n\n if (!valid) {\n throw new Error('Tumnel identity contains an invalid key pair')\n }\n\n return identity\n}\n\nasync function readIdentity(path: string): Promise<DeviceIdentity> {\n const contents = await readFile(path, 'utf8')\n return validateKeyPair(identitySchema.parse(JSON.parse(contents)))\n}\n\nasync function persistNewIdentity(path: string, identity: DeviceIdentity): Promise<void> {\n await mkdir(dirname(path), { recursive: true, mode: 0o700 })\n const handle = await open(path, 'wx', 0o600)\n\n try {\n await handle.writeFile(`${JSON.stringify(identity, null, 2)}\\n`, 'utf8')\n await handle.sync()\n } finally {\n await handle.close()\n }\n}\n\nexport async function loadOrCreateIdentity(\n path = defaultIdentityPath(),\n migrationSources = path === defaultIdentityPath() ? legacyIdentityPaths() : [],\n): Promise<DeviceIdentity> {\n try {\n return await readIdentity(path)\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n\n if (migrationSources.length > 0) {\n for (const legacyPath of migrationSources) {\n try {\n const identity = await readIdentity(legacyPath)\n try {\n await persistNewIdentity(path, identity)\n return identity\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error\n return readIdentity(path)\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error\n }\n }\n }\n\n const identity = createIdentity()\n\n try {\n await persistNewIdentity(path, identity)\n return identity\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== 'EEXIST') throw error\n return readIdentity(path)\n }\n}\n\nexport function createDeviceProof(\n identity: DeviceIdentity,\n timestamp = Date.now(),\n nonce = randomBytes(24).toString('base64url'),\n): DeviceAuthProof {\n const message = `${DEVICE_PROOF_PREFIX}\\n${identity.deviceId}\\n${timestamp}\\n${nonce}`\n const signature = sign(null, Buffer.from(message), createPrivateKey(identity.privateKey))\n\n return {\n deviceId: identity.deviceId,\n publicKey: identity.publicKey,\n timestamp,\n nonce,\n signature: signature.toString('base64url'),\n }\n}\n","import {\n BRIDGE_PROTOCOL_VERSION,\n encodeBridgeMessage,\n parseBridgeMessage,\n type BridgeEvent,\n type BridgeHello,\n type BridgeRequest,\n type BridgeResponse,\n type DeviceAuthProof,\n type JsonValue,\n} from '@openbridge/protocol'\nimport { createDeviceProof, type DeviceIdentity } from './identity.js'\nimport type { ConnectorAdapter } from './connector-adapter.js'\n\nconst CONNECT_TIMEOUT_MS = 15_000\nconst STABLE_CONNECTION_MS = 30_000\nconst INITIAL_BACKOFF_MS = 500\nconst MAX_BACKOFF_MS = 30_000\n\nexport type BridgeConnectionState = 'idle' | 'connecting' | 'connected' | 'stopped'\n\nexport type TumnelBridgeClientOptions = {\n relayUrl: string\n identity: DeviceIdentity\n adapter: ConnectorAdapter\n webSocketFactory?: (url: string) => WebSocket\n random?: () => number\n proofFactory?: () => Promise<DeviceAuthProof> | DeviceAuthProof\n}\n\nfunction bridgeUrl(\n relayUrl: string,\n identity: DeviceIdentity,\n proof: DeviceAuthProof,\n): string {\n const url = new URL(relayUrl)\n if (url.protocol === 'http:') url.protocol = 'ws:'\n if (url.protocol === 'https:') url.protocol = 'wss:'\n if (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n throw new Error('TUMNEL_RELAY_URL must use http, https, ws, or wss')\n }\n\n const basePath = url.pathname.replace(/\\/$/, '')\n url.pathname = `${basePath}/api/bridge/${encodeURIComponent(identity.deviceId)}`\n url.search = ''\n url.searchParams.set('role', 'device')\n url.searchParams.set('clientId', identity.deviceId)\n url.searchParams.set('connectorId', 'codex')\n url.searchParams.set('publicKey', proof.publicKey)\n url.searchParams.set('timestamp', String(proof.timestamp))\n url.searchParams.set('nonce', proof.nonce)\n url.searchParams.set('signature', proof.signature)\n return url.toString()\n}\n\nfunction abortableDelay(milliseconds: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n if (signal.aborted) return resolve()\n const timeout = setTimeout(resolve, milliseconds)\n signal.addEventListener(\n 'abort',\n () => {\n clearTimeout(timeout)\n resolve()\n },\n { once: true },\n )\n })\n}\n\nfunction eventName(payload: JsonValue): string {\n if (typeof payload !== 'object' || payload === null || Array.isArray(payload)) return 'codex.event'\n if (typeof payload.type === 'string') return payload.type.slice(0, 128)\n const nested = payload.payload\n if (\n typeof nested === 'object' &&\n nested !== null &&\n !Array.isArray(nested) &&\n typeof nested.type === 'string'\n ) {\n return nested.type.slice(0, 128)\n }\n return 'codex.event'\n}\n\nasync function messageText(data: unknown): Promise<string | null> {\n if (typeof data === 'string') return data\n if (data instanceof Blob) return data.text()\n if (data instanceof ArrayBuffer) return Buffer.from(data).toString('utf8')\n if (ArrayBuffer.isView(data)) {\n return Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString('utf8')\n }\n return null\n}\n\nfunction errorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : 'Codex request failed'\n return message.slice(0, 512)\n}\n\nexport class TumnelBridgeClient {\n private readonly relayUrl: string\n private readonly identity: DeviceIdentity\n private readonly adapter: ConnectorAdapter\n private readonly webSocketFactory: (url: string) => WebSocket\n private readonly random: () => number\n private readonly proofFactory: () => Promise<DeviceAuthProof> | DeviceAuthProof\n private readonly abortController = new AbortController()\n private connectionLoop?: Promise<void>\n private eventLoop?: Promise<void>\n private socket?: WebSocket\n private currentState: BridgeConnectionState = 'idle'\n\n constructor(options: TumnelBridgeClientOptions) {\n this.relayUrl = options.relayUrl\n this.identity = options.identity\n this.adapter = options.adapter\n this.webSocketFactory = options.webSocketFactory ?? ((url) => new WebSocket(url))\n this.random = options.random ?? Math.random\n this.proofFactory = options.proofFactory ?? (() => createDeviceProof(this.identity))\n }\n\n get state(): BridgeConnectionState {\n return this.currentState\n }\n\n get deviceId(): string {\n return this.identity.deviceId\n }\n\n start(): void {\n if (this.connectionLoop || this.abortController.signal.aborted) return\n this.connectionLoop = this.runConnectionLoop()\n this.eventLoop = this.runEventLoop()\n }\n\n async stop(): Promise<void> {\n if (this.currentState === 'stopped') return\n this.currentState = 'stopped'\n this.abortController.abort()\n this.socket?.close(1000, 'Connector disposed')\n await Promise.allSettled([this.connectionLoop, this.eventLoop])\n }\n\n private async runConnectionLoop(): Promise<void> {\n let attempt = 0\n\n while (!this.abortController.signal.aborted) {\n const startedAt = Date.now()\n try {\n await this.connectOnce()\n } catch (error) {\n await this.adapter.log('warn', 'Cloud relay connection failed', {\n reason: errorMessage(error),\n })\n }\n\n if (this.abortController.signal.aborted) break\n attempt = Date.now() - startedAt >= STABLE_CONNECTION_MS ? 0 : attempt + 1\n const exponential = Math.min(MAX_BACKOFF_MS, INITIAL_BACKOFF_MS * 2 ** Math.min(attempt, 10))\n const delay = Math.round(exponential * (0.75 + this.random() * 0.5))\n await this.adapter.log('info', 'Reconnecting to Cloud relay', {\n attempt,\n delayMs: delay,\n })\n await abortableDelay(delay, this.abortController.signal)\n }\n }\n\n private async connectOnce(): Promise<void> {\n this.currentState = 'connecting'\n const proof = await this.proofFactory()\n const socket = this.webSocketFactory(bridgeUrl(this.relayUrl, this.identity, proof))\n this.socket = socket\n\n return new Promise((resolve, reject) => {\n let opened = false\n const timeout = setTimeout(() => {\n socket.close(4000, 'Connection timeout')\n reject(new Error('Timed out connecting to Cloud relay'))\n }, CONNECT_TIMEOUT_MS)\n\n const abort = () => socket.close(1000, 'Connector disposed')\n this.abortController.signal.addEventListener('abort', abort, { once: true })\n\n socket.addEventListener('open', () => {\n opened = true\n clearTimeout(timeout)\n this.currentState = 'connected'\n const hello: BridgeHello = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'device.hello',\n clientId: this.identity.deviceId,\n agentVersion: '0.1.3',\n connectorId: 'codex',\n }\n socket.send(encodeBridgeMessage(hello))\n void this.adapter.log('info', 'Connected to Cloud relay', {\n deviceId: this.identity.deviceId,\n })\n })\n\n socket.addEventListener('message', (event) => {\n void this.handleMessage(socket, event.data)\n })\n\n socket.addEventListener('error', () => {\n if (!opened) {\n clearTimeout(timeout)\n reject(new Error('Cloud relay WebSocket error'))\n }\n })\n\n socket.addEventListener('close', (event) => {\n clearTimeout(timeout)\n this.abortController.signal.removeEventListener('abort', abort)\n if (this.socket === socket) this.socket = undefined\n if (!this.abortController.signal.aborted) this.currentState = 'idle'\n if (!this.abortController.signal.aborted) {\n void this.adapter.log('warn', 'Cloud relay disconnected', {\n code: event.code,\n reason: event.reason.slice(0, 256),\n wasClean: event.wasClean,\n })\n }\n if (opened) resolve()\n else reject(new Error('Cloud relay closed before connecting'))\n })\n })\n }\n\n private async handleMessage(socket: WebSocket, data: unknown): Promise<void> {\n const raw = await messageText(data)\n if (raw === 'pong' || raw === null) return\n const parsed = parseBridgeMessage(raw)\n\n if (!parsed.ok) {\n await this.adapter.log('warn', 'Ignored invalid Cloud relay message', {\n code: parsed.error.code,\n message: parsed.error.message,\n })\n return\n }\n if (parsed.message.type !== 'request') return\n await this.handleRequest(socket, parsed.message)\n }\n\n private async handleRequest(socket: WebSocket, request: BridgeRequest): Promise<void> {\n let response: BridgeResponse\n\n try {\n response = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'response',\n id: request.id,\n ok: true,\n result: await this.adapter.invoke(request.method, request.params),\n }\n } catch (error) {\n response = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'response',\n id: request.id,\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: errorMessage(error),\n },\n }\n }\n\n if (socket.readyState === WebSocket.OPEN) socket.send(encodeBridgeMessage(response))\n }\n\n private async runEventLoop(): Promise<void> {\n let attempt = 0\n\n while (!this.abortController.signal.aborted) {\n try {\n for await (const payload of this.adapter.events(this.abortController.signal)) {\n const event: BridgeEvent = {\n version: BRIDGE_PROTOCOL_VERSION,\n type: 'event',\n event: eventName(payload),\n payload,\n }\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(encodeBridgeMessage(event))\n }\n }\n attempt = 0\n } catch (error) {\n if (this.abortController.signal.aborted) break\n attempt += 1\n await this.adapter.log('warn', 'Codex event stream disconnected', {\n reason: errorMessage(error),\n attempt,\n })\n const delay = Math.min(MAX_BACKOFF_MS, INITIAL_BACKOFF_MS * 2 ** Math.min(attempt, 10))\n await abortableDelay(delay, this.abortController.signal)\n }\n }\n }\n}\n","import { z } from 'zod'\nimport type { SandboxMode } from '@openai/codex-sdk'\nimport type { ApprovalMode, ModelReasoningEffort, WebSearchMode } from '@openai/codex-sdk'\n\nexport const DEFAULT_RELAY_URL = 'https://openbridge.jlfloressanchez01.workers.dev'\nexport const DEFAULT_LOCAL_PORT = 43817\nexport const DEFAULT_SANDBOX_MODE: SandboxMode = 'workspace-write'\nexport const DEFAULT_APPROVAL_POLICY: ApprovalMode = 'on-request'\n\nconst localPortSchema = z.number().int().min(1024).max(65535)\nconst sandboxModeSchema = z.enum(['read-only', 'workspace-write', 'danger-full-access'])\nconst approvalPolicySchema = z.enum(['never', 'on-request', 'on-failure', 'untrusted'])\nconst modelReasoningEffortSchema = z.enum(['minimal', 'low', 'medium', 'high', 'xhigh'])\nconst webSearchModeSchema = z.enum(['disabled', 'cached', 'live'])\n\nconst connectorOptionsSchema = z\n .object({\n relayUrl: z.string().url().optional(),\n identityPath: z.string().min(1).optional(),\n localPort: localPortSchema.optional(),\n appOrigins: z.array(z.string().url()).max(10).optional(),\n model: z.string().min(1).max(256).optional(),\n sandboxMode: sandboxModeSchema.optional(),\n approvalPolicy: approvalPolicySchema.optional(),\n modelReasoningEffort: modelReasoningEffortSchema.optional(),\n webSearchMode: webSearchModeSchema.optional(),\n skipGitRepoCheck: z.boolean().optional(),\n networkAccess: z.boolean().optional(),\n })\n .strict()\n\nexport type TumnelCodexOptions = z.infer<typeof connectorOptionsSchema>\n\nexport type TumnelCodexConfig = {\n relayUrl: string\n identityPath?: string\n localPort: number\n appOrigins: string[]\n model?: string\n sandboxMode: SandboxMode\n approvalPolicy: ApprovalMode\n modelReasoningEffort?: ModelReasoningEffort\n webSearchMode?: WebSearchMode\n skipGitRepoCheck: boolean\n networkAccess: boolean\n}\n\nfunction envBool(value: string | undefined): boolean | undefined {\n if (value === undefined) return undefined\n return value === '1' || value.toLowerCase() === 'true'\n}\n\nexport function resolveConfig(\n options: Record<string, unknown> | undefined,\n environment: NodeJS.ProcessEnv = process.env,\n): TumnelCodexConfig {\n const parsedOptions = connectorOptionsSchema.parse(options ?? {})\n const relayUrl = parsedOptions.relayUrl ?? environment.TUMNEL_RELAY_URL ?? DEFAULT_RELAY_URL\n const configuredOrigins = environment.TUMNEL_APP_ORIGIN\n ?.split(',')\n .map((origin) => origin.trim())\n .filter(Boolean)\n\n const sandboxMode = sandboxModeSchema.parse(\n parsedOptions.sandboxMode ?? environment.CODEX_SANDBOX ?? DEFAULT_SANDBOX_MODE,\n )\n const approvalPolicy = approvalPolicySchema.parse(\n parsedOptions.approvalPolicy ?? environment.CODEX_APPROVAL_POLICY ?? DEFAULT_APPROVAL_POLICY,\n )\n\n return {\n relayUrl,\n identityPath: parsedOptions.identityPath ?? environment.TUMNEL_IDENTITY_PATH,\n localPort: localPortSchema.parse(\n parsedOptions.localPort ??\n (environment.TUMNEL_LOCAL_PORT ? Number(environment.TUMNEL_LOCAL_PORT) : DEFAULT_LOCAL_PORT),\n ),\n appOrigins: parsedOptions.appOrigins ?? configuredOrigins ?? [],\n model: parsedOptions.model ?? environment.CODEX_MODEL,\n sandboxMode,\n approvalPolicy,\n modelReasoningEffort:\n parsedOptions.modelReasoningEffort ??\n (environment.CODEX_REASONING_EFFORT as ModelReasoningEffort | undefined),\n webSearchMode:\n parsedOptions.webSearchMode ??\n (environment.CODEX_WEB_SEARCH as WebSearchMode | undefined),\n skipGitRepoCheck:\n parsedOptions.skipGitRepoCheck ?? envBool(environment.CODEX_SKIP_GIT_REPO_CHECK) ?? false,\n networkAccess:\n parsedOptions.networkAccess ?? envBool(environment.CODEX_NETWORK_ACCESS) ?? false,\n }\n}\n","import { createServer, type Server } from 'node:http'\nimport { clientIdSchema, type JsonValue } from '@openbridge/protocol'\nimport type { DeviceIdentity } from './identity.js'\nimport { createDeviceProof } from './identity.js'\n\ntype PairingServerOptions = {\n identity: DeviceIdentity\n port: number\n relayUrl: string\n appOrigins: string[]\n log: (level: 'info' | 'warn', message: string, fields?: Record<string, JsonValue>) => Promise<void>\n}\n\nexport type PairingServer = {\n port: number\n stop: () => Promise<void>\n}\n\nfunction relayOrigin(relayUrl: string): string {\n const url = new URL(relayUrl)\n if (url.protocol === 'ws:') url.protocol = 'http:'\n if (url.protocol === 'wss:') url.protocol = 'https:'\n return url.origin\n}\n\nfunction closeServer(server: Server): Promise<void> {\n return new Promise((resolve) => server.close(() => resolve()))\n}\n\nexport async function startPairingServer(options: PairingServerOptions): Promise<PairingServer | null> {\n const allowedOrigins = new Set([\n relayOrigin(options.relayUrl),\n 'http://127.0.0.1:5173',\n 'http://localhost:5173',\n ...options.appOrigins,\n ])\n\n const server = createServer((request, response) => {\n const origin = request.headers.origin\n const expectedHosts = new Set([\n `127.0.0.1:${options.port}`,\n `localhost:${options.port}`,\n ])\n\n if (!expectedHosts.has(request.headers.host ?? '')) {\n response.writeHead(403, { 'Cache-Control': 'no-store' })\n response.end('Forbidden')\n return\n }\n\n const requestUrl = new URL(request.url ?? '/', `http://${request.headers.host}`)\n if (request.method === 'GET' && requestUrl.pathname === '/v1/health') {\n const body = JSON.stringify({ ready: true })\n response.writeHead(200, {\n 'Cache-Control': 'no-store',\n 'Content-Type': 'application/json; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body).toString(),\n })\n response.end(body)\n return\n }\n\n if (request.method === 'GET' && requestUrl.pathname === '/v1/connect') {\n const returnOrigin = requestUrl.searchParams.get('returnOrigin')\n const clientId = clientIdSchema.safeParse(requestUrl.searchParams.get('clientId'))\n if (!returnOrigin || !allowedOrigins.has(returnOrigin) || !clientId.success) {\n response.writeHead(400, { 'Cache-Control': 'no-store' })\n response.end('Invalid pairing handoff')\n return\n }\n\n const payload = Buffer.from(JSON.stringify({\n proof: createDeviceProof(options.identity),\n client: { clientId: clientId.data, label: 'Desktop browser' },\n })).toString('base64url')\n const redirect = new URL('/connect', returnOrigin)\n redirect.hash = new URLSearchParams({ payload }).toString()\n response.writeHead(302, {\n 'Cache-Control': 'no-store',\n 'Referrer-Policy': 'no-referrer',\n Location: redirect.toString(),\n })\n response.end()\n return\n }\n\n if (!origin || !allowedOrigins.has(origin)) {\n response.writeHead(403, { 'Cache-Control': 'no-store' })\n response.end('Forbidden')\n return\n }\n\n const corsHeaders: Record<string, string> = {\n 'Access-Control-Allow-Origin': origin,\n 'Access-Control-Allow-Methods': 'GET, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n 'Cache-Control': 'no-store',\n Vary: 'Origin',\n }\n if (request.headers['access-control-request-private-network'] === 'true') {\n corsHeaders['Access-Control-Allow-Private-Network'] = 'true'\n }\n\n if (request.method === 'OPTIONS') {\n response.writeHead(204, corsHeaders)\n response.end()\n return\n }\n\n if (request.method !== 'GET' || requestUrl.pathname !== '/v1/pairing-proof') {\n response.writeHead(404, corsHeaders)\n response.end('Not Found')\n return\n }\n\n const body = JSON.stringify({ proof: createDeviceProof(options.identity) })\n response.writeHead(200, {\n ...corsHeaders,\n 'Content-Type': 'application/json; charset=utf-8',\n 'Content-Length': Buffer.byteLength(body).toString(),\n })\n response.end(body)\n })\n\n const listening = await new Promise<boolean>((resolve) => {\n const onError = (error: NodeJS.ErrnoException) => {\n server.removeListener('listening', onListening)\n void options.log('warn', 'Local pairing endpoint is unavailable', {\n port: options.port,\n reason: error.code ?? error.message,\n })\n resolve(false)\n }\n const onListening = () => {\n server.removeListener('error', onError)\n resolve(true)\n }\n server.once('error', onError)\n server.once('listening', onListening)\n server.listen(options.port, '127.0.0.1')\n })\n\n if (!listening) return null\n await options.log('info', 'Local pairing endpoint ready', { port: options.port })\n\n return {\n port: options.port,\n stop: () => closeServer(server),\n }\n}\n","#!/usr/bin/env node\n\nimport { createCodexConnector } from './index.js'\n\nconst waitForTumnelConnector = async (\n bridge: { readonly state: string },\n timeoutMs = 15_000,\n) => {\n const deadline = Date.now() + timeoutMs\n while (bridge.state !== 'connected' && Date.now() < deadline) {\n await new Promise((resolve) => setTimeout(resolve, 100))\n }\n return bridge.state === 'connected'\n}\n\nconst printHelp = () => {\n console.log(`Tumnel connector for Codex\n\nUsage:\n tumnel-codex install [options]\n tumnel-codex connect [options]\n\nThe install command is the standard one-command setup for Codex. It prepares the\nTumnel identity and starts the connector. The connect command remains available\nas an explicit alias.\n\nOptions:\n --model <model> Codex model id (e.g. gpt-5-mini)\n --port <port> Local pairing endpoint port (default 43817)\n --relay-url <url> Tumnel relay URL (default: production relay)\n --sandbox <mode> Sandbox: read-only | workspace-write | danger-full-access\n --approval-policy <policy> Approval: never | on-request | on-failure | untrusted\n --version Print the connector version\n -h, --help Show this help\n\nEnvironment:\n TUMNEL_RELAY_URL, TUMNEL_APP_ORIGIN, TUMNEL_IDENTITY_PATH, TUMNEL_LOCAL_PORT,\n TUMNEL_CONFIG_DIR, CODEX_MODEL, CODEX_SANDBOX, CODEX_APPROVAL_POLICY,\n CODEX_REASONING_EFFORT, CODEX_WEB_SEARCH, CODEX_NETWORK_ACCESS,\n CODEX_SKIP_GIT_REPO_CHECK, CODEX_HOME\n\nThe connect command starts the Codex agent bridge and keeps it connected to the\nTumnel relay until interrupted. Pair from the Tumnel web app when it is online.`)\n}\n\nconst printVersion = async () => {\n const { version } = JSON.parse(\n await import('node:fs/promises').then(({ readFile }) =>\n readFile(new URL('../package.json', import.meta.url), 'utf8'),\n ),\n ) as { version: string }\n console.log(`@tumnel/codex ${version}`)\n}\n\nconst run = async () => {\n const command = process.argv[2] ?? 'install'\n\n if (command === '--help' || command === '-h' || command === 'help') {\n printHelp()\n return\n }\n\n if (command === '--version' || command === '-v') {\n printVersion()\n return\n }\n\n if (command !== 'install' && command !== 'connect' && !command.startsWith('-')) {\n throw new Error(`Unknown command: ${command}`)\n }\n\n const args = command === 'install' || command === 'connect'\n ? process.argv.slice(3)\n : process.argv.slice(2)\n\n if (args.includes('--help') || args.includes('-h')) {\n printHelp()\n return\n }\n\n const versionIndex = args.indexOf('--version')\n if (versionIndex !== -1) {\n await printVersion()\n return\n }\n\n const config: Record<string, unknown> = {}\n\n const flag = (name: string): void => {\n const index = args.indexOf(name)\n if (index === -1) return\n const value = args[index + 1]\n if (!value) throw new Error(`Missing value for ${name}`)\n const key = {\n '--model': 'model',\n '--port': 'localPort',\n '--relay-url': 'relayUrl',\n '--sandbox': 'sandboxMode',\n '--approval-policy': 'approvalPolicy',\n }[name] ?? name\n config[key] = name === '--port' ? Number(value) : value\n }\n\n flag('--model')\n flag('--port')\n flag('--relay-url')\n flag('--sandbox')\n flag('--approval-policy')\n\n const packageJson = JSON.parse(\n await import('node:fs/promises').then(({ readFile }) =>\n readFile(new URL('../package.json', import.meta.url), 'utf8'),\n ),\n ) as { version: string }\n\n if (command === 'install') console.log(`Installed @tumnel/codex@${packageJson.version}`)\n\n const connector = await createCodexConnector({ config })\n const port = connector.pairingServer?.port\n\n console.log('Starting Tumnel Codex connector...')\n console.log(` Device ID: ${connector.bridge.deviceId}`)\n if (port) console.log(` Pairing port: http://127.0.0.1:${port}`)\n console.log('Waiting for the Tumnel connector...')\n if (await waitForTumnelConnector(connector.bridge)) {\n console.log('Tumnel connected.')\n } else {\n console.log('Tumnel connector started; waiting for the relay in background.')\n }\n console.log('Press Ctrl+C to stop.\\n')\n\n let stopping = false\n const stop = async () => {\n if (stopping) return\n stopping = true\n console.log('\\nStopping Tumnel Codex connector...')\n await connector.stop()\n process.exit(0)\n }\n process.on('SIGINT', () => void stop())\n process.on('SIGTERM', () => void stop())\n}\n\nrun().catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error))\n process.exitCode = 1\n})\n"],"mappings":"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","names":["z","path","projectId","result","z","existing","messages","z","z","createHash","randomBytes","homedir","dirname","join","readFile","z","identity","errorMessage","z","body","readFile"]}
|