Commit Graph

4 Commits

Author SHA1 Message Date
55fa2685ae feat(security,device): security 成为独立内核模块(闸门+策略+限式),device 接管内置工具路由
security(新模块 internal/kernelmod/security)
- 凭据闸门:出向拦截成 @{别名}、入向清洗、执行前回填(internal/security/{gate,runtime}.go)
- 工具黑白名单 + 沙箱(读写根、网络、.. 逃逸):internal/security/policy.go
- 敏感词过滤 + 提示词注入预警(Finding 不带原文):internal/security/content.go
- 按主体授权(hard-private 对非内部主体永久拒绝):internal/security/principal.go
- 插件命名限式(可选档位,插件声明/内核执行,只能收窄):internal/security/profile.go
- 启动装配从 cmd/homed 迁入模块;启动顺序判据改盯真实装配点

device(新模块)
- 正式内核模块,Provides FacDevice,KernelState.Device
- 内置工具路由表下沉到 internal/toolroute(避免 core↔kernelboot 环),
  device 保留对外入口;agent 未挂载时退化本地 switch
- Agent 侧只留 api.ToolHost/DeviceSurface 适配层

SDK
- InjectOptions.SecurityProfile:插件按 inputch 声明本轮安全档位(可选)
- InjectOptions.TurnHint:插件注入**本轮事实**,内核以独立 system 消息注入,
  不混进用户正文(人设负责怎么说话,TurnHint 只放这一轮成立的事实)
- FacilitySecurity / FacilityDevice

提示词
- 内核自带 prompt/skill/工具返回全面英文化(中文提示会让模型行为漂移)
- 机制解释下沉到 4 个内置 skill(memory/output/tool-order/plugins),
  skill 描述压到 80 runes 内(原来 94–108 全被索引截断)
- 默认人格模板英文化;[Voice] 段删除,规则并入 persona 块(单一段落)
- 历史记忆工具改名 coldcontext_query/commit,图记忆语义改称 stable memory

修复
- tracker: exec mount → unix.Mount(降权运行 + AmbientCapabilities 下才能挂)、
  区分 EPERM 与不支持;启动日志说明后果与恢复方式
- healthcheck_kernel 输出瘦身:status.Tools 只给摘要(原 98,989 tokens/151% 预算)
- plugin_list 描述讲清 auto_start(按需)与 alive(此刻是否在跑),
  明确不能由 alive=false 推断能力不存在
- pluginmgr/webui 去掉写死的 /home/newqqagent 回退路径(env → pluginDir 反推 → 报错)
- lua: 盘上适配器与内置版本不一致且无基线时响亮告警(deepseek 流式丢失
  tool_calls 导致'模型不调工具'的真因)

测试:go build ./... 通过;go test ./... 60 包全绿
2026-10-26 20:55:25 +08:00
4e70b8d5d8 refactor(module): 核心仓 Go module 路径改为 github.com/JianFeeeee/HologramAgent
批 1,不含 SDK 仓与目录改名。

- go.mod 第 1 行 module 路径
- 366 个 .go 文件的完整前缀 github.com/JianFeeeee/HomeAgent 机械替换
  (857 处,仅完整前缀;展示名/注释里的 HomeAgent 字样留给批 5)
- 未改:third_party 目录名、SDK 自身 go.mod module、go.mod replace 目标、
  homed/waiter 可执行名、.hmap 后缀
2026-10-21 12:17:19 +08:00
6d38a164eb chore(module): Go module 路径随托管地迁移 gitcode → github
## 背景

仓库早已迁移到 GitHub(`github.com/JianFeeeee/HomeAgent`,CI/CD 都在那边跑),
gitcode 保留为**国内只读镜像**(`ci.yml` 的 sync-gitcode-main 快进推送)。
但 go.mod 的 module 路径一直是 `gitcode.com/JianFeeeee/...` —— 既与权威源
不符,`meta.SourceURL`(AGPL §13 的源码提供入口)也指向镜像而非实际运行的代码。

## 关键区分(这是本次改动安全的前提)

两个 module 是**不同**的,影响面差一个数量级:

| module | 谁依赖 | 改它的后果 |
|---|---|---|
| `.../HomeAgent`(主仓) | **只有主仓自己** | 内部重构,零外部影响 |
| `.../homeagent-sdk`(SDK 仓) | 主仓 49 文件 + 所有外部插件 | 需重编插件 |

★ 实测确认:**插件不 import 主仓 module**(`strings qq/plugin.bin | grep HomeAgent` = 0),
只依赖 SDK 仓。而插件与内核的边界是 **RPC 方法名字符串**
(`plugin.init` / `tool.invoke`…,见 proc/protocol.go),**与 Go module 名无关**。
⇒ module 改名**不改变任何 wire 协议**,现网已装的插件照常运行。

SDK 的 GitHub 仓名是 `homeagentsdk`(无连字符),module 路径必须与之精确匹配,
否则 `go get` 会因路径不符失败,故取 `github.com/JianFeeeee/homeagentsdk`。

