Commit Graph

408 Commits

Author SHA1 Message Date
f2e3215c77 feat: remotedevice 二进制分块协议(录像回传+音频下发) + 工具描述增强
回应 GUI c29abe9 需服务端配套项([阻塞]两项 + [中]一项):

1. readFrame 支持 0x2 二进制帧(之前遇 0x2 直接断连):
   - 返回 opcode, 二进制帧上限放宽至 8MB
2. handleWS 二进制聚合协议(设备→网关, 录像回传):
   - cmd_data_start 开启按 req_id 聚合 → 0x2 帧追加 → cmd_data_end 聚合完成
   - 结果存 cmdresult(data_base64 字段), device_ctl_cmdresult 可取回
   - 超限防护(声明 total×2 或硬上限 64MB)
3. PushData 下发协议(网关→设备, 音频/TTS):
   - cmd_speech_start → 0x2 分块(8KB) → cmd_speech_end
   - GUI 端已实现接收侧(speakeruse 播放链路打通)
4. device_ctl_cmdrun 工具描述补齐:
   - screensue 带参示例(<内容>/<秒> <内容>)
   - camerasue 录像说明(cmdresult 含 data_base64)
   - speakeruse 文字朗读

测试: 最小 WS 客户端端到端验证二进制分块上传/PushData 下发/离线报错
2026-08-21 10:53:38 +08:00
8d368913a9 feat: webui 消息重放双重防护(client_msg_id 去重 + agent 内容级去重)
回应群聊 08-19 消息轰炸诊断(GUI SSE 重连导致消息重放):

1. webui 层 client_msg_id 单飞去重(与 GUI c29abe9 配套):
   - /api/v1/chat 解析 client_msg_id, 同 ID 重放等待首次结果直接复用
   - 响应带 deduplicated=true 标记; 无 ID 旧客户端完全兼容
   - FIFO 缓存上限 256 条防泄漏

2. agent 核心层内容级短窗口去重(兜底无 ID 客户端):
   - isDuplicateInput: source+content 为 key, 10s 窗口内重复丢弃
   - 持续轰炸时刷新时间戳保持拦截; 过期项自动清理

测试: webui 去重三场景 + agent 核心去重行为验证, 全项目 go test 通过
2026-08-21 10:23:38 +08:00
257ff0ad5d gui: 自动重登/定时授权/副屏修复 + 排障(大量JS报错根因是cookie过期)
排障: "大量JS报错"真实根因 = webui cookie 会话24h过期 → 所有 api() 请求经网关 302 → 返回登录页HTML(200非401) → renderer 拿HTML当JSON解析 → 界面持续报错/乱码

修复(api() 自动重登):
- 401 或检测登录页HTML(THEME_PLACEHOLDER/统一门户登录)时自动 syncConnAuth 重登后重试一次
- 防递归锁 _haReloginLock
- JSON解析容错(HTML不再误报)

定时撤销/恢复授权:
- prefs.deviceBridge.authSchedule {enabled, revokeTime, restoreTime}, 支持跨天(23:00-07:00)
- 主进程每分钟检查, 到点经 webui 反代 /api/v1/device/auth 撤销/恢复(防抖状态机)
- 设备页UI: 开启开关 + 撤销/恢复时间输入(保存并应用生效)
- setDeviceAuthorized 优先 authRule, 否则从 connections.json 取 URL+cookie

副屏修复:
- displays:list 对空 label(' ') trim 后显示 显示器N
- 修复 loadGuiPrefs 只返回3字段导致 screensueDisplay/exec/authSchedule 被抹掉(保存后变默认的根因)

其他:
- 移除远程调试端口(9223, 排障用)
- 保留 window.onerror/onunhandledrejection 透传(gui.log 可见 JS 错误, 便于运维)
2026-08-20 13:29:21 +08:00
c29abe9569 gui: 设备命令/能力完整实现 + 二进制分块 + 消息ID去重 + 交互优化
设备命令执行对齐服务端 cmd_type 契约:
- onDeviceMsg 解析 msg.cmd_type: homeagent->能力分发 / shell->白名单执行
- 统一回执 sendCmdResult(兼容双参), 全链路回执修复
- 修复 pi-lens auto-fix 把 trayLastCmd 改 const 导致的 TypeError(命令未执行/无回执根因)

