docs(sdk): 同步 1.3.0 能力说明与发版口径到发布线

发布线是 SDK 1.3.0 的产物来源,README 停在内核 1.2.0 的口径会让插件作者
按过期说明写代码。只捡文档,不动本线 meta.Version(这里必须恒为 1.3.0)。
This commit is contained in:
JianFeeeee
2026-09-13 14:40:35 +08:00
parent 535922c6a0
commit 87241bc4ff
2 changed files with 62 additions and 4 deletions

View File

@ -4,7 +4,7 @@ HomeAgent 插件开发 SDK用于构建与 HomeAgent 平台交互的智能插
## 版本与兼容性 ## 版本与兼容性
当前:**SDK 1.2.0**(需内核 **1.2.0+**)。 当前:**SDK 1.3.0**(需内核 **1.3.0+**)。
**版本号跟随内核的中版本patch 位恒为 `.0`** **版本号跟随内核的中版本patch 位恒为 `.0`**
@ -12,11 +12,15 @@ HomeAgent 插件开发 SDK用于构建与 HomeAgent 平台交互的智能插
|---|---| |---|---|
| 1.0.0 / 1.0.1 / … / 1.0.4 | 1.0.0 | | 1.0.0 / 1.0.1 / … / 1.0.4 | 1.0.0 |
| 1.1.0 / 1.1.1 / … / 1.1.N | **1.1.0** | | 1.1.0 / 1.1.1 / … / 1.1.N | **1.1.0** |
| 1.2.0 起 | 1.2.0 | | 1.2.0 / 1.2.1 / … / 1.2.N | **1.2.0** |
| 1.3.0 起 | **1.3.0** |
内核的 patch 位专用于 bugfix 与漏洞修复,不碰公开接口,所以 SDK 版本号不跟着动—— 内核的 patch 位专用于 bugfix 与漏洞修复,不碰公开接口,所以 SDK 版本号不跟着动——
否则你要么被迫跟版、要么怀疑自己版本过时,而接口其实一个字都没变。 否则你要么被迫跟版、要么怀疑自己版本过时,而接口其实一个字都没变。
因此 **SDK 仓在一个中版本里只发一次**`vX.Y.0`),核心的 `v1.3.1`/`v1.3.2`/… 不伴随 SDK 发版。
2026-09-13 曾误发过 `v1.3.1`,已撤回 —— patch 位带非零数字的 SDK tag 都是错误的。)
**1.0.x 插件升到 1.1.x不需要改代码也不需要重编。** 1.1.0 的新增全部是 **1.0.x 插件升到 1.1.x不需要改代码也不需要重编。** 1.1.0 的新增全部是
「插件调用、内核实现」方向,不调就不受影响(已用 SDK 0.9.2 编的旧 `plugin.bin` 「插件调用、内核实现」方向,不调就不受影响(已用 SDK 0.9.2 编的旧 `plugin.bin`
实测验证:在新内核上直接建链通过,因为握手校验的是 `ProtocolVersion`、不是 SDK 版本)。 实测验证:在新内核上直接建链通过,因为握手校验的是 `ProtocolVersion`、不是 SDK 版本)。
@ -28,6 +32,40 @@ HomeAgent 插件开发 SDK用于构建与 HomeAgent 平台交互的智能插
所以 `plugin.bin` 必须用配套的 `hmapdev` 重编后与内核**同批**安装——否则握手时协议版本 所以 `plugin.bin` 必须用配套的 `hmapdev` 重编后与内核**同批**安装——否则握手时协议版本
不匹配会被拒绝(错误信息会明确提示用配套 hmapdev 重编,不会静默降级)。 不匹配会被拒绝(错误信息会明确提示用配套 hmapdev 重编,不会静默降级)。
## 1.3.0 新增:注入优先级与动态输出通道
### 注入优先级(`InjectOptions.Priority`
插件可以声明**自己这次注入的中断级别**,内核按四级阶梯调度:
| 级别 | 常量 | 谁用 |
|---|---|---|
| L1L3 | `PriorityL1` / `PriorityL2` / `PriorityL3` | 插件按紧急程度自选L1 最低) |
| L4 | `PriorityL4` | **保留给内核与内核级插件**(内核自身事件、内核级通道) |
- 零值(不声明)与旧的注入调用**完全等价**:按排队处理,不抢占任何正在执行的回合
⇒ 存量插件不需要改一行、也不需要重编。
- 高优先级中断可以**抢占**低优先级正在跑的回合;被抢占的回合挂起、之后恢复继续
(现场保存/恢复对插件透明)。
- 排队输入**没有级别**:排队就是排队,任何中断都能插到它前面。
### 动态输出通道(`UnregisterOutputChannel`
`RegisterOutputChannel` 注册的通道此前只增不减。对**随资源生灭**的通道(典型:远程设备
一台设备一个输出通道),设备掉线后通道还在,模型会继续对一个死通道发消息并以为发成功了。
1.3.0 起成对提供:
| API | 用途 |
|---|---|
| `UnregisterOutputChannel(name)` | 注销输出通道(含能力表与工具) |
| `OutputChannelUnregistrar` / `SetOutputChannelUnregistrar` | 插件侧拿到注销句柄(内核注入) |
⚠️ 通道名要**由插件派生得又合法又唯一**(外部 id 不能直接当通道名)——
设备 id 这类外部输入可能带 `/` 等字符,而通道名会拼进 LLM 函数名 `output_send__<name>`
违规会让**整条 LLM 请求**被上游拒绝2026-09-13 生产事故:`device/<id>` 导致全量对话 403
派生规则与约束见下方「输出通道」一节。
## 注入行为与上下文裁剪1.2.0 ## 注入行为与上下文裁剪1.2.0
「记不记入记忆」与「要不要据此裁剪上下文」这两件事,原先只有 `ToolDef` 能声明; 「记不记入记忆」与「要不要据此裁剪上下文」这两件事,原先只有 `ToolDef` 能声明;

