From aa942ba5115d605098dfd163de85874819500568 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 13 Nov 2025 10:51:52 -0600 Subject: [PATCH 1/6] test --- .github/workflows/snapshot.yml | 2 +- packages/opencode/script/publish.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 402c014fd597..ab2f9c0f240c 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -4,7 +4,7 @@ on: push: branches: - dev - - opentui + - windows - v0 concurrency: ${{ github.workflow }}-${{ github.ref }} diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index ac2fce56b392..b5ac53408028 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -21,7 +21,7 @@ await $`cp -r ./bin ./dist/${pkg.name}/bin` // Copy Windows .exe if any Windows binaries were built let hasWindowsBinary = false for (const binaryName of Object.keys(binaries)) { - if (binaryName.includes("win32")) { + if (binaryName.includes("windows")) { const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe` if (fs.existsSync(winBinaryPath)) { await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe` From 933fc4aa47cd0181d7a65b850dbf5ecd5a85751b Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 13 Nov 2025 11:45:04 -0600 Subject: [PATCH 2/6] wip --- packages/opencode/bin/opencode | 145 ++++++++++++++---------- packages/opencode/bin/opencode.cmd | 13 ++- packages/opencode/script/opencode.js | 60 ++++++++++ packages/opencode/script/preinstall.mjs | 45 ++------ packages/opencode/script/publish.ts | 26 ++--- turborepo | 1 + 6 files changed, 178 insertions(+), 112 deletions(-) create mode 100644 packages/opencode/script/opencode.js create mode 160000 turborepo diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index 8f75eb1892d7..2671e453f00f 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -1,61 +1,84 @@ -#!/bin/sh -set -e - -if [ -n "$OPENCODE_BIN_PATH" ]; then - resolved="$OPENCODE_BIN_PATH" -else - # Get the real path of this script, resolving any symlinks - script_path="$0" - while [ -L "$script_path" ]; do - link_target="$(readlink "$script_path")" - case "$link_target" in - /*) script_path="$link_target" ;; - *) script_path="$(dirname "$script_path")/$link_target" ;; - esac - done - script_dir="$(dirname "$script_path")" - script_dir="$(cd "$script_dir" && pwd)" - - # Map platform names - case "$(uname -s)" in - Darwin) platform="darwin" ;; - Linux) platform="linux" ;; - MINGW*|CYGWIN*|MSYS*) platform="win32" ;; - *) platform="$(uname -s | tr '[:upper:]' '[:lower:]')" ;; - esac - - # Map architecture names - case "$(uname -m)" in - x86_64|amd64) arch="x64" ;; - aarch64) arch="arm64" ;; - armv7l) arch="arm" ;; - *) arch="$(uname -m)" ;; - esac - - name="opencode-${platform}-${arch}" - binary="opencode" - [ "$platform" = "win32" ] && binary="opencode.exe" - - # Search for the binary starting from real script location - resolved="" - current_dir="$script_dir" - while [ "$current_dir" != "/" ]; do - candidate="$current_dir/node_modules/$name/bin/$binary" - if [ -f "$candidate" ]; then - resolved="$candidate" - break - fi - current_dir="$(dirname "$current_dir")" - done - - if [ -z "$resolved" ]; then - printf "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the \"%s\" package\n" "$name" >&2 - exit 1 - fi -fi - -# Handle SIGINT gracefully -trap '' INT - -# Execute the binary with all arguments -exec "$resolved" "$@" +#!/usr/bin/env node + +const childProcess = require("child_process") +const fs = require("fs") +const path = require("path") +const os = require("os") + +function run(target) { + const result = childProcess.spawnSync(target, process.argv.slice(2), { + stdio: "inherit", + }) + if (result.error) { + console.error(result.error.message) + process.exit(1) + } + const code = typeof result.status === "number" ? result.status : 0 + process.exit(code) +} + +const envPath = process.env.OPENCODE_BIN_PATH +if (envPath) { + run(envPath) +} + +const scriptPath = fs.realpathSync(__filename) +const scriptDir = path.dirname(scriptPath) + +const platformMap = { + darwin: "darwin", + linux: "linux", + win32: "windows", +} +const archMap = { + x64: "x64", + arm64: "arm64", + arm: "arm", +} + +let platform = platformMap[os.platform()] +if (!platform) { + platform = os.platform() +} +let arch = archMap[os.arch()] +if (!arch) { + arch = os.arch() +} +const base = "opencode-" + platform + "-" + arch +const binary = platform === "windows" ? "opencode.exe" : "opencode" + +function findBinary(startDir) { + let current = startDir + for (;;) { + const modules = path.join(current, "node_modules") + if (fs.existsSync(modules)) { + const entries = fs.readdirSync(modules) + for (const entry of entries) { + if (!entry.startsWith(base)) { + continue + } + const candidate = path.join(modules, entry, "bin", binary) + if (fs.existsSync(candidate)) { + return candidate + } + } + } + const parent = path.dirname(current) + if (parent === current) { + return + } + current = parent + } +} + +const resolved = findBinary(scriptDir) +if (!resolved) { + console.error( + "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the \"" + + base + + "\" package", + ) + process.exit(1) +} + +run(resolved) diff --git a/packages/opencode/bin/opencode.cmd b/packages/opencode/bin/opencode.cmd index 775bfe688670..281543657251 100644 --- a/packages/opencode/bin/opencode.cmd +++ b/packages/opencode/bin/opencode.cmd @@ -24,7 +24,7 @@ if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( set "arch=x64" ) -set "name=opencode-!platform!-!arch!" +set "base=opencode-!platform!-!arch!" set "binary=opencode.exe" rem Search for the binary starting from script location @@ -32,10 +32,13 @@ set "resolved=" set "current_dir=%script_dir%" :search_loop -set "candidate=%current_dir%\node_modules\%name%\bin\%binary%" -if exist "%candidate%" ( - set "resolved=%candidate%" - goto :execute +if exist "%current_dir%\node_modules" ( + for /d %%d in ("%current_dir%\node_modules\%base%*") do ( + if exist "%%d\bin\%binary%" ( + set "resolved=%%d\bin\%binary%" + goto :execute + ) + ) ) rem Move up one directory diff --git a/packages/opencode/script/opencode.js b/packages/opencode/script/opencode.js new file mode 100644 index 000000000000..bf9a97605db4 --- /dev/null +++ b/packages/opencode/script/opencode.js @@ -0,0 +1,60 @@ +#!/usr/bin/env node + +import { execFileSync } from "node:child_process" + +import fs from "node:fs" +import path from "node:path" +import { fileURLToPath } from "node:url" + +export default function getExePath() { + const __dirname = path.dirname(fileURLToPath(import.meta.url)) + const normalizedDirname = __dirname.replace(/\\/g, "/") + + let exeDir + + const expectedPackage = "native-preview-" + process.platform + "-" + process.arch + + if (normalizedDirname.endsWith("/_packages/native-preview/lib")) { + // We're running directly from source in the repo. + exeDir = path.resolve(__dirname, "..", "..", "..", "built", "local") + } else if (normalizedDirname.endsWith("/built/npm/native-preview/lib")) { + // We're running from the built output. + exeDir = path.resolve(__dirname, "..", "..", expectedPackage, "lib") + } else { + // We're actually running from an installed package. + const platformPackageName = "@typescript/" + expectedPackage + let packageJson + try { + // v20.6.0, v18.19.0 + packageJson = import.meta.resolve(platformPackageName + "/package.json") + } catch (e) { + throw new Error( + "Unable to resolve " + + platformPackageName + + ". Either your platform is unsupported, or you are missing the package on disk.", + ) + } + const packageJsonPath = fileURLToPath(packageJson) + exeDir = path.join(path.dirname(packageJsonPath), "lib") + } + + const exe = path.join(exeDir, "tsgo" + (process.platform === "win32" ? ".exe" : "")) + + if (!fs.existsSync(exe)) { + throw new Error("Executable not found: " + exe) + } + + return exe +} + +const exe = getExePath() + +try { + execFileSync(exe, process.argv.slice(2), { stdio: "inherit" }) +} catch (e) { + if (e.status) { + process.exitCode = e.status + } else { + throw e + } +} diff --git a/packages/opencode/script/preinstall.mjs b/packages/opencode/script/preinstall.mjs index dfe46d9e78c2..e4b8385fa494 100644 --- a/packages/opencode/script/preinstall.mjs +++ b/packages/opencode/script/preinstall.mjs @@ -2,43 +2,22 @@ import fs from "fs" import path from "path" -import os from "os" import { fileURLToPath } from "url" -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -function main() { - if (os.platform() !== "win32") { - console.log("Non-Windows platform detected, skipping preinstall") - return - } - - console.log("Windows detected: Modifying package.json bin entry") - - // Read package.json - const packageJsonPath = path.join(__dirname, "package.json") - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")) - - // Modify bin to point to .cmd file on Windows - packageJson.bin = { - opencode: "./bin/opencode.cmd", - } - - // Write it back - fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)) - console.log("Updated package.json bin to use opencode.cmd") - - // Now you can also remove the Unix script if you want - const unixScript = path.join(__dirname, "bin", "opencode") - if (fs.existsSync(unixScript)) { - console.log("Removing Unix shell script") - fs.unlinkSync(unixScript) - } -} +const dir = path.dirname(fileURLToPath(import.meta.url)) +const packagePath = path.join(dir, "package.json") try { - main() + const content = fs.readFileSync(packagePath, "utf8") + const data = JSON.parse(content) + const current = data.bin && data.bin.opencode + if (current !== "./bin/opencode") { + data.bin = { + opencode: "./bin/opencode", + } + fs.writeFileSync(packagePath, JSON.stringify(data, null, 2)) + console.log("Normalized opencode bin entry for cross-platform launcher") + } } catch (error) { console.error("Preinstall script error:", error.message) - process.exit(0) } diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index b5ac53408028..fb836d9ebfe8 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -18,18 +18,18 @@ const { binaries } = await import("./build.ts") await $`mkdir -p ./dist/${pkg.name}` await $`cp -r ./bin ./dist/${pkg.name}/bin` -// Copy Windows .exe if any Windows binaries were built -let hasWindowsBinary = false -for (const binaryName of Object.keys(binaries)) { - if (binaryName.includes("windows")) { - const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe` - if (fs.existsSync(winBinaryPath)) { - await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe` - hasWindowsBinary = true - break - } - } -} +// // Copy Windows .exe if any Windows binaries were built +// let hasWindowsBinary = false +// for (const binaryName of Object.keys(binaries)) { +// if (binaryName.includes("windows")) { +// const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe` +// if (fs.existsSync(winBinaryPath)) { +// await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe` +// // hasWindowsBinary = true +// break +// } +// } +// } await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs` await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs` @@ -39,7 +39,7 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( { name: pkg.name + "-ai", bin: { - [pkg.name]: hasWindowsBinary ? `./bin/${pkg.name}.exe` : `./bin/${pkg.name}`, + [pkg.name]: `./bin/${pkg.name}`, }, scripts: { preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs", diff --git a/turborepo b/turborepo new file mode 160000 index 000000000000..e3a5905685d6 --- /dev/null +++ b/turborepo @@ -0,0 +1 @@ +Subproject commit e3a5905685d630b9dbcb1cdf5472c095882a9c26 From 3c4b8bc32b98d1329de12206f08cbdb386917301 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 13 Nov 2025 11:45:32 -0600 Subject: [PATCH 3/6] wip --- turborepo | 1 - 1 file changed, 1 deletion(-) delete mode 160000 turborepo diff --git a/turborepo b/turborepo deleted file mode 160000 index e3a5905685d6..000000000000 --- a/turborepo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit e3a5905685d630b9dbcb1cdf5472c095882a9c26 From 0bea9d9c479ab7f7891fe489c5c7f05636227857 Mon Sep 17 00:00:00 2001 From: GitHub Action Date: Thu, 13 Nov 2025 17:46:12 +0000 Subject: [PATCH 4/6] chore: format code --- packages/opencode/bin/opencode | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/opencode/bin/opencode b/packages/opencode/bin/opencode index 2671e453f00f..e35cc00944d6 100755 --- a/packages/opencode/bin/opencode +++ b/packages/opencode/bin/opencode @@ -74,9 +74,9 @@ function findBinary(startDir) { const resolved = findBinary(scriptDir) if (!resolved) { console.error( - "It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the \"" + + 'It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "' + base + - "\" package", + '" package', ) process.exit(1) } From f63b15abafe4caaae66b10b9810a31c002c0886b Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 13 Nov 2025 12:07:00 -0600 Subject: [PATCH 5/6] rm --- packages/opencode/bin/opencode.cmd | 61 ------------------------- packages/opencode/script/opencode.js | 60 ------------------------ packages/opencode/script/preinstall.mjs | 23 ---------- packages/opencode/script/publish.ts | 19 +------- 4 files changed, 2 insertions(+), 161 deletions(-) delete mode 100644 packages/opencode/bin/opencode.cmd delete mode 100644 packages/opencode/script/opencode.js delete mode 100644 packages/opencode/script/preinstall.mjs diff --git a/packages/opencode/bin/opencode.cmd b/packages/opencode/bin/opencode.cmd deleted file mode 100644 index 281543657251..000000000000 --- a/packages/opencode/bin/opencode.cmd +++ /dev/null @@ -1,61 +0,0 @@ -@echo off -setlocal enabledelayedexpansion - -if defined OPENCODE_BIN_PATH ( - set "resolved=%OPENCODE_BIN_PATH%" - goto :execute -) - -rem Get the directory of this script -set "script_dir=%~dp0" -set "script_dir=%script_dir:~0,-1%" - -rem Detect platform and architecture -set "platform=windows" - -rem Detect architecture -if "%PROCESSOR_ARCHITECTURE%"=="AMD64" ( - set "arch=x64" -) else if "%PROCESSOR_ARCHITECTURE%"=="ARM64" ( - set "arch=arm64" -) else if "%PROCESSOR_ARCHITECTURE%"=="x86" ( - set "arch=x86" -) else ( - set "arch=x64" -) - -set "base=opencode-!platform!-!arch!" -set "binary=opencode.exe" - -rem Search for the binary starting from script location -set "resolved=" -set "current_dir=%script_dir%" - -:search_loop -if exist "%current_dir%\node_modules" ( - for /d %%d in ("%current_dir%\node_modules\%base%*") do ( - if exist "%%d\bin\%binary%" ( - set "resolved=%%d\bin\%binary%" - goto :execute - ) - ) -) - -rem Move up one directory -for %%i in ("%current_dir%") do set "parent_dir=%%~dpi" -set "parent_dir=%parent_dir:~0,-1%" - -rem Check if we've reached the root -if "%current_dir%"=="%parent_dir%" goto :not_found -set "current_dir=%parent_dir%" -goto :search_loop - -:not_found -echo It seems that your package manager failed to install the right version of the opencode CLI for your platform. You can try manually installing the "%name%" package >&2 -exit /b 1 - -:execute -rem Execute the binary with all arguments in the same console window -rem Use start /b /wait to ensure it runs in the current shell context for all shells -start /b /wait "" "%resolved%" %* -exit /b %ERRORLEVEL% diff --git a/packages/opencode/script/opencode.js b/packages/opencode/script/opencode.js deleted file mode 100644 index bf9a97605db4..000000000000 --- a/packages/opencode/script/opencode.js +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env node - -import { execFileSync } from "node:child_process" - -import fs from "node:fs" -import path from "node:path" -import { fileURLToPath } from "node:url" - -export default function getExePath() { - const __dirname = path.dirname(fileURLToPath(import.meta.url)) - const normalizedDirname = __dirname.replace(/\\/g, "/") - - let exeDir - - const expectedPackage = "native-preview-" + process.platform + "-" + process.arch - - if (normalizedDirname.endsWith("/_packages/native-preview/lib")) { - // We're running directly from source in the repo. - exeDir = path.resolve(__dirname, "..", "..", "..", "built", "local") - } else if (normalizedDirname.endsWith("/built/npm/native-preview/lib")) { - // We're running from the built output. - exeDir = path.resolve(__dirname, "..", "..", expectedPackage, "lib") - } else { - // We're actually running from an installed package. - const platformPackageName = "@typescript/" + expectedPackage - let packageJson - try { - // v20.6.0, v18.19.0 - packageJson = import.meta.resolve(platformPackageName + "/package.json") - } catch (e) { - throw new Error( - "Unable to resolve " + - platformPackageName + - ". Either your platform is unsupported, or you are missing the package on disk.", - ) - } - const packageJsonPath = fileURLToPath(packageJson) - exeDir = path.join(path.dirname(packageJsonPath), "lib") - } - - const exe = path.join(exeDir, "tsgo" + (process.platform === "win32" ? ".exe" : "")) - - if (!fs.existsSync(exe)) { - throw new Error("Executable not found: " + exe) - } - - return exe -} - -const exe = getExePath() - -try { - execFileSync(exe, process.argv.slice(2), { stdio: "inherit" }) -} catch (e) { - if (e.status) { - process.exitCode = e.status - } else { - throw e - } -} diff --git a/packages/opencode/script/preinstall.mjs b/packages/opencode/script/preinstall.mjs deleted file mode 100644 index e4b8385fa494..000000000000 --- a/packages/opencode/script/preinstall.mjs +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env node - -import fs from "fs" -import path from "path" -import { fileURLToPath } from "url" - -const dir = path.dirname(fileURLToPath(import.meta.url)) -const packagePath = path.join(dir, "package.json") - -try { - const content = fs.readFileSync(packagePath, "utf8") - const data = JSON.parse(content) - const current = data.bin && data.bin.opencode - if (current !== "./bin/opencode") { - data.bin = { - opencode: "./bin/opencode", - } - fs.writeFileSync(packagePath, JSON.stringify(data, null, 2)) - console.log("Normalized opencode bin entry for cross-platform launcher") - } -} catch (error) { - console.error("Preinstall script error:", error.message) -} diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index fb836d9ebfe8..f06ae8cdc62e 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -3,7 +3,6 @@ import { $ } from "bun" import pkg from "../package.json" import { Script } from "@opencode-ai/script" import { fileURLToPath } from "url" -import fs from "fs" const dir = fileURLToPath(new URL("..", import.meta.url)) process.chdir(dir) @@ -17,21 +16,7 @@ const { binaries } = await import("./build.ts") await $`mkdir -p ./dist/${pkg.name}` await $`cp -r ./bin ./dist/${pkg.name}/bin` - -// // Copy Windows .exe if any Windows binaries were built -// let hasWindowsBinary = false -// for (const binaryName of Object.keys(binaries)) { -// if (binaryName.includes("windows")) { -// const winBinaryPath = `./dist/${binaryName}/bin/opencode.exe` -// if (fs.existsSync(winBinaryPath)) { -// await $`cp ${winBinaryPath} ./dist/${pkg.name}/bin/opencode.exe` -// // hasWindowsBinary = true -// break -// } -// } -// } - -await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs` +// await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs` await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs` await Bun.file(`./dist/${pkg.name}/package.json`).write( @@ -42,7 +27,7 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( [pkg.name]: `./bin/${pkg.name}`, }, scripts: { - preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs", + // preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs", postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs", }, version: Script.version, From 79a8b4d3d7ee4f09d1fa64a5f2ac36edbbc8d03b Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Thu, 13 Nov 2025 12:18:05 -0600 Subject: [PATCH 6/6] fix --- packages/opencode/script/publish.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/opencode/script/publish.ts b/packages/opencode/script/publish.ts index f06ae8cdc62e..d5afe56fb359 100755 --- a/packages/opencode/script/publish.ts +++ b/packages/opencode/script/publish.ts @@ -16,7 +16,6 @@ const { binaries } = await import("./build.ts") await $`mkdir -p ./dist/${pkg.name}` await $`cp -r ./bin ./dist/${pkg.name}/bin` -// await $`cp ./script/preinstall.mjs ./dist/${pkg.name}/preinstall.mjs` await $`cp ./script/postinstall.mjs ./dist/${pkg.name}/postinstall.mjs` await Bun.file(`./dist/${pkg.name}/package.json`).write( @@ -27,7 +26,6 @@ await Bun.file(`./dist/${pkg.name}/package.json`).write( [pkg.name]: `./bin/${pkg.name}`, }, scripts: { - // preinstall: "bun ./preinstall.mjs || node ./preinstall.mjs", postinstall: "bun ./postinstall.mjs || node ./postinstall.mjs", }, version: Script.version,