Files
MailUI4Agents/plugins/homeagent-mail-bridge/build.sh
JianFeeeee 7e696f9a8c fix(homeagent): 撤回"另一条 SDK 血脉"的错误结论;build.sh 不再猜路径;清单判据改成一致性口径
pi 用只读文件系统逐条反驳了 357662e 的根因,三条我都验证并接受:

1. **"内核链 0.9.x 血脉"不成立 —— 那是我的搜索顺序造出来的事实。**
   本机有 6+ 份 `third_party/homeagent-sdk` checkout:
     /root/ha-test/…(0.9.0,C-ABI 时代,无 plugin.bin 支持)
     /var/tmp/rel-1.3.12/…、/var/tmp/rel-1.3.11/…(1.3.0)
     /var/tmp/release-main/…、/var/tmp/clean-check/…、/var/tmp/homed-p3/…(1.2.0)
   而 build.sh 第一版按候选根目录**第一个命中就算**,命中的正是 ha-test 那份老 checkout。
   内核自己用的是 1.3.0 那份,与钉子 `sdk/v1.3.0`、与 `<SDK_ROOT>/current` **一致**。
   两条教训写进注释了:别用"第一个存在的路径"当权威来源;别把模块版本字符串当身份
   (`replace => local (devel)` 时它只是 require 行的残留)。

2. **"API 不兼容"也是同一个错造成的。** 换成正确的 SDK 之后:
     HOMEAGENT_SDK_DIR=/root/.homeagent/hmapdev/sdk/v1.3.0 bash build.sh
     → hmapdev build 成功,产出 build/plugin.bin(9018271 字节)
   也就是说**这个插件在本机编得出来**,先前的 `SettingsAPI.DataDir` 报错是拿老 checkout 编的产物。

3. **判据把能工作的配置判红**(pi §2):第 4 步原先硬校验"产物 SDK 模块版本 == 内核模块版本",
   而生产上能跑的组合恰恰是"内核 + v1.3.0 编的插件"。已删掉这个相等性判据:
   SDK 源码**只认显式指定**(HOMEAGENT_SDK_DIR),不猜、不试探;
   内核那条 dep/=> 只作为**提示**打印(并且按模块名精确联接、只接受紧跟 SDK dep 行的 `=>`,
   不再取"输出里第一个 =>");身份改记 **realpath + 内容哈希**;
   `meta.Version` 读取先剥注释(注释里的 `Version = "9.9.9"` 不再能赢)。
   真正的不变量是 **wire 协议 protocol=2 + 一次真实握手**,写在脚本末尾(部署后回看日志)。

4. **清单判据改成一致性口径**(pi §5):不再"禁止 sdk 字段"——那会把正在工作的那份清单
   (/home/newqqagent/plugins/homeagent-mail-bridge/plugin.json 声明 sdk=1.3.0,正是 08:30
   那次恢复的处置动作)判红,而我没有"内核不读该字段"的证据。现在:可以不声明;
   声明了就必须与构建机指针一致。
2026-09-14 16:38:28 +08:00