homeagent 能力:
- screensue: 独立窗口显示文字/HTML, 可配默认屏幕(displays:list IPC), 支持时长参数 "screensue [秒] 内容", 默认常驻
- camerasue: 抓拍单张 jpeg(base64文本); camerasue <N秒>=录像 mp4(libx264), 二进制分块经设备通道回传
- speakeruse: 接收服务端二进制音频(WS 0x2), 聚合后播放(aplay/paplay/ffplay/afplay/SoundPlayer)

二进制分块协议(设备<->网关):
- 录像(设备->网关): cmd_data_start/0x2帧/cmd_data_end
- 音频(网关->设备): cmd_speech_start/0x2帧/cmd_speech_end
- 设备端 WS 读写侧都支持 0x2 帧; N/A 服务端 readFrame 需配套(已发群)

消息重放/交互:
- sendChat 带 client_msg_id 唯一ID(服务端可去重), 超时明确提示勿重复发送
- 托盘菜单: 信息项 enabled(不再灰字)+200ms防抖+连接缓存, 首建立即弹出
- 托盘显示连接/设备桥/远控活动状态

UI:
- 设备页本机卡片: 设备通道配置(网关/ws_token/screensue屏幕/cmdrun目录/沙箱)
- 设备列表经 webui 反代 /api/v1/device/online 拉取
- 连接管理移除 device 类型(设备独立为 GUI 组件), toggleConnType/saveConnForm 清理
- 字体对比度提升(text-muted/secondary重调色), 内联小字 10/11px->12/13px

preload: 新增 displays.list IPC
2026-08-20 09:07:41 +08:00
768c73889e feat: webui chat 接口支持设备身份(device_id/device_name)
- handleChat body 增加 device_id/device_name 可选字段
- 来源编码: 带设备时 webui/{device_id}(agent 可见来源), 无设备保持 webui(兼容)
- injectSourceContext: 检测 device_id 时注入「当前输入来自设备[名](id)」上下文
- 验证: 带 device_id=gui-pc-002 消息 agent 正确回答来源客厅电脑; 无 device_id 兼容
2026-08-18 11:49:57 +08:00
7246aa7092 chore: gitignore 工具产物(dist/.pi-glla/.omo) v0.9.0 2026-08-18 10:36:49 +08:00
93203c4af3 gui: 托盘菜单增强(连接/设备桥/远控状态) + 设备页 dot 修复
托盘右键菜单(rebuildTrayMenu, 动态刷新):
- 后端连接: 名称 + URL + [已连接]/[未连接](authRule 判定)
- 设备桥: [已连接]/[未连接] + 设备ID + 网关地址
- 远控活动: 上次远控命令 + 结果(输出前40字) + 总次数(收到 cmd 时记录, 回执后更新)
- 刷新时机: 启动 / connections add/update/delete/setCurrent / hello_ack/bind_ack / cmd 到达与回执
- 纯文本不用 emoji

设备页方形外框修复(根因: .dot-* 只定义 background 无尺寸, 直接包文字成整块色块):
- app.js: 状态/授权改为 <span class="dot-green"></span>+文字(本机卡片+设备列表4处)
- style.css: .dot-* 补 inline-block 8x8 圆角, 空 span 呈现小圆点
2026-08-18 09:37:05 +08:00
707a01a2dd fix: SSE 心跳直接写 w+flush(事件密集/队列满仍保活长连接)
- 原心跳经 writeCh 发送, 事件密集时队列满被 drop, 远程 nginx 网关长时间无字节导致 504/半开
- 改为主循环直接 Fprintf(w, ": heartbeat\n\n") + Flush, 绕过 writeCh, 保证 15s 恒有心跳
- 对应 pi-desktop: GUI 回复丢失(SSE 3分钟被 ERR_INCOMPLETE_CHUNKED_ENCODING 切断)
2026-08-18 09:12:52 +08:00
653dd34299 feat: 插件工具按需拉取(get_plugin_tools) + 设备命令类型拆分(shell-cmd/homeagent-cmd)
1. 提示词去污染: buildToolCatalog 从全量工具定义改为按插件分组摘要
   (插件名 + 工具数 + 能力概览), 完整工具定义由新工具 get_plugin_tools(plugin_name)
   动态拉取; 新增 executeGetPluginTools 支持按插件过滤 stageHost/io 工具
