refactor: migrate to shell-env and custom desktop notifications bridge
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { execFileSync, execSync } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { platform } from "node:os";
|
||||
import { shellEnvSync } from "shell-env";
|
||||
import { z } from "zod";
|
||||
|
||||
import type { AgentProvider } from "./agent-sdk-types.js";
|
||||
@@ -104,11 +105,24 @@ export function resolveProviderCommandPrefix(
|
||||
};
|
||||
}
|
||||
|
||||
let cachedShellEnv: Record<string, string> | null = null;
|
||||
|
||||
export function resolveShellEnv(): Record<string, string> {
|
||||
if (cachedShellEnv) return cachedShellEnv;
|
||||
try {
|
||||
cachedShellEnv = shellEnvSync();
|
||||
} catch {
|
||||
cachedShellEnv = { ...process.env } as Record<string, string>;
|
||||
}
|
||||
return cachedShellEnv;
|
||||
}
|
||||
|
||||
export function applyProviderEnv(
|
||||
baseEnv: Record<string, string | undefined>,
|
||||
runtimeSettings?: ProviderRuntimeSettings
|
||||
): Record<string, string | undefined> {
|
||||
return {
|
||||
...resolveShellEnv(),
|
||||
...baseEnv,
|
||||
...(runtimeSettings?.env ?? {}),
|
||||
};
|
||||
|
||||
@@ -27,10 +27,8 @@ import type { Logger } from "pino";
|
||||
import { execSync, spawn } from "node:child_process";
|
||||
import type { ChildProcessWithoutNullStreams } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { existsSync } from "node:fs";
|
||||
import { existsSync, Dirent } from "node:fs";
|
||||
import fs from "node:fs/promises";
|
||||
import { Dirent } from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import readline from "node:readline";
|
||||
@@ -42,6 +40,7 @@ import {
|
||||
} from "./codex/tool-call-mapper.js";
|
||||
import {
|
||||
applyProviderEnv,
|
||||
findExecutable,
|
||||
resolveProviderCommandPrefix,
|
||||
type ProviderRuntimeSettings,
|
||||
} from "../provider-launch-config.js";
|
||||
@@ -150,52 +149,13 @@ function mergeCodexConfiguredDefaults(
|
||||
};
|
||||
}
|
||||
|
||||
const CODEX_TARGET_TRIPLE: Record<string, Record<string, string>> = {
|
||||
linux: { x64: "x86_64-unknown-linux-musl", arm64: "aarch64-unknown-linux-musl" },
|
||||
darwin: { x64: "x86_64-apple-darwin", arm64: "aarch64-apple-darwin" },
|
||||
win32: { x64: "x86_64-pc-windows-msvc", arm64: "aarch64-pc-windows-msvc" },
|
||||
};
|
||||
|
||||
const CODEX_PLATFORM_PACKAGE: Record<string, string> = {
|
||||
"x86_64-unknown-linux-musl": "@openai/codex-linux-x64",
|
||||
"aarch64-unknown-linux-musl": "@openai/codex-linux-arm64",
|
||||
"x86_64-apple-darwin": "@openai/codex-darwin-x64",
|
||||
"aarch64-apple-darwin": "@openai/codex-darwin-arm64",
|
||||
"x86_64-pc-windows-msvc": "@openai/codex-win32-x64",
|
||||
"aarch64-pc-windows-msvc": "@openai/codex-win32-arm64",
|
||||
};
|
||||
|
||||
function resolveBundledCodexBinary(): string | null {
|
||||
const targetTriple = CODEX_TARGET_TRIPLE[process.platform]?.[process.arch];
|
||||
if (!targetTriple) {
|
||||
return null;
|
||||
}
|
||||
const platformPackage = CODEX_PLATFORM_PACKAGE[targetTriple];
|
||||
if (!platformPackage) {
|
||||
return null;
|
||||
}
|
||||
const binaryName = process.platform === "win32" ? "codex.exe" : "codex";
|
||||
try {
|
||||
const require = createRequire(import.meta.url);
|
||||
const packageJsonPath = require.resolve(`${platformPackage}/package.json`);
|
||||
const vendorRoot = path.join(path.dirname(packageJsonPath), "vendor");
|
||||
const binaryPath = path.join(vendorRoot, targetTriple, "codex", binaryName);
|
||||
if (existsSync(binaryPath)) {
|
||||
return binaryPath;
|
||||
}
|
||||
} catch {
|
||||
// Platform package not installed
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveCodexBinary(): string {
|
||||
const bundled = resolveBundledCodexBinary();
|
||||
if (bundled) {
|
||||
return bundled;
|
||||
const found = findExecutable("codex");
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
throw new Error(
|
||||
`Bundled Codex binary not found for platform ${process.platform}-${process.arch}. Ensure the @openai/codex package and its platform-specific optional dependency are installed.`
|
||||
"Codex binary not found. Install the Codex CLI (https://github.com/openai/codex) and ensure it is available in your shell PATH."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { spawn, type ChildProcess } from "node:child_process";
|
||||
import { existsSync } from "node:fs";
|
||||
import { createRequire } from "node:module";
|
||||
import path from "node:path";
|
||||
import os from "node:os";
|
||||
import { createOpencodeClient, type OpencodeClient } from "@opencode-ai/sdk/v2/client";
|
||||
import net from "node:net";
|
||||
import type { Logger } from "pino";
|
||||
@@ -33,6 +30,7 @@ import type {
|
||||
} from "../agent-sdk-types.js";
|
||||
import {
|
||||
applyProviderEnv,
|
||||
findExecutable,
|
||||
resolveProviderCommandPrefix,
|
||||
type ProviderRuntimeSettings,
|
||||
} from "../provider-launch-config.js";
|
||||
@@ -152,40 +150,13 @@ const OpencodeToolPartToTimelineItemSchema = OpencodeToolPartTimelineEnvelopeSch
|
||||
})
|
||||
);
|
||||
|
||||
const OPENCODE_PLATFORM_MAP: Record<string, string> = {
|
||||
darwin: "darwin",
|
||||
linux: "linux",
|
||||
win32: "windows",
|
||||
};
|
||||
|
||||
function resolveBundledOpenCodeBinary(): string | null {
|
||||
const platform = OPENCODE_PLATFORM_MAP[os.platform()];
|
||||
if (!platform) {
|
||||
return null;
|
||||
}
|
||||
const arch = os.arch();
|
||||
const packageName = `opencode-${platform}-${arch}`;
|
||||
const binaryName = platform === "windows" ? "opencode.exe" : "opencode";
|
||||
try {
|
||||
const require = createRequire(import.meta.url);
|
||||
const packageJsonPath = require.resolve(`${packageName}/package.json`);
|
||||
const binaryPath = path.join(path.dirname(packageJsonPath), "bin", binaryName);
|
||||
if (existsSync(binaryPath)) {
|
||||
return binaryPath;
|
||||
}
|
||||
} catch {
|
||||
// Platform package not installed
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveOpenCodeBinary(): string {
|
||||
const bundled = resolveBundledOpenCodeBinary();
|
||||
if (bundled) {
|
||||
return bundled;
|
||||
const found = findExecutable("opencode");
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
throw new Error(
|
||||
`Bundled OpenCode binary not found for platform ${os.platform()}-${os.arch()}. Ensure the opencode-ai package and its platform-specific optional dependency are installed.`
|
||||
"OpenCode binary not found. Install OpenCode (https://github.com/opencode-ai/opencode) and ensure it is available in your shell PATH."
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -7379,7 +7379,7 @@ export class Session {
|
||||
const requestedResumeOffset =
|
||||
typeof msg.resumeOffset === 'number'
|
||||
? msg.resumeOffset
|
||||
: session.getOutputOffset()
|
||||
: 0
|
||||
const initialOffset = Math.max(0, Math.floor(requestedResumeOffset))
|
||||
const binding: {
|
||||
terminalId: string
|
||||
|
||||
Reference in New Issue
Block a user