From 8b7422f7a8378a0a34f987a6a78d0c6aad23c4e8 Mon Sep 17 00:00:00 2001 From: "rayson951005@gmail.com" Date: Tue, 14 Apr 2026 17:39:58 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E6=97=A5=E5=BF=97=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E5=88=B0=20StateDirResolver=20/=20migrate=20?= =?UTF-8?q?adapter=20log=20paths=20from=20/tmp=20to=20StateDirResolver=20(?= =?UTF-8?q?#21)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit claude-adapter.ts 和 codex-adapter.ts 移除硬编码 /tmp/agentbridge.log, 通过构造函数注入 logFile 参数,默认值从 StateDirResolver 获取。 bridge.ts 和 daemon.ts 显式传入 stateDir.logFile。 --- src/bridge.ts | 2 +- src/claude-adapter.ts | 9 +++++---- src/codex-adapter.ts | 9 +++++---- src/daemon.ts | 2 +- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/bridge.ts b/src/bridge.ts index f8a46b3..b88ee58 100644 --- a/src/bridge.ts +++ b/src/bridge.ts @@ -17,7 +17,7 @@ const CONTROL_PORT = parseInt(process.env.AGENTBRIDGE_CONTROL_PORT ?? "4502", 10 const daemonLifecycle = new DaemonLifecycle({ stateDir, controlPort: CONTROL_PORT, log }); const CONTROL_WS_URL = daemonLifecycle.controlWsUrl; -const claude = new ClaudeAdapter(); +const claude = new ClaudeAdapter(stateDir.logFile); const daemonClient = new DaemonClient(CONTROL_WS_URL); let shuttingDown = false; diff --git a/src/claude-adapter.ts b/src/claude-adapter.ts index fc4bb80..8372bca 100644 --- a/src/claude-adapter.ts +++ b/src/claude-adapter.ts @@ -21,6 +21,7 @@ import { import { EventEmitter } from "node:events"; import { randomUUID } from "node:crypto"; import { appendFileSync } from "node:fs"; +import { StateDirResolver } from "./state-dir"; import type { BridgeMessage } from "./types"; export type ReplySender = (msg: BridgeMessage, requireReply?: boolean) => Promise<{ success: boolean; error?: string }>; @@ -60,14 +61,13 @@ export const CLAUDE_INSTRUCTIONS = [ "- If the reply tool returns a busy error, Codex is still executing — wait and try again later.", ].join("\n"); -const LOG_FILE = "/tmp/agentbridge.log"; - export class ClaudeAdapter extends EventEmitter { private server: Server; private notificationSeq = 0; private sessionId: string; private readonly notificationIdPrefix: string; private replySender: ReplySender | null = null; + private readonly logFile: string; // Dual-mode transport private readonly configuredMode: DeliveryMode; @@ -76,8 +76,9 @@ export class ClaudeAdapter extends EventEmitter { private readonly maxBufferedMessages: number; private droppedMessageCount = 0; - constructor() { + constructor(logFile = new StateDirResolver().logFile) { super(); + this.logFile = logFile; this.sessionId = `codex_${Date.now()}`; this.notificationIdPrefix = randomUUID().replace(/-/g, "").slice(0, 12); @@ -337,7 +338,7 @@ export class ClaudeAdapter extends EventEmitter { const line = `[${new Date().toISOString()}] [ClaudeAdapter] ${msg}\n`; process.stderr.write(line); try { - appendFileSync(LOG_FILE, line); + appendFileSync(this.logFile, line); } catch {} } } diff --git a/src/codex-adapter.ts b/src/codex-adapter.ts index e9029ba..7113329 100644 --- a/src/codex-adapter.ts +++ b/src/codex-adapter.ts @@ -13,6 +13,7 @@ import { spawn, execSync, type ChildProcess } from "node:child_process"; import { createInterface } from "node:readline"; import { EventEmitter } from "node:events"; import { appendFileSync } from "node:fs"; +import { StateDirResolver } from "./state-dir"; import type { BridgeMessage } from "./types"; import type { ServerWebSocket } from "bun"; import { @@ -56,8 +57,6 @@ interface PendingServerResponse { timestamp: number; } -const LOG_FILE = "/tmp/agentbridge.log"; - interface PendingRequest { method: AppServerTrackedRequestMethod; threadId?: string; @@ -76,6 +75,7 @@ export class CodexAdapter extends EventEmitter { private nextInjectionId = -1; private appPort: number; private proxyPort: number; + private readonly logFile: string; private tuiConnId = 0; // tracks which TUI connection is "current" (primary) private connIdCounter = 0; // monotonically increasing counter for unique conn IDs // Secondary (picker) connections: each gets its own dedicated app-server WS @@ -107,10 +107,11 @@ export class CodexAdapter extends EventEmitter { // Generation counter to prevent stale app-server close handlers from interfering private appServerGeneration = 0; - constructor(appPort = 4500, proxyPort = 4501) { + constructor(appPort = 4500, proxyPort = 4501, logFile = new StateDirResolver().logFile) { super(); this.appPort = appPort; this.proxyPort = proxyPort; + this.logFile = logFile; } get appServerUrl() { return `ws://127.0.0.1:${this.appPort}`; } @@ -1240,6 +1241,6 @@ export class CodexAdapter extends EventEmitter { private log(msg: string) { const line = `[${new Date().toISOString()}] [CodexAdapter] ${msg}\n`; process.stderr.write(line); - try { appendFileSync(LOG_FILE, line); } catch {} + try { appendFileSync(this.logFile, line); } catch {} } } diff --git a/src/daemon.ts b/src/daemon.ts index 0ca6724..52d8a9b 100644 --- a/src/daemon.ts +++ b/src/daemon.ts @@ -41,7 +41,7 @@ const ATTENTION_WINDOW_MS = parseInt(process.env.AGENTBRIDGE_ATTENTION_WINDOW_MS const daemonLifecycle = new DaemonLifecycle({ stateDir, controlPort: CONTROL_PORT, log }); -const codex = new CodexAdapter(CODEX_APP_PORT, CODEX_PROXY_PORT); +const codex = new CodexAdapter(CODEX_APP_PORT, CODEX_PROXY_PORT, stateDir.logFile); const attachCmd = `codex --enable tui_app_server --remote ${codex.proxyUrl}`; let controlServer: ReturnType | null = null; From 2f8f622c33ebbf4dcff83db3372372b780641937 Mon Sep 17 00:00:00 2001 From: "rayson951005@gmail.com" Date: Tue, 14 Apr 2026 17:46:53 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20bridge.ts=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=97=A9=E6=9C=9F=20ensure=20state=20dir=20/=20ensure=20state?= =?UTF-8?q?=20dir=20before=20first=20log=20write?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Codex review 反馈:fresh machine 首次启动时 state dir 不存在, 早期日志会被 catch {} 吞掉。在 bridge.ts 顶层加 stateDir.ensure()。 --- src/bridge.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bridge.ts b/src/bridge.ts index b88ee58..f1e774d 100644 --- a/src/bridge.ts +++ b/src/bridge.ts @@ -10,6 +10,7 @@ import { disabledReplyError, type BridgeDisabledReason } from "./bridge-disabled import type { BridgeMessage } from "./types"; const stateDir = new StateDirResolver(); +stateDir.ensure(); const configService = new ConfigService(); const config = configService.loadOrDefault();