2. 设备命令类型: device_ctl_cmdrun 的 command 支持前缀区分
   - shell-cmd <cmd>      -> 设备端执行原生 shell
   - homeagent-<cap>      -> 设备端 HomeAgent 内置能力(如 camerasue/screensue)
   - homeagent-cmd <cap>  -> 同上(兼容写法)
   PushCmd 增加 cmd_type 字段下发给设备端分发
3. 测试: TestExecuteGetPluginTools 验证按插件拉取/全部摘要/未知插件
2026-08-18 09:07:21 +08:00
8172b776b9 gui: 设备桥完整链路修复(URL解耦+wss TLS+cookie回退+onDeviceMsg)
问题: 设备桥此前硬编码 127.0.0.1:9890 + /api/v1/device/ws 路径, 无法连远程 homed wss; startDeviceBridge 内部仍有 conn.type!=='device' 旧条件导致 prefs 驱动永不启动; onDeviceMsg 缺失导致引用未定义。

修复:
- connectDeviceWS: 支持完整 ws(s):// 端点 URL(含路径/端口), 不再硬编码 host/path; wss/https 默认 443, ws/http 默认 9890
- connectDeviceWS: TLS 支持(devTls), cookie 注入优先 connections.json 完整登录串(authRule 浏览器快照可能不完整)
- startDeviceBridge: 移除 conn.type!=='device' 拦截, 兼容 prefs 驱动 {url/token}; whenReady/device-bridge:set 已对应
- 补全 onDeviceMsg: 处理 hello_ack/bind_ack/cmd(白名单 argsSafe 执行+cmd_result 回执)
- no-proxy-server 开关(本机 clash 代理干扰 wss), 错误日志带完整响应体便于排障

卡点(已发群): 雷池 SafeLine 按 TLS 指纹(JA3)拦截 Electron BoringSSL → 403; node/python OpenSSL 同请求 101。需服务端雷池放行 /api/v1/device/ws 或 Electron 指纹白名单。
2026-08-18 08:51:56 +08:00
b2156a0987 fix: webui 设备网关 WS 反代改用 net.Dial 手动升级握手
- 之前 http.DefaultClient/Transport 不支持 ws:// scheme 与 101 升级, WS 经反代返回 502
- 改为 net.Dial 直连网关 + 手动构造 WS 升级请求(X-API-Key 注入) + http.ReadResponse 读 101
- hijack 后双向字节透传(WS 帧不动), 客户端->上游/上游->客户端
- 实测: 经 webui:8080/api/v1/device/ws 反代, 101 握手成功, 网关 Sec-Websocket-Accept 正确
- 对应 pi-desktop 排查记录: 远程 WS 设备通道现在可经远程 homed 使用
2026-08-17 18:16:57 +08:00
dd60f41aa1 feat: webui 设备网关 WS 反代(hijack 双向透传) + GUI 设备页本机卡片始终显示
- handleDeviceGatewayProxy: 识别 Upgrade:websocket 请求, 用 http.Transport(保留升级连接)
  + hijack 双向字节透传, 支持远程 homed 的 WS 设备通道(REST 已可用, WS 之前被 DefaultClient 卡死)
- renderDevices: 本机 GUI 设备卡片不再被 conn.type!=='device' 挡住,
  由 gui-prefs 的 deviceBridge 驱动(独立于连接), renderInit 从 device-bridge:get 拉取本机身份
