From 129694bf8ae9c3db0a7fb7f05f6abc0eece00f47 Mon Sep 17 00:00:00 2001 From: Aiden Cline Date: Sat, 25 Jul 2026 02:31:26 +0000 Subject: [PATCH] fix(cli): package fff node assets --- bun.lock | 10 ++++++++++ packages/cli/package.json | 10 ++++++++++ packages/cli/script/node-assets.ts | 2 ++ packages/cli/src/node/target.ts | 6 ++++++ packages/cli/vite.node.config.ts | 28 ++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+) diff --git a/bun.lock b/bun.lock index 0ac2088a60..b498427f1f 100644 --- a/bun.lock +++ b/bun.lock @@ -147,6 +147,11 @@ "ws": "8.21.0", }, "devDependencies": { + "@ff-labs/fff-bin-darwin-arm64": "0.10.1", + "@ff-labs/fff-bin-linux-arm64-gnu": "0.10.1", + "@ff-labs/fff-bin-linux-x64-gnu": "0.10.1", + "@ff-labs/fff-bin-win32-arm64": "0.10.1", + "@ff-labs/fff-bin-win32-x64": "0.10.1", "@lydell/node-pty-darwin-arm64": "1.2.0-beta.12", "@lydell/node-pty-darwin-x64": "1.2.0-beta.12", "@lydell/node-pty-linux-arm64": "1.2.0-beta.12", @@ -164,6 +169,11 @@ "@types/bun": "catalog:", "@types/semver": "catalog:", "@typescript/native-preview": "catalog:", + "@yuuang/ffi-rs-darwin-arm64": "1.3.2", + "@yuuang/ffi-rs-linux-arm64-gnu": "1.3.2", + "@yuuang/ffi-rs-linux-x64-gnu": "1.3.2", + "@yuuang/ffi-rs-win32-arm64-msvc": "1.3.2", + "@yuuang/ffi-rs-win32-x64-msvc": "1.3.2", "vite": "catalog:", "vite-plugin-solid": "catalog:", }, diff --git a/packages/cli/package.json b/packages/cli/package.json index f848b56279..94a4b20aee 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -56,6 +56,16 @@ "@lydell/node-pty-linux-x64": "1.2.0-beta.12", "@lydell/node-pty-win32-arm64": "1.2.0-beta.12", "@lydell/node-pty-win32-x64": "1.2.0-beta.12", + "@ff-labs/fff-bin-darwin-arm64": "0.10.1", + "@ff-labs/fff-bin-linux-arm64-gnu": "0.10.1", + "@ff-labs/fff-bin-linux-x64-gnu": "0.10.1", + "@ff-labs/fff-bin-win32-arm64": "0.10.1", + "@ff-labs/fff-bin-win32-x64": "0.10.1", + "@yuuang/ffi-rs-darwin-arm64": "1.3.2", + "@yuuang/ffi-rs-linux-arm64-gnu": "1.3.2", + "@yuuang/ffi-rs-linux-x64-gnu": "1.3.2", + "@yuuang/ffi-rs-win32-arm64-msvc": "1.3.2", + "@yuuang/ffi-rs-win32-x64-msvc": "1.3.2", "@parcel/watcher-darwin-arm64": "2.5.1", "@parcel/watcher-linux-arm64-glibc": "2.5.1", "@parcel/watcher-linux-x64-glibc": "2.5.1", diff --git a/packages/cli/script/node-assets.ts b/packages/cli/script/node-assets.ts index cde31db13f..3f4823d823 100644 --- a/packages/cli/script/node-assets.ts +++ b/packages/cli/script/node-assets.ts @@ -37,6 +37,8 @@ export async function collectNodeAssets(target: NodeTarget) { ...(target.platform === "linux" ? { libc: "glibc" as const } : {}), }), { key: target.parcelWatcherAsset, source: fileURLToPath(import.meta.resolve(target.parcelWatcherPackage)) }, + { key: target.fffAsset, source: fileURLToPath(import.meta.resolve(target.fffPackage)) }, + { key: target.fffFfiAsset, source: fileURLToPath(import.meta.resolve(target.fffFfiPackage)) }, { key: photonWasmAsset, source: fileURLToPath(import.meta.resolve(photonWasmAsset)), diff --git a/packages/cli/src/node/target.ts b/packages/cli/src/node/target.ts index 097d74974f..f39db8f820 100644 --- a/packages/cli/src/node/target.ts +++ b/packages/cli/src/node/target.ts @@ -11,6 +11,8 @@ export function nodeTarget(platform: string, arch: string) { const targetArch = arch as "arm64" | "x64" const nodePtyPackage = `@lydell/node-pty-${targetPlatform}-${targetArch}` const parcelWatcherPackage = `@parcel/watcher-${targetPlatform}-${targetArch}${targetPlatform === "linux" ? "-glibc" : ""}` + const fffPackage = `@ff-labs/fff-bin-${targetPlatform}-${targetArch}${targetPlatform === "linux" ? "-gnu" : ""}` + const fffFfiPackage = `@yuuang/ffi-rs-${targetPlatform}-${targetArch}${targetPlatform === "linux" ? "-gnu" : targetPlatform === "win32" ? "-msvc" : ""}` return { platform: targetPlatform, @@ -19,6 +21,10 @@ export function nodeTarget(platform: string, arch: string) { nodePtyEntryAsset: `${nodePtyPackage}/lib/index.js`, parcelWatcherPackage, parcelWatcherAsset: `${parcelWatcherPackage}/watcher.node`, + fffPackage, + fffAsset: `${fffPackage}/${targetPlatform === "darwin" ? "libfff_c.dylib" : targetPlatform === "win32" ? "fff_c.dll" : "libfff_c.so"}`, + fffFfiPackage, + fffFfiAsset: `${fffFfiPackage}/ffi-rs.${targetPlatform}-${targetArch}${targetPlatform === "linux" ? "-gnu" : targetPlatform === "win32" ? "-msvc" : ""}.node`, } } diff --git a/packages/cli/vite.node.config.ts b/packages/cli/vite.node.config.ts index 15bcc8490a..da0c054106 100644 --- a/packages/cli/vite.node.config.ts +++ b/packages/cli/vite.node.config.ts @@ -30,6 +30,30 @@ function runtimeRequirePlugin(): Plugin { } } +function fffNodePlugin(): Plugin { + return { + name: "opencode:fff-node", + enforce: "pre", + transform(code, id) { + const normalized = id.replaceAll("\\", "/") + if (normalized.endsWith("/ffi-rs/index.js")) { + const start = code.indexOf("if (!nativeBinding) {") + if (start === -1) this.error("Failed to rewrite ffi-rs native binding loader") + return `const nativeBinding = globalThis.__OPENCODE_FFF_FFI +const loadError = undefined +${code.slice(start)}` + } + if (!normalized.endsWith("/fff-node/dist/src/binary.js")) return + const transformed = code.replace( + "export function findBinary() {", + "export function findBinary() { if (process.env.FFF_BINARY_PATH) return process.env.FFF_BINARY_PATH;", + ) + if (transformed === code) this.error("Failed to rewrite FFF binary loader") + return transformed + }, + } +} + const resolve = { alias: [ { find: /^solid-js\/store$/, replacement: "solid-js/store/dist/store.js" }, @@ -165,6 +189,9 @@ process.env.OTUI_ASSET_ROOT = __ocAssetRoot process.env.OPENCODE_NODE_PTY_PATH = __ocPath.join(__ocAssetRoot, ${JSON.stringify(input.target.nodePtyEntryAsset)}) process.env.OPENCODE_PARCEL_WATCHER_PATH = __ocPath.join(__ocAssetRoot, ${JSON.stringify(input.target.parcelWatcherAsset)}) process.env.OPENCODE_PHOTON_WASM_PATH = __ocPath.join(__ocAssetRoot, ${JSON.stringify(photonWasmAsset)}) +process.env.FFF_BINARY_PATH = __ocPath.join(__ocAssetRoot, ${JSON.stringify(input.target.fffAsset)}) +process.env.OPENCODE_FFF_FFI_PATH = __ocPath.join(__ocAssetRoot, ${JSON.stringify(input.target.fffFfiAsset)}) +globalThis.__OPENCODE_FFF_FFI = require(process.env.OPENCODE_FFF_FFI_PATH) globalThis.__OPENCODE_PHOTON_WASM_PATH = process.env.OPENCODE_PHOTON_WASM_PATH if (process.platform === "linux") process.env.OPENTUI_LIBC = "glibc"` } @@ -183,6 +210,7 @@ export function mainConfig(input: NodeBuildInput): UserConfig { plugins: [ rawTextPlugin(), runtimeRequirePlugin(), + fffNodePlugin(), solid({ solid: { generate: "universal",