diff --git a/README.md b/README.md index d1577f0..f86a2c7 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ homed(内核零 IO) ← PluginSDK → 插件(所有 IO 能力) ``` +**v1.1.1 起媒体贯通插件边界**:插件与模型都能读写记忆里的图片/音频(`InsertWithMedia`、`InjectInputMedia`),媒体以 `[ <短digest>] <描述>` 标记存在于纯文本记忆中——描述是可检索的语义记忆,digest 是回到字节的钥匙。 + **v1.0.0 起外部插件是独立子进程**:经 stdio JSON-RPC(控制面)+ 共享内存段(数据面)+ 事件环(通知面)与内核通信。插件崩溃不影响内核且自动重启,换 `plugin.bin` 即生效的真热重载。 ## 设计要点 @@ -193,6 +195,10 @@ internal/ ## 项目状态 +**v1.1.1** — 多模态贯通**插件边界**。v1.1.0 让记忆系统支持了二进制多媒体节点,但那条链路只对内核自己开放;本版打通到插件与模型。公开 SDK 新增媒体字段与三个媒体注入接口(配套 [SDK v1.1.0](https://gitcode.com/JianFeeeee/homeagent-sdk/releases/tag/v1.1.0),整条 1.1.x 线共用),内核实现对应四个 RPC。桥接层此前在**静默裁字段**:插件交进来的 `Confidence`/类型/`SentenceText` 全被丢弃、`Doc` 只留三个字段、`Remove` 不解引用(媒体永久算「被引用」,GC 收不掉)。`processTextInput`/`processMediaInput` 归一成一条 `processInput`,媒体路径由此获得它一直缺的去重、`no_memory`、通道 `Cleaner`、中断语义、`EventRawInput`。修掉三处真实缺陷:**用户发的图从来没出现在 WebUI 聊天记录里**(媒体路径发布 map 而订阅方断言 string)、**`memory_commit` 的 `sentence_text` 从未暴露给模型**(而它是媒体绑定链的必经环节)、**`PluginSDK` 两处并发竞态**(`-race` 实测 11 处,插件重载瞬间偶发 nil 解引用崩溃)。 + +**v1.1.0** — 记忆系统支持**二进制多媒体节点**。内容寻址媒体存储(CAS + SQLite 元数据 + 磁盘 blob,`Get` always 重校 digest),贯通 L0(上下文事件)/L2(文档)/L3(图谱句子)三层,引用计数式 GC(有引用者绝不删)。视觉模型生成的描述文本是持久语义记忆,blob 只是可被容量 GC 淘汰的缓存。 + **v1.0.0** — 外部插件从 C ABI 动态库迁移到**子进程 + 共享内存**。首个不再加载 `.so`/`.dll` 的版本,与 0.9.x 不兼容(存量插件须用新版 `plugindev` 重编为 `plugin.bin`,**业务代码零改动**)。消除 6 类此前在生产造成故障的缺陷:热重载失效(`DF_1_NODELETE` 让 `dlclose` 成 no-op)、崩溃隔离缺失(插件 panic 带崩 homed)、stage lost update(副本模型丢失 35.8~36.8%)、cgo 超时不可中断(线程线性泄漏)、`output_send` 假成功(模型收到「已发送」而消息未送达)、Windows 能力断层(只见 3 个 stage 字段且无法写回)。三面通信:stdio JSON-RPC(控制)+ 共享内存段(数据)+ 事件环(通知);权限梯度显式化为三道闸。RPC 往返 p50 24.1µs,崩溃到恢复 <1s。 **v0.9.0** — C ABI v2:外部插件 Stage 回调支持写回(`invoke_stage` 增加 result 输出,插件可在 OnInput/AfterToolcall/PostAction 修改 RawMessage/LLMText/ToolResults 等并同步回内核),ABI 版本随内核 minor 对齐(v0.9.x → ABIVersion=2,`version_min=1` 向后兼容旧插件)。同步修复工具循环 zen 兼容补位误伤首轮 system 上下文的问题。配套 SDK 提供增强版 sanitizer 示例(坏 UTF-8/U+FFFD/ANSI 转义全链路清洗)。**该 ABI 已随 v1.0.0 退场。** @@ -218,7 +224,7 @@ internal/ | **client** | waiter + 桌面 GUI | 连接远程 HomeAgent | - Linux:`.deb`(amd64/arm64)、`.rpm`(x86_64)、`.tar.gz` -- Windows:`HomeAgent_v1.0.0_{Full,Server,Client}_win64.exe`(NSIS 安装向导) +- Windows:`HomeAgent_v1.1.1_{Full,Server,Client}_win64.exe`(NSIS 安装向导) - 免安装:`homeagent-bin-_.tar.gz`(含 homed/waiter/initconfig) - 校验:`SHA256SUMS` diff --git a/README_EN.md b/README_EN.md index afecc8f..d0f9d9f 100644 --- a/README_EN.md +++ b/README_EN.md @@ -12,6 +12,11 @@ Combined with a **three-layer memory architecture** (Context → Document → Gr homed (kernel, zero IO) ← PluginSDK → plugins (all IO capabilities) ``` +**Since v1.1.1 media reaches the plugin boundary**: plugins and the model can both read and +write images/audio in memory (`InsertWithMedia`, `InjectInputMedia`). Media lives in plain-text +memory as a `[ ] ` marker — the description is the searchable +semantic memory, the digest is the key back to the bytes. + **Since v1.0.0 external plugins are independent subprocesses**, communicating with the kernel over stdio JSON-RPC (control plane) + a shared memory segment (data plane) + an event ring (notification plane). A plugin crash cannot take down the kernel and it restarts automatically; swapping @@ -179,6 +184,28 @@ External plugin development: see [homeagent-sdk](https://gitcode.com/JianFeeeee/ ## Project Status +**v1.1.1** — Multimodal reaches the **plugin boundary**. v1.1.0 gave the memory system binary +multimedia nodes, but that path was open only to the kernel itself; this release opens it to +plugins and the model. The public SDK gains media fields and three media injection methods +(paired with [SDK v1.1.0](https://gitcode.com/JianFeeeee/homeagent-sdk/releases/tag/v1.1.0), +shared by the whole 1.1.x line), and the kernel implements the four matching RPCs. The bridge +layer had been **silently dropping fields**: `Confidence`/types/`SentenceText` handed in by a +plugin were discarded, `Doc` kept only three fields, and `Remove` never released references +(media stayed "referenced" forever, so GC could never reclaim it). `processTextInput` and +`processMediaInput` were unified into a single `processInput`, which finally gives the media +path the dedup, `no_memory`, channel `Cleaner`, interrupt semantics and correct `EventRawInput` +it had always lacked. Three real defects fixed: **user-sent images never appeared in the WebUI +chat log** (the media path published a map while the subscriber asserted a string), +**`memory_commit`'s `sentence_text` had never been exposed to the model** (though it is the +mandatory link in the media binding chain), and **two data races in `PluginSDK`** (11 reported +by `-race`; in production this showed up as sporadic nil-dereference crashes during plugin reload). + +**v1.1.0** — Memory system supports **binary multimedia nodes**. Content-addressed media store +(CAS + SQLite metadata + on-disk blobs, `Get` always re-verifies the digest) wired through L0 +(context events) / L2 (documents) / L3 (graph sentences), with reference-counted GC (referenced +items are never deleted). The description text produced by the vision model is the durable +semantic memory; the blob is only a cache that capacity GC may evict. + **v1.0.0** — External plugins moved from C ABI shared libraries to **subprocess + shared memory**. The first release that no longer loads `.so`/`.dll`, and it is incompatible with 0.9.x (existing plugins must be rebuilt into `plugin.bin` with the new `plugindev`, though **business code needs zero changes**). Eliminates 6 classes of defects that had caused production incidents: hot-reload silently failing (`DF_1_NODELETE` making `dlclose` a no-op), no crash isolation (a plugin panic took down homed), stage lost updates (35.8~36.8% loss under the copy model), uncancellable cgo timeouts (linear OS-thread leaks), `output_send` reporting false success (the model was told "sent" while the message never went out), and Windows capability degradation (only 3 stage fields visible, no write-back). Three communication planes: stdio JSON-RPC (control) + shared memory segment (data) + event ring (notification); the privilege gradient is now enforced by three explicit gates. RPC round-trip p50 24.1µs; crash-to-recovery under 1s. **v0.9.0** — C ABI v2: external plugin Stage callbacks can now write back (`invoke_stage` gained a result out-param; plugins may mutate RawMessage/LLMText/ToolResults etc. in OnInput/AfterToolcall/PostAction and have them synced to the core). ABI version now tracks core minor releases (v0.9.x → ABIVersion=2, `version_min=1` keeps old plugins loadable). Also fixes the tool-loop zen-compat placeholder that wrongly fired on first-turn system context tail. The SDK ships an enhanced sanitizer example (bad-UTF-8 / U+FFFD / ANSI-escape scrub across the whole pipeline). **This ABI retired with v1.0.0.** @@ -204,7 +231,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.0_{Full,Server,Client}_win64.exe` (NSIS installer) +- Windows: `HomeAgent_v1.1.1_{Full,Server,Client}_win64.exe` (NSIS installer) - Portable: `homeagent-bin-_.tar.gz` (homed/waiter/initconfig) - Verification: `SHA256SUMS` diff --git a/plan.md b/plan.md index bd5e2fd..ca83676 100644 --- a/plan.md +++ b/plan.md @@ -925,39 +925,30 @@ context 累积导致的内存增长。 > > 详细执行记录见 `docs/zh/plugin-migration-plan.md`(Part 0~6 全部标记完成)。 -### 12.1 待用户决策后执行:合并到 main + 发布分支 +### 12.1 ✅ 已完成:合并到 main + 发布分支(2026-09-03 ~ 09-06) -**当前卡在四个决策点**,不是技术阻塞: +四个决策点均已落定并执行: -| # | 决策点 | 备选 | 倾向 | -|---|---|---|---| -| 1 | merge 方式 | `--no-ff` 保留 25 commit / squash 压成一条 | `--no-ff`——commit message 记录了「为何共享同一块 memfd」「为何 procCore 不能嵌入」等踩坑过程 | -| 2 | 合回后是否删 feature 分支 | 删(规范要求)/ 留(8-9 周大特性) | 听用户 | -| 3 | release 构建是否再替换生产二进制 | 换(溯源干净)/ 不换(避免停服) | 听用户 | -| 4 | SDK 仓是否同步 main + release | 同步 / 只合 main / 暂不处理 | 同步——规范说「两仓版本对齐是第一优先级」 | +| # | 决策点 | 最终选择 | +|---|---|---| +| 1 | merge 方式 | **`--no-ff`** —— commit message 记录了「为何共享同一块 memfd」「为何 procCore 不能嵌入」等踩坑过程,压成一条就没了 | +| 2 | 合回后是否删 feature 分支 | **删**(`feature/plugin-proc-migration`、`feature/memory-media` 均已删,本地 + 远端) | +| 3 | release 构建是否再替换生产二进制 | **换**,且此后每个正式版都走同一流程(备份二进制 + `sqlite3 .backup` 配置库 + 记插件清单 → `install -m 0755` → restart → 健康检查) | +| 4 | SDK 仓是否同步 main + release | **同步**,且已升级为规范条款(`docs/git-branching.md` §七) | -**目标效果**: +**tag 归属问题已修**:`v1.0.0` 曾指向 feature 分支中间点 `670efcd`,已删除重打在 `release/v1.0.x` 上(`9b92a04`)。 -- `main` 含全部迁移工作且**永远可部署**(规范 §二.1)。 -- 存在 `release/v1.0.0` 分支,`v1.0.0` tag **打在 release 分支上**而非 feature。 - ⚠️ 当前 tag 指向 `670efcd`(feature 分支中间点),需删除重打。 -- 两仓版本对齐:主仓 `internal/meta.Version` = SDK 仓 `meta.Version` = `1.0.0`, - 且 vendored SDK 与 SDK 仓 release tag 内容一致。 -- 现网部署产物可追溯到 release tag 构建(规范 §四)。 +**实际演进已超出本节当初的设想**,后续发生的事写进了 `docs/git-branching.md`: -**执行序列**(决策落定后): +- 发布分支改为**一个中版本一条**(`release/v1.0.x` 承载 1.0.0/1.0.1/1.0.3/1.0.4,而非按 patch 号各开一条); +- 三级发布通道 alpha/beta/正式**由 tag 区分而非分支**; +- SDK 版本号**跟随核心的中版本、patch 位恒为 `.0`**(整条核心 1.1.x 线共用 SDK 1.1.0)—— + 所以「两仓版本对齐」指**中版本对齐**,不是三位全等; +- **beta 阶段不发 SDK**:接口未固定时发版会让插件开发者照着会变的接口写代码; +- **main 永不作发版分支**,版本号 bump / 打 tag / 构建产物只在发布分支上做。 -```bash -# 主仓 -git checkout main && git merge --no-ff feature/plugin-proc-migration -git checkout -b release/v1.0.0 main -git tag -d v1.0.0 && git tag -a v1.0.0 # 重打在 release 上 -make build VERSION=1.0.0 # 发布产物 - -# SDK 仓(同上流程) -cd third_party/homeagent-sdk -git checkout main && git merge --no-ff feature/plugin-proc-migration -git checkout -b release/v1.0.0 main && git tag -a v1.0.0 +已发布:`v1.0.0` / `v1.0.1` / `v1.0.3` / `v1.0.4`(1.0.x 线)、`v1.1.0` / `v1.1.0-beta.1` / `v1.1.1`(1.1.x 线), +SDK 仓 `v1.0.0` / `v1.1.0`。main 的版本路牌现为 `1.2.0`(尚无 tag)。 ``` --- @@ -1039,6 +1030,9 @@ git checkout -b release/v1.0.0 main && git tag -a v1.0.0 (`syscall.NewLazyDLL` 绑定 `OpenFileMappingW`/`OpenEventW`)。 - **验证程度**:仅 `GOOS=windows GOARCH=amd64 go build` 通过 + 单元测试。 **无 Windows 测试机,从未真机跑过**。 + v1.0.0 起 Windows NSIS 安装器(`HomeAgent_v*_{Full,Server,Client}_win64.exe`)已作为 + release 资产随每个正式版发布 —— 但那只证明**能打出包**,不证明包装出来的 + 共享内存/事件对象在真机上能跑通。这两件事不要混为一谈。 - **已知的语义差异**(代码注释里记了,但未实测): Windows Event 是二元信号而非计数器,多次 `SetEvent` 只唤醒一次。 推理上不影响正确性(消费者按 `readSeq` 追 `writeSeq` 批量 drain), diff --git a/third_party/homeagent-sdk/meta/meta.go b/third_party/homeagent-sdk/meta/meta.go index c2d9685..afb633a 100644 --- a/third_party/homeagent-sdk/meta/meta.go +++ b/third_party/homeagent-sdk/meta/meta.go @@ -28,8 +28,11 @@ var ( // 存量插件不需要改一行也不需要重编:新增方法由**插件调用、内核实现**, // 不调就不受影响。想用新字段的插件重编即可。 // - // ❗main 分支上此值是**下一个未发布中版本**(1.1.x 线在发布中,所以 main 是 1.2.0); - // 已发布的值看对应的 release/vX.Y.x 分支与 tag(如 release/v1.1.x 上是 1.1.0)。 + // ❗main 分支上此值是**下一个未发布中版本**;已发布的值看对应的 + // release/vX.Y.x 分支与 tag(见 核心仓 docs/git-branching.md §2.1 与 §七.1)。 + // + // 现为 1.2.0:1.1.x 线正在发布中(release/v1.1.x 上定版 1.1.0), + // main 在积攒 1.2 的东西。1.2.0 本身还没有任何 tag。 Version = "1.2.0" // Commit 是构建时的 Git commit hash。