chore(release): bump v1.0.4

v1.0.3 之后 release 线合入了两个修复(崩溃隔离测试误杀生产实例、
两处数据竞争),按发布流程第②步把版本号推进到 1.0.4。

同步更新:
  - internal/meta/meta.go    Version 1.0.3 → 1.0.4
  - deploy/packaging/installer.nsi   PRODUCT_VERSION 1.0.4
  - README.md / README_EN.md 项目状态加 v1.0.4 条目、下载文件名更新

SDKCompatibleVersion 保持 1.0.0:本版只改内核并发正确性,插件 ABI/
协议未变,存量 plugin.bin 无需重编。

此提交不 pick 回 main(main 版本号始终是下一个未发布版本)。
This commit is contained in:
JianFeeeee
2026-09-05 07:26:01 +08:00
parent eb02f00998
commit 208d39c296
4 changed files with 8 additions and 4 deletions

View File

@ -193,6 +193,8 @@ internal/
## 项目状态
**v1.0.4** — 两处数据竞争修复(现网 `/api/v1/device/ws` 通道与终端推流)。此前 `-race` 全仓复验即暴露:`remotedevice` 网关对同一连接的 `bufio.Writer` 由两条路径并发写(`handleWS` 主循环回写 hello_ack/绑定回执/pong`PushJSON`/`PushData` 的 agent→设备下发`bufio.Writer` 非线程安全,`TestWSPushDataAudio` 异步下发即稳定撞车;`agentcli` 终端把共享读缓冲传给 reader goroutineOS 层持续覆写)又在 `readLoop``copy(data, buf[:r.n])`,读写并发。修法:连接级写锁(`wconn.wmu`Push* 与 handleWS 共用同一把锁,`PushData` 整条下发持锁保证协议顺序)与「读结果随 `readResult` 自带切片传递、不再共享缓冲」。全仓 `go test ./... -race` 由 7 处 race / 5 个测试 FAIL 变为 32 包全绿。
**v1.0.3** — 内核 stage 协调器双重解锁修复。现网 homed 主进程曾一次 `fatal error: sync: unlock of unlocked mutex` 整体死亡(带走全部 27 个子进程插件):`Host.endStage` 把「递减 inflight、判定最后离开者」放在 `coordMu` 临界区之外,而摘除协调器在临界区之内,于是后到插件能挂进一个正在收尾的协调器、被误判成最后离开者,对同一把 `stageMu` 解了两次。**`sync.Mutex` 双重解锁是 runtime fatal 而非 panic两层 `recover` 结构上拦不住**,这才让「插件崩溃不拖垮内核」的隔离设计整体失效。修法是把计数、判定、摘除收进同一临界区,并把首进者写共享段的 `enter()` 也移入锁内(此前后到者可能读到写一半的段)。配套 5 个回归用例,含把旧实现 stash 回来验证测试确实能复现 fatal 的反向验证。
**v1.0.1** — 多模态 bugfix。插件 ABI/协议未变1.0.0 编出的 `plugin.bin` 无需重编。修三类缺陷1**看图假成功**——媒体块挂在 tool message 上不被模型当作可视内容实测同一张图tool message 0/3 读到、独立 user message 3/3改为另起一条紧随其后的 user message 承载落实插件文案一直在说的「注入后续对话」2**新增多模态能力声明与回退链**——`core.llm.sources.<name>.vision/.audio` 声明源能否真正处理媒体(网关会静默剥离 `image_url` 后仍返回 200带图与不带图 prompt_tokens 完全相同),不支持时自动走视觉源转写成文字,并落实了 `core.input_processing.image.fallback_provider` 这批早已注册却从未被读取的配置项3**`see_video` 帧数语义反了**——`fps=1/N` 是频率不是数量20s 视频请求 10 帧只得 2 帧、请求 1 帧反得 20 帧,改为 `ffprobe` 取时长 + `fps=N/时长` + `-frames:v` 硬封顶。
@ -222,7 +224,7 @@ internal/
| **client** | waiter + 桌面 GUI | 连接远程 HomeAgent |
- Linux`.deb`amd64/arm64)、`.rpm`x86_64)、`.tar.gz`
- Windows`HomeAgent_v1.0.3_{Full,Server,Client}_win64.exe`NSIS 安装向导
- Windows`HomeAgent_v1.0.4_{Full,Server,Client}_win64.exe`NSIS 安装向导
- 免安装`homeagent-bin-<os>_<arch>.tar.gz` homed/waiter/initconfig
- 校验`SHA256SUMS`

View File

