Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/bridge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ 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();

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;
Expand Down
9 changes: 5 additions & 4 deletions src/claude-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }>;
Expand Down Expand Up @@ -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;
Expand All @@ -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);

Expand Down Expand Up @@ -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 {}
}
}
9 changes: 5 additions & 4 deletions src/codex-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -56,8 +57,6 @@ interface PendingServerResponse {
timestamp: number;
}

const LOG_FILE = "/tmp/agentbridge.log";

interface PendingRequest {
method: AppServerTrackedRequestMethod;
threadId?: string;
Expand All @@ -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
Expand Down Expand Up @@ -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}`; }
Expand Down Expand Up @@ -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 {}
}
}
2 changes: 1 addition & 1 deletion src/daemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof Bun.serve> | null = null;
Expand Down
Loading