## 改动

- `go.mod` / `go.sum`:两个 module 路径 + require/replace
- 277 个 Go 文件 + Makefile + 打包脚本的 import 与 ldflags 路径
- SDK 仓 `meta.CoreModule`、`tools/hmapdev` 的 module 声明与工程模板
- 对外文档/链接的仓库地址(README、PLUGIN_DEV、OVERVIEW 等)

## 明确**保留** gitcode 的地方(镜像机制,不能动)

- `GITCODE_TOKEN`、`GC_URL="…@gitcode.com"`(CI 同步 job)
- `gitcode.com/api/v5/...`(release 附件上传)
- git remote `gitcode`(镜像拉取/推送)
- `docs/zh/ci-cd-runbook.md`(整篇讲镜像运维)

## 验证

- `go build ./...` / `go vet ./...` 绿
- `go test ./... -count=1` → 48 包 ok / 0 FAIL
- hmapdev 工具链编译通过(`third_party/homeagent-sdk/tools/hmapdev`)
- 全仓残留检查:module 形态的 `gitcode.com/JianFeeeee` = 0
- 镜像机制抽验:GC_URL / @gitcode / api/v5 / remote 均完好

## 顺带修正

`hmapdev/templates.go` 的注释此前写「gitcode 的模块不在 proxy.golang.org 上」——
module 已迁 GitHub,该论断不再成立。改为如实说明**为何仍默认 replace 到本机 SDK**:
离线可构建、避免版本漂移、内网可用。理由与托管地无关,故 replace 保留。
2026-10-08 10:40:17 +08:00
d0cec35894 feat(toolcall): 结果契约诚实化 —— Success 不再恒真 + 结构化失败可回填(阶段 1b/1d)
问题(实测,三条互相印证):
· ToolResult.Success 硬编码 true(task.go 唯一赋值点)⇒ 该字段在结构上
  不可能为 false,是**谎报字段**;
· 工具失败以 nil error + 错误**值**返回(files 的 errorResult、
  pluginmgr 的 {"error":…}),上游无从判别;
· stepToolAfter 用 `Result.(string)` 断言,而插件返回的多是 map ⇒
  断言几乎恒失败,after_toolcall 阶段对结构化结果的改写**静默失效**。

改动:
· third_party/homeagent-sdk: 新增 ToolError{Field,Reason,Detail,Hint}
  与 Error()。纯新增、无签名变更,存量插件不必改动(零值语义:
  内核的失败识别同时兼容既有三种约定,新类型是可选项而非迁移要求)。
· internal/sdk: 补 ToolError 别名。
· core/toolerror.go: isToolError / toolErrorText / renderToolResult。
  ⚠️ 判据必须同时兼容仓内**三种**既有失败约定,且**不得**把成功误判:
   ① {"error": msg}  ② {"isError":true,content:…}  ③ *ToolError
  明确不判失败的:exit_code != 0(业务结果,带真实 stdout/stderr)、
  stderr 非空(cmd 成功常带 warn)、字符串/数字/bool/数组/nil
  (自由文本按成功处理:宁可少报失败,也不把正常结果报成失败)。
· core/toolcall.go: executeToolCallOutcome 返回 toolOutcome{Text,Raw},
  **Raw 必须在成功分支也带上**——否则结构化失败在 fmt.Sprintf("%v")
  那一步被抹平,Success 又退回恒真。panic 与 60s 超时统一以 ToolError
  表达(可执行 Hint,避免模型原样重试工具故障)。
· core/task.go: Success=!isToolError(Raw);修恒失败的类型断言;
  TaskFrame 增 CurRaw(未降级的原值)。

判据:
· toolerror_test.go 单元级:三种失败约定识别 / 成功形态不误判 /
  非零退出不算工具失败 / ToolError 识别。
· TestStageCtxSuccessIsHonestEndToEnd 端到端读 f.StageCtx.ToolResults,
  验证**内核产出的值本身**,而非辅助函数。

变异验证(两轮):
· Success 退回硬编码 true ⇒ 端到端判据 3 个子用例 FAIL;
· 把字符串判据改成 strings.Contains(x,"error") ⇒ 「成功文本含 error 字样」
  用例 FAIL。**第二轮暴露了判据缺口**(最初没有该用例),已补。

过程中三次自伤(均由判据/编译暴露):用正则批量包装 return 时把
多行 fmt.Sprintf 截断;包装范围溢出到返回 string 的辅助函数;
测试里重复注册同名工具导致 IOManager 取到错误的 device。

遗留:全量 go test ./internal/... 在本机无法完整跑完——/tmp 是 9.8G
tmpfs 且已 98% 占用,link 阶段报 "no space left on device";
/var/tmp 另有约 29G 陈旧 release worktree。与本次改动无关(未触碰
memory/* 等失败包),已在干净基线(70b3ddd)对比确认。
2026-09-27 09:17:16 +08:00