@hua-labs/tap 0.3.1 → 0.4.0
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 +0 -9
- package/dist/bridges/codex-app-server-auth-gateway.d.mts +9 -1
- package/dist/bridges/codex-app-server-auth-gateway.mjs +183 -14
- package/dist/bridges/codex-app-server-auth-gateway.mjs.map +1 -1
- package/dist/bridges/codex-app-server-bridge.d.mts +224 -5
- package/dist/bridges/codex-app-server-bridge.mjs +1138 -687
- package/dist/bridges/codex-app-server-bridge.mjs.map +1 -1
- package/dist/bridges/codex-bridge-runner.mjs +17 -2
- package/dist/bridges/codex-bridge-runner.mjs.map +1 -1
- package/dist/cli.mjs +703 -95
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +502 -57
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-server.mjs +327 -70
- package/dist/mcp-server.mjs.map +1 -1
- package/package.json +4 -3
- package/LICENSE +0 -21
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/bridges/codex-app-server-bridge.ts","../../../../scripts/codex-app-server-bridge.ts"],"sourcesContent":["import { pathToFileURL } from \"node:url\";\nimport { resolve } from \"node:path\";\nimport { main } from \"../../../../scripts/codex-app-server-bridge.js\";\n\nexport * from \"../../../../scripts/codex-app-server-bridge.js\";\n\nfunction isDirectExecution(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n return import.meta.url === pathToFileURL(resolve(entry)).href;\n}\n\nif (isDirectExecution()) {\n main().catch((error) => {\n console.error(\n error instanceof Error ? (error.stack ?? error.message) : String(error),\n );\n process.exitCode = 1;\n });\n}\n","#!/usr/bin/env node --experimental-strip-types\n\nimport { createHash } from \"crypto\";\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"fs\";\nimport { isAbsolute, join, resolve } from \"path\";\nimport { pathToFileURL } from \"url\";\n\ntype BusyMode = \"wait\" | \"steer\";\n\ninterface Options {\n repoRoot: string;\n commsDir: string;\n agentId: string;\n agentName: string;\n stateDir: string;\n pollSeconds: number;\n reconnectSeconds: number;\n messageLookbackMinutes: number;\n processExistingMessages: boolean;\n dryRun: boolean;\n runOnce: boolean;\n waitAfterDispatchSeconds: number;\n appServerUrl: string;\n connectAppServerUrl: string;\n gatewayToken: string | null;\n gatewayTokenFile: string | null;\n busyMode: BusyMode;\n threadId: string | null;\n ephemeral: boolean;\n}\n\ninterface InboxRoute {\n sender: string;\n recipient: string;\n subject: string;\n}\n\ninterface Candidate {\n markerId: string;\n filePath: string;\n fileName: string;\n sender: string;\n recipient: string;\n subject: string;\n body: string;\n mtimeMs: number;\n}\n\ninterface ThreadStateRecord {\n threadId: string;\n updatedAt: string;\n appServerUrl: string;\n ephemeral: boolean;\n cwd?: string | null;\n}\n\ninterface HeartbeatRecord {\n pid: number;\n agent: string;\n updatedAt: string;\n pollSeconds: number;\n appServerUrl: string;\n connected: boolean;\n initialized: boolean;\n threadId: string | null;\n threadCwd?: string | null;\n activeTurnId: string | null;\n turnStartedAt: string | null;\n lastTurnStatus: string | null;\n lastNotificationMethod: string | null;\n lastNotificationAt: string | null;\n lastError: string | null;\n lastSuccessfulAppServerAt: string | null;\n lastSuccessfulAppServerMethod: string | null;\n consecutiveFailureCount: number;\n busyMode: BusyMode;\n}\n\ninterface BridgeHealthState {\n consecutiveFailureCount: number;\n}\n\nexport interface HeadlessWarmupClient {\n activeTurnId: string | null;\n lastTurnStatus: string | null;\n startTurn(inputText: string): Promise<string | null>;\n refreshCurrentThreadState(): Promise<void>;\n}\n\nexport interface LoadedThreadCandidate {\n id: string;\n cwd: string;\n updatedAt: number;\n statusType: string | null;\n thread: any;\n}\n\ninterface RequestRecord {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params: unknown;\n}\n\ninterface HeartbeatStoreRecord {\n id?: string;\n agent?: string;\n}\n\ntype HeartbeatStore = Record<string, HeartbeatStoreRecord>;\n\ninterface JsonRpcResponse {\n id?: number;\n result?: any;\n error?: {\n code?: number;\n message?: string;\n data?: unknown;\n };\n method?: string;\n params?: any;\n}\n\nconst DEFAULT_AGENT = String.fromCharCode(0xc628);\nconst DEFAULT_APP_SERVER_URL = \"ws://127.0.0.1:4501\";\nconst AUTH_SUBPROTOCOL_PREFIX = \"tap-auth-\";\nconst PLACEHOLDER_AGENT_VALUES = new Set([\n \"unknown\",\n \"unnamed\",\n \"<set-per-session>\",\n]);\nexport const HEADLESS_WARMUP_PROMPT = [\n \"You are a tap worker agent connected via the tap-comms inbox.\",\n \"This is a one-time warmup turn for headless bridge startup.\",\n \"Do not take any external actions.\",\n \"Reply briefly, then wait for future inbox instructions.\",\n].join(\" \");\nconst HEADLESS_WARMUP_TIMEOUT_MS = 30_000;\nconst TURN_COMPLETION_POLL_MS = 250;\nconst TURN_COMPLETION_REFRESH_MS = 1_000;\n\nfunction normalizeThreadCwd(cwd: string): string {\n return resolve(cwd).replace(/\\\\/g, \"/\").toLowerCase();\n}\n\nexport function threadCwdMatches(\n expectedCwd: string,\n actualCwd: string | null | undefined,\n): boolean {\n if (!actualCwd) {\n return false;\n }\n\n return normalizeThreadCwd(expectedCwd) === normalizeThreadCwd(actualCwd);\n}\n\nexport function chooseLoadedThreadForCwd(\n cwd: string,\n threads: LoadedThreadCandidate[],\n): LoadedThreadCandidate | null {\n const matching = threads.filter((thread) =>\n threadCwdMatches(cwd, thread.cwd),\n );\n if (matching.length === 0) {\n return null;\n }\n\n matching.sort((left, right) => {\n const leftActive = left.statusType === \"active\" ? 1 : 0;\n const rightActive = right.statusType === \"active\" ? 1 : 0;\n if (leftActive !== rightActive) {\n return rightActive - leftActive;\n }\n return right.updatedAt - left.updatedAt;\n });\n\n return matching[0] ?? null;\n}\n\nfunction printHelp(): void {\n console.log(`Codex App Server bridge\n\nUsage:\n node --experimental-strip-types scripts/codex-app-server-bridge.ts [options]\n\nOptions:\n --repo-root=<path>\n --comms-dir=<path>\n --agent-name=<name>\n --state-dir=<path>\n --poll-seconds=<n>\n --reconnect-seconds=<n>\n --message-lookback-minutes=<n>\n --process-existing-messages\n --dry-run\n --run-once\n --wait-after-dispatch-seconds=<n>\n --app-server-url=<ws-url>\n --gateway-token-file=<path>\n --busy-mode=wait|steer\n --thread-id=<id>\n --ephemeral\n --help\n`);\n}\n\nfunction parseNumber(value: string, flag: string): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new Error(`Invalid ${flag}: ${value}`);\n }\n return parsed;\n}\n\nfunction readFlagValue(argv: string[], index: number, flag: string): string {\n const current = argv[index];\n const eqIndex = current.indexOf(\"=\");\n if (eqIndex >= 0) {\n return current.slice(eqIndex + 1);\n }\n\n const next = argv[index + 1];\n if (!next || next.startsWith(\"--\")) {\n throw new Error(`Missing value for ${flag}`);\n }\n return next;\n}\n\nfunction parseArgs(argv: string[]): {\n repoRoot?: string;\n commsDir?: string;\n agentName?: string;\n stateDir?: string;\n pollSeconds?: number;\n reconnectSeconds?: number;\n messageLookbackMinutes?: number;\n processExistingMessages: boolean;\n dryRun: boolean;\n runOnce: boolean;\n waitAfterDispatchSeconds?: number;\n appServerUrl?: string;\n gatewayTokenFile?: string;\n busyMode?: BusyMode;\n threadId?: string;\n ephemeral: boolean;\n} {\n const parsed = {\n processExistingMessages: false,\n dryRun: false,\n runOnce: false,\n ephemeral: false,\n } as {\n repoRoot?: string;\n commsDir?: string;\n agentName?: string;\n stateDir?: string;\n pollSeconds?: number;\n reconnectSeconds?: number;\n messageLookbackMinutes?: number;\n processExistingMessages: boolean;\n dryRun: boolean;\n runOnce: boolean;\n waitAfterDispatchSeconds?: number;\n appServerUrl?: string;\n gatewayTokenFile?: string;\n busyMode?: BusyMode;\n threadId?: string;\n ephemeral: boolean;\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const flag = argv[index];\n const consumesNext = !flag.includes(\"=\");\n\n if (flag === \"--help\") {\n printHelp();\n process.exit(0);\n }\n\n if (flag === \"--process-existing-messages\") {\n parsed.processExistingMessages = true;\n continue;\n }\n\n if (flag === \"--dry-run\") {\n parsed.dryRun = true;\n continue;\n }\n\n if (flag === \"--run-once\") {\n parsed.runOnce = true;\n continue;\n }\n\n if (flag === \"--ephemeral\") {\n parsed.ephemeral = true;\n continue;\n }\n\n if (flag.startsWith(\"--repo-root\")) {\n parsed.repoRoot = readFlagValue(argv, index, \"--repo-root\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--comms-dir\")) {\n parsed.commsDir = readFlagValue(argv, index, \"--comms-dir\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--agent-name\")) {\n parsed.agentName = readFlagValue(argv, index, \"--agent-name\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--state-dir\")) {\n parsed.stateDir = readFlagValue(argv, index, \"--state-dir\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--poll-seconds\")) {\n parsed.pollSeconds = parseNumber(\n readFlagValue(argv, index, \"--poll-seconds\"),\n \"--poll-seconds\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--reconnect-seconds\")) {\n parsed.reconnectSeconds = parseNumber(\n readFlagValue(argv, index, \"--reconnect-seconds\"),\n \"--reconnect-seconds\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--message-lookback-minutes\")) {\n parsed.messageLookbackMinutes = parseNumber(\n readFlagValue(argv, index, \"--message-lookback-minutes\"),\n \"--message-lookback-minutes\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--app-server-url\")) {\n parsed.appServerUrl = readFlagValue(argv, index, \"--app-server-url\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--gateway-token-file\")) {\n parsed.gatewayTokenFile = readFlagValue(\n argv,\n index,\n \"--gateway-token-file\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--wait-after-dispatch-seconds\")) {\n parsed.waitAfterDispatchSeconds = parseNumber(\n readFlagValue(argv, index, \"--wait-after-dispatch-seconds\"),\n \"--wait-after-dispatch-seconds\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--busy-mode\")) {\n const value = readFlagValue(argv, index, \"--busy-mode\");\n if (value !== \"wait\" && value !== \"steer\") {\n throw new Error(`Invalid --busy-mode: ${value}`);\n }\n parsed.busyMode = value;\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--thread-id\")) {\n parsed.threadId = readFlagValue(argv, index, \"--thread-id\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n throw new Error(`Unknown argument: ${flag}`);\n }\n\n return parsed;\n}\n\nfunction timestamp(): string {\n return new Date().toISOString().replace(\"T\", \" \").replace(\"Z\", \" UTC\");\n}\n\nfunction logStatus(message: string): void {\n console.log(`[${timestamp()}] ${message}`);\n}\n\nfunction ensureDir(target: string): string {\n if (!existsSync(target)) {\n mkdirSync(target, { recursive: true });\n }\n return resolve(target);\n}\n\nfunction convertTapPath(input: string): string {\n const trimmed = input.trim().replace(/^[\"'`]+|[\"'`]+$/g, \"\");\n if (/^[A-Za-z]:\\\\/.test(trimmed)) {\n return trimmed;\n }\n\n const match = trimmed.match(/^\\/([A-Za-z])\\/(.*)$/);\n if (match) {\n return `${match[1].toUpperCase()}:\\\\${match[2].replace(/\\//g, \"\\\\\")}`;\n }\n\n return trimmed;\n}\n\nfunction resolveRepoRoot(explicit?: string): string {\n if (explicit) {\n return resolve(explicit);\n }\n\n return process.cwd();\n}\n\nfunction resolveCommsDir(repoRoot: string, explicit?: string): string {\n if (explicit) {\n return resolve(convertTapPath(explicit));\n }\n\n const tapConfigPath = join(repoRoot, \".tap-config\");\n if (!existsSync(tapConfigPath)) {\n throw new Error(\n \"Unable to resolve comms directory. Pass --comms-dir explicitly.\",\n );\n }\n\n const configText = readFileSync(tapConfigPath, \"utf8\");\n const match = configText.match(/^TAP_COMMS_DIR=\"?(.*?)\"?$/m);\n if (!match?.[1]) {\n throw new Error(\n \"Unable to resolve comms directory. Pass --comms-dir explicitly.\",\n );\n }\n\n return resolveTapConfigPath(repoRoot, match[1]);\n}\n\nfunction resolvePreferredAgentName(requested?: string): string | null {\n if (requested?.trim()) {\n return requested.trim();\n }\n\n for (const envName of [\"TAP_AGENT_NAME\", \"CODEX_TAP_AGENT_NAME\"]) {\n const candidate = process.env[envName];\n if (candidate?.trim()) {\n return candidate.trim();\n }\n }\n\n return null;\n}\n\nfunction normalizeAgentToken(value?: string | null): string | null {\n const normalized = value?.trim();\n if (!normalized || PLACEHOLDER_AGENT_VALUES.has(normalized)) {\n return null;\n }\n\n return normalized.replace(/-/g, \"_\");\n}\n\nexport function resolveAgentId(preferredAgentName?: string | null): string {\n return (\n normalizeAgentToken(process.env.TAP_AGENT_ID) ??\n normalizeAgentToken(preferredAgentName) ??\n \"unknown\"\n );\n}\n\nfunction sanitizeStateSegment(agentName: string): string {\n const normalized = agentName\n .trim()\n .replace(/[<>:\"/\\\\|?*\\x00-\\x1f]/g, \"-\")\n .replace(/[. ]+$/g, \"\");\n\n return normalized || \"agent\";\n}\n\nfunction buildDefaultStateDir(\n repoRoot: string,\n preferredAgentName?: string | null,\n): string {\n const suffix = preferredAgentName?.trim()\n ? `-${sanitizeStateSegment(preferredAgentName)}`\n : \"\";\n return resolve(join(repoRoot, \".tmp\", `codex-app-server-bridge${suffix}`));\n}\n\nfunction resolveStateDir(\n repoRoot: string,\n explicit?: string,\n preferredAgentName?: string | null,\n): string {\n const root = explicit\n ? resolve(explicit)\n : buildDefaultStateDir(repoRoot, preferredAgentName);\n\n ensureDir(root);\n ensureDir(join(root, \"processed\"));\n ensureDir(join(root, \"logs\"));\n return root;\n}\n\nfunction resolveAgentName(\n preferredAgentName: string | null,\n stateDir: string,\n): string {\n if (preferredAgentName?.trim()) {\n return preferredAgentName.trim();\n }\n\n const agentFile = join(stateDir, \"agent-name.txt\");\n if (existsSync(agentFile)) {\n const candidate = readFileSync(agentFile, \"utf8\").trim();\n if (candidate) {\n return candidate;\n }\n }\n\n return DEFAULT_AGENT;\n}\n\nfunction persistAgentName(stateDir: string, agentName: string): void {\n writeFileSync(join(stateDir, \"agent-name.txt\"), `${agentName}\\n`, \"utf8\");\n}\n\n// buildProtectedAppServerUrl removed — subprotocol auth replaces query-param tokens.\n\n/**\n * Strip sensitive tokens from error messages before persisting to disk.\n * Catches: query-string tokens (?tap_token=...), subprotocol tokens (tap-auth-...),\n * and any base64url-like strings that look like auth tokens.\n */\nfunction sanitizeErrorForPersistence(error: string | null): string | null {\n if (!error) return null;\n return error\n .replace(/([?&])tap_token=[^\\s&)\"'}]+/gi, \"$1tap_token=***\")\n .replace(/\"tap_token\"\\s*:\\s*\"[^\"]*\"/g, '\"tap_token\":\"***\"')\n .replace(/tap-auth-[A-Za-z0-9_-]+/g, \"tap-auth-***\")\n .replace(/Bearer\\s+[A-Za-z0-9_.-]+/gi, \"Bearer ***\");\n}\n\nfunction readGatewayTokenFile(tokenFile: string): string {\n const token = readFileSync(tokenFile, \"utf8\").trim();\n if (!token) {\n throw new Error(`Gateway token file is empty: ${tokenFile}`);\n }\n return token;\n}\n\nfunction resolveTapConfigPath(repoRoot: string, input: string): string {\n const converted = convertTapPath(input);\n return isAbsolute(converted)\n ? resolve(converted)\n : resolve(repoRoot, converted);\n}\n\nfunction readThreadState(stateDir: string): ThreadStateRecord | null {\n const threadPath = join(stateDir, \"thread.json\");\n if (!existsSync(threadPath)) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(\n readFileSync(threadPath, \"utf8\"),\n ) as ThreadStateRecord;\n if (parsed.threadId) {\n return parsed;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nfunction readHeartbeatState(stateDir: string): HeartbeatRecord | null {\n const heartbeatPath = join(stateDir, \"heartbeat.json\");\n if (!existsSync(heartbeatPath)) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(heartbeatPath, \"utf8\")) as HeartbeatRecord;\n } catch {\n return null;\n }\n}\n\nfunction parseUpdatedAt(value?: string | null): number {\n if (!value) {\n return 0;\n }\n\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction appServerUrlMatches(\n expectedAppServerUrl: string,\n actualAppServerUrl?: string | null,\n): boolean {\n return actualAppServerUrl?.trim() === expectedAppServerUrl;\n}\n\nfunction hasValidHeartbeatThreadCwd(\n threadCwd?: string | null,\n): threadCwd is string {\n const normalized = threadCwd?.trim();\n if (!normalized) {\n return false;\n }\n\n return (\n isAbsolute(normalized) ||\n /^[A-Za-z]:[\\\\/]/.test(normalized) ||\n normalized.startsWith(\"\\\\\\\\\")\n );\n}\n\nexport function loadResumableThreadState(\n stateDir: string,\n fallbackAppServerUrl: string,\n): ThreadStateRecord | null {\n const savedThread = readThreadState(stateDir);\n const heartbeat = readHeartbeatState(stateDir);\n const heartbeatThreadId = heartbeat?.threadId?.trim();\n\n if (!heartbeatThreadId) {\n return savedThread;\n }\n\n if (!appServerUrlMatches(fallbackAppServerUrl, heartbeat?.appServerUrl)) {\n return savedThread;\n }\n\n if (!hasValidHeartbeatThreadCwd(heartbeat?.threadCwd)) {\n return savedThread;\n }\n\n const heartbeatBackedThread: ThreadStateRecord = {\n threadId: heartbeatThreadId,\n updatedAt:\n heartbeat?.updatedAt ??\n savedThread?.updatedAt ??\n new Date().toISOString(),\n appServerUrl:\n heartbeat?.appServerUrl ||\n savedThread?.appServerUrl ||\n fallbackAppServerUrl,\n ephemeral: savedThread?.ephemeral ?? false,\n cwd:\n heartbeat?.threadCwd ??\n (savedThread?.threadId === heartbeatThreadId\n ? (savedThread.cwd ?? null)\n : null),\n };\n\n let preferred = savedThread;\n if (!savedThread?.threadId) {\n preferred = heartbeatBackedThread;\n } else if (savedThread.threadId === heartbeatThreadId) {\n preferred = {\n ...savedThread,\n updatedAt: heartbeatBackedThread.updatedAt ?? savedThread.updatedAt,\n appServerUrl: heartbeatBackedThread.appServerUrl,\n cwd: heartbeatBackedThread.cwd ?? savedThread.cwd ?? null,\n };\n } else if (\n parseUpdatedAt(heartbeat?.updatedAt) > parseUpdatedAt(savedThread.updatedAt)\n ) {\n preferred = heartbeatBackedThread;\n }\n\n return preferred;\n}\n\nfunction persistThreadState(\n stateDir: string,\n threadId: string,\n appServerUrl: string,\n ephemeral: boolean,\n cwd: string | null,\n): void {\n const payload: ThreadStateRecord = {\n threadId,\n updatedAt: new Date().toISOString(),\n appServerUrl,\n ephemeral,\n cwd,\n };\n writeFileSync(\n join(stateDir, \"thread.json\"),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nfunction getGeneralInboxCutoff(\n stateDir: string,\n lookbackMinutes: number,\n processExistingMessages: boolean,\n): Date {\n if (processExistingMessages) {\n return new Date(0);\n }\n\n if (lookbackMinutes > 0) {\n return new Date(Date.now() - lookbackMinutes * 60_000);\n }\n\n const cutoffPath = join(stateDir, \"general-inbox-cutoff.txt\");\n if (existsSync(cutoffPath)) {\n try {\n return new Date(readFileSync(cutoffPath, \"utf8\").trim());\n } catch {\n return new Date();\n }\n }\n\n const cutoff = new Date();\n writeFileSync(cutoffPath, `${cutoff.toISOString()}\\n`, \"utf8\");\n return cutoff;\n}\n\nexport function recipientMatchesAgent(\n recipient: string,\n agentId: string,\n agentName: string,\n): boolean {\n const normalizedRecipient = recipient.trim();\n if (!normalizedRecipient) {\n return false;\n }\n\n const canonicalRecipient = normalizedRecipient.replace(/-/g, \"_\");\n const canonicalAgentId = agentId.trim().replace(/-/g, \"_\");\n\n return (\n normalizedRecipient === \"전체\" ||\n normalizedRecipient === \"all\" ||\n canonicalRecipient === canonicalAgentId ||\n normalizedRecipient === agentName\n );\n}\n\nexport function isOwnMessageSender(\n sender: string,\n agentId: string,\n agentName: string,\n): boolean {\n const normalizedSender = sender.trim();\n if (!normalizedSender) {\n return false;\n }\n\n const canonicalSender = normalizedSender.replace(/-/g, \"_\");\n const canonicalAgentId = agentId.trim().replace(/-/g, \"_\");\n\n return canonicalSender === canonicalAgentId || normalizedSender === agentName;\n}\n\nfunction getInboxRoute(fileName: string): InboxRoute {\n const stem = fileName.replace(/\\.md$/i, \"\");\n const parts = stem.split(\"-\");\n let offset = 0;\n if (parts[0] && /^\\d{8}$/.test(parts[0])) {\n offset = 1;\n }\n\n return {\n sender: parts[offset] ?? \"\",\n recipient: parts[offset + 1] ?? \"\",\n subject: parts.slice(offset + 2).join(\"-\"),\n };\n}\n\nfunction buildMarkerId(filePath: string, mtimeMs: number): string {\n return createHash(\"sha1\").update(`${filePath}|${mtimeMs}`).digest(\"hex\");\n}\n\nfunction getProcessedMarkerPath(stateDir: string, markerId: string): string {\n return join(stateDir, \"processed\", `${markerId}.done`);\n}\n\nfunction loadHeartbeats(commsDir: string): HeartbeatStore {\n try {\n return JSON.parse(readFileSync(join(commsDir, \"heartbeats.json\"), \"utf8\"));\n } catch {\n return {};\n }\n}\n\nfunction formatAgentLabel(\n agentIdOrName: string,\n displayName?: string | null,\n): string {\n const normalizedId = agentIdOrName.trim();\n const normalizedName = displayName?.trim();\n\n if (!normalizedId) {\n return normalizedName ?? agentIdOrName;\n }\n\n if (!normalizedName || normalizedName === normalizedId) {\n return normalizedId;\n }\n\n return `${normalizedName} [${normalizedId}]`;\n}\n\nexport function resolveAddressLabel(\n address: string,\n heartbeats: HeartbeatStore,\n): string {\n const normalized = address.trim();\n if (!normalized || normalized === \"전체\" || normalized === \"all\") {\n return address;\n }\n\n const direct = heartbeats[normalized];\n if (direct?.agent?.trim()) {\n return formatAgentLabel(normalized, direct.agent);\n }\n\n for (const [agentId, heartbeat] of Object.entries(heartbeats)) {\n if (heartbeat.agent?.trim() === normalized) {\n return formatAgentLabel(agentId, heartbeat.agent);\n }\n }\n\n return normalized;\n}\n\nexport function resolveCurrentAgentName(\n agentId: string,\n fallbackAgentName: string,\n heartbeats: HeartbeatStore,\n): string {\n const currentName = heartbeats[agentId]?.agent?.trim();\n if (currentName) {\n return currentName;\n }\n\n for (const heartbeat of Object.values(heartbeats)) {\n if (heartbeat.id?.trim() === agentId && heartbeat.agent?.trim()) {\n return heartbeat.agent.trim();\n }\n }\n\n return fallbackAgentName;\n}\n\nfunction refreshAgentIdentity(\n options: Options,\n heartbeats: HeartbeatStore,\n): string {\n const nextAgentName = resolveCurrentAgentName(\n options.agentId,\n options.agentName,\n heartbeats,\n );\n\n if (nextAgentName !== options.agentName) {\n options.agentName = nextAgentName;\n persistAgentName(options.stateDir, nextAgentName);\n }\n\n return nextAgentName;\n}\n\n// When running in headless reviewer mode, review-request files are handled\n// by the headless loop (engine/headless-loop.ts), not the generic bridge.\n// Skip them here to prevent race conditions.\nconst HEADLESS_SKIP_PATTERNS = [\n /리뷰\\s*요청/,\n /review[- ]?request/i,\n /재리뷰/,\n /re-?review/i,\n];\n\nfunction shouldSkipInHeadlessMode(fileName: string, body: string): boolean {\n if (process.env.TAP_HEADLESS !== \"true\") return false;\n const combined = `${fileName}\\n${body}`;\n return HEADLESS_SKIP_PATTERNS.some((p) => p.test(combined));\n}\n\nfunction collectCandidates(\n inboxDir: string,\n agentId: string,\n agentName: string,\n): Candidate[] {\n const entries = readdirSync(inboxDir, { withFileTypes: true })\n .filter(\n (entry) => entry.isFile() && entry.name.toLowerCase().endsWith(\".md\"),\n )\n .map((entry) => {\n const filePath = join(inboxDir, entry.name);\n const stats = statSync(filePath);\n return { entry, filePath, stats };\n })\n .sort((left, right) => left.stats.mtimeMs - right.stats.mtimeMs);\n\n const candidates: Candidate[] = [];\n for (const item of entries) {\n const route = getInboxRoute(item.entry.name);\n if (!recipientMatchesAgent(route.recipient, agentId, agentName)) {\n continue;\n }\n\n if (isOwnMessageSender(route.sender, agentId, agentName)) {\n continue;\n }\n\n const body = readFileSync(item.filePath, \"utf8\");\n\n // In headless mode, skip review-request files — handled by headless loop\n if (shouldSkipInHeadlessMode(item.entry.name, body)) {\n continue;\n }\n\n candidates.push({\n markerId: buildMarkerId(item.filePath, item.stats.mtimeMs),\n filePath: item.filePath,\n fileName: item.entry.name,\n sender: route.sender,\n recipient: route.recipient,\n subject: route.subject,\n body,\n mtimeMs: item.stats.mtimeMs,\n });\n }\n\n return candidates;\n}\n\nfunction getPendingCandidates(\n options: Options,\n cutoff: Date,\n): {\n heartbeats: HeartbeatStore;\n candidates: Candidate[];\n} {\n const inboxDir = join(options.commsDir, \"inbox\");\n if (!existsSync(inboxDir)) {\n throw new Error(`Inbox directory not found: ${inboxDir}`);\n }\n\n const heartbeats = loadHeartbeats(options.commsDir);\n const agentName = refreshAgentIdentity(options, heartbeats);\n const cutoffMs = cutoff.getTime();\n const candidates = collectCandidates(\n inboxDir,\n options.agentId,\n agentName,\n ).filter((candidate) => {\n if (candidate.mtimeMs < cutoffMs) {\n return false;\n }\n\n return !existsSync(\n getProcessedMarkerPath(options.stateDir, candidate.markerId),\n );\n });\n\n return { heartbeats, candidates };\n}\n\nexport function buildUserInput(\n candidate: Candidate,\n agentName: string,\n heartbeats: HeartbeatStore,\n): string {\n const sender = resolveAddressLabel(candidate.sender || \"unknown\", heartbeats);\n const recipient = resolveAddressLabel(\n candidate.recipient || agentName,\n heartbeats,\n );\n const subject = candidate.subject || \"(none)\";\n const body = candidate.body.trim();\n\n return [\n `Tap-comms inbox message for ${agentName}.`,\n `Sender: ${sender}`,\n `Recipient: ${recipient}`,\n `Subject: ${subject}`,\n `File: ${candidate.fileName}`,\n \"\",\n \"Message body:\",\n body || \"(empty)\",\n \"\",\n \"---\",\n \"Instructions: Read the message above and respond using the tap_reply tool.\",\n `Use tap_reply(to: \"${candidate.sender || \"unknown\"}\", subject: \"<your-subject>\", content: \"<your-response>\") to send your response.`,\n \"If the message is a review request, perform the review and reply with your findings.\",\n \"If the message is informational, acknowledge briefly via tap_reply.\",\n \"Do NOT respond with plain text only — you MUST use the tap_reply tool.\",\n ].join(\"\\n\");\n}\n\nfunction writeProcessedMarker(\n stateDir: string,\n candidate: Candidate,\n dispatchMode: \"start\" | \"steer\",\n threadId: string | null,\n turnId: string | null,\n): void {\n const payload = {\n requestFile: candidate.filePath,\n requestName: candidate.fileName,\n sender: candidate.sender,\n recipient: candidate.recipient,\n subject: candidate.subject,\n dispatchMode,\n threadId,\n turnId,\n markedAt: new Date().toISOString(),\n };\n writeFileSync(\n getProcessedMarkerPath(stateDir, candidate.markerId),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nfunction writeLastDispatch(\n stateDir: string,\n candidate: Candidate,\n dispatchMode: \"start\" | \"steer\",\n threadId: string | null,\n turnId: string | null,\n): void {\n const payload = {\n requestFile: candidate.filePath,\n requestName: candidate.fileName,\n markerId: candidate.markerId,\n sender: candidate.sender,\n recipient: candidate.recipient,\n subject: candidate.subject,\n dispatchMode,\n threadId,\n turnId,\n dispatchedAt: new Date().toISOString(),\n };\n writeFileSync(\n join(stateDir, \"last-dispatch.json\"),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nfunction formatJsonRpcError(error: JsonRpcResponse[\"error\"]): string {\n if (!error) {\n return \"Unknown App Server error\";\n }\n\n return JSON.stringify(\n {\n code: error.code,\n message: error.message,\n data: error.data,\n },\n null,\n 2,\n );\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolvePromise) => {\n setTimeout(resolvePromise, ms);\n });\n}\n\nexport async function waitForTurnCompletion(\n client: Pick<\n HeadlessWarmupClient,\n \"activeTurnId\" | \"lastTurnStatus\" | \"refreshCurrentThreadState\"\n >,\n turnId: string,\n timeoutMs: number,\n): Promise<string | null> {\n const deadline = Date.now() + timeoutMs;\n let nextRefreshAt = Date.now();\n\n while (Date.now() < deadline) {\n if (!client.activeTurnId || client.activeTurnId !== turnId) {\n return client.lastTurnStatus;\n }\n\n if (Date.now() >= nextRefreshAt) {\n await client.refreshCurrentThreadState().catch(() => undefined);\n if (!client.activeTurnId || client.activeTurnId !== turnId) {\n return client.lastTurnStatus;\n }\n nextRefreshAt = Date.now() + TURN_COMPLETION_REFRESH_MS;\n }\n\n await delay(\n Math.min(TURN_COMPLETION_POLL_MS, Math.max(deadline - Date.now(), 0)),\n );\n }\n\n await client.refreshCurrentThreadState().catch(() => undefined);\n if (!client.activeTurnId || client.activeTurnId !== turnId) {\n return client.lastTurnStatus;\n }\n\n throw new Error(`Timed out waiting for turn ${turnId} to complete`);\n}\n\nexport async function maybeBootstrapHeadlessTurn(\n options: Options,\n cutoff: Date,\n client: HeadlessWarmupClient,\n): Promise<boolean> {\n if (\n process.env.TAP_HEADLESS !== \"true\" &&\n process.env.TAP_COLD_START_WARMUP !== \"true\"\n ) {\n return false;\n }\n\n const { candidates } = getPendingCandidates(options, cutoff);\n if (\n candidates.length > 0 ||\n client.activeTurnId ||\n client.lastTurnStatus !== null\n ) {\n return false;\n }\n\n logStatus(\"headless cold-start: sending warmup turn\");\n const turnId = await client.startTurn(HEADLESS_WARMUP_PROMPT);\n if (!turnId) {\n throw new Error(\n \"Headless cold-start warmup failed: turn/start did not return a turn id. \" +\n \"Run: npx @hua-labs/tap doctor\",\n );\n }\n\n try {\n const status = await waitForTurnCompletion(\n client,\n turnId,\n HEADLESS_WARMUP_TIMEOUT_MS,\n );\n if (status !== \"completed\") {\n throw new Error(\n `turn ${turnId} finished with status ${status ?? \"unknown\"}`,\n );\n }\n\n logStatus(`headless cold-start warmup completed (${status})`);\n return true;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Headless cold-start warmup failed: ${reason}. ` +\n \"Run: npx @hua-labs/tap doctor\",\n );\n }\n}\n\nfunction shouldRetrySteerAsStart(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes(\"no active turn\") ||\n message.includes(\"expectedturnid\") ||\n (message.includes(\"turn/steer failed\") &&\n (message.includes(\"active turn\") || message.includes(\"not found\")))\n );\n}\n\nasync function readSocketData(data: unknown): Promise<string> {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data).toString(\"utf8\");\n }\n\n if (ArrayBuffer.isView(data)) {\n return Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString(\n \"utf8\",\n );\n }\n\n if (typeof Blob !== \"undefined\" && data instanceof Blob) {\n return await data.text();\n }\n\n return String(data);\n}\n\nclass AppServerClient {\n private socket: WebSocket | null = null;\n private readonly url: string;\n private readonly gatewayToken: string | null;\n private readonly logger: (message: string) => void;\n private nextId = 1;\n private pending = new Map<\n number,\n {\n resolve: (value: any) => void;\n reject: (reason?: unknown) => void;\n method: string;\n }\n >();\n\n connected = false;\n initialized = false;\n threadId: string | null = null;\n currentThreadCwd: string | null = null;\n activeTurnId: string | null = null;\n turnStartedAt: string | null = null;\n lastTurnStatus: string | null = null;\n lastNotificationMethod: string | null = null;\n lastNotificationAt: string | null = null;\n lastError: string | null = null;\n lastSuccessfulAppServerAt: string | null = null;\n lastSuccessfulAppServerMethod: string | null = null;\n\n constructor(\n url: string,\n logger: (message: string) => void,\n gatewayToken?: string | null,\n ) {\n this.url = url;\n this.logger = logger;\n this.gatewayToken = gatewayToken ?? null;\n }\n\n async connect(): Promise<void> {\n if (this.connected && this.socket?.readyState === WebSocket.OPEN) {\n return;\n }\n\n // Authenticate via WebSocket subprotocol instead of URL query param.\n // Token stays out of URLs (no log/referer/history leakage).\n const wsOptions: { protocols?: string[] } = {};\n if (this.gatewayToken) {\n wsOptions.protocols = [`${AUTH_SUBPROTOCOL_PREFIX}${this.gatewayToken}`];\n }\n this.socket = new WebSocket(this.url, wsOptions);\n\n await new Promise<void>((resolvePromise, rejectPromise) => {\n let settled = false;\n\n const resolveOnce = () => {\n if (settled) {\n return;\n }\n settled = true;\n resolvePromise();\n };\n\n const rejectOnce = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n rejectPromise(error);\n };\n\n this.socket?.addEventListener(\n \"open\",\n () => {\n this.connected = true;\n this.logger(`connected to app-server at ${this.url}`);\n resolveOnce();\n },\n { once: true },\n );\n\n this.socket?.addEventListener(\"error\", () => {\n const error = new Error(\n `Failed to connect to App Server at ${this.url}`,\n );\n this.lastError = error.message;\n rejectOnce(error);\n });\n\n this.socket?.addEventListener(\"close\", () => {\n this.connected = false;\n this.initialized = false;\n this.activeTurnId = null;\n this.turnStartedAt = null;\n this.logger(\"disconnected from app-server\");\n this.rejectPending(new Error(\"App Server connection closed\"));\n });\n\n this.socket?.addEventListener(\"message\", (event) => {\n void this.handleMessage(event.data);\n });\n });\n\n await this.request(\"initialize\", {\n clientInfo: {\n name: \"tap-app-server-bridge\",\n title: \"tap app-server bridge\",\n version: \"0.1.0\",\n },\n capabilities: {\n experimentalApi: false,\n },\n });\n this.initialized = true;\n }\n\n async disconnect(): Promise<void> {\n if (!this.socket) {\n return;\n }\n\n this.socket.close();\n this.connected = false;\n this.initialized = false;\n this.socket = null;\n }\n\n async ensureThread(\n explicitThreadId: string | null,\n savedThread: ThreadStateRecord | null,\n cwd: string,\n ephemeral: boolean,\n ): Promise<string> {\n if (explicitThreadId) {\n try {\n const resumeResponse = await this.request(\"thread/resume\", {\n threadId: explicitThreadId,\n persistExtendedHistory: false,\n });\n const resumedThreadId = resumeResponse?.thread?.id ?? explicitThreadId;\n await this.refreshThreadState(resumedThreadId);\n this.logger(\n `resumed thread ${resumedThreadId}${\n this.activeTurnId ? ` (active turn ${this.activeTurnId})` : \"\"\n }`,\n );\n return resumedThreadId;\n } catch (error) {\n this.logger(\n `thread resume failed for ${explicitThreadId}; starting a fresh thread (${String(error)})`,\n );\n }\n }\n\n const loadedThreadId = await this.findLoadedThread(cwd);\n if (loadedThreadId) {\n return loadedThreadId;\n }\n\n if (savedThread?.threadId) {\n if (savedThread.cwd && !threadCwdMatches(cwd, savedThread.cwd)) {\n this.logger(\n `saved thread ${savedThread.threadId} cwd ${savedThread.cwd} does not match ${cwd}; skipping saved thread`,\n );\n } else {\n try {\n const resumeResponse = await this.request(\"thread/resume\", {\n threadId: savedThread.threadId,\n persistExtendedHistory: false,\n });\n const resumedThreadId =\n resumeResponse?.thread?.id ?? savedThread.threadId;\n await this.refreshThreadState(resumedThreadId);\n if (!threadCwdMatches(cwd, this.currentThreadCwd)) {\n this.logger(\n `saved thread ${resumedThreadId} cwd ${\n this.currentThreadCwd ?? \"unknown\"\n } does not match ${cwd}; starting a fresh thread`,\n );\n this.threadId = null;\n this.currentThreadCwd = null;\n this.activeTurnId = null;\n this.turnStartedAt = null;\n this.lastTurnStatus = null;\n } else {\n this.logger(\n `resumed saved thread ${resumedThreadId}${\n this.activeTurnId ? ` (active turn ${this.activeTurnId})` : \"\"\n }`,\n );\n return resumedThreadId;\n }\n } catch (error) {\n this.logger(\n `saved thread resume failed for ${savedThread.threadId}; starting a fresh thread (${String(error)})`,\n );\n }\n }\n }\n\n const startResponse = await this.request(\"thread/start\", {\n cwd,\n ephemeral,\n experimentalRawEvents: false,\n persistExtendedHistory: false,\n });\n\n const startedThreadId = startResponse?.thread?.id;\n if (!startedThreadId) {\n throw new Error(\"thread/start did not return a thread id\");\n }\n\n this.syncThreadStateFromThread(startResponse?.thread);\n this.threadId = startedThreadId;\n this.currentThreadCwd = this.currentThreadCwd ?? cwd;\n this.activeTurnId = null;\n this.lastTurnStatus = null;\n this.logger(`started thread ${startedThreadId}`);\n return startedThreadId;\n }\n\n async findLoadedThread(cwd: string): Promise<string | null> {\n const response = await this.request(\"thread/loaded/list\", {\n limit: 20,\n });\n const threadIds = Array.isArray(response?.data)\n ? response.data.filter(\n (value: unknown): value is string => typeof value === \"string\",\n )\n : [];\n\n if (threadIds.length === 0) {\n return null;\n }\n\n const threads: LoadedThreadCandidate[] = [];\n\n for (const threadId of threadIds) {\n try {\n const threadResponse = await this.request(\"thread/read\", {\n threadId,\n includeTurns: true,\n });\n const thread = threadResponse?.thread;\n if (!thread?.id) {\n continue;\n }\n threads.push({\n id: thread.id,\n cwd: typeof thread.cwd === \"string\" ? thread.cwd : \"\",\n updatedAt:\n typeof thread.updatedAt === \"number\" ? thread.updatedAt : 0,\n statusType: thread.status?.type ?? null,\n thread,\n });\n } catch {\n continue;\n }\n }\n\n const chosen = chooseLoadedThreadForCwd(cwd, threads);\n if (!chosen) {\n if (threads.length > 0) {\n this.logger(`loaded threads exist but none match cwd ${cwd}`);\n }\n return null;\n }\n this.syncThreadStateFromThread(chosen.thread);\n this.logger(\n `attached to loaded thread ${chosen.id}${\n this.activeTurnId ? ` (active turn ${this.activeTurnId})` : \"\"\n }`,\n );\n return chosen.id;\n }\n\n async startTurn(inputText: string): Promise<string | null> {\n const threadId = this.requireThreadId();\n const response = await this.request(\"turn/start\", {\n threadId,\n input: [\n {\n type: \"text\",\n text: inputText,\n text_elements: [],\n },\n ],\n });\n\n const turnId = response?.turn?.id ?? null;\n if (turnId) {\n this.activeTurnId = turnId;\n this.turnStartedAt = new Date().toISOString();\n }\n return turnId;\n }\n\n async steerTurn(inputText: string): Promise<string> {\n const threadId = this.requireThreadId();\n const turnId = this.requireActiveTurnId();\n\n await this.request(\"turn/steer\", {\n threadId,\n expectedTurnId: turnId,\n input: [\n {\n type: \"text\",\n text: inputText,\n text_elements: [],\n },\n ],\n });\n\n return turnId;\n }\n\n isBusy(): boolean {\n return Boolean(this.activeTurnId);\n }\n\n async refreshCurrentThreadState(): Promise<void> {\n if (!this.threadId) {\n return;\n }\n\n await this.refreshThreadState(this.threadId);\n }\n\n private requireThreadId(): string {\n if (!this.threadId) {\n throw new Error(\"No active App Server thread is available\");\n }\n return this.threadId;\n }\n\n private requireActiveTurnId(): string {\n if (!this.activeTurnId) {\n throw new Error(\"No active turn is available for turn/steer\");\n }\n return this.activeTurnId;\n }\n\n private async refreshThreadState(threadId: string): Promise<void> {\n const threadResponse = await this.request(\"thread/read\", {\n threadId,\n includeTurns: true,\n });\n this.syncThreadStateFromThread(threadResponse?.thread);\n }\n\n private syncThreadStateFromThread(thread: any): void {\n if (typeof thread?.id === \"string\") {\n this.threadId = thread.id;\n }\n this.currentThreadCwd = typeof thread?.cwd === \"string\" ? thread.cwd : null;\n\n let activeTurnId: string | null = null;\n let lastTurnStatus: string | null = null;\n const turns = Array.isArray(thread?.turns) ? thread.turns : [];\n for (const turn of turns) {\n if (typeof turn?.status === \"string\") {\n lastTurnStatus = turn.status;\n }\n if (turn?.status === \"inProgress\" && typeof turn.id === \"string\") {\n activeTurnId = turn.id;\n }\n }\n\n if (activeTurnId && activeTurnId !== this.activeTurnId) {\n this.turnStartedAt = new Date().toISOString();\n } else if (!activeTurnId) {\n this.turnStartedAt = null;\n }\n this.activeTurnId = activeTurnId;\n this.lastTurnStatus = lastTurnStatus;\n }\n\n private async handleMessage(data: unknown): Promise<void> {\n const text = await readSocketData(data);\n const message = JSON.parse(text) as JsonRpcResponse;\n\n if (\n typeof message.id === \"number\" &&\n (Object.hasOwn(message, \"result\") || Object.hasOwn(message, \"error\"))\n ) {\n const pending = this.pending.get(message.id);\n if (!pending) {\n return;\n }\n\n this.pending.delete(message.id);\n if (message.error) {\n const errorText = formatJsonRpcError(message.error);\n this.lastError = errorText;\n pending.reject(new Error(`${pending.method} failed: ${errorText}`));\n return;\n }\n\n pending.resolve(message.result);\n this.lastSuccessfulAppServerAt = new Date().toISOString();\n this.lastSuccessfulAppServerMethod = pending.method;\n this.lastError = null;\n return;\n }\n\n if (!message.method) {\n return;\n }\n\n this.lastNotificationMethod = message.method;\n this.lastNotificationAt = new Date().toISOString();\n this.handleNotification(message.method, message.params);\n }\n\n private handleNotification(method: string, params: any): void {\n switch (method) {\n case \"thread/started\":\n if (params?.thread?.id) {\n this.threadId = params.thread.id;\n }\n if (typeof params?.thread?.cwd === \"string\") {\n this.currentThreadCwd = params.thread.cwd;\n }\n this.logger(`thread started ${params?.thread?.id ?? \"\"}`.trim());\n break;\n case \"thread/status/changed\":\n this.logger(\n `thread status changed (${params?.thread?.status?.type ?? params?.status?.type ?? \"unknown\"})`,\n );\n break;\n case \"turn/started\":\n if (params?.turn?.id) {\n this.activeTurnId = params.turn.id;\n this.turnStartedAt = new Date().toISOString();\n this.logger(`turn started ${params.turn.id}`);\n }\n break;\n case \"turn/completed\": {\n this.lastTurnStatus = params?.turn?.status ?? null;\n const prevTurnStartedAt = this.turnStartedAt;\n this.activeTurnId = null;\n this.turnStartedAt = null;\n const elapsedMs = prevTurnStartedAt\n ? Date.now() - new Date(prevTurnStartedAt).getTime()\n : null;\n const elapsedSuffix =\n elapsedMs !== null\n ? ` — ${Math.round(elapsedMs / 1000)}s elapsed`\n : \"\";\n this.logger(\n `turn completed (${this.lastTurnStatus ?? \"unknown\"})${elapsedSuffix}`,\n );\n break;\n }\n case \"error\":\n this.lastError = JSON.stringify(params ?? {}, null, 2);\n this.logger(`app-server error notification: ${this.lastError}`);\n break;\n default:\n break;\n }\n }\n\n private request(method: string, params: unknown): Promise<any> {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n throw new Error(`Cannot call ${method}; App Server socket is not open`);\n }\n\n const id = this.nextId;\n this.nextId += 1;\n\n const request: RequestRecord = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n };\n\n return new Promise((resolvePromise, rejectPromise) => {\n this.pending.set(id, {\n resolve: resolvePromise,\n reject: rejectPromise,\n method,\n });\n this.socket?.send(JSON.stringify(request));\n });\n }\n\n private rejectPending(error: Error): void {\n for (const pending of this.pending.values()) {\n pending.reject(error);\n }\n this.pending.clear();\n }\n}\n\nlet heartbeatCount = 0;\n\nfunction writeHeartbeat(\n options: Options,\n client: AppServerClient | null,\n health: BridgeHealthState,\n): void {\n if (client?.threadId) {\n const savedThread = readThreadState(options.stateDir);\n persistThreadState(\n options.stateDir,\n client.threadId,\n options.appServerUrl,\n options.ephemeral,\n client.currentThreadCwd ?? savedThread?.cwd ?? null,\n );\n }\n\n const payload: HeartbeatRecord = {\n pid: process.pid,\n agent: options.agentName,\n updatedAt: new Date().toISOString(),\n pollSeconds: options.pollSeconds,\n appServerUrl: options.appServerUrl,\n connected: client?.connected ?? false,\n initialized: client?.initialized ?? false,\n threadId: client?.threadId ?? null,\n threadCwd: client?.currentThreadCwd ?? null,\n activeTurnId: client?.activeTurnId ?? null,\n turnStartedAt: client?.turnStartedAt ?? null,\n lastTurnStatus: client?.lastTurnStatus ?? null,\n lastNotificationMethod: client?.lastNotificationMethod ?? null,\n lastNotificationAt: client?.lastNotificationAt ?? null,\n lastError: sanitizeErrorForPersistence(client?.lastError ?? null),\n lastSuccessfulAppServerAt: client?.lastSuccessfulAppServerAt ?? null,\n lastSuccessfulAppServerMethod:\n client?.lastSuccessfulAppServerMethod ?? null,\n consecutiveFailureCount: health.consecutiveFailureCount,\n busyMode: options.busyMode,\n };\n\n writeFileSync(\n join(options.stateDir, \"heartbeat.json\"),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n\n heartbeatCount += 1;\n if (heartbeatCount % 5 === 0) {\n logStatus(\n `heartbeat: connected=${payload.connected}, thread=${payload.threadId ?? \"null\"}, turns=${payload.activeTurnId ? \"active\" : \"0\"}`,\n );\n }\n\n // Also update comms heartbeats.json so tap_who sees this agent\n const status = client?.connected ? \"active\" : \"idle\";\n updateCommsHeartbeat(options, status);\n}\n\n// ── Comms heartbeat (shared agent registry) ───────────────────────────\n// The MCP channel maintains comms/heartbeats.json for tap_who / tap doctor.\n// When Codex can't call MCP tools (hyphen bug, tool-hidden sessions), the\n// bridge updates this file directly so the agent stays visible.\n\nconst COMMS_HEARTBEAT_LOCK_TIMEOUT_MS = 2_000;\nconst COMMS_LOCK_STALE_AGE_MS = 10_000;\n\nfunction acquireCommsLock(lockPath: string): boolean {\n const deadline = Date.now() + COMMS_HEARTBEAT_LOCK_TIMEOUT_MS;\n while (Date.now() < deadline) {\n try {\n writeFileSync(lockPath, String(process.pid), { flag: \"wx\" });\n return true;\n } catch {\n // Lock exists — check if stale\n try {\n const lockAge = Date.now() - statSync(lockPath).mtimeMs;\n if (lockAge > COMMS_LOCK_STALE_AGE_MS) {\n unlinkSync(lockPath);\n // Retry with exclusive create\n try {\n writeFileSync(lockPath, String(process.pid), { flag: \"wx\" });\n return true;\n } catch {\n // Another process grabbed it between unlink and our wx\n }\n }\n } catch {\n // Lock disappeared between check and stat — retry\n }\n const start = Date.now();\n while (Date.now() - start < 50) {\n /* spin */\n }\n }\n }\n return false;\n}\n\nfunction releaseCommsLock(lockPath: string): void {\n try {\n unlinkSync(lockPath);\n } catch {\n // Already removed\n }\n}\n\nfunction updateCommsHeartbeat(options: Options, status: string): void {\n const heartbeatsPath = join(options.commsDir, \"heartbeats.json\");\n const lockPath = join(options.commsDir, \".heartbeats.lock\");\n\n if (!acquireCommsLock(lockPath)) {\n return; // Non-critical — skip this cycle\n }\n\n try {\n let store: Record<string, unknown> = {};\n try {\n store = JSON.parse(readFileSync(heartbeatsPath, \"utf-8\"));\n } catch {\n // Empty or corrupt — start fresh\n }\n\n // Use agentId as key (SSOT for heartbeat store), not agentName.\n // This matches tap-comms.ts which keys by routing id.\n const key = options.agentId;\n const existing = store[key] as Record<string, unknown> | undefined;\n store[key] = {\n id: options.agentId,\n agent: options.agentName,\n timestamp: new Date().toISOString(),\n lastActivity: new Date().toISOString(),\n joinedAt: (existing?.joinedAt as string) ?? new Date().toISOString(),\n status,\n };\n\n const tmpPath = heartbeatsPath + \".tmp.\" + process.pid;\n writeFileSync(tmpPath, JSON.stringify(store, null, 2), \"utf-8\");\n renameSync(tmpPath, heartbeatsPath);\n } catch {\n // Non-critical — comms heartbeat update failure should never crash bridge\n } finally {\n releaseCommsLock(lockPath);\n }\n}\n\nasync function dispatchCandidate(\n client: AppServerClient,\n options: Options,\n candidate: Candidate,\n heartbeats: HeartbeatStore,\n): Promise<boolean> {\n const input = buildUserInput(candidate, options.agentName, heartbeats);\n\n logStatus(\n `dispatching from ${candidate.sender || \"unknown\"}: ${candidate.subject || \"(none)\"}`,\n );\n\n if (client.isBusy()) {\n if (options.busyMode !== \"steer\") {\n return false;\n }\n\n try {\n const turnId = await client.steerTurn(input);\n writeProcessedMarker(\n options.stateDir,\n candidate,\n \"steer\",\n client.threadId,\n turnId,\n );\n writeLastDispatch(\n options.stateDir,\n candidate,\n \"steer\",\n client.threadId,\n turnId,\n );\n logStatus(`steered active turn with ${candidate.fileName}`);\n return true;\n } catch (error) {\n await client.refreshCurrentThreadState().catch(() => undefined);\n\n if (!client.isBusy()) {\n return dispatchCandidate(client, options, candidate, heartbeats);\n }\n\n if (shouldRetrySteerAsStart(error)) {\n client.activeTurnId = null;\n client.turnStartedAt = null;\n logStatus(\n `steer fallback -> start for ${candidate.fileName} (${String(error)})`,\n );\n return dispatchCandidate(client, options, candidate, heartbeats);\n }\n\n throw error;\n }\n }\n\n const turnId = await client.startTurn(input);\n writeProcessedMarker(\n options.stateDir,\n candidate,\n \"start\",\n client.threadId,\n turnId,\n );\n writeLastDispatch(\n options.stateDir,\n candidate,\n \"start\",\n client.threadId,\n turnId,\n );\n logStatus(`dispatched ${candidate.fileName} to thread ${client.threadId}`);\n return true;\n}\n\nasync function runScan(\n options: Options,\n cutoff: Date,\n client: AppServerClient | null,\n): Promise<boolean> {\n const { heartbeats, candidates } = getPendingCandidates(options, cutoff);\n for (const candidate of candidates) {\n if (options.dryRun) {\n logStatus(`dry-run candidate ${candidate.fileName}`);\n continue;\n }\n\n if (!client) {\n throw new Error(\"App Server client is not available\");\n }\n\n const dispatched = await dispatchCandidate(\n client,\n options,\n candidate,\n heartbeats,\n );\n if (!dispatched && options.busyMode === \"wait\") {\n return false;\n }\n return true;\n }\n\n return false;\n}\n\nasync function waitForTurnDrain(\n options: Options,\n client: AppServerClient,\n health: BridgeHealthState,\n): Promise<void> {\n const deadline = Date.now() + options.waitAfterDispatchSeconds * 1_000;\n while (Date.now() < deadline) {\n writeHeartbeat(options, client, health);\n if (!client.activeTurnId) {\n return;\n }\n await delay(1_000);\n }\n}\n\nexport function buildOptions(argv: string[]): Options {\n const parsed = parseArgs(argv);\n const repoRoot = resolveRepoRoot(parsed.repoRoot);\n const commsDir = resolveCommsDir(repoRoot, parsed.commsDir);\n const preferredAgentName = resolvePreferredAgentName(parsed.agentName);\n const stateDir = resolveStateDir(\n repoRoot,\n parsed.stateDir,\n preferredAgentName,\n );\n const agentName = resolveAgentName(preferredAgentName, stateDir);\n const agentId = resolveAgentId(agentName);\n persistAgentName(stateDir, agentName);\n const gatewayTokenFile =\n parsed.gatewayTokenFile?.trim() ||\n process.env.TAP_GATEWAY_TOKEN_FILE?.trim() ||\n null;\n const appServerUrl =\n parsed.appServerUrl?.trim() ||\n process.env.CODEX_APP_SERVER_URL ||\n DEFAULT_APP_SERVER_URL;\n\n return {\n repoRoot,\n commsDir,\n agentId,\n stateDir,\n agentName,\n pollSeconds: parsed.pollSeconds ?? 5,\n reconnectSeconds: parsed.reconnectSeconds ?? 5,\n messageLookbackMinutes: parsed.messageLookbackMinutes ?? 10,\n processExistingMessages: parsed.processExistingMessages,\n dryRun: parsed.dryRun,\n runOnce: parsed.runOnce,\n waitAfterDispatchSeconds: parsed.waitAfterDispatchSeconds ?? 0,\n appServerUrl,\n connectAppServerUrl: appServerUrl,\n gatewayToken: gatewayTokenFile\n ? readGatewayTokenFile(gatewayTokenFile)\n : null,\n gatewayTokenFile,\n busyMode: parsed.busyMode ?? \"steer\",\n threadId: parsed.threadId?.trim() || null,\n ephemeral: parsed.ephemeral,\n };\n}\n\nexport async function main(): Promise<void> {\n const options = buildOptions(process.argv.slice(2));\n const cutoff = getGeneralInboxCutoff(\n options.stateDir,\n options.messageLookbackMinutes,\n options.processExistingMessages,\n );\n const initialSavedThread = loadResumableThreadState(\n options.stateDir,\n options.appServerUrl,\n );\n\n logStatus(\"codex app-server bridge ready\");\n console.log(` repo: ${options.repoRoot}`);\n console.log(` comms: ${options.commsDir}`);\n console.log(` agent: ${options.agentName}`);\n console.log(` state: ${options.stateDir}`);\n console.log(` app-server: ${options.appServerUrl}`);\n console.log(` busy-mode: ${options.busyMode}`);\n if (options.waitAfterDispatchSeconds > 0) {\n console.log(\n ` wait: ${options.waitAfterDispatchSeconds}s after dispatch`,\n );\n }\n console.log(\n ` lookback: ${\n options.processExistingMessages\n ? \"existing messages\"\n : `${options.messageLookbackMinutes} minute(s)`\n }`,\n );\n if (options.threadId || initialSavedThread?.threadId) {\n console.log(\n ` thread: ${options.threadId ?? initialSavedThread?.threadId}`,\n );\n }\n if (options.dryRun) {\n logStatus(\"dry-run mode enabled\");\n }\n\n let client: AppServerClient | null = null;\n const health: BridgeHealthState = {\n consecutiveFailureCount: 0,\n };\n\n while (true) {\n try {\n if (!options.dryRun) {\n if (!client || !client.connected) {\n client = new AppServerClient(\n options.connectAppServerUrl,\n logStatus,\n options.gatewayToken,\n );\n await client.connect();\n const savedThread = loadResumableThreadState(\n options.stateDir,\n options.appServerUrl,\n );\n\n const threadId = await client.ensureThread(\n options.threadId,\n savedThread,\n options.repoRoot,\n options.ephemeral,\n );\n persistThreadState(\n options.stateDir,\n threadId,\n options.appServerUrl,\n options.ephemeral,\n client.currentThreadCwd ?? options.repoRoot,\n );\n writeHeartbeat(options, client, health);\n const bootstrapped = await maybeBootstrapHeadlessTurn(\n options,\n cutoff,\n client,\n );\n if (bootstrapped) {\n writeHeartbeat(options, client, health);\n }\n }\n }\n\n const dispatched = await runScan(options, cutoff, client);\n if (dispatched && client && options.waitAfterDispatchSeconds > 0) {\n await waitForTurnDrain(options, client, health);\n }\n health.consecutiveFailureCount = 0;\n writeHeartbeat(options, client, health);\n\n if (options.runOnce) {\n break;\n }\n\n await delay(options.pollSeconds * 1_000);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logStatus(`bridge error: ${message}`);\n if (client) {\n client.lastError = message;\n }\n health.consecutiveFailureCount += 1;\n writeHeartbeat(options, client, health);\n\n if (options.runOnce) {\n throw error;\n }\n\n client?.disconnect().catch(() => undefined);\n client = null;\n logStatus(`reconnecting in ${options.reconnectSeconds}s...`);\n await delay(options.reconnectSeconds * 1_000);\n }\n }\n\n await client?.disconnect();\n}\n\nfunction isDirectExecution(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n return import.meta.url === pathToFileURL(resolve(entry)).href;\n}\n\nif (isDirectExecution()) {\n main().catch((error) => {\n console.error(\n error instanceof Error ? (error.stack ?? error.message) : String(error),\n );\n process.exitCode = 1;\n });\n}\n"],"mappings":"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","names":["pathToFileURL","resolve","turnId","isDirectExecution","pathToFileURL","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../../src/bridges/codex-app-server-bridge.ts","../../../../scripts/bridge/bridge-types.ts","../../../../scripts/bridge/bridge-routing.ts","../../../tap-plugin/channels/tap-identity.ts","../../../../scripts/bridge/bridge-config.ts","../../src/config/resolve.ts","../../../../scripts/bridge/bridge-candidates.ts","../../../../scripts/bridge/bridge-logging.ts","../../../../scripts/bridge/bridge-format.ts","../../../../scripts/bridge/bridge-dispatch.ts","../../../../scripts/bridge/bridge-ws-client.ts","../../../../scripts/bridge/bridge-main.ts","../../../../scripts/codex-app-server-bridge.ts"],"sourcesContent":["import { pathToFileURL } from \"node:url\";\nimport { resolve } from \"node:path\";\nimport { main } from \"../../../../scripts/codex-app-server-bridge.js\";\n\nexport * from \"../../../../scripts/codex-app-server-bridge.js\";\n\nfunction isDirectExecution(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n return import.meta.url === pathToFileURL(resolve(entry)).href;\n}\n\nif (isDirectExecution()) {\n main().catch((error) => {\n console.error(\n error instanceof Error ? (error.stack ?? error.message) : String(error),\n );\n process.exitCode = 1;\n });\n}\n","// bridge-types.ts — All interfaces, types, type aliases, and constants\n\nexport type BusyMode = \"wait\" | \"steer\";\nexport type LogLevel = \"debug\" | \"info\" | \"warn\" | \"error\";\n\nexport interface Options {\n repoRoot: string;\n commsDir: string;\n agentId: string;\n agentName: string;\n stateDir: string;\n pollSeconds: number;\n reconnectSeconds: number;\n messageLookbackMinutes: number;\n processExistingMessages: boolean;\n dryRun: boolean;\n runOnce: boolean;\n waitAfterDispatchSeconds: number;\n appServerUrl: string;\n connectAppServerUrl: string;\n gatewayToken: string | null;\n gatewayTokenFile: string | null;\n busyMode: BusyMode;\n logLevel: LogLevel;\n threadId: string | null;\n ephemeral: boolean;\n}\n\nexport interface InboxRoute {\n sender: string;\n recipient: string;\n subject: string;\n}\n\nexport interface Candidate {\n markerId: string;\n filePath: string;\n fileName: string;\n sender: string;\n recipient: string;\n subject: string;\n body: string;\n mtimeMs: number;\n}\n\nexport interface ThreadStateRecord {\n threadId: string;\n updatedAt: string;\n appServerUrl: string;\n ephemeral: boolean;\n cwd?: string | null;\n}\n\nexport interface HeartbeatRecord {\n pid: number;\n agent: string;\n updatedAt: string;\n pollSeconds: number;\n appServerUrl: string;\n authenticated: boolean;\n connected: boolean;\n initialized: boolean;\n threadId: string | null;\n threadCwd?: string | null;\n activeTurnId: string | null;\n turnStartedAt: string | null;\n lastTurnStatus: string | null;\n lastNotificationMethod: string | null;\n lastNotificationAt: string | null;\n lastError: string | null;\n lastSuccessfulAppServerAt: string | null;\n lastSuccessfulAppServerMethod: string | null;\n consecutiveFailureCount: number;\n busyMode: BusyMode;\n}\n\nexport interface BridgeHealthState {\n consecutiveFailureCount: number;\n}\n\nexport interface HeadlessWarmupClient {\n activeTurnId: string | null;\n lastTurnStatus: string | null;\n startTurn(inputText: string): Promise<string | null>;\n refreshCurrentThreadState(): Promise<void>;\n}\n\nexport interface LoadedThreadCandidate {\n id: string;\n cwd: string;\n updatedAt: number;\n statusType: string | null;\n thread: any;\n}\n\nexport interface RequestRecord {\n jsonrpc: \"2.0\";\n id: number;\n method: string;\n params: unknown;\n}\n\nexport interface HeartbeatStoreRecord {\n id?: string;\n agent?: string;\n}\n\nexport type HeartbeatStore = Record<string, HeartbeatStoreRecord>;\n\nexport interface JsonRpcResponse {\n id?: number;\n result?: any;\n error?: {\n code?: number;\n message?: string;\n data?: unknown;\n };\n method?: string;\n params?: any;\n}\n\nexport const DEFAULT_AGENT = String.fromCharCode(0xc628);\nexport const DEFAULT_APP_SERVER_URL = \"ws://127.0.0.1:4501\";\nexport const AUTH_SUBPROTOCOL_PREFIX = \"tap-auth-\";\nexport const PLACEHOLDER_AGENT_VALUES = new Set([\n \"unknown\",\n \"unnamed\",\n \"<set-per-session>\",\n]);\nexport const HEADLESS_WARMUP_PROMPT = [\n \"You are a tap worker agent connected via the tap-comms inbox.\",\n \"This is a one-time warmup turn for headless bridge startup.\",\n \"Do not take any external actions.\",\n \"Reply briefly, then wait for future inbox instructions.\",\n].join(\" \");\nexport const HEADLESS_WARMUP_TIMEOUT_MS = 30_000;\nexport const TURN_COMPLETION_POLL_MS = 250;\nexport const TURN_COMPLETION_REFRESH_MS = 1_000;\n\n// When running in headless reviewer mode, review-request files are handled\n// by the headless loop (engine/headless-loop.ts), not the generic bridge.\n// Skip them here to prevent race conditions.\nexport const HEADLESS_SKIP_PATTERNS = [\n /리뷰\\s*요청/,\n /review[- ]?request/i,\n /재리뷰/,\n /re-?review/i,\n];\n\n// ── Comms heartbeat (shared agent registry) ───────────────────────────\nexport const COMMS_HEARTBEAT_LOCK_TIMEOUT_MS = 2_000;\nexport const COMMS_LOCK_STALE_AGE_MS = 10_000;\n\n/** M203: Timeout after which an active turn is considered stale (5 minutes). */\nexport const STALE_TURN_MS = 5 * 60 * 1000;\n","// bridge-routing.ts — Agent identity, message routing, frontmatter parsing\n\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { join, resolve } from \"path\";\nimport {\n DEFAULT_AGENT,\n HeartbeatStore,\n InboxRoute,\n LoadedThreadCandidate,\n Options,\n PLACEHOLDER_AGENT_VALUES,\n STALE_TURN_MS,\n} from \"./bridge-types.js\";\nimport {\n canonicalizeAgentId,\n matchesAgentRecipient as sharedMatchesAgentRecipient,\n isOwnMessageAddress as sharedIsOwnMessageAddress,\n} from \"../../packages/tap-plugin/channels/tap-identity.js\";\n\n/**\n * M206: Re-export canonicalizeAgentId as canonicalize for backward compat.\n */\nexport function canonicalize(id: string): string {\n return canonicalizeAgentId(id);\n}\n\nexport function normalizeThreadCwd(cwd: string): string {\n return resolve(cwd).replace(/\\\\/g, \"/\").toLowerCase();\n}\n\nexport function threadCwdMatches(\n expectedCwd: string,\n actualCwd: string | null | undefined,\n): boolean {\n if (!actualCwd) {\n return false;\n }\n\n return normalizeThreadCwd(expectedCwd) === normalizeThreadCwd(actualCwd);\n}\n\nexport function chooseLoadedThreadForCwd(\n cwd: string,\n threads: LoadedThreadCandidate[],\n): LoadedThreadCandidate | null {\n const matching = threads.filter((thread) =>\n threadCwdMatches(cwd, thread.cwd),\n );\n if (matching.length === 0) {\n return null;\n }\n\n matching.sort((left, right) => {\n const leftActive = left.statusType === \"active\" ? 1 : 0;\n const rightActive = right.statusType === \"active\" ? 1 : 0;\n if (leftActive !== rightActive) {\n return rightActive - leftActive;\n }\n return right.updatedAt - left.updatedAt;\n });\n\n return matching[0] ?? null;\n}\n\nexport function normalizeAgentToken(value?: string | null): string | null {\n const normalized = value?.trim();\n if (!normalized || PLACEHOLDER_AGENT_VALUES.has(normalized)) {\n return null;\n }\n\n return canonicalize(normalized);\n}\n\nexport function resolveAgentId(preferredAgentName?: string | null): string {\n return (\n normalizeAgentToken(process.env.TAP_AGENT_ID) ??\n normalizeAgentToken(preferredAgentName) ??\n \"unknown\"\n );\n}\n\nexport function resolveAgentName(\n preferredAgentName: string | null,\n stateDir: string,\n): string {\n if (preferredAgentName?.trim()) {\n return preferredAgentName.trim();\n }\n\n const agentFile = join(stateDir, \"agent-name.txt\");\n if (existsSync(agentFile)) {\n const candidate = readFileSync(agentFile, \"utf8\").trim();\n if (candidate) {\n return candidate;\n }\n }\n\n return DEFAULT_AGENT;\n}\n\nexport function resolveCurrentAgentName(\n agentId: string,\n fallbackAgentName: string,\n heartbeats: HeartbeatStore,\n): string {\n const currentName = heartbeats[agentId]?.agent?.trim();\n if (currentName) {\n return currentName;\n }\n\n for (const heartbeat of Object.values(heartbeats)) {\n if (heartbeat.id?.trim() === agentId && heartbeat.agent?.trim()) {\n return heartbeat.agent.trim();\n }\n }\n\n return fallbackAgentName;\n}\n\nexport function resolveAddressLabel(\n address: string,\n heartbeats: HeartbeatStore,\n): string {\n const normalized = address.trim();\n if (!normalized || normalized === \"전체\" || normalized === \"all\") {\n return address;\n }\n\n const direct = heartbeats[normalized];\n if (direct?.agent?.trim()) {\n return formatAgentLabel(normalized, direct.agent);\n }\n\n for (const [agentId, heartbeat] of Object.entries(heartbeats)) {\n if (heartbeat.agent?.trim() === normalized) {\n return formatAgentLabel(agentId, heartbeat.agent);\n }\n }\n\n return normalized;\n}\n\nexport function persistAgentName(stateDir: string, agentName: string): void {\n writeFileSync(join(stateDir, \"agent-name.txt\"), `${agentName}\\n`, \"utf8\");\n}\n\nexport function formatAgentLabel(\n agentIdOrName: string,\n displayName?: string | null,\n): string {\n const normalizedId = agentIdOrName.trim();\n const normalizedName = displayName?.trim();\n\n if (!normalizedId) {\n return normalizedName ?? agentIdOrName;\n }\n\n if (!normalizedName || normalizedName === normalizedId) {\n return normalizedId;\n }\n\n return `${normalizedName} [${normalizedId}]`;\n}\n\n/**\n * Resolve the current display name from heartbeats and persist if changed.\n * Returns the resolved name WITHOUT mutating options.agentName — callers\n * should use the return value for the current scan cycle only.\n * This prevents recipient matching from losing the original configured name.\n */\nexport function refreshAgentIdentity(\n options: Options,\n heartbeats: HeartbeatStore,\n): string {\n const nextAgentName = resolveCurrentAgentName(\n options.agentId,\n options.agentName,\n heartbeats,\n );\n\n if (nextAgentName !== options.agentName) {\n // Persist for next startup, but don't mutate options mid-cycle\n persistAgentName(options.stateDir, nextAgentName);\n }\n\n return nextAgentName;\n}\n\n/**\n * M206: Delegate to shared tap-identity helper.\n * Kept as named export for barrel backward compatibility.\n */\nexport function recipientMatchesAgent(\n recipient: string,\n agentId: string,\n agentName: string,\n): boolean {\n return sharedMatchesAgentRecipient(recipient, agentId, agentName);\n}\n\n/**\n * M206: Delegate to shared tap-identity helper.\n * Kept as named export for barrel backward compatibility.\n */\nexport function isOwnMessageSender(\n sender: string,\n agentId: string,\n agentName: string,\n): boolean {\n return sharedIsOwnMessageAddress(sender, agentId, agentName);\n}\n\n/**\n * M203: Check if a turn's activeFlags indicate it cannot accept steer.\n * Returns true if the turn should be treated as not active.\n */\nexport function isTurnStuckOnApproval(activeFlags: string[]): boolean {\n return activeFlags.includes(\"waitingOnApproval\");\n}\n\n/**\n * M203: Check if a turn has been running longer than the stale threshold.\n */\nexport function isTurnStale(\n turnStartedAt: string | null,\n nowMs: number = Date.now(),\n): boolean {\n if (!turnStartedAt) return false;\n return nowMs - new Date(turnStartedAt).getTime() > STALE_TURN_MS;\n}\n\nexport function shouldRetrySteerAsStart(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n\n const message = error.message.toLowerCase();\n return (\n message.includes(\"no active turn\") ||\n message.includes(\"expectedturnid\") ||\n (message.includes(\"turn/steer failed\") &&\n (message.includes(\"active turn\") || message.includes(\"not found\")))\n );\n}\n\n/**\n * Parse YAML frontmatter from message content for routing.\n * Returns null if no valid frontmatter found.\n */\nexport function parseBridgeFrontmatter(\n content: string,\n): { sender: string; recipient: string; subject: string } | null {\n const match = content.match(/^---\\r?\\n([\\s\\S]*?)\\r?\\n---/);\n if (!match) return null;\n\n const fields: Record<string, string> = {};\n for (const line of match[1].split(\"\\n\")) {\n const kv = line.match(/^(\\w+):\\s*(.+)$/);\n if (kv) fields[kv[1]] = kv[2].trim();\n }\n\n if (!fields.from || !fields.to) return null;\n\n return {\n sender: fields.from,\n recipient: fields.to,\n subject: fields.subject ?? \"\",\n };\n}\n\n/**\n * Strip YAML frontmatter from message content, returning only the body.\n */\nexport function stripBridgeFrontmatter(content: string): string {\n return content.replace(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n*/, \"\");\n}\n\nexport function getInboxRoute(fileName: string, body?: string): InboxRoute {\n if (body) {\n const fm = parseBridgeFrontmatter(body);\n if (fm) return fm;\n }\n return getInboxRouteFromFilename(fileName);\n}\n\nexport function getInboxRouteFromFilename(fileName: string): InboxRoute {\n const stem = fileName.replace(/\\.md$/i, \"\");\n const parts = stem.split(\"-\");\n let offset = 0;\n if (parts[0] && /^\\d{8}$/.test(parts[0])) {\n offset = 1;\n }\n\n return {\n sender: parts[offset] ?? \"\",\n recipient: parts[offset + 1] ?? \"\",\n subject: parts.slice(offset + 2).join(\"-\"),\n };\n}\n","const BROADCAST_RECIPIENTS = new Set([\"전체\", \"all\"]);\n\nexport const PLACEHOLDER_AGENT_VALUES = new Set([\n \"unknown\",\n \"unnamed\",\n \"<set-per-session>\",\n]);\n\nfunction trimAddress(value?: string | null): string {\n return value?.trim() ?? \"\";\n}\n\nexport function canonicalizeAgentId(value: string): string {\n return trimAddress(value).replace(/-/g, \"_\");\n}\n\nexport function isBroadcastRecipient(value: string): boolean {\n return BROADCAST_RECIPIENTS.has(trimAddress(value));\n}\n\nexport function isPlaceholderAgentValue(value?: string | null): boolean {\n const normalized = trimAddress(value);\n return !normalized || PLACEHOLDER_AGENT_VALUES.has(normalized);\n}\n\nexport function sameRoutingAddress(left: string, right: string): boolean {\n const normalizedLeft = trimAddress(left);\n const normalizedRight = trimAddress(right);\n if (!normalizedLeft || !normalizedRight) {\n return false;\n }\n\n if (\n isBroadcastRecipient(normalizedLeft) &&\n isBroadcastRecipient(normalizedRight)\n ) {\n return true;\n }\n\n return (\n normalizedLeft === normalizedRight ||\n canonicalizeAgentId(normalizedLeft) === canonicalizeAgentId(normalizedRight)\n );\n}\n\nexport function matchesAgentRecipient(\n recipient: string,\n agentId: string,\n agentName: string,\n): boolean {\n const normalizedRecipient = trimAddress(recipient);\n if (!normalizedRecipient) {\n return false;\n }\n\n return (\n isBroadcastRecipient(normalizedRecipient) ||\n sameRoutingAddress(normalizedRecipient, agentId) ||\n normalizedRecipient === trimAddress(agentName)\n );\n}\n\nexport function isOwnMessageAddress(\n sender: string,\n agentId: string,\n agentName: string,\n): boolean {\n const normalizedSender = trimAddress(sender);\n if (!normalizedSender) {\n return false;\n }\n\n return (\n sameRoutingAddress(normalizedSender, agentId) ||\n normalizedSender === trimAddress(agentName)\n );\n}\n\nexport function normalizeRecipientList(\n rawRecipients: unknown,\n exclude: string[] = [],\n): string[] | undefined {\n let recipients: string[] | undefined;\n if (rawRecipients == null) {\n recipients = undefined;\n } else if (typeof rawRecipients === \"string\") {\n const trimmed = trimAddress(rawRecipients);\n recipients = trimmed ? [trimmed] : undefined;\n } else if (Array.isArray(rawRecipients)) {\n const valid = rawRecipients\n .filter(\n (value): value is string =>\n typeof value === \"string\" && trimAddress(value).length > 0,\n )\n .map((value) => trimAddress(value));\n recipients = valid.length > 0 ? valid : undefined;\n } else {\n recipients = undefined;\n }\n\n if (!recipients) {\n return undefined;\n }\n\n const filtered: string[] = [];\n for (const recipient of recipients) {\n if (exclude.some((value) => sameRoutingAddress(value, recipient))) {\n continue;\n }\n if (filtered.some((value) => sameRoutingAddress(value, recipient))) {\n continue;\n }\n filtered.push(recipient);\n }\n\n return filtered.length > 0 ? filtered : undefined;\n}\n","// bridge-config.ts — CLI argument parsing and options building\n\nimport { existsSync, mkdirSync, readFileSync } from \"fs\";\nimport { isAbsolute, join, resolve } from \"path\";\nimport { normalizeTapPath } from \"../../packages/tap-comms/src/config/resolve.js\";\nimport {\n BusyMode,\n DEFAULT_APP_SERVER_URL,\n LogLevel,\n Options,\n} from \"./bridge-types.js\";\nimport {\n persistAgentName,\n resolveAgentId,\n resolveAgentName,\n} from \"./bridge-routing.js\";\n\nfunction ensureDir(target: string): string {\n if (!existsSync(target)) {\n mkdirSync(target, { recursive: true });\n }\n return resolve(target);\n}\n\nfunction printHelp(): void {\n console.log(`Codex App Server bridge\n\nUsage:\n node --experimental-strip-types scripts/codex-app-server-bridge.ts [options]\n\nOptions:\n --repo-root=<path>\n --comms-dir=<path>\n --agent-name=<name>\n --state-dir=<path>\n --poll-seconds=<n>\n --reconnect-seconds=<n>\n --message-lookback-minutes=<n>\n --process-existing-messages\n --dry-run\n --run-once\n --wait-after-dispatch-seconds=<n>\n --app-server-url=<ws-url>\n --gateway-token-file=<path>\n --busy-mode=wait|steer\n --log-level=debug|info|warn|error\n --thread-id=<id>\n --ephemeral\n --help\n`);\n}\n\nfunction parseNumber(value: string, flag: string): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed) || parsed < 0) {\n throw new Error(`Invalid ${flag}: ${value}`);\n }\n return parsed;\n}\n\nfunction readFlagValue(argv: string[], index: number, flag: string): string {\n const current = argv[index];\n const eqIndex = current.indexOf(\"=\");\n if (eqIndex >= 0) {\n return current.slice(eqIndex + 1);\n }\n\n const next = argv[index + 1];\n if (!next || next.startsWith(\"--\")) {\n throw new Error(`Missing value for ${flag}`);\n }\n return next;\n}\n\nexport function parseArgs(argv: string[]): {\n repoRoot?: string;\n commsDir?: string;\n agentName?: string;\n stateDir?: string;\n pollSeconds?: number;\n reconnectSeconds?: number;\n messageLookbackMinutes?: number;\n processExistingMessages: boolean;\n dryRun: boolean;\n runOnce: boolean;\n waitAfterDispatchSeconds?: number;\n appServerUrl?: string;\n gatewayTokenFile?: string;\n busyMode?: BusyMode;\n logLevel?: LogLevel;\n threadId?: string;\n ephemeral: boolean;\n} {\n const parsed = {\n processExistingMessages: false,\n dryRun: false,\n runOnce: false,\n ephemeral: false,\n } as {\n repoRoot?: string;\n commsDir?: string;\n agentName?: string;\n stateDir?: string;\n pollSeconds?: number;\n reconnectSeconds?: number;\n messageLookbackMinutes?: number;\n processExistingMessages: boolean;\n dryRun: boolean;\n runOnce: boolean;\n waitAfterDispatchSeconds?: number;\n appServerUrl?: string;\n gatewayTokenFile?: string;\n busyMode?: BusyMode;\n logLevel?: LogLevel;\n threadId?: string;\n ephemeral: boolean;\n };\n\n for (let index = 0; index < argv.length; index += 1) {\n const flag = argv[index];\n const consumesNext = !flag.includes(\"=\");\n\n if (flag === \"--help\") {\n printHelp();\n process.exit(0);\n }\n\n if (flag === \"--process-existing-messages\") {\n parsed.processExistingMessages = true;\n continue;\n }\n\n if (flag === \"--dry-run\") {\n parsed.dryRun = true;\n continue;\n }\n\n if (flag === \"--run-once\") {\n parsed.runOnce = true;\n continue;\n }\n\n if (flag === \"--ephemeral\") {\n parsed.ephemeral = true;\n continue;\n }\n\n if (flag.startsWith(\"--repo-root\")) {\n parsed.repoRoot = readFlagValue(argv, index, \"--repo-root\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--comms-dir\")) {\n parsed.commsDir = readFlagValue(argv, index, \"--comms-dir\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--agent-name\")) {\n parsed.agentName = readFlagValue(argv, index, \"--agent-name\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--state-dir\")) {\n parsed.stateDir = readFlagValue(argv, index, \"--state-dir\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--poll-seconds\")) {\n parsed.pollSeconds = parseNumber(\n readFlagValue(argv, index, \"--poll-seconds\"),\n \"--poll-seconds\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--reconnect-seconds\")) {\n parsed.reconnectSeconds = parseNumber(\n readFlagValue(argv, index, \"--reconnect-seconds\"),\n \"--reconnect-seconds\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--message-lookback-minutes\")) {\n parsed.messageLookbackMinutes = parseNumber(\n readFlagValue(argv, index, \"--message-lookback-minutes\"),\n \"--message-lookback-minutes\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--app-server-url\")) {\n parsed.appServerUrl = readFlagValue(argv, index, \"--app-server-url\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--gateway-token-file\")) {\n parsed.gatewayTokenFile = readFlagValue(\n argv,\n index,\n \"--gateway-token-file\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--wait-after-dispatch-seconds\")) {\n parsed.waitAfterDispatchSeconds = parseNumber(\n readFlagValue(argv, index, \"--wait-after-dispatch-seconds\"),\n \"--wait-after-dispatch-seconds\",\n );\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--busy-mode\")) {\n const value = readFlagValue(argv, index, \"--busy-mode\");\n if (value !== \"wait\" && value !== \"steer\") {\n throw new Error(`Invalid --busy-mode: ${value}`);\n }\n parsed.busyMode = value;\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--thread-id\")) {\n parsed.threadId = readFlagValue(argv, index, \"--thread-id\");\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n if (flag.startsWith(\"--log-level\")) {\n const value = readFlagValue(argv, index, \"--log-level\");\n if (\n value !== \"debug\" &&\n value !== \"info\" &&\n value !== \"warn\" &&\n value !== \"error\"\n ) {\n throw new Error(`Invalid --log-level: ${value}`);\n }\n parsed.logLevel = value;\n if (consumesNext) {\n index += 1;\n }\n continue;\n }\n\n throw new Error(`Unknown argument: ${flag}`);\n }\n\n return parsed;\n}\n\nexport function resolveRepoRoot(explicit?: string): string {\n if (explicit) {\n return resolve(explicit);\n }\n\n return process.cwd();\n}\n\nexport function resolveTapConfigPath(repoRoot: string, input: string): string {\n const converted = normalizeTapPath(input);\n return isAbsolute(converted)\n ? resolve(converted)\n : resolve(repoRoot, converted);\n}\n\nexport function resolveCommsDir(repoRoot: string, explicit?: string): string {\n if (explicit) {\n return resolve(normalizeTapPath(explicit));\n }\n\n const tapConfigPath = join(repoRoot, \".tap-config\");\n if (!existsSync(tapConfigPath)) {\n throw new Error(\n \"Unable to resolve comms directory. Pass --comms-dir explicitly.\",\n );\n }\n\n const configText = readFileSync(tapConfigPath, \"utf8\");\n const match = configText.match(/^TAP_COMMS_DIR=\"?(.*?)\"?$/m);\n if (!match?.[1]) {\n throw new Error(\n \"Unable to resolve comms directory. Pass --comms-dir explicitly.\",\n );\n }\n\n return resolveTapConfigPath(repoRoot, match[1]);\n}\n\nexport function resolvePreferredAgentName(requested?: string): string | null {\n if (requested?.trim()) {\n return requested.trim();\n }\n\n for (const envName of [\"TAP_AGENT_NAME\", \"CODEX_TAP_AGENT_NAME\"]) {\n const candidate = process.env[envName];\n if (candidate?.trim()) {\n return candidate.trim();\n }\n }\n\n return null;\n}\n\nexport function sanitizeStateSegment(agentName: string): string {\n const normalized = agentName\n .trim()\n .replace(/[<>:\"/\\\\|?*\\x00-\\x1f]/g, \"-\")\n .replace(/[. ]+$/g, \"\");\n\n return normalized || \"agent\";\n}\n\nexport function buildDefaultStateDir(\n repoRoot: string,\n preferredAgentName?: string | null,\n): string {\n const suffix = preferredAgentName?.trim()\n ? `-${sanitizeStateSegment(preferredAgentName)}`\n : \"\";\n return resolve(join(repoRoot, \".tmp\", `codex-app-server-bridge${suffix}`));\n}\n\nexport function resolveStateDir(\n repoRoot: string,\n explicit?: string,\n preferredAgentName?: string | null,\n): string {\n const root = explicit\n ? resolve(explicit)\n : buildDefaultStateDir(repoRoot, preferredAgentName);\n\n ensureDir(root);\n ensureDir(join(root, \"processed\"));\n ensureDir(join(root, \"logs\"));\n return root;\n}\n\nexport function readGatewayTokenFile(tokenFile: string): string {\n const token = readFileSync(tokenFile, \"utf8\").trim();\n if (!token) {\n throw new Error(`Gateway token file is empty: ${tokenFile}`);\n }\n return token;\n}\n\nexport function buildOptions(argv: string[]): Options {\n const parsed = parseArgs(argv);\n const repoRoot = resolveRepoRoot(parsed.repoRoot);\n const commsDir = resolveCommsDir(repoRoot, parsed.commsDir);\n const preferredAgentName = resolvePreferredAgentName(parsed.agentName);\n const stateDir = resolveStateDir(\n repoRoot,\n parsed.stateDir,\n preferredAgentName,\n );\n const agentName = resolveAgentName(preferredAgentName, stateDir);\n const agentId = resolveAgentId(agentName);\n persistAgentName(stateDir, agentName);\n const gatewayTokenFile =\n parsed.gatewayTokenFile?.trim() ||\n process.env.TAP_GATEWAY_TOKEN_FILE?.trim() ||\n null;\n const appServerUrl =\n parsed.appServerUrl?.trim() ||\n process.env.CODEX_APP_SERVER_URL ||\n DEFAULT_APP_SERVER_URL;\n\n return {\n repoRoot,\n commsDir,\n agentId,\n stateDir,\n agentName,\n pollSeconds: parsed.pollSeconds ?? 5,\n reconnectSeconds: parsed.reconnectSeconds ?? 5,\n messageLookbackMinutes: parsed.messageLookbackMinutes ?? 10,\n processExistingMessages: parsed.processExistingMessages,\n dryRun: parsed.dryRun,\n runOnce: parsed.runOnce,\n waitAfterDispatchSeconds: parsed.waitAfterDispatchSeconds ?? 0,\n appServerUrl,\n connectAppServerUrl: appServerUrl,\n gatewayToken: gatewayTokenFile\n ? readGatewayTokenFile(gatewayTokenFile)\n : null,\n gatewayTokenFile,\n busyMode: parsed.busyMode ?? \"steer\",\n logLevel: parsed.logLevel ?? \"info\",\n threadId: parsed.threadId?.trim() || null,\n ephemeral: parsed.ephemeral,\n };\n}\n","import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type {\n TapSharedConfig,\n TapLocalConfig,\n TapResolvedConfig,\n ConfigSource,\n ConfigResolution,\n} from \"./types.js\";\n\n// ─── File names ────────────────────────────────────────────────\n\nexport const SHARED_CONFIG_FILE = \"tap-config.json\";\nexport const LOCAL_CONFIG_FILE = \"tap-config.local.json\";\nexport const LEGACY_CONFIG_FILE = \".tap-config\";\n\n// ─── Defaults ──────────────────────────────────────────────────\n\nconst DEFAULT_RUNTIME_COMMAND = \"node\";\nconst DEFAULT_APP_SERVER_URL = \"ws://127.0.0.1:4501\";\n\n// ─── Repo root discovery ───────────────────────────────────────\n\nimport { _noGitWarned, _setNoGitWarned, log } from \"../utils.js\";\n\nexport function findRepoRoot(startDir: string = process.cwd()): string {\n let dir = path.resolve(startDir);\n while (true) {\n if (fs.existsSync(path.join(dir, \".git\"))) return dir;\n if (fs.existsSync(path.join(dir, \"package.json\"))) {\n if (!_noGitWarned) {\n _setNoGitWarned();\n log(\n \"No .git directory found. Resolved tap root via package.json. \" +\n \"That's fine outside git; use --comms-dir to choose a different comms location.\",\n );\n }\n return dir;\n }\n const parent = path.dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n if (!_noGitWarned) {\n _setNoGitWarned();\n log(\n \"No git repository or package.json found. Using the current directory as tap root. \" +\n \"That's fine outside git; use --comms-dir to choose a different comms location.\",\n );\n }\n return process.cwd();\n}\n\n// ─── JSON file loading ─────────────────────────────────────────\n\nfunction loadJsonFile<T>(filePath: string): T | null {\n if (!fs.existsSync(filePath)) return null;\n try {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n}\n\nexport function loadSharedConfig(repoRoot: string): TapSharedConfig | null {\n return loadJsonFile<TapSharedConfig>(path.join(repoRoot, SHARED_CONFIG_FILE));\n}\n\nexport function loadLocalConfig(repoRoot: string): TapLocalConfig | null {\n return loadJsonFile<TapLocalConfig>(path.join(repoRoot, LOCAL_CONFIG_FILE));\n}\n\nfunction readLegacyShellValue(configText: string, key: string): string | null {\n const match = configText.match(new RegExp(`^${key}=\"?(.+?)\"?$`, \"m\"));\n return match?.[1]?.trim() || null;\n}\n\nfunction loadLegacyShellConfig(repoRoot: string): TapSharedConfig | null {\n const filePath = path.join(repoRoot, LEGACY_CONFIG_FILE);\n if (!fs.existsSync(filePath)) return null;\n\n try {\n const raw = fs.readFileSync(filePath, \"utf-8\");\n const commsDir = readLegacyShellValue(raw, \"TAP_COMMS_DIR\");\n if (!commsDir) return null;\n return { commsDir };\n } catch {\n return null;\n }\n}\n\n// ─── CLI overrides ─────────────────────────────────────────────\n\nexport interface ConfigOverrides {\n commsDir?: string;\n stateDir?: string;\n runtimeCommand?: string;\n appServerUrl?: string;\n}\n\n// ─── Resolution ────────────────────────────────────────────────\n\n/**\n * Resolve config with priority: CLI flag > env > local config > shared config > auto.\n */\nexport function resolveConfig(\n overrides: ConfigOverrides = {},\n startDir?: string,\n): ConfigResolution {\n const repoRoot = findRepoRoot(startDir);\n const shared = loadSharedConfig(repoRoot) ?? {};\n const local = loadLocalConfig(repoRoot) ?? {};\n const legacy = loadLegacyShellConfig(repoRoot) ?? {};\n\n const sources: Record<keyof TapResolvedConfig, ConfigSource> = {\n repoRoot: \"auto\",\n commsDir: \"auto\",\n stateDir: \"auto\",\n runtimeCommand: \"auto\",\n appServerUrl: \"auto\",\n towerName: \"auto\",\n };\n\n // ─── commsDir ──────────────────────────────────────────────\n let commsDir: string;\n if (overrides.commsDir) {\n commsDir = resolvePath(repoRoot, overrides.commsDir);\n sources.commsDir = \"cli-flag\";\n } else if (process.env.TAP_COMMS_DIR) {\n commsDir = resolvePath(repoRoot, process.env.TAP_COMMS_DIR);\n sources.commsDir = \"env\";\n } else if (local.commsDir) {\n commsDir = resolvePath(repoRoot, local.commsDir);\n sources.commsDir = \"local-config\";\n } else if (shared.commsDir) {\n commsDir = resolvePath(repoRoot, shared.commsDir);\n sources.commsDir = \"shared-config\";\n } else if (legacy.commsDir) {\n commsDir = resolvePath(repoRoot, legacy.commsDir);\n sources.commsDir = \"legacy-shell-config\";\n } else {\n commsDir = path.join(repoRoot, \"tap-comms\");\n }\n\n // ─── stateDir ──────────────────────────────────────────────\n let stateDir: string;\n if (overrides.stateDir) {\n stateDir = resolvePath(repoRoot, overrides.stateDir);\n sources.stateDir = \"cli-flag\";\n } else if (process.env.TAP_STATE_DIR) {\n stateDir = resolvePath(repoRoot, process.env.TAP_STATE_DIR);\n sources.stateDir = \"env\";\n } else if (local.stateDir) {\n stateDir = resolvePath(repoRoot, local.stateDir);\n sources.stateDir = \"local-config\";\n } else if (shared.stateDir) {\n stateDir = resolvePath(repoRoot, shared.stateDir);\n sources.stateDir = \"shared-config\";\n } else {\n stateDir = path.join(repoRoot, \".tap-comms\");\n }\n\n // ─── runtimeCommand ────────────────────────────────────────\n let runtimeCommand: string;\n if (overrides.runtimeCommand) {\n runtimeCommand = overrides.runtimeCommand;\n sources.runtimeCommand = \"cli-flag\";\n } else if (process.env.TAP_RUNTIME_COMMAND) {\n runtimeCommand = process.env.TAP_RUNTIME_COMMAND;\n sources.runtimeCommand = \"env\";\n } else if (local.runtimeCommand) {\n runtimeCommand = local.runtimeCommand;\n sources.runtimeCommand = \"local-config\";\n } else if (shared.runtimeCommand) {\n runtimeCommand = shared.runtimeCommand;\n sources.runtimeCommand = \"shared-config\";\n } else {\n runtimeCommand = DEFAULT_RUNTIME_COMMAND;\n }\n\n // ─── appServerUrl ──────────────────────────────────────────\n let appServerUrl: string;\n if (overrides.appServerUrl) {\n appServerUrl = overrides.appServerUrl;\n sources.appServerUrl = \"cli-flag\";\n } else if (process.env.TAP_APP_SERVER_URL) {\n appServerUrl = process.env.TAP_APP_SERVER_URL;\n sources.appServerUrl = \"env\";\n } else if (local.appServerUrl) {\n appServerUrl = local.appServerUrl;\n sources.appServerUrl = \"local-config\";\n } else if (shared.appServerUrl) {\n appServerUrl = shared.appServerUrl;\n sources.appServerUrl = \"shared-config\";\n } else {\n appServerUrl = DEFAULT_APP_SERVER_URL;\n }\n\n // ─── towerName ──────────────────────────────────────────────\n const towerName = local.towerName ?? shared.towerName ?? null;\n\n return {\n config: {\n repoRoot,\n commsDir,\n stateDir,\n runtimeCommand,\n appServerUrl,\n towerName,\n },\n sources,\n };\n}\n\n// ─── Save helpers ──────────────────────────────────────────────\n\nexport function saveSharedConfig(\n repoRoot: string,\n config: TapSharedConfig,\n): void {\n const filePath = path.join(repoRoot, SHARED_CONFIG_FILE);\n const tmp = `${filePath}.tmp.${process.pid}`;\n fs.writeFileSync(tmp, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n fs.renameSync(tmp, filePath);\n}\n\nexport function saveLocalConfig(\n repoRoot: string,\n config: TapLocalConfig,\n): void {\n const filePath = path.join(repoRoot, LOCAL_CONFIG_FILE);\n const tmp = `${filePath}.tmp.${process.pid}`;\n fs.writeFileSync(tmp, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n fs.renameSync(tmp, filePath);\n}\n\n// ─── Helpers ───────────────────────────────────────────────────\n\n/** Resolve a path relative to repoRoot, or keep absolute as-is. */\nfunction resolvePath(repoRoot: string, p: string): string {\n const normalized = normalizeTapPath(p);\n return path.isAbsolute(normalized)\n ? normalized\n : path.resolve(repoRoot, normalized);\n}\n\nexport function normalizeTapPath(input: string): string {\n const trimmed = input.trim().replace(/^[\"'`]+|[\"'`]+$/g, \"\");\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed)) {\n return trimmed;\n }\n\n // MSYS/Git Bash `/c/...` → `C:\\...` conversion — Windows only.\n // On POSIX, `/d/...` is a legitimate absolute path and must not be rewritten.\n if (process.platform === \"win32\") {\n const match = trimmed.match(/^\\/([A-Za-z])\\/(.*)$/);\n if (match) {\n return `${match[1].toUpperCase()}:\\\\${match[2].replace(/\\//g, \"\\\\\")}`;\n }\n }\n\n return trimmed;\n}\n","// bridge-candidates.ts — Message collection and filtering\n\nimport { createHash } from \"crypto\";\nimport { existsSync, readFileSync, readdirSync, statSync } from \"fs\";\nimport { join } from \"path\";\nimport {\n Candidate,\n HEADLESS_SKIP_PATTERNS,\n HeartbeatStore,\n Options,\n} from \"./bridge-types.js\";\nimport { createBridgeLogger } from \"./bridge-logging.js\";\nimport {\n getInboxRoute,\n isOwnMessageSender,\n recipientMatchesAgent,\n refreshAgentIdentity,\n stripBridgeFrontmatter,\n} from \"./bridge-routing.js\";\n\nconst routingLogger = createBridgeLogger(\"routing\");\n\nexport function buildMarkerId(filePath: string, mtimeMs: number): string {\n return createHash(\"sha1\").update(`${filePath}|${mtimeMs}`).digest(\"hex\");\n}\n\nexport function getProcessedMarkerPath(\n stateDir: string,\n markerId: string,\n): string {\n return join(stateDir, \"processed\", `${markerId}.done`);\n}\n\nexport function loadHeartbeats(commsDir: string): HeartbeatStore {\n try {\n return JSON.parse(readFileSync(join(commsDir, \"heartbeats.json\"), \"utf8\"));\n } catch {\n return {};\n }\n}\n\nexport function shouldSkipInHeadlessMode(\n fileName: string,\n body: string,\n): boolean {\n if (process.env.TAP_HEADLESS !== \"true\") return false;\n const combined = `${fileName}\\n${body}`;\n return HEADLESS_SKIP_PATTERNS.some((p) => p.test(combined));\n}\n\nexport function collectCandidates(\n inboxDir: string,\n agentId: string,\n agentName: string,\n aliasName?: string,\n): Candidate[] {\n const entries = readdirSync(inboxDir, { withFileTypes: true })\n .filter(\n (entry) => entry.isFile() && entry.name.toLowerCase().endsWith(\".md\"),\n )\n .map((entry) => {\n const filePath = join(inboxDir, entry.name);\n const stats = statSync(filePath);\n return { entry, filePath, stats };\n })\n .sort((left, right) => left.stats.mtimeMs - right.stats.mtimeMs);\n\n const candidates: Candidate[] = [];\n let filteredByRecipient = 0;\n let filteredBySelf = 0;\n let filteredByHeadless = 0;\n for (const item of entries) {\n let body: string;\n try {\n body = readFileSync(item.filePath, \"utf8\");\n } catch {\n continue;\n }\n\n // Frontmatter-first routing (M202): try frontmatter, fall back to filename\n const route = getInboxRoute(item.entry.name, body);\n // M205: Match against configured name AND heartbeat-refreshed alias\n if (\n !recipientMatchesAgent(route.recipient, agentId, agentName) &&\n !(aliasName && recipientMatchesAgent(route.recipient, agentId, aliasName))\n ) {\n filteredByRecipient += 1;\n continue;\n }\n\n if (\n isOwnMessageSender(route.sender, agentId, agentName) ||\n (aliasName && isOwnMessageSender(route.sender, agentId, aliasName))\n ) {\n filteredBySelf += 1;\n continue;\n }\n\n // In headless mode, skip review-request files — handled by headless loop\n if (shouldSkipInHeadlessMode(item.entry.name, body)) {\n filteredByHeadless += 1;\n continue;\n }\n\n candidates.push({\n markerId: buildMarkerId(item.filePath, item.stats.mtimeMs),\n filePath: item.filePath,\n fileName: item.entry.name,\n sender: route.sender,\n recipient: route.recipient,\n subject: route.subject,\n body: stripBridgeFrontmatter(body),\n mtimeMs: item.stats.mtimeMs,\n });\n }\n\n routingLogger.debug(\"candidate scan completed\", {\n inboxDir,\n scanned: entries.length,\n matched: candidates.length,\n filteredByRecipient,\n filteredBySelf,\n filteredByHeadless,\n agentId,\n agentName,\n aliasName,\n });\n\n return candidates;\n}\n\nexport function getPendingCandidates(\n options: Options,\n cutoff: Date,\n): {\n heartbeats: HeartbeatStore;\n candidates: Candidate[];\n} {\n const inboxDir = join(options.commsDir, \"inbox\");\n if (!existsSync(inboxDir)) {\n throw new Error(`Inbox directory not found: ${inboxDir}`);\n }\n\n const heartbeats = loadHeartbeats(options.commsDir);\n const refreshedName = refreshAgentIdentity(options, heartbeats);\n const cutoffMs = cutoff.getTime();\n // Collect candidates matching the configured name\n const candidates = collectCandidates(\n inboxDir,\n options.agentId,\n options.agentName,\n // M205: Also accept messages addressed to the heartbeat-refreshed name\n refreshedName !== options.agentName ? refreshedName : undefined,\n ).filter((candidate) => {\n if (candidate.mtimeMs < cutoffMs) {\n return false;\n }\n\n return !existsSync(\n getProcessedMarkerPath(options.stateDir, candidate.markerId),\n );\n });\n\n routingLogger.debug(\"pending candidates resolved\", {\n agentId: options.agentId,\n configuredName: options.agentName,\n refreshedName:\n refreshedName !== options.agentName ? refreshedName : undefined,\n candidateCount: candidates.length,\n cutoff: cutoff.toISOString(),\n });\n\n return { heartbeats, candidates };\n}\n","// bridge-logging.ts — Structured bridge logging with scoped levels\n\nimport { LogLevel } from \"./bridge-types.js\";\n\nexport type LogContext = Record<string, unknown>;\n\nexport interface BridgeLogger {\n debug(message: string, context?: LogContext): void;\n info(message: string, context?: LogContext): void;\n warn(message: string, context?: LogContext): void;\n error(message: string, context?: LogContext): void;\n}\n\nconst LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n debug: 10,\n info: 20,\n warn: 30,\n error: 40,\n};\n\nlet currentLogLevel: LogLevel = \"info\";\n\nexport function configureBridgeLogging(level: LogLevel): void {\n currentLogLevel = level;\n}\n\nfunction shouldLog(level: LogLevel): boolean {\n return LOG_LEVEL_PRIORITY[level] >= LOG_LEVEL_PRIORITY[currentLogLevel];\n}\n\nfunction formatValue(value: unknown): string {\n if (typeof value === \"string\") {\n return JSON.stringify(value);\n }\n\n if (\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n typeof value === \"bigint\"\n ) {\n return String(value);\n }\n\n if (value === null) {\n return \"null\";\n }\n\n return JSON.stringify(value);\n}\n\nfunction formatContext(context?: LogContext): string {\n if (!context) {\n return \"\";\n }\n\n const entries = Object.entries(context).filter(\n ([, value]) => value !== undefined,\n );\n if (entries.length === 0) {\n return \"\";\n }\n\n return ` ${entries\n .map(([key, value]) => `${key}=${formatValue(value)}`)\n .join(\" \")}`;\n}\n\nexport function logBridge(\n level: LogLevel,\n message: string,\n context?: LogContext,\n): void {\n if (!shouldLog(level)) {\n return;\n }\n\n const ts = new Date().toISOString().replace(\"T\", \" \").replace(\"Z\", \" UTC\");\n const line = `[${ts}] ${level.toUpperCase()} ${message}${formatContext(context)}`;\n\n if (level === \"error\") {\n console.error(line);\n return;\n }\n\n if (level === \"warn\") {\n console.warn(line);\n return;\n }\n\n console.log(line);\n}\n\nexport function createBridgeLogger(scope: string): BridgeLogger {\n const scopedMessage = (message: string) => `[${scope}] ${message}`;\n\n return {\n debug(message, context) {\n logBridge(\"debug\", scopedMessage(message), context);\n },\n info(message, context) {\n logBridge(\"info\", scopedMessage(message), context);\n },\n warn(message, context) {\n logBridge(\"warn\", scopedMessage(message), context);\n },\n error(message, context) {\n logBridge(\"error\", scopedMessage(message), context);\n },\n };\n}\n","// bridge-format.ts — Message formatting for dispatch\n\nimport { writeFileSync } from \"fs\";\nimport { join } from \"path\";\nimport { Candidate, HeartbeatStore } from \"./bridge-types.js\";\nimport { resolveAddressLabel } from \"./bridge-routing.js\";\nimport { getProcessedMarkerPath } from \"./bridge-candidates.js\";\n\nexport function buildUserInput(\n candidate: Candidate,\n agentName: string,\n heartbeats: HeartbeatStore,\n): string {\n const sender = resolveAddressLabel(candidate.sender || \"unknown\", heartbeats);\n const recipient = resolveAddressLabel(\n candidate.recipient || agentName,\n heartbeats,\n );\n const subject = candidate.subject || \"(none)\";\n const body = candidate.body.trim();\n\n return [\n `Tap-comms inbox message for ${agentName}.`,\n `Sender: ${sender}`,\n `Recipient: ${recipient}`,\n `Subject: ${subject}`,\n `File: ${candidate.fileName}`,\n \"\",\n \"Message body:\",\n body || \"(empty)\",\n \"\",\n \"---\",\n \"Instructions: Read the message above and respond using the tap_reply tool.\",\n `Use tap_reply(to: \"${candidate.sender || \"unknown\"}\", subject: \"<your-subject>\", content: \"<your-response>\") to send your response.`,\n \"If the message is a review request, perform the review and reply with your findings.\",\n \"If the message is informational, acknowledge briefly via tap_reply.\",\n \"Do NOT respond with plain text only — you MUST use the tap_reply tool.\",\n ].join(\"\\n\");\n}\n\nexport function writeProcessedMarker(\n stateDir: string,\n candidate: Candidate,\n dispatchMode: \"start\" | \"steer\",\n threadId: string | null,\n turnId: string | null,\n): void {\n const payload = {\n requestFile: candidate.filePath,\n requestName: candidate.fileName,\n sender: candidate.sender,\n recipient: candidate.recipient,\n subject: candidate.subject,\n dispatchMode,\n threadId,\n turnId,\n markedAt: new Date().toISOString(),\n };\n writeFileSync(\n getProcessedMarkerPath(stateDir, candidate.markerId),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nexport function writeLastDispatch(\n stateDir: string,\n candidate: Candidate,\n dispatchMode: \"start\" | \"steer\",\n threadId: string | null,\n turnId: string | null,\n): void {\n const payload = {\n requestFile: candidate.filePath,\n requestName: candidate.fileName,\n markerId: candidate.markerId,\n sender: candidate.sender,\n recipient: candidate.recipient,\n subject: candidate.subject,\n dispatchMode,\n threadId,\n turnId,\n dispatchedAt: new Date().toISOString(),\n };\n writeFileSync(\n join(stateDir, \"last-dispatch.json\"),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n","// bridge-dispatch.ts — Dispatch orchestration + heartbeat\n\nimport {\n existsSync,\n readFileSync,\n renameSync,\n statSync,\n unlinkSync,\n writeFileSync,\n} from \"fs\";\nimport { join } from \"path\";\nimport {\n BridgeHealthState,\n Candidate,\n COMMS_HEARTBEAT_LOCK_TIMEOUT_MS,\n COMMS_LOCK_STALE_AGE_MS,\n HeadlessWarmupClient,\n HeartbeatRecord,\n HeartbeatStore,\n HEADLESS_WARMUP_PROMPT,\n HEADLESS_WARMUP_TIMEOUT_MS,\n Options,\n ThreadStateRecord,\n TURN_COMPLETION_POLL_MS,\n TURN_COMPLETION_REFRESH_MS,\n} from \"./bridge-types.js\";\nimport { createBridgeLogger } from \"./bridge-logging.js\";\nimport { shouldRetrySteerAsStart } from \"./bridge-routing.js\";\nimport { getPendingCandidates } from \"./bridge-candidates.js\";\nimport {\n buildUserInput,\n writeLastDispatch,\n writeProcessedMarker,\n} from \"./bridge-format.js\";\nimport { AppServerClient } from \"./bridge-ws-client.js\";\n\nconst dispatchLogger = createBridgeLogger(\"dispatch\");\nconst heartbeatLogger = createBridgeLogger(\"heartbeat\");\n\nexport function sanitizeErrorForPersistence(\n error: string | null,\n): string | null {\n if (!error) return null;\n return (\n error\n // URL query token params\n .replace(/([?&])tap_token=[^\\s&)\"'}]+/gi, \"$1tap_token=***\")\n .replace(/([?&])token=[^\\s&)\"'}]+/gi, \"$1token=***\")\n .replace(/([?&])secret=[^\\s&)\"'}]+/gi, \"$1secret=***\")\n .replace(/([?&])key=[^\\s&)\"'}]+/gi, \"$1key=***\")\n // JSON string values for sensitive keys\n .replace(/\"tap_token\"\\s*:\\s*\"[^\"]*\"/g, '\"tap_token\":\"***\"')\n .replace(/\"token\"\\s*:\\s*\"[^\"]*\"/g, '\"token\":\"***\"')\n .replace(/\"secret\"\\s*:\\s*\"[^\"]*\"/g, '\"secret\":\"***\"')\n .replace(/\"password\"\\s*:\\s*\"[^\"]*\"/g, '\"password\":\"***\"')\n .replace(/\"authorization\"\\s*:\\s*\"[^\"]*\"/gi, '\"authorization\":\"***\"')\n // WebSocket subprotocol auth prefix\n .replace(/tap-auth-[A-Za-z0-9_.\\-/+=]+/g, \"tap-auth-***\")\n // Bearer tokens in any context\n .replace(/Bearer\\s+[A-Za-z0-9_.\\-/+=]+/gi, \"Bearer ***\")\n // Generic long hex/base64 secrets (32+ chars — likely tokens)\n .replace(/(?<=[=:\"\\s])[A-Za-z0-9_\\-/+=]{40,}(?=[\"\\s&)}'}\\],]|$)/g, \"***\")\n );\n}\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolvePromise) => {\n setTimeout(resolvePromise, ms);\n });\n}\n\nexport function readThreadState(stateDir: string): ThreadStateRecord | null {\n const threadPath = join(stateDir, \"thread.json\");\n if (!existsSync(threadPath)) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(\n readFileSync(threadPath, \"utf8\"),\n ) as ThreadStateRecord;\n if (parsed.threadId) {\n return parsed;\n }\n } catch {\n return null;\n }\n\n return null;\n}\n\nexport function persistThreadState(\n stateDir: string,\n threadId: string,\n appServerUrl: string,\n ephemeral: boolean,\n cwd: string | null,\n): void {\n const payload: ThreadStateRecord = {\n threadId,\n updatedAt: new Date().toISOString(),\n appServerUrl,\n ephemeral,\n cwd,\n };\n writeFileSync(\n join(stateDir, \"thread.json\"),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nexport function acquireCommsLock(lockPath: string): boolean {\n const deadline = Date.now() + COMMS_HEARTBEAT_LOCK_TIMEOUT_MS;\n while (Date.now() < deadline) {\n try {\n writeFileSync(lockPath, String(process.pid), { flag: \"wx\" });\n return true;\n } catch {\n // Lock exists — check if stale\n try {\n const lockAge = Date.now() - statSync(lockPath).mtimeMs;\n if (lockAge > COMMS_LOCK_STALE_AGE_MS) {\n unlinkSync(lockPath);\n // Retry with exclusive create\n try {\n writeFileSync(lockPath, String(process.pid), { flag: \"wx\" });\n return true;\n } catch {\n // Another process grabbed it between unlink and our wx\n }\n }\n } catch {\n // Lock disappeared between check and stat — retry\n }\n const start = Date.now();\n while (Date.now() - start < 50) {\n /* spin */\n }\n }\n }\n return false;\n}\n\nexport function releaseCommsLock(lockPath: string): void {\n try {\n unlinkSync(lockPath);\n } catch {\n // Already removed\n }\n}\n\nexport function updateCommsHeartbeat(options: Options, status: string): void {\n const heartbeatsPath = join(options.commsDir, \"heartbeats.json\");\n const lockPath = join(options.commsDir, \".heartbeats.lock\");\n\n if (!acquireCommsLock(lockPath)) {\n return; // Non-critical — skip this cycle\n }\n\n try {\n let store: Record<string, unknown> = {};\n try {\n store = JSON.parse(readFileSync(heartbeatsPath, \"utf-8\"));\n } catch {\n // Empty or corrupt — start fresh\n }\n\n // Use agentId as key (SSOT for heartbeat store), not agentName.\n // This matches tap-comms.ts which keys by routing id.\n const key = options.agentId;\n const existing = store[key] as Record<string, unknown> | undefined;\n store[key] = {\n id: options.agentId,\n agent: options.agentName,\n timestamp: new Date().toISOString(),\n lastActivity: new Date().toISOString(),\n joinedAt: (existing?.joinedAt as string) ?? new Date().toISOString(),\n status,\n };\n\n const tmpPath = heartbeatsPath + \".tmp.\" + process.pid;\n writeFileSync(tmpPath, JSON.stringify(store, null, 2), \"utf-8\");\n renameSync(tmpPath, heartbeatsPath);\n } catch {\n // Non-critical — comms heartbeat update failure should never crash bridge\n } finally {\n releaseCommsLock(lockPath);\n }\n}\n\nlet heartbeatCount = 0;\n\nexport function writeHeartbeat(\n options: Options,\n client: AppServerClient | null,\n health: BridgeHealthState,\n): void {\n if (client?.threadId) {\n const savedThread = readThreadState(options.stateDir);\n persistThreadState(\n options.stateDir,\n client.threadId,\n options.appServerUrl,\n options.ephemeral,\n client.currentThreadCwd ?? savedThread?.cwd ?? null,\n );\n }\n\n const payload: HeartbeatRecord = {\n pid: process.pid,\n agent: options.agentName,\n updatedAt: new Date().toISOString(),\n pollSeconds: options.pollSeconds,\n appServerUrl: options.appServerUrl,\n authenticated: Boolean(options.gatewayToken),\n connected: client?.connected ?? false,\n initialized: client?.initialized ?? false,\n threadId: client?.threadId ?? null,\n threadCwd: client?.currentThreadCwd ?? null,\n activeTurnId: client?.activeTurnId ?? null,\n turnStartedAt: client?.turnStartedAt ?? null,\n lastTurnStatus: client?.lastTurnStatus ?? null,\n lastNotificationMethod: client?.lastNotificationMethod ?? null,\n lastNotificationAt: client?.lastNotificationAt ?? null,\n lastError: sanitizeErrorForPersistence(client?.lastError ?? null),\n lastSuccessfulAppServerAt: client?.lastSuccessfulAppServerAt ?? null,\n lastSuccessfulAppServerMethod:\n client?.lastSuccessfulAppServerMethod ?? null,\n consecutiveFailureCount: health.consecutiveFailureCount,\n busyMode: options.busyMode,\n };\n\n writeFileSync(\n join(options.stateDir, \"heartbeat.json\"),\n `${JSON.stringify(payload, null, 2)}\\n`,\n \"utf8\",\n );\n\n heartbeatCount += 1;\n if (heartbeatCount % 5 === 0) {\n heartbeatLogger.debug(\"heartbeat written\", {\n connected: payload.connected,\n threadId: payload.threadId ?? \"null\",\n activeTurnId: payload.activeTurnId ?? null,\n consecutiveFailureCount: payload.consecutiveFailureCount,\n });\n }\n\n // Also update comms heartbeats.json so tap_who sees this agent\n const status = client?.connected ? \"active\" : \"idle\";\n updateCommsHeartbeat(options, status);\n}\n\nexport async function dispatchCandidate(\n client: AppServerClient,\n options: Options,\n candidate: Candidate,\n heartbeats: HeartbeatStore,\n): Promise<boolean> {\n const input = buildUserInput(candidate, options.agentName, heartbeats);\n\n dispatchLogger.info(\"dispatching candidate\", {\n sender: candidate.sender || \"unknown\",\n recipient: candidate.recipient || options.agentName,\n subject: candidate.subject || \"(none)\",\n fileName: candidate.fileName,\n threadId: client.threadId,\n activeTurnId: client.activeTurnId,\n busyMode: options.busyMode,\n });\n\n if (client.isBusy()) {\n if (options.busyMode !== \"steer\") {\n dispatchLogger.debug(\"bridge busy and steer disabled\", {\n fileName: candidate.fileName,\n activeTurnId: client.activeTurnId,\n });\n return false;\n }\n\n try {\n const turnId = await client.steerTurn(input);\n writeProcessedMarker(\n options.stateDir,\n candidate,\n \"steer\",\n client.threadId,\n turnId,\n );\n writeLastDispatch(\n options.stateDir,\n candidate,\n \"steer\",\n client.threadId,\n turnId,\n );\n dispatchLogger.info(\"steered active turn\", {\n fileName: candidate.fileName,\n threadId: client.threadId,\n turnId,\n });\n return true;\n } catch (error) {\n await client.refreshCurrentThreadState().catch(() => undefined);\n\n if (!client.isBusy()) {\n return dispatchCandidate(client, options, candidate, heartbeats);\n }\n\n if (shouldRetrySteerAsStart(error)) {\n client.activeTurnId = null;\n client.turnStartedAt = null;\n dispatchLogger.warn(\"steer fallback to start\", {\n fileName: candidate.fileName,\n threadId: client.threadId,\n error: sanitizeErrorForPersistence(String(error)),\n });\n return dispatchCandidate(client, options, candidate, heartbeats);\n }\n\n throw error;\n }\n }\n\n const turnId = await client.startTurn(input);\n writeProcessedMarker(\n options.stateDir,\n candidate,\n \"start\",\n client.threadId,\n turnId,\n );\n writeLastDispatch(\n options.stateDir,\n candidate,\n \"start\",\n client.threadId,\n turnId,\n );\n dispatchLogger.info(\"started turn for candidate\", {\n fileName: candidate.fileName,\n threadId: client.threadId,\n turnId,\n });\n return true;\n}\n\nexport async function runScan(\n options: Options,\n cutoff: Date,\n client: AppServerClient | null,\n): Promise<{ dispatched: boolean; maxMtimeMs: number }> {\n const { heartbeats, candidates } = getPendingCandidates(options, cutoff);\n if (candidates.length === 0) {\n dispatchLogger.debug(\"no pending candidates\", {\n cutoff: cutoff.toISOString(),\n agentName: options.agentName,\n });\n }\n let maxMtimeMs = 0;\n for (const candidate of candidates) {\n if (options.dryRun) {\n dispatchLogger.info(\"dry-run candidate\", {\n fileName: candidate.fileName,\n sender: candidate.sender,\n recipient: candidate.recipient,\n });\n maxMtimeMs = Math.max(maxMtimeMs, candidate.mtimeMs);\n continue;\n }\n\n if (!client) {\n throw new Error(\"App Server client is not available\");\n }\n\n const dispatched = await dispatchCandidate(\n client,\n options,\n candidate,\n heartbeats,\n );\n if (!dispatched && options.busyMode === \"wait\") {\n return { dispatched: false, maxMtimeMs };\n }\n maxMtimeMs = Math.max(maxMtimeMs, candidate.mtimeMs);\n return { dispatched: true, maxMtimeMs };\n }\n\n return { dispatched: false, maxMtimeMs: 0 };\n}\n\nexport async function waitForTurnDrain(\n options: Options,\n client: AppServerClient,\n health: BridgeHealthState,\n): Promise<void> {\n const deadline = Date.now() + options.waitAfterDispatchSeconds * 1_000;\n while (Date.now() < deadline) {\n writeHeartbeat(options, client, health);\n if (!client.activeTurnId) {\n return;\n }\n await delay(1_000);\n }\n\n dispatchLogger.warn(\"wait-after-dispatch deadline reached\", {\n threadId: client.threadId,\n activeTurnId: client.activeTurnId,\n waitAfterDispatchSeconds: options.waitAfterDispatchSeconds,\n });\n}\n\nexport async function waitForTurnCompletion(\n client: Pick<\n HeadlessWarmupClient,\n \"activeTurnId\" | \"lastTurnStatus\" | \"refreshCurrentThreadState\"\n >,\n turnId: string,\n timeoutMs: number,\n): Promise<string | null> {\n const deadline = Date.now() + timeoutMs;\n let nextRefreshAt = Date.now();\n\n while (Date.now() < deadline) {\n if (!client.activeTurnId || client.activeTurnId !== turnId) {\n return client.lastTurnStatus;\n }\n\n if (Date.now() >= nextRefreshAt) {\n await client.refreshCurrentThreadState().catch(() => undefined);\n if (!client.activeTurnId || client.activeTurnId !== turnId) {\n return client.lastTurnStatus;\n }\n nextRefreshAt = Date.now() + TURN_COMPLETION_REFRESH_MS;\n }\n\n await delay(\n Math.min(TURN_COMPLETION_POLL_MS, Math.max(deadline - Date.now(), 0)),\n );\n }\n\n await client.refreshCurrentThreadState().catch(() => undefined);\n if (!client.activeTurnId || client.activeTurnId !== turnId) {\n return client.lastTurnStatus;\n }\n\n throw new Error(`Timed out waiting for turn ${turnId} to complete`);\n}\n\nexport async function maybeBootstrapHeadlessTurn(\n options: Options,\n cutoff: Date,\n client: HeadlessWarmupClient,\n): Promise<boolean> {\n if (\n process.env.TAP_HEADLESS !== \"true\" &&\n process.env.TAP_COLD_START_WARMUP !== \"true\"\n ) {\n return false;\n }\n\n const { candidates } = getPendingCandidates(options, cutoff);\n if (\n candidates.length > 0 ||\n client.activeTurnId ||\n client.lastTurnStatus !== null\n ) {\n return false;\n }\n\n dispatchLogger.info(\"headless cold-start warmup starting\", {\n threadId: client.activeTurnId,\n });\n const turnId = await client.startTurn(HEADLESS_WARMUP_PROMPT);\n if (!turnId) {\n throw new Error(\n \"Headless cold-start warmup failed: turn/start did not return a turn id. \" +\n \"Run: npx @hua-labs/tap doctor\",\n );\n }\n\n try {\n const status = await waitForTurnCompletion(\n client,\n turnId,\n HEADLESS_WARMUP_TIMEOUT_MS,\n );\n if (status !== \"completed\") {\n throw new Error(\n `turn ${turnId} finished with status ${status ?? \"unknown\"}`,\n );\n }\n\n dispatchLogger.info(\"headless cold-start warmup completed\", {\n turnId,\n status,\n });\n return true;\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n throw new Error(\n `Headless cold-start warmup failed: ${reason}. ` +\n \"Run: npx @hua-labs/tap doctor\",\n );\n }\n}\n","// bridge-ws-client.ts — AppServerClient class (WebSocket + JSON-RPC + thread/turn state)\n\nimport {\n AUTH_SUBPROTOCOL_PREFIX,\n JsonRpcResponse,\n LoadedThreadCandidate,\n RequestRecord,\n ThreadStateRecord,\n} from \"./bridge-types.js\";\nimport { BridgeLogger } from \"./bridge-logging.js\";\nimport { sanitizeErrorForPersistence } from \"./bridge-dispatch.js\";\nimport {\n chooseLoadedThreadForCwd,\n isTurnStale,\n isTurnStuckOnApproval,\n threadCwdMatches,\n} from \"./bridge-routing.js\";\n\nexport async function readSocketData(data: unknown): Promise<string> {\n if (typeof data === \"string\") {\n return data;\n }\n\n if (data instanceof ArrayBuffer) {\n return Buffer.from(data).toString(\"utf8\");\n }\n\n if (ArrayBuffer.isView(data)) {\n return Buffer.from(data.buffer, data.byteOffset, data.byteLength).toString(\n \"utf8\",\n );\n }\n\n if (typeof Blob !== \"undefined\" && data instanceof Blob) {\n return await data.text();\n }\n\n return String(data);\n}\n\nexport function formatJsonRpcError(error: JsonRpcResponse[\"error\"]): string {\n if (!error) {\n return \"Unknown App Server error\";\n }\n\n return JSON.stringify(\n {\n code: error.code,\n message: error.message,\n data: error.data,\n },\n null,\n 2,\n );\n}\n\nlet nextAppServerClientId = 1;\n\nexport class AppServerClient {\n private socket: WebSocket | null = null;\n private readonly url: string;\n private readonly gatewayToken: string | null;\n private readonly logger: BridgeLogger;\n private readonly clientId = nextAppServerClientId++;\n private nextId = 1;\n private pending = new Map<\n number,\n {\n resolve: (value: any) => void;\n reject: (reason?: unknown) => void;\n method: string;\n }\n >();\n\n connected = false;\n initialized = false;\n threadId: string | null = null;\n currentThreadCwd: string | null = null;\n activeTurnId: string | null = null;\n turnStartedAt: string | null = null;\n lastTurnStatus: string | null = null;\n lastNotificationMethod: string | null = null;\n lastNotificationAt: string | null = null;\n lastError: string | null = null;\n lastSuccessfulAppServerAt: string | null = null;\n lastSuccessfulAppServerMethod: string | null = null;\n\n constructor(url: string, logger: BridgeLogger, gatewayToken?: string | null) {\n this.url = url;\n this.logger = logger;\n this.gatewayToken = gatewayToken ?? null;\n }\n\n async connect(): Promise<void> {\n if (this.connected && this.socket?.readyState === WebSocket.OPEN) {\n return;\n }\n\n // M175: Warn when connecting without auth — unauthenticated connections\n // allow any local process to control the app-server session.\n if (!this.gatewayToken) {\n this.logger.warn(\n \"connecting without auth token — app-server session is unprotected. \" +\n \"Use --gateway-token-file or TAP_GATEWAY_TOKEN_FILE to enable auth.\",\n { url: this.url },\n );\n }\n\n // Authenticate via WebSocket subprotocol instead of URL query param.\n // Token stays out of URLs (no log/referer/history leakage).\n const wsOptions: { protocols?: string[] } = {};\n if (this.gatewayToken) {\n wsOptions.protocols = [`${AUTH_SUBPROTOCOL_PREFIX}${this.gatewayToken}`];\n }\n this.socket = new WebSocket(this.url, wsOptions);\n\n await new Promise<void>((resolvePromise, rejectPromise) => {\n let settled = false;\n\n const resolveOnce = () => {\n if (settled) {\n return;\n }\n settled = true;\n resolvePromise();\n };\n\n const rejectOnce = (error: Error) => {\n if (settled) {\n return;\n }\n settled = true;\n rejectPromise(error);\n };\n\n this.socket?.addEventListener(\n \"open\",\n () => {\n this.connected = true;\n this.logger.info(\"connected to app-server\", {\n clientId: this.clientId,\n url: this.url,\n authenticated: Boolean(this.gatewayToken),\n });\n resolveOnce();\n },\n { once: true },\n );\n\n this.socket?.addEventListener(\"error\", () => {\n const error = new Error(\n `Failed to connect to App Server at ${this.url}`,\n );\n this.lastError = sanitizeErrorForPersistence(error.message);\n this.logger.error(\"failed to connect to app-server\", {\n clientId: this.clientId,\n url: this.url,\n error: this.lastError,\n });\n rejectOnce(error);\n });\n\n this.socket?.addEventListener(\"close\", () => {\n this.connected = false;\n this.initialized = false;\n this.activeTurnId = null;\n this.turnStartedAt = null;\n this.logger.warn(\"disconnected from app-server\", {\n clientId: this.clientId,\n url: this.url,\n });\n this.rejectPending(new Error(\"App Server connection closed\"));\n });\n\n this.socket?.addEventListener(\"message\", (event) => {\n void this.handleMessage(event.data);\n });\n });\n\n await this.request(\"initialize\", {\n clientInfo: {\n name: \"tap-app-server-bridge\",\n title: \"tap app-server bridge\",\n version: \"0.1.0\",\n },\n capabilities: {\n experimentalApi: false,\n },\n });\n this.initialized = true;\n }\n\n async disconnect(): Promise<void> {\n if (!this.socket) {\n return;\n }\n\n this.socket.close();\n this.connected = false;\n this.initialized = false;\n this.socket = null;\n }\n\n async ensureThread(\n explicitThreadId: string | null,\n savedThread: ThreadStateRecord | null,\n cwd: string,\n ephemeral: boolean,\n ): Promise<string> {\n if (explicitThreadId) {\n try {\n const resumeResponse = await this.request(\"thread/resume\", {\n threadId: explicitThreadId,\n persistExtendedHistory: false,\n });\n const resumedThreadId = resumeResponse?.thread?.id ?? explicitThreadId;\n await this.refreshThreadState(resumedThreadId);\n this.logger.info(\"resumed explicit thread\", {\n clientId: this.clientId,\n threadId: resumedThreadId,\n activeTurnId: this.activeTurnId,\n });\n return resumedThreadId;\n } catch (error) {\n this.logger.warn(\n \"explicit thread resume failed; starting fresh thread\",\n {\n clientId: this.clientId,\n threadId: explicitThreadId,\n error: sanitizeErrorForPersistence(String(error)),\n },\n );\n }\n }\n\n const loadedThreadId = await this.findLoadedThread(cwd);\n if (loadedThreadId) {\n return loadedThreadId;\n }\n\n if (savedThread?.threadId) {\n if (savedThread.cwd && !threadCwdMatches(cwd, savedThread.cwd)) {\n this.logger.warn(\"saved thread cwd mismatch; skipping saved thread\", {\n clientId: this.clientId,\n threadId: savedThread.threadId,\n savedCwd: savedThread.cwd,\n expectedCwd: cwd,\n });\n } else {\n try {\n const resumeResponse = await this.request(\"thread/resume\", {\n threadId: savedThread.threadId,\n persistExtendedHistory: false,\n });\n const resumedThreadId =\n resumeResponse?.thread?.id ?? savedThread.threadId;\n await this.refreshThreadState(resumedThreadId);\n if (!threadCwdMatches(cwd, this.currentThreadCwd)) {\n this.logger.warn(\"saved thread resumed with mismatched cwd\", {\n clientId: this.clientId,\n threadId: resumedThreadId,\n expectedCwd: cwd,\n actualCwd: this.currentThreadCwd ?? \"unknown\",\n });\n this.threadId = null;\n this.currentThreadCwd = null;\n this.activeTurnId = null;\n this.turnStartedAt = null;\n this.lastTurnStatus = null;\n } else {\n this.logger.info(\"resumed saved thread\", {\n clientId: this.clientId,\n threadId: resumedThreadId,\n activeTurnId: this.activeTurnId,\n });\n return resumedThreadId;\n }\n } catch (error) {\n this.logger.warn(\n \"saved thread resume failed; starting fresh thread\",\n {\n clientId: this.clientId,\n threadId: savedThread.threadId,\n error: sanitizeErrorForPersistence(String(error)),\n },\n );\n }\n }\n }\n\n const startResponse = await this.request(\"thread/start\", {\n cwd,\n ephemeral,\n experimentalRawEvents: false,\n persistExtendedHistory: false,\n });\n\n const startedThreadId = startResponse?.thread?.id;\n if (!startedThreadId) {\n throw new Error(\"thread/start did not return a thread id\");\n }\n\n this.syncThreadStateFromThread(startResponse?.thread);\n this.threadId = startedThreadId;\n this.currentThreadCwd = this.currentThreadCwd ?? cwd;\n this.activeTurnId = null;\n this.lastTurnStatus = null;\n this.logger.info(\"started thread\", {\n clientId: this.clientId,\n threadId: startedThreadId,\n cwd: this.currentThreadCwd,\n ephemeral,\n });\n return startedThreadId;\n }\n\n async findLoadedThread(cwd: string): Promise<string | null> {\n const response = await this.request(\"thread/loaded/list\", {\n limit: 20,\n });\n const threadIds = Array.isArray(response?.data)\n ? response.data.filter(\n (value: unknown): value is string => typeof value === \"string\",\n )\n : [];\n\n if (threadIds.length === 0) {\n return null;\n }\n\n const threads: LoadedThreadCandidate[] = [];\n\n for (const threadId of threadIds) {\n try {\n const threadResponse = await this.request(\"thread/read\", {\n threadId,\n includeTurns: true,\n });\n const thread = threadResponse?.thread;\n if (!thread?.id) {\n continue;\n }\n threads.push({\n id: thread.id,\n cwd: typeof thread.cwd === \"string\" ? thread.cwd : \"\",\n updatedAt:\n typeof thread.updatedAt === \"number\" ? thread.updatedAt : 0,\n statusType: thread.status?.type ?? null,\n thread,\n });\n } catch {\n continue;\n }\n }\n\n const chosen = chooseLoadedThreadForCwd(cwd, threads);\n if (!chosen) {\n if (threads.length > 0) {\n this.logger.debug(\"loaded threads exist but none match cwd\", {\n clientId: this.clientId,\n cwd,\n loadedThreadCount: threads.length,\n });\n }\n return null;\n }\n this.syncThreadStateFromThread(chosen.thread);\n this.logger.info(\"attached to loaded thread\", {\n clientId: this.clientId,\n threadId: chosen.id,\n activeTurnId: this.activeTurnId,\n cwd: chosen.cwd,\n });\n return chosen.id;\n }\n\n async startTurn(inputText: string): Promise<string | null> {\n const threadId = this.requireThreadId();\n const response = await this.request(\"turn/start\", {\n threadId,\n input: [\n {\n type: \"text\",\n text: inputText,\n text_elements: [],\n },\n ],\n });\n\n const turnId = response?.turn?.id ?? null;\n if (turnId) {\n this.activeTurnId = turnId;\n this.turnStartedAt = new Date().toISOString();\n }\n return turnId;\n }\n\n async steerTurn(inputText: string): Promise<string> {\n const threadId = this.requireThreadId();\n const turnId = this.requireActiveTurnId();\n\n await this.request(\"turn/steer\", {\n threadId,\n expectedTurnId: turnId,\n input: [\n {\n type: \"text\",\n text: inputText,\n text_elements: [],\n },\n ],\n });\n\n return turnId;\n }\n\n isBusy(): boolean {\n if (!this.activeTurnId) return false;\n if (isTurnStale(this.turnStartedAt)) {\n this.logger.warn(\"active turn is stale; treating bridge as idle\", {\n clientId: this.clientId,\n turnId: this.activeTurnId,\n turnStartedAt: this.turnStartedAt,\n });\n this.activeTurnId = null;\n this.turnStartedAt = null;\n return false;\n }\n return true;\n }\n\n async refreshCurrentThreadState(): Promise<void> {\n if (!this.threadId) {\n return;\n }\n\n await this.refreshThreadState(this.threadId);\n }\n\n private requireThreadId(): string {\n if (!this.threadId) {\n throw new Error(\"No active App Server thread is available\");\n }\n return this.threadId;\n }\n\n private requireActiveTurnId(): string {\n if (!this.activeTurnId) {\n throw new Error(\"No active turn is available for turn/steer\");\n }\n return this.activeTurnId;\n }\n\n private async refreshThreadState(threadId: string): Promise<void> {\n const threadResponse = await this.request(\"thread/read\", {\n threadId,\n includeTurns: true,\n });\n this.syncThreadStateFromThread(threadResponse?.thread);\n }\n\n private syncThreadStateFromThread(thread: any): void {\n if (typeof thread?.id === \"string\") {\n this.threadId = thread.id;\n }\n this.currentThreadCwd = typeof thread?.cwd === \"string\" ? thread.cwd : null;\n\n let activeTurnId: string | null = null;\n let lastTurnStatus: string | null = null;\n\n // M203: Check thread-level status.activeFlags (live production shape)\n const threadActiveFlags: string[] = Array.isArray(\n thread?.status?.activeFlags,\n )\n ? thread.status.activeFlags\n : [];\n const threadStuckOnApproval = isTurnStuckOnApproval(threadActiveFlags);\n if (threadStuckOnApproval) {\n this.logger.warn(\"thread waitingOnApproval; ignoring in-progress turns\", {\n clientId: this.clientId,\n threadId: this.threadId,\n });\n }\n\n const turns = Array.isArray(thread?.turns) ? thread.turns : [];\n for (const turn of turns) {\n if (typeof turn?.status === \"string\") {\n lastTurnStatus = turn.status;\n }\n if (turn?.status === \"inProgress\" && typeof turn.id === \"string\") {\n // M203: Skip if thread-level or turn-level waitingOnApproval\n if (threadStuckOnApproval) {\n continue;\n }\n const turnActiveFlags: string[] = Array.isArray(turn.activeFlags)\n ? turn.activeFlags\n : [];\n if (isTurnStuckOnApproval(turnActiveFlags)) {\n this.logger.warn(\"turn waitingOnApproval; ignoring turn as active\", {\n clientId: this.clientId,\n turnId: turn.id,\n });\n continue;\n }\n activeTurnId = turn.id;\n }\n }\n\n if (activeTurnId && activeTurnId !== this.activeTurnId) {\n this.turnStartedAt = new Date().toISOString();\n } else if (!activeTurnId) {\n this.turnStartedAt = null;\n }\n this.activeTurnId = activeTurnId;\n this.lastTurnStatus = lastTurnStatus;\n }\n\n private async handleMessage(data: unknown): Promise<void> {\n const text = await readSocketData(data);\n const message = JSON.parse(text) as JsonRpcResponse;\n\n if (\n typeof message.id === \"number\" &&\n (Object.hasOwn(message, \"result\") || Object.hasOwn(message, \"error\"))\n ) {\n const pending = this.pending.get(message.id);\n if (!pending) {\n return;\n }\n\n this.pending.delete(message.id);\n if (message.error) {\n const errorText = formatJsonRpcError(message.error);\n this.lastError = sanitizeErrorForPersistence(errorText);\n this.logger.error(\"app-server request failed\", {\n clientId: this.clientId,\n method: pending.method,\n error: this.lastError,\n });\n pending.reject(new Error(`${pending.method} failed: ${errorText}`));\n return;\n }\n\n pending.resolve(message.result);\n this.lastSuccessfulAppServerAt = new Date().toISOString();\n this.lastSuccessfulAppServerMethod = pending.method;\n this.lastError = null;\n return;\n }\n\n if (!message.method) {\n return;\n }\n\n this.lastNotificationMethod = message.method;\n this.lastNotificationAt = new Date().toISOString();\n this.logger.debug(\"received app-server notification\", {\n clientId: this.clientId,\n method: message.method,\n });\n this.handleNotification(message.method, message.params);\n }\n\n private handleNotification(method: string, params: any): void {\n switch (method) {\n case \"thread/started\":\n if (params?.thread?.id) {\n this.threadId = params.thread.id;\n }\n if (typeof params?.thread?.cwd === \"string\") {\n this.currentThreadCwd = params.thread.cwd;\n }\n this.logger.info(\"thread started notification\", {\n clientId: this.clientId,\n threadId: params?.thread?.id ?? null,\n cwd: params?.thread?.cwd ?? null,\n });\n break;\n case \"thread/status/changed\":\n this.logger.debug(\"thread status changed\", {\n clientId: this.clientId,\n threadId: params?.thread?.id ?? this.threadId,\n status:\n params?.thread?.status?.type ?? params?.status?.type ?? \"unknown\",\n });\n break;\n case \"turn/started\":\n if (params?.turn?.id) {\n this.activeTurnId = params.turn.id;\n this.turnStartedAt = new Date().toISOString();\n this.logger.info(\"turn started\", {\n clientId: this.clientId,\n threadId: this.threadId,\n turnId: params.turn.id,\n });\n }\n break;\n case \"turn/completed\": {\n this.lastTurnStatus = params?.turn?.status ?? null;\n const prevTurnStartedAt = this.turnStartedAt;\n this.activeTurnId = null;\n this.turnStartedAt = null;\n const elapsedMs = prevTurnStartedAt\n ? Date.now() - new Date(prevTurnStartedAt).getTime()\n : null;\n this.logger.info(\"turn completed\", {\n clientId: this.clientId,\n threadId: this.threadId,\n status: this.lastTurnStatus ?? \"unknown\",\n elapsedSeconds:\n elapsedMs !== null ? Math.round(elapsedMs / 1000) : undefined,\n });\n break;\n }\n case \"error\":\n this.lastError = sanitizeErrorForPersistence(\n JSON.stringify(params ?? {}, null, 2),\n );\n this.logger.error(\"app-server error notification\", {\n clientId: this.clientId,\n error: this.lastError,\n });\n break;\n default:\n break;\n }\n }\n\n private request(method: string, params: unknown): Promise<any> {\n if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {\n throw new Error(`Cannot call ${method}; App Server socket is not open`);\n }\n\n const id = this.nextId;\n this.nextId += 1;\n\n const request: RequestRecord = {\n jsonrpc: \"2.0\",\n id,\n method,\n params,\n };\n\n return new Promise((resolvePromise, rejectPromise) => {\n this.pending.set(id, {\n resolve: resolvePromise,\n reject: rejectPromise,\n method,\n });\n this.socket?.send(JSON.stringify(request));\n });\n }\n\n private rejectPending(error: Error): void {\n for (const pending of this.pending.values()) {\n pending.reject(error);\n }\n this.pending.clear();\n }\n}\n","// bridge-main.ts — Entry point, main loop, signal handling\n\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { isAbsolute, join, resolve } from \"path\";\nimport { pathToFileURL } from \"url\";\nimport {\n BridgeHealthState,\n HeartbeatRecord,\n ThreadStateRecord,\n} from \"./bridge-types.js\";\nimport {\n configureBridgeLogging,\n createBridgeLogger,\n} from \"./bridge-logging.js\";\nimport { buildOptions } from \"./bridge-config.js\";\nimport {\n maybeBootstrapHeadlessTurn,\n persistThreadState,\n readThreadState,\n runScan,\n waitForTurnDrain,\n writeHeartbeat,\n} from \"./bridge-dispatch.js\";\nimport { AppServerClient } from \"./bridge-ws-client.js\";\nimport { sanitizeErrorForPersistence } from \"./bridge-dispatch.js\";\n\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolvePromise) => {\n setTimeout(resolvePromise, ms);\n });\n}\n\nexport function readHeartbeatState(stateDir: string): HeartbeatRecord | null {\n const heartbeatPath = join(stateDir, \"heartbeat.json\");\n if (!existsSync(heartbeatPath)) {\n return null;\n }\n\n try {\n return JSON.parse(readFileSync(heartbeatPath, \"utf8\")) as HeartbeatRecord;\n } catch {\n return null;\n }\n}\n\nfunction parseUpdatedAt(value?: string | null): number {\n if (!value) {\n return 0;\n }\n\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction appServerUrlMatches(\n expectedAppServerUrl: string,\n actualAppServerUrl?: string | null,\n): boolean {\n return actualAppServerUrl?.trim() === expectedAppServerUrl;\n}\n\nfunction hasValidHeartbeatThreadCwd(\n threadCwd?: string | null,\n): threadCwd is string {\n const normalized = threadCwd?.trim();\n if (!normalized) {\n return false;\n }\n\n return (\n isAbsolute(normalized) ||\n /^[A-Za-z]:[\\\\/]/.test(normalized) ||\n normalized.startsWith(\"\\\\\\\\\")\n );\n}\n\nexport function loadResumableThreadState(\n stateDir: string,\n fallbackAppServerUrl: string,\n): ThreadStateRecord | null {\n const savedThread = readThreadState(stateDir);\n const heartbeat = readHeartbeatState(stateDir);\n const heartbeatThreadId = heartbeat?.threadId?.trim();\n\n if (!heartbeatThreadId) {\n return savedThread;\n }\n\n if (!appServerUrlMatches(fallbackAppServerUrl, heartbeat?.appServerUrl)) {\n return savedThread;\n }\n\n if (!hasValidHeartbeatThreadCwd(heartbeat?.threadCwd)) {\n return savedThread;\n }\n\n const heartbeatBackedThread: ThreadStateRecord = {\n threadId: heartbeatThreadId,\n updatedAt:\n heartbeat?.updatedAt ??\n savedThread?.updatedAt ??\n new Date().toISOString(),\n appServerUrl:\n heartbeat?.appServerUrl ||\n savedThread?.appServerUrl ||\n fallbackAppServerUrl,\n ephemeral: savedThread?.ephemeral ?? false,\n cwd:\n heartbeat?.threadCwd ??\n (savedThread?.threadId === heartbeatThreadId\n ? (savedThread.cwd ?? null)\n : null),\n };\n\n let preferred = savedThread;\n if (!savedThread?.threadId) {\n preferred = heartbeatBackedThread;\n } else if (savedThread.threadId === heartbeatThreadId) {\n preferred = {\n ...savedThread,\n updatedAt: heartbeatBackedThread.updatedAt ?? savedThread.updatedAt,\n appServerUrl: heartbeatBackedThread.appServerUrl,\n cwd: heartbeatBackedThread.cwd ?? savedThread.cwd ?? null,\n };\n } else if (\n parseUpdatedAt(heartbeat?.updatedAt) > parseUpdatedAt(savedThread.updatedAt)\n ) {\n preferred = heartbeatBackedThread;\n }\n\n return preferred;\n}\n\nexport function getGeneralInboxCutoff(\n stateDir: string,\n lookbackMinutes: number,\n processExistingMessages: boolean,\n): Date {\n if (processExistingMessages) {\n return new Date(0);\n }\n\n const lookbackCutoff =\n lookbackMinutes > 0\n ? new Date(Date.now() - lookbackMinutes * 60_000)\n : null;\n\n // Prefer saved cutoff (last processed timestamp) over lookback window\n // to avoid re-dispatching already-processed messages on restart.\n const cutoffPath = join(stateDir, \"general-inbox-cutoff.txt\");\n if (existsSync(cutoffPath)) {\n try {\n const saved = new Date(readFileSync(cutoffPath, \"utf8\").trim());\n if (!isNaN(saved.getTime())) {\n // Use the more recent of saved cutoff vs lookback window\n if (lookbackCutoff && lookbackCutoff > saved) {\n return lookbackCutoff;\n }\n return saved;\n }\n } catch {\n // fall through to lookback/now\n }\n }\n\n if (lookbackCutoff) {\n return lookbackCutoff;\n }\n\n const cutoff = new Date();\n writeFileSync(cutoffPath, `${cutoff.toISOString()}\\n`, \"utf8\");\n return cutoff;\n}\n\nexport async function main(): Promise<void> {\n const options = buildOptions(process.argv.slice(2));\n configureBridgeLogging(options.logLevel);\n const logger = createBridgeLogger(\"bridge\");\n const cutoff = getGeneralInboxCutoff(\n options.stateDir,\n options.messageLookbackMinutes,\n options.processExistingMessages,\n );\n const initialSavedThread = loadResumableThreadState(\n options.stateDir,\n options.appServerUrl,\n );\n\n logger.info(\"codex app-server bridge ready\", {\n repoRoot: options.repoRoot,\n commsDir: options.commsDir,\n agentName: options.agentName,\n stateDir: options.stateDir,\n appServerUrl: options.appServerUrl,\n busyMode: options.busyMode,\n logLevel: options.logLevel,\n waitAfterDispatchSeconds:\n options.waitAfterDispatchSeconds > 0\n ? options.waitAfterDispatchSeconds\n : undefined,\n lookback: options.processExistingMessages\n ? \"existing messages\"\n : `${options.messageLookbackMinutes} minute(s)`,\n threadId: options.threadId ?? initialSavedThread?.threadId,\n });\n if (options.dryRun) {\n logger.info(\"dry-run mode enabled\");\n }\n\n let client: AppServerClient | null = null;\n const health: BridgeHealthState = {\n consecutiveFailureCount: 0,\n };\n\n while (true) {\n try {\n if (!options.dryRun) {\n if (!client || !client.connected) {\n client = new AppServerClient(\n options.connectAppServerUrl,\n createBridgeLogger(\"app-server\"),\n options.gatewayToken,\n );\n await client.connect();\n const savedThread = loadResumableThreadState(\n options.stateDir,\n options.appServerUrl,\n );\n logger.debug(\"resolved resumable thread state\", {\n savedThreadId: savedThread?.threadId,\n savedThreadCwd: savedThread?.cwd ?? null,\n });\n\n const threadId = await client.ensureThread(\n options.threadId,\n savedThread,\n options.repoRoot,\n options.ephemeral,\n );\n persistThreadState(\n options.stateDir,\n threadId,\n options.appServerUrl,\n options.ephemeral,\n client.currentThreadCwd ?? options.repoRoot,\n );\n writeHeartbeat(options, client, health);\n const bootstrapped = await maybeBootstrapHeadlessTurn(\n options,\n cutoff,\n client,\n );\n if (bootstrapped) {\n writeHeartbeat(options, client, health);\n }\n }\n }\n\n const scanResult = await runScan(options, cutoff, client);\n if (scanResult.dispatched && scanResult.maxMtimeMs > 0) {\n // Advance the persisted cutoff to the latest dispatched message mtime\n // (not wall-clock now) to avoid skipping messages that arrived mid-scan\n const cutoffPath = join(options.stateDir, \"general-inbox-cutoff.txt\");\n const advancedCutoff = new Date(scanResult.maxMtimeMs);\n writeFileSync(cutoffPath, `${advancedCutoff.toISOString()}\\n`, \"utf8\");\n }\n if (\n scanResult.dispatched &&\n client &&\n options.waitAfterDispatchSeconds > 0\n ) {\n await waitForTurnDrain(options, client, health);\n }\n health.consecutiveFailureCount = 0;\n writeHeartbeat(options, client, health);\n\n if (options.runOnce) {\n break;\n }\n\n await delay(options.pollSeconds * 1_000);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error(\"bridge error\", {\n error: sanitizeErrorForPersistence(message),\n });\n if (client) {\n client.lastError = sanitizeErrorForPersistence(message);\n }\n health.consecutiveFailureCount += 1;\n writeHeartbeat(options, client, health);\n\n if (options.runOnce) {\n // Sanitize before re-throwing — top-level catch may log raw message\n const sanitized = sanitizeErrorForPersistence(message);\n throw new Error(sanitized ?? message);\n }\n\n client?.disconnect().catch(() => undefined);\n client = null;\n logger.warn(\"reconnecting after bridge error\", {\n reconnectSeconds: options.reconnectSeconds,\n consecutiveFailureCount: health.consecutiveFailureCount,\n });\n await delay(options.reconnectSeconds * 1_000);\n }\n }\n\n await client?.disconnect();\n}\n\nexport function isDirectExecution(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n return import.meta.url === pathToFileURL(resolve(entry)).href;\n}\n","#!/usr/bin/env node --experimental-strip-types\n\n// Re-export everything for backward compatibility\nexport * from \"./bridge/bridge-types.js\";\nexport * from \"./bridge/bridge-routing.js\";\nexport * from \"./bridge/bridge-config.js\";\nexport * from \"./bridge/bridge-candidates.js\";\nexport * from \"./bridge/bridge-format.js\";\nexport * from \"./bridge/bridge-ws-client.js\";\nexport * from \"./bridge/bridge-dispatch.js\";\nexport * from \"./bridge/bridge-main.js\";\n\nimport { resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { main } from \"./bridge/bridge-main.js\";\nimport { sanitizeErrorForPersistence } from \"./bridge/bridge-dispatch.js\";\n\n// isDirectExecution must live in the barrel — import.meta.url must\n// refer to this file, not bridge-main.ts, for argv[1] comparison.\nfunction isDirectExecution(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n return import.meta.url === pathToFileURL(resolve(entry)).href;\n}\n\nif (isDirectExecution()) {\n main().catch((error) => {\n const raw =\n error instanceof Error ? (error.stack ?? error.message) : String(error);\n console.error(sanitizeErrorForPersistence(raw));\n process.exitCode = 1;\n });\n}\n"],"mappings":"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","names":["pathToFileURL","resolve","existsSync","readFileSync","isAbsolute","join","resolve","existsSync","resolve","isAbsolute","join","readFileSync","existsSync","readFileSync","join","join","readFileSync","existsSync","writeFileSync","join","writeFileSync","join","existsSync","readFileSync","renameSync","statSync","writeFileSync","join","join","existsSync","readFileSync","writeFileSync","statSync","renameSync","turnId","existsSync","readFileSync","writeFileSync","isAbsolute","join","resolve","delay","join","existsSync","readFileSync","isAbsolute","writeFileSync","resolve","resolve","pathToFileURL","isDirectExecution","pathToFileURL","resolve","isDirectExecution","pathToFileURL","resolve"]}
|