- 对应 pi-desktop 排查记录(WS 反代不可用/本机卡片被挡)修复
2026-08-17 18:02:16 +08:00
5a8fda955a gui: 性能修复(星图/reasoning/渲染循环)+设备桥配置解耦(独立prefs+IPC)
性能(卡死修复, 已部署本机验证 GPU 91%->14%):
- reasoning_content 懒加载: 折叠正文不再 marked.parse, 点击展开时才解析
- 星图动画仅"星图"子面板激活才跑, 12fps限制, 关抗锯齿+pixelRatio=1, 粒子3000->1200
- renderAll/refreshAll 非chat视图跳过聊天整块重建
- switchView(chat) 多段延迟滚动到底部(修复进入停在顶部)

设备桥(配置与连接解耦, 为远程homed被控做准备):
- 设备桥改由 gui-prefs.json 的 deviceBridge{enabled,gateway,token} 驱动, 不再依赖 type=device 连接
- 新增 IPC device-bridge:get/set (状态查询+动态启停), preload 暴露 deviceBridge API
- whenReady 按 prefs 启动设备桥

待后续: 设备页UI入口(renderDevices 本机卡片仍被 conn.type!==device 条件挡住, 需改为始终显示+调用 device-bridge:set)
2026-08-17 17:35:47 +08:00
a9ec8f5b2b Merge branch 'main' of gitcode.com:JianFeeeee/HomeAgent 2026-08-17 09:34:42 +08:00
ef5f010e87 device gateway: remotedevice 插件(设备接入网关) + GUI/waiter 受控设备桥 + 设备页/授权开关/托盘/退出进托盘 + 白屏修复(惰性Tray) + deviceinfo 工具 2026-08-17 09:34:25 +08:00
2338f3f4f3 fix: 插件增量重载 + clawhubadapter ipcGoroutine 优雅退出
- Registry.Reload 改为增量: 对比插件入口文件(plugin.so/main.lua) SHA256, 仅重载有变更的插件, 未变更保持运行, 消除 plgreload 触发全量 StopAll+Load 导致的重复加载与内置插件状态错乱
- Registry 新增 pluginHashes 记录 + pluginEntryHash 辅助
- clawhubadapter.ipcGoroutine 无退出条件导致重载后旧 goroutine 永久残留(线程累积): 增加 stopCh/stopOnce, Stop() 关闭, ipcGoroutine 用 select 监听退出
- 新增 TestRegistryIncrementalReload 验证无变更跳过/变更重载
2026-08-17 08:53:39 +08:00
e43b7aa216 test: PluginManager 接口含 ReloadOne 的编译期契约验证 2026-08-16 18:52:56 +08:00
2089d41c0f sync: 同步 SDK PluginMgr API 与 dispatch 48/49/50 (vendored 副本) 2026-08-16 18:44:28 +08:00
eb577afed2 fix: healthcheck auto-check 幂等重启(stopCh 可重建, 修复 plgreload 后定时器失效) 2026-08-16 18:27:25 +08:00
da327ac3e1 feat: 导出单插件重载到 SDK (CORE_PLUGIN_RELOAD_ONE/48 + LIST/49 + IS_DISABLED/50)
- PluginManager 接口新增 ReloadOne(name) error
- cabi dispatch: case 48 单插件重载, 49 列已加载, 50 查询禁用
- 外部 SDK 新增 PluginMgrAPI(ReloadOne/ListLoadedPlugins/IsPluginDisabled)  + bridge dispatchPluginMgr 注入
2026-08-16 18:27:25 +08:00
c52331cd5e gui+webui: 聊天界面升级(PiDeck风格思考/工具卡片+滴入动画) & 流式卡顿修复(防抖局部增量渲染) & 主题系统修复(启动恢复色板/弹窗溢出wrap) 2026-08-16 09:57:29 +08:00
3f32006341 gui: 修复总网关认证(host域cookie注入+session.fetch登录+sl-session合并) & 连接持久化完整字段+网关徽标; vendor 本地 three.js 备用 2026-08-16 08:17:34 +08:00
59c9dd5153 docs+test: Lua stage 写回能力文档与测试(与 C ABI v2 对齐) 2026-08-15 18:08:01 +08:00
b4006212e7 feat: Lua 插件 stage 写回支持(与 C ABI v2 对齐)
makeStageHandler 现在把 ctx 以 Lua table 引用传给 handler,
handler 修改的字段(raw_message/llm_text/final_text/response/tool_calls/
tool_results/user_id/group_id/no_memory)同步写回内核 StageContext。
新增 TestLuaStageWriteback 验证 on_input/post_action 的写回。
2026-08-15 18:02:50 +08:00
0d963ed86f sync: 同步 SDK meta.go CABINumMin 兼容修复(与 SDK 仓一致) 2026-08-15 17:26:33 +08:00
1bc2bf5d8d fix: WebUI 配置数字科学计数法 + 增强输出通道引导提示词
- webui settings PUT: 整数型 float64(如 QQ 号)规范化为 int64 存储,
  避免 fmt.Sprint 以科学计数法(2.198972886e+09)存库导致读取解析失败
