将 opencode(终端 AI 编码智能体)移植到 OpenHarmony 标准系统。
-
opencode v1.18.31 是 TypeScript on Bun 的单二进制应用(TUI/web/核心全部 TS),而 OpenHarmony 用户态是 musl libc,无 Bun、无官方 Node
-
本移植的做法:opencode 源码打补丁后打包为 Node.js 目标的纯 JS bundle;用 OHOS 工具链交叉编译 Node.js v26.8.2(
x86_64-linux-ohos),二者都推到鸿蒙上原生运行 -
改动极小:opencode 侧 7 个文件 + 1 个新文件(约 90 行),另有 bundle 阶段的 2 个 stub 与 1 个外部分发依赖,已固化为可复现脚本
-
✅ 已在 OpenHarmony 7.0.0.39(x86_64,VMware 虚拟机)上端到端验证:
- 交叉编译的
node在设备上原生运行(v26.8.2 openharmony x64,node:sqlite可用) opencode serve监听0.0.0.0:15000,/global/health→{"healthy":true,"version":"local"}- 完整对话链路跑通:prompt → 设备上 opencode → 设备上 llama-server → Qwen2.5 → 返回
OPENCODE-ON-OHOS-WORKS opencode run(非交互 CLI)在设备上返回RUN-OK- web UI 正常返回 HTML(HTTP 200,
<title>OpenCode</title>) - ripgrep 14.1.1 在设备上运行正常(补上 README 原先的已知缺口)
- 详细记录见 docs/verification.md,原始日志见 logs/
- 交叉编译的
鸿蒙设备 (OpenHarmony 7.0, x86_64)
├── ohos-node (bin/node) ← 本仓 ohos-node/build-x86_64.sh 交叉编译
├── opencode bundle (index.js + wasm) ← 本仓 bundle/build-bundle.sh 打包
│ └── serve 0.0.0.0:15000 ← agent/会话/HTTP API 全部在本机
├── opencode.json → llama-server:8080 ← 模型也在这台鸿蒙机器上(llama.cpp 移植)
└── 客户端三选一:
· 浏览器开 http://<设备IP>:15000 ← opencode 自带 web UI
· 另一台机器 opencode attach http://<设备IP>:15000
· 设备本机 node index.js run "..." ← 纯 CLI 非交互模式
上游 Node 的构建系统已支持 --dest-os=openharmony(OpenHarmony-SIG 社区验证于 arm64),本仓将其扩展到 x86_64:LLVM-19(OHOS clang)+ --openssl-no-asm 交叉编译,产物动态链接系统 musl(同 llama.cpp 移植,除 libc 外无其他依赖)。
运行时两个要点(实测得出,部署脚本已内置):
OPENSSL_CONF=/dev/null必须设置。OHOS 镜像带/etc/ssl/certs但没有/etc/ssl/openssl.cnf,Node 启动时 OpenSSL 会因找不到该文件而直接报错退出:指向OpenSSL configuration error: ... calling fopen(/etc/ssl/openssl.cnf, rb)/dev/null即可正常启动(opencode 走 HTTP 到本机 llama-server,不需要 OpenSSL 配置)。libc++_shared.so无需额外部署。产物 NEEDED 里有libc++_shared.so,但 OHOS 系统自带/system/lib64/libc++_shared.so(1.3 MB),实测可直接加载。
opencode 侧的 Bun 依赖实测面很小:
| 依赖 | 数量 | 处理 |
|---|---|---|
bun:sqlite(运行时) |
2 处 | #db/#sqlite 条件导入本身就有 node 变体(node:sqlite),补丁把 default 指向它 |
bun:ffi(运行时) |
1 处 | 仅 win32 终端控制,bundle stub 兜底 |
Bun.* 全局 API |
31 处 | 一个 55 行 prelude polyfill(stringWidth/hash/stdin.text) |
from "bun" 导入 |
3 处 | 改为 node:url(对 Bun 无副作用) |
| 动态 require 的包 | 1 个 | jsonc-parser 以 --external + 随包分发 |
- OpenHarmony SDK(native + toolchains):同 llama.cpp 移植(见
E:\移植\port-package\README.md第二节)。 - WSL Ubuntu 24.04(或任意 Linux):Node 交叉编译宿主,需 16GB+ 磁盘(LLVM-19 + node 源码 + 构建产物)。
- Bun + Node.js 22.5+(Windows/Linux 均可):打包宿主。
# 1) 交叉编译 Node for OpenHarmony x86_64(WSL 内,约 20-40 分钟)
cd ~/ohos-node-x64 && cp <port>/ohos-node/build-x86_64.sh . && sh build-x86_64.sh
# 产物: ~/ohos-node-x64/node-v26.8.2-openharmony-x86_64/bin/node
# 2) 打包 opencode bundle(任意有 Bun+Node 的主机)
cd <port>/bundle && ./build-bundle.sh v1.18.31
# 产物: <port>/bundle/dist-ohos/不想自己编译? 预编译产物在 Releases:
node-v26.8.2-openharmony-x86_64.tar.gz(Node 运行时,交叉编译约需 20–40 分钟)与opencode-bundle-ohos-x86_64.tar.gz(opencode bundle)。下载后直接跳到下面第 2 步。
export PATH="/e/移植/ohos-sdk/toolchains:$PATH"
hdc tconn <设备IP>:5555
cd <port>/deploy
NODE_TARBALL=~/ohos-node-x64/node-v26.8.2-openharmony-x86_64.tar.gz \
./deploy-ohos.sh <设备IP>:5555
# 自动完成:推 node+bundle → 解压 → 启动 server(0.0.0.0:15000) → hdc fport → 健康检查模型:设备上跑 llama-server(见 llama.cpp 移植仓),把 opencode.json.example 放到设备的项目目录。
注意 -c 要给足:opencode 的 system prompt + 工具定义约 7800 token,-c 小于此值会导致 prompt 被截断、模型只输出无意义模板。已验证可用的配置是 -c 16384:
# 设备上启动模型服务(务必真正脱离 hdc 会话,否则会话一结束进程就被杀)
hdc shell "cd /data/local/tmp/llama && \
setsid OPENSSL_CONF=/dev/null ./llama-server \
-m qwen2.5-0.5b-instruct-q4_0.gguf --host 127.0.0.1 --port 8080 -c 16384 \
> server.log 2>&1 < /dev/null"opencode 与 llama-server 跑在同一台设备上,所以 opencode.json 里用 http://127.0.0.1:8080/v1 即可(见 test-proj/opencode-local.json)。
hdc file send opencode.json /data/local/tmp/opencode/proj/
# 本机对话(非交互):重定向到文件,不要依赖 hdc shell 的终端回显
hdc -t <IP>:5555 shell "cd /data/local/tmp/opencode/proj && \
HOME=/data/local/tmp/opencode/home OPENSSL_CONF=/dev/null \
/data/local/tmp/opencode/node/bin/node \
/data/local/tmp/opencode/bundle/index.js run '用一句话介绍你自己' < /dev/null"实测提示:
opencode run的输出走 TUI 渲染,直接经hdc shell回传时转义序列会被吞掉、看起来像"卡住"。重定向到文件再cat即可看到正常结果(见logs/device-run.log)。
- 首轮对话很慢(约 5 分钟):opencode 的 system prompt + 工具定义约 7800 token,而设备上 Qwen2.5-0.5B 纯 CPU 的 prompt 处理只有 ~24 tok/s。这是模型/硬件规模问题,不是移植缺陷。缓解手段:
- llama-server 已带 prompt cache,第二轮起只处理增量(实测 7806 → 仅 2900 新 token)
- 换更小的 agent 配置(
agent/mode里裁减工具集)可显著降低 prompt 长度 - 用更大的机器或更小的模型才谈得上流畅交互
- TUI 全屏界面(
opencode/attach的交互终端)依赖@opentui/solid与可靠的 PTY;hdc shell 的 PTY 支持待实测。web UI 与 CLIrun已确认可用 - 设备上无 git 时项目识别能力降级
x86_64面向标准系统 PC/虚拟机;arm64 真机可直接用 hqzing/ohos-node 官方预构建包替换本仓的 node 构建- Node 交叉编译脚本未做签名步骤(
binary-sign-tool);若目标镜像强制签名校验,用 SDK toolchains 里的工具对bin/node自签 - 已解决(原列于本节):
Grep 工具缺 ripgrep→dist/bin/rg(Rustx86_64-unknown-linux-ohos交叉编译)实测在设备上正常,rg --version→ 14.1.1libc++ 运行时依赖→ OHOS 系统自带/system/lib64/libc++_shared.so,无需部署
- opencode 补丁(
patches/0001-*.patch)本质是 Node 运行时兼容修复,与上游进行中的 Node 兼容方向一致,可整理后提 PR - Node for OHOS x86_64 构建脚本可回馈 hqzing/ohos-node(上游目前只发 arm64 预构建包);另建议上游在 README 记录
OPENSSL_CONF=/dev/null这一 OHOS 运行时要求
本移植的补丁与脚本遵循 opencode 的上游许可(MIT)。