feat(server): bundle Codex and OpenCode binaries instead of requiring global installs
This commit is contained in:
Generated
+279
@@ -6402,6 +6402,128 @@
|
||||
"node": ">=20.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex": {
|
||||
"version": "0.114.0",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0.tgz",
|
||||
"integrity": "sha512-HMo8LRR6CtfKkaa28xvFK6eOarmBFTDfsrS9GJtEoaspGGemFok494CpafDspiTZaHZZGHfSUe5SWTUxYq7OaA==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"codex": "bin/codex.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@openai/codex-darwin-arm64": "npm:@openai/codex@0.114.0-darwin-arm64",
|
||||
"@openai/codex-darwin-x64": "npm:@openai/codex@0.114.0-darwin-x64",
|
||||
"@openai/codex-linux-arm64": "npm:@openai/codex@0.114.0-linux-arm64",
|
||||
"@openai/codex-linux-x64": "npm:@openai/codex@0.114.0-linux-x64",
|
||||
"@openai/codex-win32-arm64": "npm:@openai/codex@0.114.0-win32-arm64",
|
||||
"@openai/codex-win32-x64": "npm:@openai/codex@0.114.0-win32-x64"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-darwin-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-darwin-arm64.tgz",
|
||||
"integrity": "sha512-c9dlgo9O+66alr3s3G36fKE3KaO2+xrLZ/QcU3oujDruV86pqgVSEK2njHi+WIyyOa6m2AyWxdaHLEbKxPCNRg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-darwin-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-darwin-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-darwin-x64.tgz",
|
||||
"integrity": "sha512-oPAPeZSaJZ1AQneFPSJu44uqbZr63Bxut9FOTWZwuSqYx4YEees7i0HJmJcqQc0XnCbYtHJdqo/i07Uv374NLw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-linux-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-linux-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-linux-arm64.tgz",
|
||||
"integrity": "sha512-oUFZGZgMiEqmo85C+dfhckpVApH25alLWfwBgfKr2IRgdx/tovy8vN101f6kj01E6nDDe4LfJdNSZGtZht4fRA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-linux-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-linux-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-linux-x64.tgz",
|
||||
"integrity": "sha512-MF6RhxfBoccccd5CYII2C7TL2TvYzombBQhanDZfQAajr6n7IuoazCmoHDlrFHS4AcSw9bYA4MRlrwEjbEjgsw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-win32-arm64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-win32-arm64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-win32-arm64.tgz",
|
||||
"integrity": "sha512-CnRMHopj3en9aqQ2UaDW7EgpEGkxHdZVLLRq2cOy5D0HyuzF6Qb6595ADoFVJHEmPeN5Iz/KUbiGs5GLDjUwOA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@openai/codex-win32-x64": {
|
||||
"name": "@openai/codex",
|
||||
"version": "0.114.0-win32-x64",
|
||||
"resolved": "https://registry.npmjs.org/@openai/codex/-/codex-0.114.0-win32-x64.tgz",
|
||||
"integrity": "sha512-ztRsH5Z+gPVZ5ZInx6HzXsTFFkuEdjk3Ay0UGVOhRRCWvevXQi/SL4eU8hwysCYrs8K/WRq3mo4c95w9zQ2wLw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@opencode-ai/sdk": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.2.6.tgz",
|
||||
@@ -21560,6 +21682,161 @@
|
||||
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/opencode-ai": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-ai/-/opencode-ai-1.2.24.tgz",
|
||||
"integrity": "sha512-LaSoATkVEF6jyXNnAPrkqYpmHsZfuf2uPLDSEGJkL4hT6HYFq8LkoknHDjCGIiE5Be3MmId4+l17eSIKDfmddw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"opencode": "bin/opencode"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"opencode-darwin-arm64": "1.2.24",
|
||||
"opencode-darwin-x64": "1.2.24",
|
||||
"opencode-darwin-x64-baseline": "1.2.24",
|
||||
"opencode-linux-arm64": "1.2.24",
|
||||
"opencode-linux-arm64-musl": "1.2.24",
|
||||
"opencode-linux-x64": "1.2.24",
|
||||
"opencode-linux-x64-baseline": "1.2.24",
|
||||
"opencode-linux-x64-baseline-musl": "1.2.24",
|
||||
"opencode-linux-x64-musl": "1.2.24",
|
||||
"opencode-windows-x64": "1.2.24",
|
||||
"opencode-windows-x64-baseline": "1.2.24"
|
||||
}
|
||||
},
|
||||
"node_modules/opencode-darwin-arm64": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-darwin-arm64/-/opencode-darwin-arm64-1.2.24.tgz",
|
||||
"integrity": "sha512-mk5AkNbmATLwjnczd09Fu9dLTPcW4GSlRlIGWJBbLuGSPe7DWfbuhA5tj00VuaGeC09wDKVnW06BxWp/gRzgMQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-darwin-x64": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-darwin-x64/-/opencode-darwin-x64-1.2.24.tgz",
|
||||
"integrity": "sha512-SuG7ItUejx42z9Bz46t0R3LLFIM34vZUcwJAkqqpS6MRd1KV9G4OQIJl9BR+Cwwvk70iqCnoDxj5NgFZjeeNOw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-darwin-x64-baseline": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-darwin-x64-baseline/-/opencode-darwin-x64-baseline-1.2.24.tgz",
|
||||
"integrity": "sha512-+MT/ZkgXxeID/kOcT04SBn8Vg+4tk8CytKldaNDLgUnsi/78vTxDXWs0Cc21Ohc894r45fEtOOb5npSNIMOVfQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-linux-arm64": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-linux-arm64/-/opencode-linux-arm64-1.2.24.tgz",
|
||||
"integrity": "sha512-zSpbVCwVfUQ/Bey1MEGkJg3A52EiIPgnpS44HwmSANkiLPVXRBVuwbFYN2qJ7eJVAH939K9+QPmDOW4X8DWKeQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-linux-arm64-musl": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-linux-arm64-musl/-/opencode-linux-arm64-musl-1.2.24.tgz",
|
||||
"integrity": "sha512-LY28mspJOJ2s32E0AbrfbdWH5Bw+5YQkuB3ACJiVxW1MafjhRgPOsXjnw38WMiFjZ+NbhSPBOKnL0guKseVd4Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-linux-x64": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-linux-x64/-/opencode-linux-x64-1.2.24.tgz",
|
||||
"integrity": "sha512-OM3umRJ2ZpDe4YtDOGp32cQCqvMPuFJBKKngfvWL4zz4EWDzLPttb0sNL7xdC1xR/XidtADRYcvtzc2rr7/4Rw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-linux-x64-baseline": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-linux-x64-baseline/-/opencode-linux-x64-baseline-1.2.24.tgz",
|
||||
"integrity": "sha512-yakykM+GxCMZ5WK2G0CQk5cGJkoKt09A/8Y0bhKy7l+Jc/QiTV2ZIlBwT5FO15dnuGlNH6zvukLyOQvOZinM+Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-linux-x64-baseline-musl": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-linux-x64-baseline-musl/-/opencode-linux-x64-baseline-musl-1.2.24.tgz",
|
||||
"integrity": "sha512-XHPuf9Rj9nWkVX7JJZ5NtYx9UWT0hPiem/kAhZzYITseRGmQMMfFAhIOBYYvvlzJzgdhcrLi198kJHaKCdXjag==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-linux-x64-musl": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-linux-x64-musl/-/opencode-linux-x64-musl-1.2.24.tgz",
|
||||
"integrity": "sha512-nFT4J4m4wKiZh4RsfgQJlW6W2w/VtMNnXnMiQk93FnncSf0nUXEB5Nam3P+vCjdR3i4cs355JiOvbshnMiJGSA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-windows-x64": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-windows-x64/-/opencode-windows-x64-1.2.24.tgz",
|
||||
"integrity": "sha512-7nkwFgS8Jn35kgw+6JIWRU6PmbggSuTDiQ+RnFGoySFgYW/Sz/R30Z4KmnbfJLElzEef0kX+nZQasfVl0pSf6A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/opencode-windows-x64-baseline": {
|
||||
"version": "1.2.24",
|
||||
"resolved": "https://registry.npmjs.org/opencode-windows-x64-baseline/-/opencode-windows-x64-baseline-1.2.24.tgz",
|
||||
"integrity": "sha512-hXp1nPnkrHgM6cid1AogRJvjz931UbZ/G165B6AAR1gOb5EqtIh2gZcT0IRUyjooEpwH7+oGFRhT+3Kql/M0WA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.9.4",
|
||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||
@@ -27796,6 +28073,7 @@
|
||||
"@lezer/markdown": "^1.6.2",
|
||||
"@lezer/python": "^1.1.18",
|
||||
"@modelcontextprotocol/sdk": "^1.20.1",
|
||||
"@openai/codex": "^0.114.0",
|
||||
"@opencode-ai/sdk": "1.2.6",
|
||||
"@sctg/sentencepiece-js": "^1.1.0",
|
||||
"@xterm/headless": "^6.0.0",
|
||||
@@ -27810,6 +28088,7 @@
|
||||
"node-pty": "1.2.0-beta.11",
|
||||
"onnxruntime-node": "^1.23.0",
|
||||
"openai": "^4.20.0",
|
||||
"opencode-ai": "^1.2.24",
|
||||
"pino": "^10.2.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
"qrcode": "^1.5.4",
|
||||
|
||||
@@ -409,12 +409,71 @@ async function pruneClaudeAgentSdk(runtimeRoot) {
|
||||
}
|
||||
}
|
||||
|
||||
async function pruneCodexCli(runtimeRoot) {
|
||||
const codexTargetTriple = {
|
||||
darwin: { arm64: "aarch64-apple-darwin", x64: "x86_64-apple-darwin" },
|
||||
linux: { arm64: "aarch64-unknown-linux-musl", x64: "x86_64-unknown-linux-musl" },
|
||||
win32: { arm64: "aarch64-pc-windows-msvc", x64: "x86_64-pc-windows-msvc" },
|
||||
};
|
||||
const codexPlatformPackages = [
|
||||
"@openai/codex-darwin-arm64",
|
||||
"@openai/codex-darwin-x64",
|
||||
"@openai/codex-linux-arm64",
|
||||
"@openai/codex-linux-x64",
|
||||
"@openai/codex-win32-arm64",
|
||||
"@openai/codex-win32-x64",
|
||||
];
|
||||
const currentTriple = codexTargetTriple[process.platform]?.[process.arch];
|
||||
const currentPackage = currentTriple
|
||||
? `@openai/codex-${process.platform === "win32" ? "win32" : process.platform}-${process.arch}`
|
||||
: null;
|
||||
|
||||
const openaiScope = path.join(runtimeRoot, "node_modules", "@openai");
|
||||
for (const pkg of codexPlatformPackages) {
|
||||
const pkgName = pkg.replace("@openai/", "");
|
||||
if (currentPackage && pkg === currentPackage) {
|
||||
continue;
|
||||
}
|
||||
await removeIfExists(path.join(openaiScope, pkgName));
|
||||
}
|
||||
}
|
||||
|
||||
async function pruneOpenCodeCli(runtimeRoot) {
|
||||
const opencodePlatformPackages = [
|
||||
"opencode-darwin-arm64",
|
||||
"opencode-darwin-x64",
|
||||
"opencode-linux-arm64",
|
||||
"opencode-linux-x64",
|
||||
"opencode-linux-x64-baseline",
|
||||
"opencode-linux-arm64-musl",
|
||||
"opencode-linux-x64-musl",
|
||||
"opencode-linux-x64-baseline-musl",
|
||||
"opencode-windows-x64",
|
||||
"opencode-windows-arm64",
|
||||
];
|
||||
const platformMap = { darwin: "darwin", linux: "linux", win32: "windows" };
|
||||
const currentPlatform = platformMap[process.platform];
|
||||
const currentPackage = currentPlatform
|
||||
? `opencode-${currentPlatform}-${process.arch}`
|
||||
: null;
|
||||
|
||||
const nodeModules = path.join(runtimeRoot, "node_modules");
|
||||
for (const pkg of opencodePlatformPackages) {
|
||||
if (currentPackage && pkg === currentPackage) {
|
||||
continue;
|
||||
}
|
||||
await removeIfExists(path.join(nodeModules, pkg));
|
||||
}
|
||||
}
|
||||
|
||||
async function pruneManagedRuntime(runtimeRoot) {
|
||||
await Promise.all([
|
||||
pruneNodeDistribution(runtimeRoot),
|
||||
pruneOnnxRuntime(runtimeRoot),
|
||||
pruneNodePty(runtimeRoot),
|
||||
pruneClaudeAgentSdk(runtimeRoot),
|
||||
pruneCodexCli(runtimeRoot),
|
||||
pruneOpenCodeCli(runtimeRoot),
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
"dependencies": {
|
||||
"@ai-sdk/openai": "2.0.52",
|
||||
"@anthropic-ai/claude-agent-sdk": "^0.2.11",
|
||||
"@openai/codex": "^0.114.0",
|
||||
"@deepgram/sdk": "^3.4.0",
|
||||
"@getpaseo/relay": "0.1.25",
|
||||
"@lezer/common": "^1.5.0",
|
||||
@@ -87,6 +88,7 @@
|
||||
"node-pty": "1.2.0-beta.11",
|
||||
"onnxruntime-node": "^1.23.0",
|
||||
"openai": "^4.20.0",
|
||||
"opencode-ai": "^1.2.24",
|
||||
"pino": "^10.2.0",
|
||||
"pino-pretty": "^13.1.3",
|
||||
"qrcode": "^1.5.4",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { execSync, spawn } from "node:child_process";
|
||||
import { spawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import { promises } from "node:fs";
|
||||
@@ -69,8 +69,6 @@ import type {
|
||||
} from "../agent-sdk-types.js";
|
||||
import {
|
||||
applyProviderEnv,
|
||||
findExecutable,
|
||||
isProviderCommandAvailable,
|
||||
type ProviderRuntimeSettings,
|
||||
} from "../provider-launch-config.js";
|
||||
import { getOrchestratorModeInstructions } from "../orchestrator-instructions.js";
|
||||
@@ -358,22 +356,11 @@ type ClaudeAgentClientOptions = {
|
||||
|
||||
type ClaudeAgentSessionOptions = {
|
||||
defaults?: { agents?: Record<string, AgentDefinition> };
|
||||
claudePath: string | null;
|
||||
runtimeSettings?: ProviderRuntimeSettings;
|
||||
handle?: AgentPersistenceHandle;
|
||||
logger: Logger;
|
||||
};
|
||||
|
||||
function resolveClaudeBinary(): string {
|
||||
const claudePath = findExecutable("claude");
|
||||
if (claudePath) {
|
||||
return claudePath;
|
||||
}
|
||||
throw new Error(
|
||||
"Claude CLI not found. Install claude or configure agents.providers.claude.command.mode='replace'."
|
||||
);
|
||||
}
|
||||
|
||||
function resolveClaudeSpawnCommand(
|
||||
spawnOptions: SpawnOptions,
|
||||
runtimeSettings?: ProviderRuntimeSettings
|
||||
@@ -1400,31 +1387,18 @@ export class ClaudeAgentClient implements AgentClient {
|
||||
|
||||
private readonly defaults?: { agents?: Record<string, AgentDefinition> };
|
||||
private readonly logger: Logger;
|
||||
private readonly claudePath: string | null;
|
||||
private readonly runtimeSettings?: ProviderRuntimeSettings;
|
||||
|
||||
constructor(options: ClaudeAgentClientOptions) {
|
||||
this.defaults = options.defaults;
|
||||
this.logger = options.logger.child({ module: "agent", provider: "claude" });
|
||||
this.runtimeSettings = options.runtimeSettings;
|
||||
this.claudePath = findExecutable("claude");
|
||||
if (this.claudePath) {
|
||||
try {
|
||||
const version = execSync(`${this.claudePath} --version`, { encoding: "utf8" }).trim();
|
||||
this.logger.trace({ claudePath: this.claudePath, version }, "Resolved Claude binary");
|
||||
} catch {
|
||||
this.logger.trace({ claudePath: this.claudePath }, "Resolved Claude binary (version unknown)");
|
||||
}
|
||||
} else {
|
||||
this.logger.trace("Claude binary not found in PATH; SDK will use bundled binary");
|
||||
}
|
||||
}
|
||||
|
||||
async createSession(config: AgentSessionConfig): Promise<AgentSession> {
|
||||
const claudeConfig = this.assertConfig(config);
|
||||
return new ClaudeAgentSession(claudeConfig, {
|
||||
defaults: this.defaults,
|
||||
claudePath: this.claudePath,
|
||||
runtimeSettings: this.runtimeSettings,
|
||||
logger: this.logger,
|
||||
});
|
||||
@@ -1443,7 +1417,6 @@ export class ClaudeAgentClient implements AgentClient {
|
||||
const claudeConfig = this.assertConfig(mergedConfig);
|
||||
return new ClaudeAgentSession(claudeConfig, {
|
||||
defaults: this.defaults,
|
||||
claudePath: this.claudePath,
|
||||
runtimeSettings: this.runtimeSettings,
|
||||
handle,
|
||||
logger: this.logger,
|
||||
@@ -1478,11 +1451,11 @@ export class ClaudeAgentClient implements AgentClient {
|
||||
}
|
||||
|
||||
async isAvailable(): Promise<boolean> {
|
||||
const commandConfig = this.runtimeSettings?.command;
|
||||
if (commandConfig?.mode === "replace") {
|
||||
return isProviderCommandAvailable(commandConfig, resolveClaudeBinary);
|
||||
const command = this.runtimeSettings?.command;
|
||||
if (command?.mode === "replace") {
|
||||
return fs.existsSync(command.argv[0]);
|
||||
}
|
||||
return this.claudePath !== null;
|
||||
return true;
|
||||
}
|
||||
|
||||
private assertConfig(config: AgentSessionConfig): ClaudeAgentConfig {
|
||||
@@ -1499,7 +1472,6 @@ class ClaudeAgentSession implements AgentSession {
|
||||
|
||||
private readonly config: ClaudeAgentConfig;
|
||||
private readonly defaults?: { agents?: Record<string, AgentDefinition> };
|
||||
private readonly claudePath: string | null;
|
||||
private readonly runtimeSettings?: ProviderRuntimeSettings;
|
||||
private readonly logger: Logger;
|
||||
private query: Query | null = null;
|
||||
@@ -1546,7 +1518,6 @@ class ClaudeAgentSession implements AgentSession {
|
||||
) {
|
||||
this.config = config;
|
||||
this.defaults = options.defaults;
|
||||
this.claudePath = options.claudePath;
|
||||
this.runtimeSettings = options.runtimeSettings;
|
||||
this.logger = options.logger;
|
||||
const handle = options.handle;
|
||||
@@ -2319,7 +2290,6 @@ class ClaudeAgentSession implements AgentSession {
|
||||
permissionMode: this.currentMode,
|
||||
agents: this.defaults?.agents,
|
||||
canUseTool: this.handlePermissionRequest,
|
||||
...(this.claudePath ? { pathToClaudeCodeExecutable: this.claudePath } : {}),
|
||||
// Use Claude Code preset system prompt and load CLAUDE.md files
|
||||
// Append provider-agnostic system prompt and orchestrator instructions for agents.
|
||||
systemPrompt: {
|
||||
|
||||
@@ -27,8 +27,10 @@ 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 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";
|
||||
@@ -40,8 +42,6 @@ import {
|
||||
} from "./codex/tool-call-mapper.js";
|
||||
import {
|
||||
applyProviderEnv,
|
||||
findExecutable,
|
||||
isProviderCommandAvailable,
|
||||
resolveProviderCommandPrefix,
|
||||
type ProviderRuntimeSettings,
|
||||
} from "../provider-launch-config.js";
|
||||
@@ -150,13 +150,52 @@ 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 codexPath = findExecutable("codex");
|
||||
if (codexPath) {
|
||||
return codexPath;
|
||||
const bundled = resolveBundledCodexBinary();
|
||||
if (bundled) {
|
||||
return bundled;
|
||||
}
|
||||
throw new Error(
|
||||
"Codex CLI not found. Please install codex globally: npm install -g @openai/codex"
|
||||
`Bundled Codex binary not found for platform ${process.platform}-${process.arch}. Ensure the @openai/codex package and its platform-specific optional dependency are installed.`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3235,6 +3274,10 @@ export class CodexAppServerAgentClient implements AgentClient {
|
||||
}
|
||||
|
||||
async isAvailable(): Promise<boolean> {
|
||||
return isProviderCommandAvailable(this.runtimeSettings?.command, resolveCodexBinary);
|
||||
const command = this.runtimeSettings?.command;
|
||||
if (command?.mode === "replace") {
|
||||
return existsSync(command.argv[0]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
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";
|
||||
@@ -29,8 +33,6 @@ import type {
|
||||
} from "../agent-sdk-types.js";
|
||||
import {
|
||||
applyProviderEnv,
|
||||
findExecutable,
|
||||
isProviderCommandAvailable,
|
||||
resolveProviderCommandPrefix,
|
||||
type ProviderRuntimeSettings,
|
||||
} from "../provider-launch-config.js";
|
||||
@@ -150,13 +152,40 @@ 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 opencodePath = findExecutable("opencode");
|
||||
if (opencodePath) {
|
||||
return opencodePath;
|
||||
const bundled = resolveBundledOpenCodeBinary();
|
||||
if (bundled) {
|
||||
return bundled;
|
||||
}
|
||||
throw new Error(
|
||||
"OpenCode CLI not found. Please install opencode globally so Paseo can launch the provider."
|
||||
`Bundled OpenCode binary not found for platform ${os.platform()}-${os.arch()}. Ensure the opencode-ai package and its platform-specific optional dependency are installed.`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -522,10 +551,11 @@ export class OpenCodeAgentClient implements AgentClient {
|
||||
}
|
||||
|
||||
async isAvailable(): Promise<boolean> {
|
||||
return isProviderCommandAvailable(
|
||||
this.runtimeSettings?.command,
|
||||
resolveOpenCodeBinary
|
||||
);
|
||||
const command = this.runtimeSettings?.command;
|
||||
if (command?.mode === "replace") {
|
||||
return existsSync(command.argv[0]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private assertConfig(config: AgentSessionConfig): OpenCodeAgentConfig {
|
||||
|
||||
Reference in New Issue
Block a user