- 系统提示词【输出规则】重写: 明确消息不会自动路由,
  区分同步通道(直接返回文本)与异步通道(必须调用 output_send__{通道}),
  引导模型优先回复当前输入通道并带正确 meta(user_id/group_id)
2026-08-15 17:24:14 +08:00
014870a0e0 fix: 兼容旧 ABI 插件 + 移除 plugin.Open 致命 fallback
- CABINumMin 恢复为 1: 旧工具链编译的插件写入整数 version=1/2,
  与新版内核结构体兼容(仅缺 stage 写回能力), 应允许加载而非拒绝
- tryLoadSO 移除 Go plugin.Open fallback: 本项目插件统一为 c-shared,
  对 c-shared .so 调用 plugin.Open 会 fatal (no plugin module data) 不可恢复,
  直接返回 cabi.Load 错误避免启动崩溃
2026-08-15 16:31:51 +08:00
710b1afdf9 C ABI v2: invoke_stage 写回 + ABI 版本对齐核心版本号 (v0.9.0)
- C ABI invoke_stage 增加 result 输出参数,外部插件 stage 回调可将修改后的
  StageContext(RawMessage/LLMText/FinalText/Response/ToolResults) 写回内核
- ABI 标识版本改为字符串 semver 与核心 Version 对齐(ABIVersion="0.9.0"),
  C 层协商用派生整数 CABINum=900(major*100+minor),不再使用独立数字编码
- version_min 保证 v0.8.x(800) 旧插件向后兼容可加载
- 修复工具循环 zen 兼容补位误伤首轮 system 上下文(仅尾部为 assistant/tool 时补位)
- 更新 README 项目状态说明
2026-08-15 15:38:57 +08:00
15b45c7653 gui: renderChat 增加防护与日志; log:r 改 invoke; 修 SSE 流式丢失气泡; chat 布局 overflow 修复 2026-08-15 09:03:07 +08:00
2e47ceed8b healthcheck: 存量改进; mcp: sse 改进 2026-08-14 16:15:24 +08:00
c820280f16 webui: 多色板主题与外观弹层(主题色/背景图/模糊) 2026-08-14 16:15:24 +08:00
9e4afa3040 gui: 多主题外观(6色板/背景图缓存)/连接认证(总网关登录窗自动抓Cookie)/中英切换/插件禁用 2026-08-14 16:14:20 +08:00
76d86d4dba fix: webui 聊天面板打开时定位到最新消息(switchTab/渲染签名命中分支/图片加载后均强制滚底) 2026-08-14 12:38:24 +08:00
d3bd4c2fe6 fix: output_send 气泡时序(chatFinalIdx 插入)与 channel_output 后流式丢失 2026-08-14 00:58:41 +08:00
147d0baaf9 fix: LLM 工具循环 400、中断消息注入、ConPTY 终端支持
- agent: 工具轮请求尾部补 user 占位(zen 网关强制),tool 消息正确配对
- agent: 工具提醒/中断以 system 角色注入并带 [中断消息] 前缀,不进用户履历;系统提示词说明中断消息格式
- agentcli: 基于 ConPTY 的交互式终端(ptywin fork),terminal_create/read/write/resize/close/watch
- webui: server 输出通道适配器(保留 reasoning_content/disable_thinking)
- GUI: 沉浸式标题栏、icon 圆角重制、mascot 等打磨
2026-08-14 00:48:40 +08:00
816597caac fix: WebUI and handler bug fixes
Backend:
- handleChat/handleOpenAICompletions: added 60s timeout via context.WithTimeout
- handleAgents POST: added config.Put() to persist agent config
- handleKnowledge GET: fixed error handling (was swallowing Search errors)
- addChatMsg: reduced persistence to latest 50 messages (was 200)
- SSE: added Last-Event-ID parsing for reconnection support