98 lines
6.0 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# 构建 homeagent-mail-bridge —— 用**明确指定的** SDK 源码,并记录"这次到底用了哪份代码"。
#
# # 这份脚本被改过一轮因为它的第一版判错了根因pi 2026-09-14 晚逐条反驳)
#
# 第一版的错:把 `go version -m <内核>` 里的
# dep ... homeagent-sdk v0.9.2 / => ./third_party/homeagent-sdk (devel)
# 当成"内核链的是 0.9.x 血脉",然后按候选根目录**第一个命中就算**去解析 SDK 源码,
# 命中的是 `/root/ha-test/third_party/homeagent-sdk`C-ABI 时代的老 checkout无 plugin.bin 支持)。
# 而本机共有 6+ 份同名 checkout内核自己用的是 1.3.0 那份。两个教训:
#
# ① **不要用"第一个存在的路径"当权威来源** —— 猜根目录会命中不相关的 checkout
# "两条血脉"于是成了脚本的产物,而不是事实;
# ② **不要把模块版本字符串当身份** —— `replace => local (devel)` 时那个版本号
# 只是 require 行的文本残留,不代表实际编译的代码。
#
# 所以现在SDK 源码**只认显式指定**`HOMEAGENT_SDK_DIR`)。
# 不猜、不试探、不"第一个命中"。要指定内核的构建目录就显式传进来。
#
# # 不变量是什么
#
# 不是"版本号相等"(那正是第一版想抛弃的东西),而是 **wire 协议 + 一次真实握手**
# 产物要能被内核 `protocol=2` 认下来。这个脚本能做的是"把身份记清楚 + 把明显不对的挡下来"
# 真握手由内核启动时完成(所以部署后要回看一次日志,见末尾提示)。
set -euo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SDK_MODULE="gitcode.com/JianFeeeee/homeagent-sdk"
KERNEL_BIN="${HOMEAGENT_KERNEL_BIN:-/usr/local/bin/homed}"
die() { echo "构建失败:$*" >&2; exit 1; }
# cron/非登录 shell 里 HOME 可能没设Go 会因此拒绝工作(曾经在这里栽过)
export HOME="${HOME:-/root}"
export GOPATH="${GOPATH:-$HOME/go}"
export GOCACHE="${GOCACHE:-${TMPDIR:-/tmp}/go-build-agentmail}"
mkdir -p "$GOCACHE"
# ── 1. SDK 源码:只认显式指定 ───────────────────────────────────────
[[ -n "${HOMEAGENT_SDK_DIR:-}" ]] || die "必须显式指定 SDK 源码树HOMEAGENT_SDK_DIR=/path/to/homeagent-sdk
为什么不让脚本自己猜:本机有 6+ 份同名 checkout有的是 C-ABI 时代的老代码),
第一版按候选根目录'第一个命中就算',命中了 /root/ha-test 那份老 checkout
于是把'内核链老血脉'这个**错误结论**当成了事实写进注释。猜路径 = 制造事实。"
SDK_DIR="$(cd "$HOMEAGENT_SDK_DIR" && pwd)"
[[ -f "$SDK_DIR/go.mod" ]] || die "$SDK_DIR 不是 Go 模块(没有 go.mod"
# 身份用 **realpath + 内容哈希**,不用版本字符串(版本号可能是 -ldflags 注入的默认值,
# 也可能是注释里的示例 —— 后者我在 electron 侧的判据里刚踩过一次)。
SDK_HASH="$(find "$SDK_DIR" -type f -name '*.go' -print0 2>/dev/null | sort -z | xargs -0 cat 2>/dev/null | sha256sum | cut -c1-16)"
SDK_VER="$(sed 's://.*::' "$SDK_DIR/meta/meta.go" 2>/dev/null | grep -m1 -oE 'Version = "[0-9]+\.[0-9]+\.[0-9]+"' | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' || true)"
echo "[build] SDK 源码:$SDK_DIR"
echo "[build] meta.Version已剥注释= ${SDK_VER:-未知} 内容哈希 = ${SDK_HASH:-未知}"
# 内核签名的**提示**(不是判据):按模块名精确联接,不按"输出里第一个 =>"。
# "两张表各缺一半时必须按 id 联接"—— 读 go version -m 的输出同理。
if [[ -x "$KERNEL_BIN" ]]; then
KERNEL_INFO="$(go version -m "$KERNEL_BIN" 2>/dev/null || true)"
KERNEL_SDK_LINE="$(awk -v m="$SDK_MODULE" '$1=="dep" && $2==m {print NR": "$0}' <<<"$KERNEL_INFO" | head -1)"
if [[ -n "$KERNEL_SDK_LINE" ]]; then
KERNEL_SDK_DEP="$(cut -d' ' -f3 <<<"${KERNEL_SDK_LINE#*: }")"
# 只接受**紧跟在 SDK 那一行之后**的 => 行(按位置配对的唯一正确写法)
KERNEL_SDK_REPL="$(awk -v m="$SDK_MODULE" '
$1=="dep" && $2==m {want=NR+1}
want && NR==want && $1=="=>" {print $2; exit}' <<<"$KERNEL_INFO")"
echo "[build] 内核 $KERNEL_BIN 的 dep 行:$KERNEL_SDK_DEP${KERNEL_SDK_REPL:+(本地替换 $KERNEL_SDK_REPL}"
echo "[build] 注意:这条只是**提示**,不是判据 —— replace 到本地目录时这个版本号只是 require 行的残留,"
echo "[build] 而且它指向的相对路径未必是本机这份源码。要对齐请显式传 HOMEAGENT_SDK_DIR。"
fi
fi
# ── 2. 用临时 modfile 替换,不改动受版本管理的 go.mod ───────────────
cd "$HERE"
TMP_MOD="$(mktemp -d)/go.local.mod"
cp go.mod "$TMP_MOD"
go mod edit -modfile="$TMP_MOD" -replace "$SDK_MODULE=$SDK_DIR"
export GOFLAGS="${GOFLAGS:-} -modfile=$TMP_MOD"
# 注意:这个插件**没有** `func main()`(入口由 hmapdev 生成/包装),
# 所以 `go build ./...` 会报 "function main is undeclared" —— 那是正常的,
# 不能用它来数 API 兼容性错误;真正的编译在 hmapdev 那一步。
hmapdev build || die "hmapdev build 失败(编译错误见上;它才是真正的编译入口)"
# ── 3. 产物自报身份 ─────────────────────────────────────────────────
BIN="build/plugin.bin"
[[ -f "$BIN" ]] || die "没找到产物 $BIN"
echo "[build] 产物:$BIN$(stat -c%s "$BIN") 字节)"
echo "[build] 本次身份SDK=$SDK_DIR hash=$SDK_HASH version=${SDK_VER:-未知}"
cat > build/BUILD_INFO.txt <<EOF
sdkDir=$SDK_DIR
sdkHash=$SDK_HASH
sdkMetaVersion=${SDK_VER:-unknown}
builtAt=$(date -Iseconds)
EOF
echo "[build] 已写 build/BUILD_INFO.txt —— 部署后请回看内核日志确认握手:"
echo " grep -a 'mail-bridge' /home/newqqagent/log/homed_*.log | tail -5"
echo " (判据不是版本号相等,而是 protocol=2 建链成功、且没有崩溃重启循环)"