Changes before error encountered

Agent-Logs-Url: https://github.com/ComposioHQ/agent-orchestrator/sessions/9f3caf0b-66fb-4eff-bd3f-7fb9ab889630

Co-authored-by: Priyanchew <57816400+Priyanchew@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-04 22:06:00 +00:00 committed by GitHub
parent 2a81a10b5b
commit eaa27b9b79
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 16 additions and 14 deletions

View File

@ -320,7 +320,7 @@ function ghInstallAttempts(): InstallAttempt[] {
{ cmd: "sudo", args: ["dnf", "install", "-y", "gh"], label: "sudo dnf install -y gh" },
];
}
if (process.platform === "win32") {
if (isWindows()) {
return [
{
cmd: "winget",
@ -1625,7 +1625,7 @@ function isLocalPath(arg: string): boolean {
* the parent process the user explicitly asked us to stop AO.
*/
async function sweepWindowsPtyHostsBeforeParentKill(): Promise<void> {
if (process.platform !== "win32") return;
if (!isWindows()) return;
try {
const mod = (await import("@aoagents/ao-plugin-runtime-process")) as {
sweepWindowsPtyHosts?: () => Promise<{

View File

@ -1,11 +1,11 @@
import { renameSync, writeFileSync, unlinkSync } from "node:fs";
import { isWindows } from "./platform.js";
// Windows file-locking workaround. `renameSync` can fail with EPERM/EACCES when
// antivirus, the Windows indexer, or another process briefly holds a handle on
// the destination path. The failures are transient — a short retry loop is the
// standard fix (same pattern Node's own `fs.rm` uses internally).
const IS_WINDOWS = process.platform === "win32";
const RENAME_RETRIES = IS_WINDOWS ? 10 : 0;
const RENAME_RETRIES = isWindows() ? 10 : 0;
const RENAME_RETRY_DELAY_MS = 50;
function renameWithRetry(src: string, dest: string): void {

View File

@ -10,7 +10,7 @@ import { WebSocketServer, WebSocket } from "ws";
import { spawn } from "node:child_process";
import { type Socket, connect as netConnect } from "node:net";
import { findTmux, resolveTmuxSession, resolvePipePath, validateSessionId } from "./tmux-utils.js";
import { getEnvDefaults } from "@aoagents/ao-core";
import { getEnvDefaults, isWindows } from "@aoagents/ao-core";
// These types mirror src/lib/mux-protocol.ts exactly.
// tsconfig.server.json constrains rootDir to "server/", so we cannot import
@ -503,6 +503,7 @@ export function handleWindowsPipeMessage(
pipeSocket.on("error", (err) => {
winPipes.delete(pipeKey);
winPipeBuffers.delete(pipeKey);
pipeSocket.destroy();
if (ws.readyState === WS_OPEN) {
ws.send(
JSON.stringify({
@ -604,14 +605,14 @@ export function handleWindowsPipeMessage(
export function createMuxWebSocket(tmuxPath?: string | null): WebSocketServer | null {
// On Windows, we use named pipe relay instead of node-pty/tmux.
// Allow the server to be created without ptySpawn on Windows.
if (!ptySpawn && process.platform !== "win32") {
if (!ptySpawn && !isWindows()) {
console.warn("[MuxServer] node-pty not available — mux WebSocket will be disabled");
return null;
}
// On Windows, terminal I/O goes through named pipe relay — no TerminalManager needed.
const terminalManager =
ptySpawn && process.platform !== "win32" ? new TerminalManager(tmuxPath ?? undefined) : null;
ptySpawn && !isWindows() ? new TerminalManager(tmuxPath ?? undefined) : null;
const nextPort = process.env.PORT || "3000";
const broadcaster = new SessionBroadcaster(nextPort);
@ -669,7 +670,7 @@ export function createMuxWebSocket(tmuxPath?: string | null): WebSocketServer |
try {
if (type === "open") {
if (process.platform === "win32") {
if (isWindows()) {
handleWindowsPipeMessage(
msg as { id: string; type: string; projectId?: string; data?: string; cols?: number; rows?: number },
ws,
@ -739,7 +740,7 @@ export function createMuxWebSocket(tmuxPath?: string | null): WebSocketServer |
}
}
} else if (type === "data" && "data" in msg) {
if (process.platform === "win32") {
if (isWindows()) {
handleWindowsPipeMessage(
msg as { id: string; type: string; projectId?: string; data: string },
ws,
@ -751,7 +752,7 @@ export function createMuxWebSocket(tmuxPath?: string | null): WebSocketServer |
terminalManager?.write(id, msg.data, projectId);
}
} else if (type === "resize" && "cols" in msg && "rows" in msg) {
if (process.platform === "win32") {
if (isWindows()) {
handleWindowsPipeMessage(
msg as { id: string; type: string; projectId?: string; cols: number; rows: number },
ws,
@ -763,7 +764,7 @@ export function createMuxWebSocket(tmuxPath?: string | null): WebSocketServer |
terminalManager?.resize(id, msg.cols, msg.rows, projectId);
}
} else if (type === "close") {
if (process.platform === "win32") {
if (isWindows()) {
handleWindowsPipeMessage(
msg as { id: string; type: string; projectId?: string; data?: string; cols?: number; rows?: number },
ws,
@ -840,7 +841,7 @@ export function createMuxWebSocket(tmuxPath?: string | null): WebSocketServer |
subscriptions.clear();
// Windows: close all open pipe sockets
for (const pipeSocket of winPipes.values()) {
pipeSocket.end();
pipeSocket.destroy();
}
winPipes.clear();
winPipeBuffers.clear();

View File

@ -9,6 +9,7 @@ import { execFileSync } from "node:child_process";
import { readdirSync, existsSync, readFileSync } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { isWindows } from "@aoagents/ao-core";
/** Session ID validation regex — alphanumeric, hyphens, underscores only */
export const SESSION_ID_PATTERN = /^[a-zA-Z0-9_-]+$/;
@ -110,7 +111,7 @@ export function validateSessionId(sessionId: string): boolean {
export function findTmux(
execFn: typeof execFileSync = execFileSync,
): string | null {
if (process.platform === "win32") return null;
if (isWindows()) return null;
const candidates = [
"/opt/homebrew/bin/tmux", // macOS ARM (Homebrew)
"/usr/local/bin/tmux", // macOS Intel (Homebrew)
@ -233,7 +234,7 @@ export function resolvePipePath(
readFile?: (path: string) => string;
} = defaultFs,
): string | null {
if (process.platform !== "win32") return null;
if (!isWindows()) return null;
const readFile = fs.readFile ?? ((p: string) => readFileSync(p, "utf8"));
const aoBase = join(fs.homedir(), ".agent-orchestrator");