Frontend:
- api(): added HTTP status code checking (throw on non-ok responses)
- setInterval(renderAll, 15000): replaced with smartRefresh() that only refreshes data and redraws active non-form tabs
- Added btn-warning/btn-success CSS classes
- SSE: fixed reconnection防叠加 in onerror handler

Tests: all passing
2026-08-13 10:18:53 +08:00
0bee4c657e add napcat-design-dna.json (original Design DNA reference) 2026-08-12 16:36:39 +08:00
21bd27b688 plan.md: add WebUI 改进计划 (参考 NapCat Design DNA)
- 设计系统适配表: 配色/字体/间距/圆角/玻璃态/阴影/动效/图标
- 信息架构重构: 侧边栏/面包屑/卡片网格/数据可视化
- 交互体验对标: 3D倾斜卡片/弹簧按钮/Toast/空状态/确认弹窗
- 实施路线 Phase 8.1-8.7 (非阻塞, 核心修复后)
- 技术约束: 保持 Go html/template + embed.FS, 无 Node 构建链
2026-08-12 16:17:49 +08:00
9d5a914941 Phase 0.1/1/3/6: 核心生产问题修复
Healthcheck 隔离 (Phase 0.1):
- 新增 internal/sdk/selftest.go: VirtualInstance 完全隔离自检空间
- PluginSDK.Selftest()/SelftestReset() 暴露隔离实例 (含 mutex)
- LLM 自检只读白名单 isSafeReadonlyTool 防写类工具污染生产
- 单测验证: healthcheck 后生产实例内容不变 + 无残留
- 存量清理: 删除 gotest/luatest 残留目录

GraphDB 去重 (Phase 1):
- migrateRelationUnique: 启动自动重建 relations 表加 UNIQUE 约束并去重
- Commit 改为存在性检查, 重复三元组仅刷新 confidence 不重复插入
- 3 个 dedup 单测全绿

配置时长解析 (Phase 3):
- parseDurationExtended 支持 2d/1w/3h 等人类可读单位
- GetDuration 全局生效, 防 2d 静默回退 30m

Agentcli 通知风暴治理 (Phase 6):
- 语义通知: 累积 notify_bytes(2KB) 或间隔 notify_interval(2s) 触发
- 生命周期即时通知: 启动/进程退出/EOF 立即通知
- 可配置 settings, 保留通知机制保证 agent 感知终端存在
- 运维止血: 已杀掉幽灵 PID 3716282 (bash git sparse clone 运行 16h)

Plan.md: 新增设计意图备忘(插件即App/分层记忆), 更新各 Phase 进度
2026-08-12 13:51:40 +08:00
c19fea2584 provider: 音频多模态序列化为 OpenAI「input_audio」格式
HomeAgent 的 ContentBlock.AudioURL 原本输出 audio_url(非 OpenAI 标准块);
现通过 MarshalJSON 在 base64 数据时自动转为 OpenAI input_audio
({data,format}),供支持音频的模型识别。非 base64(url)保留原样透传。
- parseAudioDataURL: data:mime;base64,data → (data,format)
- audioFormatFromMIME: wav/mp3/mp4/ogg/flac
- 新增单测:base64 转 input_audio、url 保留 audio_url

验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后服务健康
2026-08-10 12:55:43 +08:00
27183312ad adapters: 支持多模态(对照 llmsproxy)
- ollama: content 数组拆分文本/images(base64),映射到 Ollama messages.images;
  流式透传 reasoning_content 与增量 tool_calls
