| fix(browser): browser_search 解析现代 Bing 版式,并把解析失败显式报错 旧实现三处叠加,模型只拿到「标题=来源行 URL 串、无摘要」,表现为反复换词重搜: - www.bing.com 对程序化请求常回 302,拿不到结果块 → 改 cn.bing.com - 块内第一个 <a> 当标题 → 抓到来源行 deepin.orghttps://www.deepin.org;改取 h2 > a, 并解开 /ck/a?...&u=a1<base64url> 跳转包装 - 摘要正则 <div class="b_caption">.*?<p> 对现代版式 0 命中(已迁到 p.b_lineclamp*) - 分块不再用 (.*?)</li>:块内可能嵌套 <li>(deep links)会在错误位置截断 - 解析不出结果时明确报错,不再伪装成 "No results found." 夹具 testdata/bing_cn.html 为真实 cn.bing.com 响应裁剪;新增 5 项单测。 版本 2.4.0 → 2.4.1(2.4.0 = 交互式 timeout 改必填,此前已提交)。 验证:go test -race 全过、vet/gofmt 干净;线上实测返回真实标题+摘要+规整链接。 | 30 天前 |
| fix(browser)!: 截图落盘返回路径,不再回 base64 用户报告:截图直接返回二进制(base64)对 agent 十分不友好。确认属实,且 生产日志里有 agent 的**绕行实证**(2026-10-10): browser_screenshot → cmd_run(自己 base64 解码写盘)→ describe_image 那一轮跑了 920 秒。 ## 为什么 base64 是错的 工具结果是 JSON 文本,base64 PNG 会**整段进模型上下文**,而模型看不见 这些字符里的图 —— 纯粹浪费: 视口截图 100-500KB ⇒ base64 后 137-685KB(约 3-17 万 token) 更关键的是它把「解码 + 写文件」这件重复劳动推给了每个消费方,而模型做不到。 内核早有对应约定:describe_image 的 path 参数描述写着 「★处理设备/工具回传的媒体时必须传(screensee / camerasue 会回传 file 路径)」。 本插件返回路径才是合上这个约定。 ## 改动 - 截图落盘到 <data_dir>/browser_screenshots/,返回**绝对路径** - 结果里带 hint 直接告诉模型「调 describe_image(path=...)」—— 工具描述模型可能漏看,结果里的提示更近 - inline=true 才额外带 base64/data_uri(只有确实拿不到文件系统的场景才用) - 落盘失败**明确报错**,不静默退回 base64:那会让「上下文被灌爆」 在磁盘满/权限错时重新出现且没有迹象 - 文件名带毫秒时间戳 + 会话 id:同一轮内多次截图是常态 (生产日志里一轮截了 3 次),固定名会静默覆盖 - 会话 id 过滤路径分隔符(它来自模型且被拼进路径,否则 ../ 能写出目录外) - 未注入 data_dir 时降级到临时目录,而不是让截图整条失败 ## 判据(5 条,可杀变异,逐个实测) screenshot_test.go: - 落盘 + 返回绝对路径 + 内容逐字节一致 - 连续截图不互相覆盖(文件名去时间戳 → FAIL) - 会话 id 路径穿越被挡(../../etc/evil 仍在目录内) - 未注入目录时降级而非报错 - 工具描述必须提 path 与 describe_image(描述退回 base64 → FAIL) - handleScreenshot 返回结构必须是 path 而非 base64 (整段替换为旧实现 → FAIL;保留 path 但无条件加 base64 → FAIL) **判据本身修过两次(都是变异测试发现的)**: 1. 第一版只看 res["base64"] = b64,把 base64 写成 map 字面量的键就绕过了 2. 第二版按整段文本查 "inline",而**注释里也有 "inline"** ⇒ 把保护开关 改成 if false 仍能通过。改为先 stripLineComments 再查真实代码行 全 20 个 example 编译通过;browser 插件 go test + plugin 模式构建通过。 | 2 天前 |
| chore(module)!: module 路径随托管地迁移 gitcode → github SDK 仓已迁到 GitHub 作为权威源,go module 路径同步: gitcode.com/JianFeeeee/homeagent-sdk → github.com/JianFeeeee/homeagentsdk ## 范围 74 个文件:71 个 Go 源码 + go.mod/go.sum + hmapdev 模板 + CI 与打包脚本。 主仓(HomeAgent)侧对应改动是 6d38a164。本仓这些文件当时**不在工作树上** (见下),所以那次的批量替换扫不到它们——这里是补偿。 ## 为何这批文件当时不在工作树上(事故与恢复) 10-08 07:58 主仓做 checkout/cherry-pick 序列时,把本仓工作树的 20 个文件 误清理了(example/*/plugin.go + plg.json,10 个示例)。 根因是**结构误判**:本仓是「一目录两仓库」结构下主仓 third_party/ 里的 **独立 git 仓库**,而主仓 .gitignore 忽略了 example/,于是它在主仓 git status 里不可见 —— 看着像「不受跟踪的构建产物」,实际是本仓受跟踪的源码。 已全部恢复(git checkout -- <D 文件>,只恢复删除、不动迁移改动), 20 个文件与 HEAD 逐字节一致。 **破坏的连锁后果**:恢复出来的 plugin.go 仍写着旧 module 路径, 因为迁移时它们已不在工作树上。所以这次补偿是必须的,不是可选优化。 ## 保留 gitcode 引用 以下位置的 gitcode **有意保留**,不要"顺手清掉": - README.md / docs 里「二进制实际分发地址目前是 gitcode」的说明 - mkdocs.yml 的 gitcode 镜像链接(国内直连更快) - tools/hmapdev/templates.go 里「SDK 已从 gitcode 迁到 GitHub」的注释 gitcode 仍是**只读镜像**(源码同步;release 附件暂时仍在那边)。 ## 验证 - 本仓根 module:go build ./... + go test ./... 全通过 - 全部 20 个 example:go vet 通过(补偿前 10 个因旧 module 路径失败) - example/qq:go test 通过,且能从源码 build 出可用 plugin 产物 | 3 天前 |
| feat: add example plugins (ai_image, calendar, music, rss, weather), fix .gitignore, move gengskill to tools/ | 2 个月前 |
| chore(module)!: module 路径随托管地迁移 gitcode → github SDK 仓已迁到 GitHub 作为权威源,go module 路径同步: gitcode.com/JianFeeeee/homeagent-sdk → github.com/JianFeeeee/homeagentsdk ## 范围 74 个文件:71 个 Go 源码 + go.mod/go.sum + hmapdev 模板 + CI 与打包脚本。 主仓(HomeAgent)侧对应改动是 6d38a164。本仓这些文件当时**不在工作树上** (见下),所以那次的批量替换扫不到它们——这里是补偿。 ## 为何这批文件当时不在工作树上(事故与恢复) 10-08 07:58 主仓做 checkout/cherry-pick 序列时,把本仓工作树的 20 个文件 误清理了(example/*/plugin.go + plg.json,10 个示例)。 根因是**结构误判**:本仓是「一目录两仓库」结构下主仓 third_party/ 里的 **独立 git 仓库**,而主仓 .gitignore 忽略了 example/,于是它在主仓 git status 里不可见 —— 看着像「不受跟踪的构建产物」,实际是本仓受跟踪的源码。 已全部恢复(git checkout -- <D 文件>,只恢复删除、不动迁移改动), 20 个文件与 HEAD 逐字节一致。 **破坏的连锁后果**:恢复出来的 plugin.go 仍写着旧 module 路径, 因为迁移时它们已不在工作树上。所以这次补偿是必须的,不是可选优化。 ## 保留 gitcode 引用 以下位置的 gitcode **有意保留**,不要"顺手清掉": - README.md / docs 里「二进制实际分发地址目前是 gitcode」的说明 - mkdocs.yml 的 gitcode 镜像链接(国内直连更快) - tools/hmapdev/templates.go 里「SDK 已从 gitcode 迁到 GitHub」的注释 gitcode 仍是**只读镜像**(源码同步;release 附件暂时仍在那边)。 ## 验证 - 本仓根 module:go build ./... + go test ./... 全通过 - 全部 20 个 example:go vet 通过(补偿前 10 个因旧 module 路径失败) - example/qq:go test 通过,且能从源码 build 出可用 plugin 产物 | 3 天前 |
| fix(browser): browser_search 解析现代 Bing 版式,并把解析失败显式报错 旧实现三处叠加,模型只拿到「标题=来源行 URL 串、无摘要」,表现为反复换词重搜: - www.bing.com 对程序化请求常回 302,拿不到结果块 → 改 cn.bing.com - 块内第一个 <a> 当标题 → 抓到来源行 deepin.orghttps://www.deepin.org;改取 h2 > a, 并解开 /ck/a?...&u=a1<base64url> 跳转包装 - 摘要正则 <div class="b_caption">.*?<p> 对现代版式 0 命中(已迁到 p.b_lineclamp*) - 分块不再用 (.*?)</li>:块内可能嵌套 <li>(deep links)会在错误位置截断 - 解析不出结果时明确报错,不再伪装成 "No results found." 夹具 testdata/bing_cn.html 为真实 cn.bing.com 响应裁剪;新增 5 项单测。 版本 2.4.0 → 2.4.1(2.4.0 = 交互式 timeout 改必填,此前已提交)。 验证:go test -race 全过、vet/gofmt 干净;线上实测返回真实标题+摘要+规整链接。 | 30 天前 |
| fix(browser)!: 截图落盘返回路径,不再回 base64 用户报告:截图直接返回二进制(base64)对 agent 十分不友好。确认属实,且 生产日志里有 agent 的**绕行实证**(2026-10-10): browser_screenshot → cmd_run(自己 base64 解码写盘)→ describe_image 那一轮跑了 920 秒。 ## 为什么 base64 是错的 工具结果是 JSON 文本,base64 PNG 会**整段进模型上下文**,而模型看不见 这些字符里的图 —— 纯粹浪费: 视口截图 100-500KB ⇒ base64 后 137-685KB(约 3-17 万 token) 更关键的是它把「解码 + 写文件」这件重复劳动推给了每个消费方,而模型做不到。 内核早有对应约定:describe_image 的 path 参数描述写着 「★处理设备/工具回传的媒体时必须传(screensee / camerasue 会回传 file 路径)」。 本插件返回路径才是合上这个约定。 ## 改动 - 截图落盘到 <data_dir>/browser_screenshots/,返回**绝对路径** - 结果里带 hint 直接告诉模型「调 describe_image(path=...)」—— 工具描述模型可能漏看,结果里的提示更近 - inline=true 才额外带 base64/data_uri(只有确实拿不到文件系统的场景才用) - 落盘失败**明确报错**,不静默退回 base64:那会让「上下文被灌爆」 在磁盘满/权限错时重新出现且没有迹象 - 文件名带毫秒时间戳 + 会话 id:同一轮内多次截图是常态 (生产日志里一轮截了 3 次),固定名会静默覆盖 - 会话 id 过滤路径分隔符(它来自模型且被拼进路径,否则 ../ 能写出目录外) - 未注入 data_dir 时降级到临时目录,而不是让截图整条失败 ## 判据(5 条,可杀变异,逐个实测) screenshot_test.go: - 落盘 + 返回绝对路径 + 内容逐字节一致 - 连续截图不互相覆盖(文件名去时间戳 → FAIL) - 会话 id 路径穿越被挡(../../etc/evil 仍在目录内) - 未注入目录时降级而非报错 - 工具描述必须提 path 与 describe_image(描述退回 base64 → FAIL) - handleScreenshot 返回结构必须是 path 而非 base64 (整段替换为旧实现 → FAIL;保留 path 但无条件加 base64 → FAIL) **判据本身修过两次(都是变异测试发现的)**: 1. 第一版只看 res["base64"] = b64,把 base64 写成 map 字面量的键就绕过了 2. 第二版按整段文本查 "inline",而**注释里也有 "inline"** ⇒ 把保护开关 改成 if false 仍能通过。改为先 stripLineComments 再查真实代码行 全 20 个 example 编译通过;browser 插件 go test + plugin 模式构建通过。 | 2 天前 |
| fix(browser): browser_search 解析现代 Bing 版式,并把解析失败显式报错 旧实现三处叠加,模型只拿到「标题=来源行 URL 串、无摘要」,表现为反复换词重搜: - www.bing.com 对程序化请求常回 302,拿不到结果块 → 改 cn.bing.com - 块内第一个 <a> 当标题 → 抓到来源行 deepin.orghttps://www.deepin.org;改取 h2 > a, 并解开 /ck/a?...&u=a1<base64url> 跳转包装 - 摘要正则 <div class="b_caption">.*?<p> 对现代版式 0 命中(已迁到 p.b_lineclamp*) - 分块不再用 (.*?)</li>:块内可能嵌套 <li>(deep links)会在错误位置截断 - 解析不出结果时明确报错,不再伪装成 "No results found." 夹具 testdata/bing_cn.html 为真实 cn.bing.com 响应裁剪;新增 5 项单测。 版本 2.4.0 → 2.4.1(2.4.0 = 交互式 timeout 改必填,此前已提交)。 验证:go test -race 全过、vet/gofmt 干净;线上实测返回真实标题+摘要+规整链接。 | 30 天前 |
| fix(browser)!: 截图落盘返回路径,不再回 base64 用户报告:截图直接返回二进制(base64)对 agent 十分不友好。确认属实,且 生产日志里有 agent 的**绕行实证**(2026-10-10): browser_screenshot → cmd_run(自己 base64 解码写盘)→ describe_image 那一轮跑了 920 秒。 ## 为什么 base64 是错的 工具结果是 JSON 文本,base64 PNG 会**整段进模型上下文**,而模型看不见 这些字符里的图 —— 纯粹浪费: 视口截图 100-500KB ⇒ base64 后 137-685KB(约 3-17 万 token) 更关键的是它把「解码 + 写文件」这件重复劳动推给了每个消费方,而模型做不到。 内核早有对应约定:describe_image 的 path 参数描述写着 「★处理设备/工具回传的媒体时必须传(screensee / camerasue 会回传 file 路径)」。 本插件返回路径才是合上这个约定。 ## 改动 - 截图落盘到 <data_dir>/browser_screenshots/,返回**绝对路径** - 结果里带 hint 直接告诉模型「调 describe_image(path=...)」—— 工具描述模型可能漏看,结果里的提示更近 - inline=true 才额外带 base64/data_uri(只有确实拿不到文件系统的场景才用) - 落盘失败**明确报错**,不静默退回 base64:那会让「上下文被灌爆」 在磁盘满/权限错时重新出现且没有迹象 - 文件名带毫秒时间戳 + 会话 id:同一轮内多次截图是常态 (生产日志里一轮截了 3 次),固定名会静默覆盖 - 会话 id 过滤路径分隔符(它来自模型且被拼进路径,否则 ../ 能写出目录外) - 未注入 data_dir 时降级到临时目录,而不是让截图整条失败 ## 判据(5 条,可杀变异,逐个实测) screenshot_test.go: - 落盘 + 返回绝对路径 + 内容逐字节一致 - 连续截图不互相覆盖(文件名去时间戳 → FAIL) - 会话 id 路径穿越被挡(../../etc/evil 仍在目录内) - 未注入目录时降级而非报错 - 工具描述必须提 path 与 describe_image(描述退回 base64 → FAIL) - handleScreenshot 返回结构必须是 path 而非 base64 (整段替换为旧实现 → FAIL;保留 path 但无条件加 base64 → FAIL) **判据本身修过两次(都是变异测试发现的)**: 1. 第一版只看 res["base64"] = b64,把 base64 写成 map 字面量的键就绕过了 2. 第二版按整段文本查 "inline",而**注释里也有 "inline"** ⇒ 把保护开关 改成 if false 仍能通过。改为先 stripLineComments 再查真实代码行 全 20 个 example 编译通过;browser 插件 go test + plugin 模式构建通过。 | 2 天前 |