@ -179,6 +179,8 @@ External plugin development: see [homeagent-sdk](https://gitcode.com/JianFeeeee/
## Project Status
**v1.0.4** — Two data-race fixes (the live `/api/v1/device/ws` gateway and terminal streaming). A full `-race` pass exposed both: `remotedevice` wrote one connection's `bufio.Writer` from two concurrent paths (`handleWS` loop replies hello_ack/bind_ack/pong, plus `PushJSON`/`PushData` agent→device pushes) — `bufio.Writer` is not thread-safe, and `TestWSPushDataAudio` async push hit it reliably; `agentcli` handed the shared read buffer to the reader goroutine (which the OS keeps overwriting) while `readLoop` did `copy(data, buf[:r.n])` — concurrent read/write of the same buffer. Fix: connection-level write lock (`wconn.wmu`, shared by Push* and handleWS; `PushData` holds it across the whole start/chunks/end sequence to preserve protocol order) plus carrying read results in per-result slices instead of a shared buffer. Repo-wide `go test ./... -race` went from 7 races / 5 failing tests to all-clean.
**v1.0.3** — Kernel stage-coordinator double-unlock fix. The production `homed` main process once died outright with `fatal error: sync: unlock of unlocked mutex`, taking all 27 subprocess plugins with it: `Host.endStage` performed "decrement inflight, decide whether I'm the last leaver" *outside* the `coordMu` critical section while detaching the coordinator *inside* it, so a late-arriving plugin could attach to a coordinator that was already finishing, be misjudged as the last leaver, and unlock the same `stageMu` twice. **A `sync.Mutex` double unlock is a runtime fatal, not a panic, so the two layers of `recover` structurally cannot catch it**—which is exactly why the "a crashing plugin must not take down the kernel" isolation design failed wholesale here. The fix folds counting, decision, and detach into one critical section, and also moves the first arriver's `enter()` (which writes the shared segment) inside the lock—previously a late arriver could read a half-written segment. Ships with 5 regression cases, including a reverse check that stashes the old implementation back to confirm the tests really do reproduce the fatal.
**v1.0.1** — Multimodal bugfix. The plugin ABI/protocol is unchanged, so `plugin.bin` artifacts built for 1.0.0 need no rebuild. Three defects fixed: (1) **vision silently failing**—media blocks attached to a tool message are not treated as viewable content by the model (measured on one image: 0/3 read from a tool message, 3/3 from a standalone user message); media now rides its own user message placed immediately after, which is what the plugin's own wording ("injected into the following conversation") always claimed; (2) **new multimodal capability declaration + fallback chain**`core.llm.sources.<name>.vision/.audio` declares whether a source can genuinely process media (a gateway may strip `image_url` and still return 200, with identical prompt_tokens with and without the image); when it cannot, media is transcribed to text via a vision-capable source, finally wiring up the long-registered but never-read `core.input_processing.image.fallback_provider` settings; (3) **`see_video` frame-count semantics were inverted**—`fps=1/N` is a *rate*, not a count, so a 20s video yielded 2 frames when 10 were requested and 20 frames when 1 was requested; now `ffprobe` measures duration and the filter becomes `fps=N/duration` with `-frames:v` as a hard cap.
@ -208,7 +210,7 @@ External plugin development: see [homeagent-sdk](https://gitcode.com/JianFeeeee/
| **client** | waiter + desktop GUI | Connecting to a remote HomeAgent |
- Linux: `.deb` (amd64/arm64), `.rpm` (x86_64), `.tar.gz`
- Windows: `HomeAgent_v1.0.3_{Full,Server,Client}_win64.exe` (NSIS installer)
- Windows: `HomeAgent_v1.0.4_{Full,Server,Client}_win64.exe` (NSIS installer)
- Portable: `homeagent-bin-<os>_<arch>.tar.gz` (homed/waiter/initconfig)
- Verification: `SHA256SUMS`

View File

@ -14,7 +14,7 @@
# 此前硬编码 0.8.0 而 release 已到 1.0.0,装出来的包在「添加/删除程序」里
# 会显示错误版本DisplayVersion 也取自这个宏)。
!ifndef PRODUCT_VERSION
!define PRODUCT_VERSION "1.0.3"
!define PRODUCT_VERSION "1.0.4"
!endif
!if "${VARIANT}" == "full"

View File

@ -13,7 +13,7 @@ var (
//
// 1.0.1:多模态修复。仅内核与内置插件改动,插件 ABI/协议未变,
// 1.0.0 编出的 plugin.bin 无需重编。
Version = "1.0.3"
Version = "1.0.4"
// Commit 是构建时的 Git commit hash。
Commit = "unknown"