- anthropic: OpenAI content(字符串/数组) 转 Anthropic blocks(文本 + image{source})
  + thinking/空 arguments tool_use/input_json_delta 流
- openai 透传 adapter 已保留多模态 content 数组(验收确认)
- 新增多模态单测:ollama images / anthropic image.source / openai passthrough

验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后服务健康
2026-08-10 12:17:15 +08:00
f960fde785 agent: 更智能的 LLM provider 调度(byModel 精确路由 + AUTO 优先级链)
吸收 llmsproxy 的调度思想适配 HomeAgent“一源一模型”结构:
- RoutableProvider{Model,Priority} 次级接口(不破坏既有 Provider 实现)
- ProviderManager.OrderedProviders 改为按 (优先级 desc, 可用, 默认优先) 稳定排序,
  AUTO/空模型走该优先级链
- 新增 ProviderManager.ResolveForModel:精确模型名路由到归属源,找不到回落 AUTO 链
- LuaAdaptedProvider 不再无条件覆写 req.Model;显式模型名原样转发
- LLMSource.Priority + core.llm.sources.<name>.priority 配置项
- process.go: 显式模型走 ResolveForModel,AUTO 走 OrderedProviders
- 新增路由单测(优先级排序 + byModel 解析)

验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后服务健康
2026-08-10 11:54:45 +08:00
f0dacef281 lua: 吸收 llmsproxy 适配器高级特性(worker 池/静态预提取/动态签名钩子)
- 适配器 worker 池化:单 LState+全局锁(串行瓶颈)→ 每 adapter 一个 gopher-lua
  LState 池,按使用该 adapter 的源并发上限求和配置池大小,并发 transform 互不阻塞
- staticInfo 预提取:name/version/endpoint/headers 加载期编译缓存,Endpoint/Headers
  读缓存不占 worker;加载即预编译首个 worker
- build_headers 动态钩子 + hmac/sha256/base64/tohex 全局:签名型上游(kimicode 等)可接入
- provider applyAdapterHeaders 接入动态头(url/method/body/api_key/timestamp/source 元数据),
  未定义时回落静态 headers,缺省补 Authorization
- LLMSource.MaxConcurrent + core.llm.sources.<name>.max_concurrent,注册时汇总
  VM.ConfigureConcurrency
- 新增 Lua VM 测试(load/transform/build_headers/并发)