View File

@ -4,7 +4,7 @@ Plugin development SDK for building intelligent plugins that interact with the H
## Version and Compatibility ## Version and Compatibility
Current: **SDK 1.2.0** (requires kernel **1.2.0+**). Current: **SDK 1.3.0** (requires kernel **1.3.0+**).
**The version tracks the kernel's minor version, with the patch position pinned at `.0`**: **The version tracks the kernel's minor version, with the patch position pinned at `.0`**:
@ -12,13 +12,33 @@ Current: **SDK 1.2.0** (requires kernel **1.2.0+**).
|---|---| |---|---|
| 1.0.0 / 1.0.1 / … / 1.0.4 | 1.0.0 | | 1.0.0 / 1.0.1 / … / 1.0.4 | 1.0.0 |
| 1.1.0 / 1.1.1 / … / 1.1.N | **1.1.0** | | 1.1.0 / 1.1.1 / … / 1.1.N | **1.1.0** |
| 1.2.0 onward | 1.2.0 | | 1.2.0 / 1.2.1 / … / 1.2.N | **1.2.0** |
| 1.3.0 onward | **1.3.0** |
The kernel's patch position is reserved for bugfixes and vulnerability fixes, which never touch the The kernel's patch position is reserved for bugfixes and vulnerability fixes, which never touch the
public interface, so the SDK version has no reason to move with it — otherwise you would either be public interface, so the SDK version has no reason to move with it — otherwise you would either be
forced to chase releases or suspect your version is stale, when not one character of the interface forced to chase releases or suspect your version is stale, when not one character of the interface
has changed. has changed.
The SDK repository therefore publishes **exactly once per minor version** (`vX.Y.0`); kernel patches
such as `v1.3.1` do not trigger an SDK release. (A `v1.3.1` tag was mistakenly cut on 2026-09-13 and
has been withdrawn — any SDK tag with a non-zero patch position is wrong.)
## New in 1.3.0: Injection Priority and Dynamic Output Channels
- **`InjectOptions.Priority` / `PriorityL1``PriorityL4`** — a plugin declares the interrupt level of
its own injection; the kernel schedules L1L4, where **L4 is reserved for the kernel and
kernel-level plugins**. The zero value is fully equivalent to the old three-argument call
(queued, never preempting), so existing plugins need neither a code change nor a rebuild.
Queued input has no level: anything can jump ahead of it.
- **`UnregisterOutputChannel` / `OutputChannelUnregistrar` / `SetOutputChannelUnregistrar`** —
channels that die with their resource (one channel per remote device) can now be unregistered;
previously they lingered and the model kept "successfully" sending into a dead channel.
- **Channel names must be legal and unique.** The name is spliced into the LLM function name
`output_send__<name>`, so it may only contain `[A-Za-z0-9_-]`. A real production incident
(2026-09-13): `device/<id>` made every LLM request fail with 403. Derive channel names from
external IDs — never use the raw ID.
**Upgrading a 1.0.x plugin to 1.1.x: no code changes, no rebuild.** Everything added in 1.1.0 is **Upgrading a 1.0.x plugin to 1.1.x: no code changes, no rebuild.** Everything added in 1.1.0 is
in the "plugin calls, kernel implements" direction, so not calling it means not being affected in the "plugin calls, kernel implements" direction, so not calling it means not being affected
(verified with an old `plugin.bin` built against SDK 0.9.2: it handshakes fine on the new kernel, (verified with an old `plugin.bin` built against SDK 0.9.2: it handshakes fine on the new kernel,