feat(cli): add Node runtime bootstrap

This commit is contained in:
Simon Klee
2026-07-10 09:36:21 +02:00
parent 0c2efdbf5c
commit f145d8040e
6 changed files with 139 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
import path from "node:path"
import { fileURLToPath } from "node:url"
import { webTreeSitterWasmAsset } from "./target"
const root = process.env.OPENCODE_NODE_ASSETS_DIR ?? fileURLToPath(new URL("./assets/", import.meta.url))
export function resolveNodeAsset(asset: string) {
return path.join(root, asset)
}
export function resolveOpenTuiAsset(relative: string) {
return resolveNodeAsset(`@opentui/core/${relative}`)
}
export function resolveWebTreeSitterWasm() {
return resolveNodeAsset(webTreeSitterWasmAsset)
}
+3
View File
@@ -0,0 +1,3 @@
import "./plugin-runtime.promise"
import "./plugin-runtime.effect"
import "../index"
+4
View File
@@ -0,0 +1,4 @@
import { opentuiNativeAsset } from "./target"
import { resolveNodeAsset } from "./assets.node"
export default await resolveNodeAsset(opentuiNativeAsset)
@@ -0,0 +1,28 @@
import {
Agent,
Command,
Connection,
Credential,
Integration,
Model,
Plugin,
Provider,
Reference,
Skill,
} from "@opencode-ai/plugin/v2/effect"
import { Tool } from "@opencode-ai/plugin/v2/effect/tool"
const key = Symbol.for("opencode.plugin.v2.effect")
;(globalThis as typeof globalThis & { [key]?: unknown })[key] = {
Agent,
Command,
Connection,
Credential,
Integration,
Model,
Plugin,
Provider,
Reference,
Skill,
Tool,
}
@@ -0,0 +1,26 @@
import {
Agent,
Command,
Connection,
Credential,
Integration,
Model,
Plugin,
Provider,
Reference,
Skill,
} from "@opencode-ai/plugin/v2"
const key = Symbol.for("opencode.plugin.v2.promise")
;(globalThis as typeof globalThis & { [key]?: unknown })[key] = {
Agent,
Command,
Connection,
Credential,
Integration,
Model,
Plugin,
Provider,
Reference,
Skill,
}
+61
View File
@@ -0,0 +1,61 @@
const nativeLibraries = {
darwin: "libopentui.dylib",
linux: "libopentui.so",
win32: "opentui.dll",
} as const
export type NodeTarget = ReturnType<typeof nodeTarget>
export function nodeTarget(platform: string, arch: string) {
if (!(platform in nativeLibraries) || (arch !== "arm64" && arch !== "x64")) {
throw new Error(`Unsupported Node executable target: ${platform}-${arch}`)
}
const targetPlatform = platform as keyof typeof nativeLibraries
const targetArch = arch as "arm64" | "x64"
const opentuiNativePackage = `@opentui/core-${targetPlatform}-${targetArch}`
const nodePtyPackage = `@lydell/node-pty-${targetPlatform}-${targetArch}`
const parcelWatcherPackage = `@parcel/watcher-${targetPlatform}-${targetArch}${targetPlatform === "linux" ? "-glibc" : ""}`
return {
platform: targetPlatform,
arch: targetArch,
opentuiNativePackage,
opentuiNativeAsset: `${opentuiNativePackage}/${nativeLibraries[targetPlatform]}`,
nodePtyPackage,
nodePtyEntryAsset: `${nodePtyPackage}/lib/index.js`,
parcelWatcherPackage,
parcelWatcherAsset: `${parcelWatcherPackage}/watcher.node`,
}
}
const target = nodeTarget(process.platform, process.arch)
export const opentuiNativePackage = target.opentuiNativePackage
export const opentuiNativeAsset = target.opentuiNativeAsset
export const opentuiParserWorkerAsset = "@opentui/core/parser.worker.js"
export const webTreeSitterWasmAsset = "web-tree-sitter/tree-sitter.wasm"
export const photonWasmAsset = "@silvia-odwyer/photon-node/photon_rs_bg.wasm"
export const nodeExecArgv = ["--experimental-ffi", "--use-system-ca", "--disable-warning=ExperimentalWarning"] as const
export const opentuiParserAssets = [
"@opentui/core/assets/javascript/highlights.scm",
"@opentui/core/assets/javascript/tree-sitter-javascript.wasm",
"@opentui/core/assets/typescript/highlights.scm",
"@opentui/core/assets/typescript/tree-sitter-typescript.wasm",
"@opentui/core/assets/markdown/highlights.scm",
"@opentui/core/assets/markdown/tree-sitter-markdown.wasm",
"@opentui/core/assets/markdown/injections.scm",
"@opentui/core/assets/markdown_inline/highlights.scm",
"@opentui/core/assets/markdown_inline/tree-sitter-markdown_inline.wasm",
"@opentui/core/assets/zig/highlights.scm",
"@opentui/core/assets/zig/tree-sitter-zig.wasm",
] as const
export const attentionSoundAssets = [
"@opencode-ai/ui/audio/bip-bop-01.mp3",
"@opencode-ai/ui/audio/bip-bop-03.mp3",
"@opencode-ai/ui/audio/staplebops-06.mp3",
"@opencode-ai/ui/audio/nope-03.mp3",
"@opencode-ai/ui/audio/yup-01.mp3",
] as const