验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后 9 adapter 全部预加载
2026-08-10 11:29:57 +08:00
6d64543918 feat: 内置 ai_image 插件接入 llmsproxy 生图端点
- 新增 internal/plugins/ai_image(开箱即用,纯 Go,无外部依赖):
  - 注册 ai_image_generate 工具,POST base_url + /images/generations
  - 配置项 base_url(默认 http://127.0.0.1:8081/v1)/api_key(留空回落 core.llm.api_key)/model/size
  - 兼容 OpenAI /v1/images/generations 响应(url 与 b64_json)
- plugins/all.go 注册 ai_image
- 生图上游由 llmsproxy 侧后续配置(HomeAgent 直达其端点)

验证: go build/test 全绿;部署后 ai_image 加载、工具注册、agent 可调用
2026-08-10 10:35:47 +08:00
8dcce5a3a9 webui 删除彻底化:清理残留 config/defs/provider 悬空
审计发现 webui 多处删除只清一处、留下鬼影:
- RemovePlugin: 仅 DROP config_<name> 与 defs,config 表 plugin.<name>.* 键永不删 →
  补 DELETE config LIKE 'plugin.<name>.%'
- ConfigRegistry.Delete: 删 core.llm.sources.<name>.* 后遗留 ConfigDef、且删 core.llm.*
  不更新 guard 快照(重启/failback 会把已删源复活)→ 同步清 source defs + 写 llm 快照
- llm_impl.ReloadFromConfig: 删除默认源后 core.llm.provider 悬空,SetDefault 指向不存在源
  → 仅当源仍注册时才 SetDefault
- clawhubadapter 测试 mockSettings 补 RemoveCore/RemovePlugin
- mcp 服务器删除仍为进程内需 reload 生效(符合既有 removeServerHandler 语义)

验证: go test ./... 26 包 0 失败;本机部署 sources=3、27 插件加载、对话正常
2026-08-10 09:51:30 +08:00
cd2a27a8cc webui: 修复 '删除源/服务器' 只置 <nil> 不真删的问题
前端 deleteSource/deleteMCPServer 通过 PUT value:null 删除,但后端 handleSettings
PUT 只 SetCore/SetPlugin(fmt.Sprint(nil) → 字面 '<nil>'),导致 core.llm.sources.<name>.*
等键残留不可达的 <nil> 行,污染 LLM 源与探活。

- SettingsAPI 新增 RemoveCore/RemovePlugin;settingsImpl 接入 ConfigRegistry.Delete
- webui handleSettings PUT:body.Value==null 时改走删除分支(核心表/插件表均适配)
- 现状验证:mocktest.* 残留已从本机 config.db 清除,sources=3,无无效源
2026-08-10 09:35:29 +08:00
171e6f233b llm: 统一源接入层修复(对照 llmsproxy)
- provider: 新增 OpenAI-compatible 响应/流兜底解析,Lua adapter 异常时也能解析
  choices/message/tool_calls/usage(含 function.arguments 缺失、对象/字符串参数)
- 过滤无效 LLM 源(<nil>/空/缺 http(s) scheme),main 与 ReloadFromConfig 均跳过,
  避免 mocktest 等坏源污染 fallback 与 healthcheck
- adapter(openai/deepseek/groq/mistral/github/kimicode): 修 tool_calls 对
  nil function 的崩溃,兼容扁平/嵌套结构;openai 流透传 reasoning/tool_calls
- config: ToConfig 探活端点过滤无效 base_url,修复 supervisor 误报 LLM unreachable
2026-08-09 20:39:54 +08:00
a62f5ba0fa agentcli: Windows ConPTY 适配分支(原生实现替代剔除桩)+ cabi loader.c build tag 修复
- agentcli 平台无关化:plugin.go 拆为公共层 + ptyTerm 接口,新增
  pty_linux.go(/dev/ptmx 原实现搬移,行为不变)与 pty_windows.go
  (ConPTY 原生实现,CreatePseudoConsole + PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
  注入子进程,双管道读写/ResizePseudoConsole/GetExitCodeProcess,零第三方依赖)
- plugin_stub.go 收紧为 !linux && !windows(darwin 等仍走桩)
- plugin_test.go build tag 放宽到 linux || windows
- cabi/loader.c 补 linux || darwin build tag,修复 Windows 下
  cgo 禁用时残留 C 源文件的编译错误
- 验证:Linux 全量构建+测试通过;Windows CGO 交叉编译 + go vet 全包零错误
2026-08-07 12:32:45 +08:00
bc9ef15eb0 三层回退恢复机制(L0写前留档/L1恢复梯子/L2离线回滚)+ guard 父守护
- L0: files 插件写受保护系统路径(/etc 等)前自动留档,AbstractBeforeWrite 到 data/file_baseline
- L1: failback 受限 worker 执行恢复梯子 probe→还原DNS/proxy→还原LLM配置+ReloadFromConfig→probe,N轮有界
- L2: tracker changeset 持久化原文 blob,guard 离线 RollbackFromDisk 回滚 agentfs;SystemSnapshot 支撑
- guard 父守护: 心跳 IPC(PING/ACK unix socket, 文件心跳回退)、失败计数、退出码协议(42/43/44)、最后手段
- 发行版路径适配: system.protected_paths/network_paths 可注入,默认面向主流 Linux
- Windows 兼容: guard.go/failback.go 加 //go:build linux, guard_windows.go 提供 no-op 桩
- 修复: guard.yaml last_resort 键冲突、changeset Content 不落盘导致离线回滚丢原文

Build 全绿, vet 干净, system/recovery/ipc/tracker 单元测试全过
2026-08-05 16:00:08 +08:00
33e97f2a99 clawhubadapter: sidecar_test mockSettings 补 Remove 接口方法 2026-08-05 10:00:05 +08:00