mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-01 06:47:29 +00:00
## ① 提示词:只有显式调用 outputch 才会送达用户(用户明确要求)
模型最常见的错误不是不会调工具,而是**以为返回文本就等于回复了** ——
在异步通道(qq/wechat/群聊)上那等于自言自语,用户永远收不到。
改动前【输出规则】开篇是「消息不会自动发送到对话来源通道,你必须自己决定
如何回复」,语气偏描述。改为开篇总述句:
**只有显式调用 `output_send__{通道名}` 才会把内容送达用户。**
返回纯文本只是在这次推理里说话,用户看不到 —— 除非是下面说的同步通道。
同时补上本次内核新增能力:payload 传数组可一次发多条。
## ② 契约值改名:ProxyAuthHomeAgent="homeagent" → ProxyAuthAgent="agent"
用户指示契约值一起改。常量名与字符串值同时改,但**保留旧值读取路径**:
ProxyAuthAgent = "agent" ← 新值
ProxyAuthAgentLegacy = "homeagent" ← 只用于兼容读取
ProxyAuthHomeAgent = ProxyAuthAgent (Deprecated 别名,存量源码可编译)
为什么必须保留:`Auth` 是**写进 plugin.json 的持久化声明值**。存量配置里
写着旧值 —— 本机实测 `/home/newqqagent/plugins/huawei_smarthome/plugin.json:19`
就是 `"auth": "homeagent"`。只认新值 ⇒ 该插件加载时被判为非法声明 ⇒
反代不生效,症状是「插件好好的但页面打不开」,且无任何报错指向改名。
### 归一化是安全关键
`EffectiveProxyAuth` 把**空串与旧值都归一化为 ProxyAuthAgent**。
判断点全都写成 `auth == ProxyAuthAgent`。若不归一化,就得每点写两遍比较
—— **漏一处就是鉴权绕过**:旧值被判为「非门户鉴权」⇒ 跳过 authorizeProxy
⇒ 请求直接透传给上游。所以兼容收在一个函数里,不散落在调用点。
### 顺带修掉两处隐患
1. `webui/proxy.go` 的裸字面量 `"homeagent"`(非法行占位)改为
`sdk.ProxyAuthAgent` —— 裸字面量在改名时会被漏掉,届时它悄悄变成
未知值,而未知值在旧代码里等于「无鉴权」。
2. 两处鉴权判断改用 `EffectiveProxyAuth(...)`,堵住旧值绕过。
## 判据
| 判据 | 覆盖 | 变异自证 |
|---|---|---|
| `TestSystemPromptRequiresExplicitOutputCall` | 总述句必须存在、必须说明「返回文本用户看不到」、同步通道是唯一例外、payload 可传数组 | 删掉总述句 ⇒ 红 |
| `TestProxyAuthLegacyValueStillAccepted` | 旧值仍被接受 + 必须归一化为新值 | 去掉归一化分支 ⇒ 「旧值应归一化为 "agent",实际 "homeagent"」红 |
## 验证
- `go build ./...` / `go vet ./...` 干净
- webui / internal-sdk / agent-core 全绿
- SDK 仓(独立提交 acd1166):`go build` + `go test ./...` 0 失败
118 lines
6.3 KiB
Go
118 lines
6.3 KiB
Go
// Package meta 收集 HologramAgent SDK 的全部元数据。
|
||
// 版本号应与核心 meta.Version 保持一致。
|
||
package meta
|
||
|
||
var (
|
||
// Version 是 HologramAgent SDK 版本号。
|
||
// 通过 `-ldflags="-X github.com/JianFeeeee/homeagentsdk/meta.Version=vX.Y.Z"` 注入。
|
||
//
|
||
// 版本号语义:**SDK 版本跟随核心的中版本,patch 位恒为 .0**。
|
||
// 整条核心 1.1.x 线(1.1.0、1.1.1、1.1.7…)共用 SDK 1.1.0;
|
||
// 只有核心进入 1.2.0 这种中版本跃迁时 SDK 才升到 1.2.0。
|
||
// 这样插件开发者只需关心「我在为哪个中版本写插件」,
|
||
// 不必跟着核心的每个 bugfix 换 SDK 依赖(见 核心仓 docs/git-branching.md §七)。
|
||
//
|
||
// 1.0.0:插件运行模型从 C ABI 动态库改为子进程 + 共享内存。
|
||
// 公开 SDK 接口零改动,但产物形态变了(plugin.so → plugin.bin)。
|
||
// 1.1.0:多模态贯通插件边界。**全部是新增,无签名变更**:
|
||
// - Triple.SentenceText / Triple.MediaDigests
|
||
// - Doc.MediaDigests / Doc.Attachments、MediaAttachment
|
||
// - TextEvent.Attachments
|
||
// - DocMemoryAPI.InsertWithMedia
|
||
// - IOInjector 的 InjectInputMedia / InjectInputMediaSync /
|
||
// InjectInterruptMedia;PluginSDK 补上缺失的 SetToolBlocks 包装
|
||
// 同版修掉两处并发竞态(sdk/stress_test.go 的 -race 实证,不是理论风险):
|
||
// PluginSDK 的 API 字段与 autoRestart 标志此前无锁,而写方
|
||
// (内核注入 API、插件 SetAutoRestart)与读方(插件后台 goroutine
|
||
// 注入、内核 registry 读 AutoRestart)天然跨 goroutine。
|
||
// 存量插件不需要改一行也不需要重编:新增方法由**插件调用、内核实现**,
|
||
// 不调就不受影响。想用新字段的插件重编即可。
|
||
//
|
||
// 1.2.0:注入行为的记忆/裁剪标志位。**全部是新增,无签名变更**:
|
||
// - InjectOptions{NoMemory, ContextPolicy}
|
||
// - IOInjector 的六个 *Opts 变体(排队/中断/同步/带媒体各一对)
|
||
// - ChannelDef.ContextPolicy(顺带给 ChannelDef 补上 JSON tag:
|
||
// 它要跨进程传给内核,而 Cleaner 是函数必须忽略;无 tag 时只能
|
||
// 手写字段白名单,新增字段会被静默丢掉)
|
||
// 语义:零值 InjectOptions 与旧的三参数方法完全等价(记入记忆 +
|
||
// 不裁剪),因此存量插件不需要改一行也不需要重编。
|
||
// 裁剪(ContextPolicy=prune)必须显式声明——它会归档丢弃低相关事件。
|
||
//
|
||
// ❗main 分支上此值是**下一个未发布中版本**;已发布的值看对应的
|
||
// release/vX.Y.x 分支与 tag(见 核心仓 docs/git-branching.md §2.1 与 §七.1)。
|
||
//
|
||
// 现为 1.4.0:1.3.0 已随核心的正式 tag `v1.3.0` 定版并发版(本仓 tag v1.3.0、
|
||
// release/v1.3.x 承载它),该号从此归发布线所有,main 遂推进到下一个未发布中版本。
|
||
//
|
||
// ❗本仓**不发 patch tag**(§七.1):一个中版本只发一次 `vX.Y.0`,核心的 1.3.x
|
||
// 后续 patch **不伴随 SDK 发版** —— patch 位恒为 `.0`,带非零 patch 的 SDK tag
|
||
// 都是错的。(2026-09-13 曾误发 `v1.3.1`,已撤回;`v1.2.1` 是同一类历史遗留。)
|
||
//
|
||
Version = "1.4.0"
|
||
|
||
// Commit 是构建时的 Git commit hash。
|
||
Commit = "unknown"
|
||
|
||
// BuildTime 是构建时间。
|
||
BuildTime = "unknown"
|
||
|
||
// SDKName 是 SDK 名称。
|
||
SDKName = "HologramAgent SDK"
|
||
|
||
// SDKModule 是本 SDK 仓当前的 Go module path。
|
||
//
|
||
// ★ 2026-10-08 随托管地迁移:`gitcode.com/JianFeeeee/homeagent-sdk`
|
||
// → `github.com/JianFeeeee/homeagentsdk`(仓库迁到 GitHub)。
|
||
//
|
||
// ❗已有插件的 go.mod 里写的仍是旧路径(本机实测 qq/vanblog/mcquery/
|
||
// fileproc/mail-bridge 五个插件工作区全是 gitcode.com/...)。
|
||
// 因此凡是要「识别 SDK 模块」的判定必须**两种都接受**
|
||
// (见 hmapdev 的 sdkModulePath 助手),不能只认新名——
|
||
// 只认新名会让旧插件被当成「不是 SDK 模块」而静默走错分支。
|
||
SDKModule = "github.com/JianFeeeee/homeagentsdk"
|
||
|
||
// LegacySDKModule 是迁移前的 SDK module path,仍需被识别。
|
||
LegacySDKModule = "gitcode.com/JianFeeeee/homeagent-sdk"
|
||
|
||
// CoreModule 是核心仓的 Go module path,供 hmapdev 生成 go.mod 时使用。
|
||
//
|
||
// ★ 2026-10-08 随主仓托管地迁移而更新:仓库在 GitHub
|
||
// (github.com/JianFeeeee/HologramAgent),module 路径同步。
|
||
// 注意它与 SDKModule 不是同一个仓:插件只依赖 SDK,**不依赖主仓**,
|
||
// 所以改本常量不影响任何已有插件。
|
||
CoreModule = "github.com/JianFeeeee/HologramAgent"
|
||
|
||
// CoreVersion 是此 SDK 所兼容的最低核心版本。
|
||
//
|
||
// 1.0.0 是硬下限而非建议值:0.9.x 内核只会 dlopen `.so`,
|
||
// 本版工具链产出的 `plugin.bin` 在旧内核上根本不会被识别。
|
||
//
|
||
// ⚠️ 1.1.0 新增的媒体接口需要核心 **1.1.1+**(更早的核心没有
|
||
// doc.insertWithMedia / io.injectMedia* 这些 RPC,调用会返回 unknown method)。
|
||
// 这里仍写 1.0.0,因为它是「SDK 能在其上运行」的下限;
|
||
// 媒体接口是可选能力,不用就不受影响。
|
||
//
|
||
// ⚠️ 1.2.0 新增的注入标志位同理需要核心 **1.2.0+**:内核在 1.2.0 之前会
|
||
// 忽略注入参数里的 no_memory/context_policy 字段(不会报错,但不生效)。
|
||
// 想用这些标志位的插件应当要求核心 1.2.0+;不用就不受影响。
|
||
CoreVersion = "1.0.0"
|
||
)
|
||
|
||
// FullVersion 返回完整的版本字符串。
|
||
func FullVersion() string {
|
||
return SDKName + " v" + Version + " (" + Commit + ")"
|
||
}
|
||
|
||
// ---- 协议兼容性 ----
|
||
//
|
||
// **不自定协议号**:兼容性只认双方版本号的**主版本段**。
|
||
// 主版本相同即兼容(1.x 内全是纯追加);跨主版本则是破坏性变更
|
||
// (如 1.0.0 从 C ABI 改子进程),握手时显式拒绝并提示重编。
|
||
//
|
||
// C ABI 时代的 ABIVersion / CABINum / 51 个 Core<Method> 整数 ID 已随
|
||
// Part 6.2 删除 internal/plugin/cabi/ 一并退场:
|
||
// - 整数 method id 平移为 method 名字符串(proc/protocol.go 的 Method* 常量)
|
||
// - 版本协商改为握手帧里的 core_version / sdk_version 主版本比对
|
||
//
|
||
// 保留那些常量只会让人以为它们还在生效。
|