Commit Graph
51 Commits
Author SHA1 Message Date
AskaEth 1ac02bd77e feat(gateway,admin-web): 面板可编辑 provider 推理形状 / 角色级路由 / multimodal 真语义(裁决 03.4.2/03.4.1)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 后端:AdminLlmProvider 暴露 reasoning{kind}(恒下发,""=未声明=auto)、personaModels、personaProviders;
  顶层新增 reasoningKinds / personaProviderOptions 两个**取值域**(唯一来源= runtimeconfig 导出枚举,
  校验错误文案也由枚举拼接 ⇒ 不可能漂移)
- 读写共用同一映射(admin_llm_provider.go),避免「读侧少一个键 ⇒ 面板一保存就抹掉」
- 写侧语义:缺失=保留、给出=整块/整表替换;非法值一律 runtimeconfig.Group.Validate() ⇒ 400 bad_request
  (实测非法 kind 返回 400 且 models.json 完全不动,而非 500 静默失败)
- 前端:新增 LlmProviderRouting(推理形状下拉 + multimodal 开关 + 按角色路由编辑器);
  目录能力位改三态(true/false/未标注),「未标注」不再谎称「不支持」;目录/角色清单不可用时
  **不阻塞编辑**且与「字段为空」是不同状态;绝无 mock/sample 回退
- 复核:build/vet 绿 + gateway/config 包测试绿 + tsc 0 错 + vite build 成功;2 条变异反证(删 reasoning
  补丁 → 2 例红;删 Group.Validate → 该 400 用例红)已还原
- 注意(主会话已知):npm run build 把新 SPA 写进 frontend/web/dist,而运行中的二进制优先从磁盘读该目录
  ⇒ :10942 目前是「新面板 + 旧后端」,等阶段 5 全绿后按红线「先 build 到位、再一次 restart」切换
2026-10-04 13:06:54 +08:00
AskaEth 3972ea4007 refactor(admin-web): 模型目录面板改走既有 API 层(adminGetLlmCatalog)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 新增 lib/api/admin.ts 的 adminGetLlmCatalog({refresh}) + 目录响应类型(lib/types/admin.ts),并由 lib/api.ts 再导出
- LlmCatalogPanel 不再直连 lib/api/core(它曾是全仓唯一这样做的 admin 模块),行为不变:
  五种状态判定、gzip 响应、离线粘贴导入均保持
- 复核:grep lib/api/core 全仓前端 0 命中;npx tsc --noEmit 0 错;npm run build 成功
2026-10-04 12:45:36 +08:00
AskaEth 63236c9b00 feat(capability,gateway): 工具策略落盘 + 主代理代审真接线(裁决 1.1 核对/1.3/10.4.2/13.4.3)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 1.1(核对):registry 默认两布尔 false 已一致,零代码改动(设计文档已按裁决改写)
- 1.3 + 10.4.2:新增迁移 0012_tool_policy(tool_policies 表,表名复数 + idx_tool_policies_name);
  新增 registry.PolicyStore/SQLitePolicyStore,启动 Load 覆盖注册初值、SetPolicy 先落库后改内存
  (落盘失败保持旧值并报错);面板保存路径不变但从此重启仍在
- 13.4.3:代审真接线 —— restrict.SensitiveCall 结构化判定(terminal / file write / http POST)、
  restrict.Gate/Reviewer/Resolver(无代审者或代审报错一律 fail-closed 拦截),
  组合根装进 loop.Options.Hooks 的 CallAdmit;gateway.RecordApproval 落 audit_logs
  (who=角色名 / what=approval.<工具> / result=granted|denied)并广播 approval_notice 帧
- 前端:代审小字「xxx 想要干什么,我审查后批准了」进聊天流顶部(帧→store→组件,文案单一来源
  复用 audit.Approval.Explain()),附纯 node 逻辑测试
- 复核:迁移在 data/cyrene.db **副本**上 up/down/up 各一次通过;TestRegistry_PolicyStoreSurvivesRestart
  与 TestAdminSetPolicySurvivesRestart 证明「重启后策略仍在」;terminal 触发代审 + 审计有行有端到端断言
2026-10-04 12:30:16 +08:00
AskaEth adef36538f feat(auth,gateway,user): X-API-Key 真接线 + key 一律超管 + owner 档案真落盘(裁决 15.4.2/15.4.3/10.4.5/08.4.2)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 15.4.2:管理 API 与 Bearer 共用同一 Authorize 路径,X-API-Key 命中签发表即过门;未知/已吊销/空值 401 且不回落 Bearer(fail-closed)
- 15.4.3:key 表去掉角色维度,任一有效 key 鉴权后即 owner;签发接口取消 role 分级(不再读请求体)
- 10.4.5:新增 GET/PUT /api/v1/admin/owner-profile(owner-only,PUT 带审计 owner.profile.update),0600 原子落盘 + 活档案热替换;前端主人档案改接真实 API,读不到即禁用保存,删掉硬编码默认档案
- 08.4.2:persona 的 identity.systemPrompt 必填,缺失/空白 400 显式报错,不再派生回落
2026-10-04 12:07:51 +08:00
AskaEth 6e0323b446 refactor(frontend): 拆 types.ts(871) / ws.ts::dispatchFrame(266)(纯搬移 + barrel)
执行方案 DevDocs/audit/_plan.md 阶段 0 · G0-D:
- lib/types.ts(871) → lib/types/ 11 个域文件 + 14 行 `export *` barrel(仿 lib/api.ts 先例)
  chat / ws / session / agent / flow / persona / api / admin(269) / adminWrite(176) / kook /
  notification
- lib/ws.ts(494) → 203 行入口 + lib/ws/handlers/ 8 文件;dispatchFrame(266 行) 改为按组
  分发链(7 个 handler 各持一组 case,命中 return true,未命中走原 default 兜底),
  33 个 case 标签一一守恒

机械证明:type 导出集 86 个守恒(拆后并集 diff 为空);去掉空行与 import/export 语句后
**784=784 行、排序 diff 为空**;dispatchFrame 的 case 标签集 33=33 守恒;ws.ts 的
scheduleReconnect 至文件尾与 HEAD 字节级一致。
65 个 lib/types 消费方 + 3 个 lib/ws 消费方**零改动**通过 —— tsc 0 错误正是这一点的强判据。

验证:npx tsc --noEmit 0 错误;npm run build 成功;9 个前端逻辑测试全绿(含真实驱动
拆后 dispatchFrame 的 messageSync 54 checks 与 personaSession 23 checks);
最大文件 admin.ts 269 行、最大函数 openSocket 72 行(均达标)。
2026-10-04 10:54:06 +08:00
AskaEth c7ecc3a249 feat(session,web): 会话角色不可变 — PATCH 拒 personaId + 移除前端换角色入口
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
design/22 §8-1(主人 2026-10-03 拍板):会话角色在创建时确定、之后不可变,
要换角色必须新开会话。

后端:
- PATCH /api/v1/sessions/{id} 的 personaId 改为 json.RawMessage 判「键出现」,
  出现即 400(null/""/未知 id 一律拒),且先于会话存在性检查;错误消息点名 personaId
- 删除 Server.setSessionPersona 与 PATCH 的 501 分支;title/pinned 行为逐字不变
- sessionPersonaWriter 接口与 history.Store.SetSessionPersona 保留(存储能力)

前端:
- 移除会话行「切换角色」入口与面板「挂角色」下拉(含 setSessionPersona action、
  lib/sessionPersona.ts);保留「新建会话选角色」;面板「角色」列改为只读展示

契约:Docs/api-client.md -> v0.46(破坏性:依赖 PATCH 换角色的客户端须改为新建会话)

验证:go build/vet ./... 绿;gateway+history 包测试绿(-count=1);前端 npm run build
(tsc --noEmit + vite build)绿;9 个前端逻辑测试全绿。
变异验证:改回「静默忽略」/「写绑定」两种反向实现,新断言均 FAIL。
2026-10-03 21:24:51 +08:00
AskaEth 3732c538cc feat(admin): 人格页「绑定会话数」+ 渠道账号绑定角色(B 批次 2 前端)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
按 design/22 §4.4/§4.6 + §7-4/7-7(契约先行,后端由并行代理实现)。
- 人格页:展示每个角色绑定的会话数——面板侧用 GET /admin/sessions 的 personaId 聚合(personaId 为空 = 继承默认角色,已计入默认角色并在 UI 写明口径),随既有 useAutoReload 刷新;**未新增后端字段**
- 渠道级绑定 UI:每个渠道账号加「角色」下拉(选项取 GET /admin/personas),保存走 PUT /admin/channels/{platform}/config 的 personaId;已绑角色回填、未绑定显示「跟随默认角色」(不冒充某个角色);提示语写明**群聊/陌生人会话始终用默认角色**,避免暗示可覆盖隔离会话
- 验收:npm run build 绿 + 逻辑测试(personaSession/messageSync)通过
2026-10-03 20:50:07 +08:00
AskaEth 2aa3233f84 feat(persona,web): 人格读侧(thinking 三态 + 角色级 mood)+ 面板表单 + mood 播种
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
按 design/04 §3.2(thinking 语义,showToUser 三态)+ design/01 §2.1 + 主人两条定论(心情跟角色不跟会话;mood 初值走口径 ①:由角色读端点暴露、前端加载播种)。
- 管理侧 GET /admin/personas 的 PersonaSummary 增 thinking(budgetTokens/effort/mode/showToUser)——**showToUser 保持三态**(未配置 ≠ false)
- 用户侧 GET /personas 增**角色级 mood**(取自 emotion 层该角色当前状态,非从消息推断)→ 前端加载播种 currentMood,消除「刷新后心情徽标短暂为空」
- 前端 Personas 页加 thinking 四控件(预算/effort/模式/showToUser 三态):只做输入校验,**provider 是否真支持由后端 WARN 决定,前端不假装能力**
- 先拆 useAppStore 选择器(原 494/500)到独立模块再做,避免越线
- Docs/api-client 版本号 +1(两处契约 + 三态与角色级 mood 语义)
- 验收:go build/vet/test 全绿 + linux/darwin 交叉编译 + 前端 build 绿 + personaSession/messageSync 逻辑测试通过
2026-10-03 20:40:44 +08:00
AskaEth 66a96d2f93 feat(web): 会话级角色 — 角色跟随激活会话 + 选角入口 + 面板挂角色(B 批次 1 前端)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
按 DevDocs/design/22 §4.6/§5(7) 实现(后端由并行代理在做,按已定契约先行)。
- currentPersona 由「全局单值」改为「跟随激活会话」:新增 lib/sessionPersona.ts 解析(personaId 空 → 回落默认角色),App/TopBar/chat/lib/persona.ts 全部改为按激活会话取角色(头像/背景/名字/心情随会话切换)
- 交互:新建次级会话可选角色;会话换角色入口;管理面板 Sessions 页加「挂角色」下拉(走 PATCH /sessions/{id})
- 组件拆分:Nav.tsx 228→143(抽出 NavItem.tsx 53)、新增 SessionRail.tsx 275(会话侧栏)
- 契约:types.ts / lib/api/sessions.ts 加 personaId?(建会话/改会话支持)
- mood 改为**按角色分桶**(同一角色的多个会话共享该角色心情);升级后旧 mood 值不保留(刷新即空)——属行为变化,已在报告注明
- 测试:新增 personaSession.test.ts 40 checks(角色解析/回落/乐观更新与回滚)+ 既有 messageSync 54 checks 回归
- 验收:npm run build 绿;**未做浏览器端到端**(无 jsdom/渲染测试底座),UI 交互与失败路径提示未渲染验证
- 已知余量:useAppStore.ts 494/500 行(下次改动前应先拆 selectCurrentPersona/useCurrentPersona/useCurrentMood)
2026-10-03 20:05:40 +08:00
AskaEth f42ea1e41c feat(web): B4 枚举标签映射 — labelFor 未知值原样显示
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 新增 lib/enums.ts:platform/mood 标签 + labelFor(kind,value),未知值原样返回(display-raw 红线),注释标明权威来源是 GET /api/v1/meta/enums
- 4 处 mood 渲染改用标签(Nav/TopBar/chat×2);未动 types.ts 的 MODES/Mode
- 新增纯逻辑测试 enums.test.ts(47 项,esbuild+node,零新依赖)
- 未动 admin channelFields 的第二份 PLATFORM_LABEL(记入待办)
2026-10-03 16:55:22 +08:00
AskaEth a828edacc5 feat(web): D4 会话未读徽标 — 打开即已读 + 消费 session_read
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- SessionMeta.unreadCount(可选,兼容旧后端)+ api/sessions.markSessionRead
- lib/sessionRead.ts:会话历史落地后再推游标(best-effort,失败静默,下次 GET /sessions 收敛)+ 帧归属判定(ws.ts 因此留在 500 行内)
- store.clearUnread 无变化时返回同一 state,避免多余重渲染;Nav 徽标沿用 Miuix token(mu-radius-pill/mu-err/mu-rise-in)
- 逻辑测试 35 → 54 项,含变异校验(改成 clearUnread(activeSessionId) 即 FAIL)
2026-10-03 16:47:56 +08:00
AskaEth 04a8ee0727 feat(web): 流式帧按会话过滤,非激活会话不再串入当前气泡
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- WsDownEvent 增 sessionId;流式分支(message/thinking/tool_call/tool_execution/stream_chunk/stream_end 及 legacy thinking/tool_used)统一过 streamFrameApplies
- 会话列表未解析(activeSessionId 为空)时保持改前行为,避免误丢主人自己的流
- 抽出 lib/streamScope.ts 承载该判断,ws.ts 回到 500 行红线内
- messageSync.test.ts 增 21 项断言(跨会话丢弃/激活追加/无 session 兼容/未解析回退)
2026-10-03 16:08:53 +08:00
AskaEth 1ac126fc9e feat(web): D 消息编辑/删除前端入口 + 日志聚合前端(Observability后端tail) + 修api-client契约
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- D前端: lib/api/messages.ts(patchMessage/deleteMessage,兼容裸DTO与{message}) + MessageActions.tsx(仅user消息; 单击/右键/450ms长按开Miuix玻璃菜单; 编辑弹窗预填+字数→乐观updateMessageById→patchMessage→失败回滚; 删除确认→deleteMessage→removeMessageById; 乐观气泡禁用) + chat.tsx挂载 + Icon加edit/trash/more
- 日志前端: types(AdminLogLine time:string|number) + adminSystem.adminObservabilityLogs + Observability.tsx 后端分级tail(level筛选chip注明'该级及以上'+等宽行HH:mm:ss.SSS·level着色·source·msg+30s刷新) 下半保留WS回显
- Docs/api-client §6a/§4.2 修正: PATCH /messages/{id} 实际返回 {data:<DTO>} 非 {data:{message}}(前端已双向兼容,避免误导Android)
- 前端 build 绿(167 modules); SSR冒烟11 checks
- 遗留: 未实机登录; 菜单absolute理论上边缘可裁切(可改portal)
2026-10-03 15:23:27 +08:00
AskaEth 2720d77331 feat(gateway+web): D 消息编辑/删除 WS 实时广播 — message_edited/message_deleted
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 后端: ws_hub.go broadcastMessageEdited(完整DTO,thinking剥离)/broadcastMessageDeleted(全广播+sessionId,前端过滤); history_write.go PATCH/DELETE成功后触发(404/400/501不广播); history/message_ops.go GetMessage(导出壳,取删除前sessionId)
- 前端: useAppStore.updateMessageById/removeMessageById + messageEventApplies(同会话过滤); ws.ts 消费两事件(缺content丢弃); dispatchFrame导出(可测)
- 真机e2e: PATCH/DELETE → WS收到 message_edited/message_deleted, 二次删404无帧
- Docs/api-client v0.34 §3.8; 测试 history_write_broadcast_test + messageSync.test(14 checks)
- 遗留: 前端编辑/删除UI入口+api客户端函数未接(lib/api 无 PATCH/DELETE messages); ws_hub.go 589行>500(既有)
2026-09-30 11:58:49 +08:00
AskaEth 4c3c98d5d4 refactor(web): 拆 lib/api.ts 789→109 barrel + lib/api/ 8域文件(纯搬移零逻辑)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- lib/api/{core,auth,chat,sessions,personas,admin,adminChannels,adminSystem}.ts
- api.ts 改纯 barrel 显式 re-export(export type for types, isolatedModules); 导出名 77→77, 36处导入点零改动
- 代码行多重集比对一致(仅 request/limitQuery 各加一 export 供兄弟模块); 每文件≤500/函数≤80
- 前端 build 绿(165 modules)
2026-09-30 11:52:35 +08:00
AskaEth 34c8cc4dca feat(admin): A6 通知页前端 — 统一通知/事件中心(管理面板#16)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- Notifications.tsx(254行): 类型筛选(全部/system/channel/backthink/audit,服务端重拉) + before游标加载更多(id去重/到底判定) + 空态/错误(后端文案) + 30s静默刷新; 卡片行(非AdminTable,避其rowKey升序与倒序feed冲突); Miuix
- api.ts adminListNotifications + types.ts AdminNotification(Query) + sections.tsx 侧栏项{id:notifications,group:运行时,icon:light} + AdminApp renderSection + router.ts VALID_SECTIONS
- 契约: GET /admin/notifications?type=&before=&limit= → {data:[{id,type,title,body,source,createdAt}]}; 未读/清空需后端read端点(诚实Notice,不做前端假实现)
- 前端 build 绿(157 modules); 后端端点由并发代理[194]落地
- icon 用现有 light(Icon.tsx 无 bell; 如需铃铛另加 path)
2026-09-30 08:57:15 +08:00
AskaEth 2dee372fb2 feat(backthink/admin): ③b — rag/delete 真实现 + D1 推送出口钩子(自建优先→个推兜底) + api-reference 补 D2/D3/D5 补丁
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- B5: POST /admin/rag/delete 真做(DeleteDocument→DeleteProject 级联删章节+索引清理, owner+审计, 200/404/500, 500降级兜底); users/iot scenarios+rules 诚实501(无用户表/IoT场景规则模型, 消息写明缺什么, 不伪造), 锁住 501+not_implemented
- D1: backthink/push_outlet.go PushExporter{Export}; pushOutlet 自建HTTP(2xx=送达, token仅Authorization头+error脱敏)优先→Getui兜底(未接入, 诚实日志'getui not integrated'+(false,nil)); backthink.Deps.Exporter → pusher.withExporter, Push 在WS/IM后 exportAsync(detached+5s超时, 失败仅日志, 不破坏现有投递, 限流不上报); config PushOutletConfig(PUSH_EXPORTER_* + GETUI_*占位)
- 前端 Rag.tsx/api.ts 删除后 reload + 类型; Docs/api-client v0.31 + api-reference(#23 owner/200-404, §8.4, 端点表PATCH/DELETE messages + pinned + messages?q=)
- 测试(push_outlet/admin_rag_delete/admin_honest501/knowledge store), 后端+前端build全绿+3平台交叉编译
- 刻意: Getui SDK 未接入(无SDK不硬造), 主人自建服务填 PUSH_EXPORTER_URL/TOKEN 即可
2026-09-09 00:08:29 +08:00
AskaEth 18b2040c95 feat(admin): 面板补全 — 插件安装表单+已装列表 / LLM组maxTokens展示编辑 / POST admin/llm 部分编辑合并
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 前端: api.ts(adminPluginInstall带config/uninstall/listInstalledPlugins) + types + plugins/InstalledPlugins.tsx(已装列表+安装表单, Miuix) + llm/LlmProviderForm.tsx(maxTokens输入) ; Plugins.tsx去假安装按钮
- 后端 admin_write_llm_channels.go: llmProviderRequest字段改指针, mergeLlmProvider部分合并(省略保留原值), runtimeconfig/models.go Find
- 新增测试 admin_write_test TestAdminAddLlmProviderPartialEditPreservesFields
- 前端 build + 后端 build/vet/test 全绿; Docs/api-client v0.29
- (面板无法实机登录, 用 react-dom/server 冒烟渲染 LlmModule/PluginsModule)
2026-09-08 23:47:09 +08:00
AskaEth 747b9ad414 feat(web): 聊天请求携带行为模式 mode(A3) — useChat 读当前 mode 经 REST 发送
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- api.ts chatStream 新增可选 mode,空则不写键(后端回落chat)
- useChat.ts 发送时带上 useModeStore 当前 mode,使非chat模式消息在Web端真正落库
- 修正 docblock(移除虚构的WS chat回退描述)
2026-09-08 21:07:59 +08:00
Aska cf25c6643d feat(admin): 系统设置接入已实现的后端4端点(吊销key/轮换JWT/备份/恢复),未实现项诚实标注
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
2026-09-08 04:53:22 +08:00
Aska 36bd19e997 fix(weixin): 扫码登录二维码真实可扫——前端生成QR(修坏图) + DecodeConfig容忍空config
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
weixin qrcode_img_content 是微信liteapp HTML页(非图片),后端fetch转base64只得<!doctype>→前端img坏图。
- 后端 login-qr 改返回 qrUrl(qrcode_img_content URL)+qrCode(原始qrcode),去掉坏 qrImage
- 前端用 qrcode 库从 qrUrl 生成真实二维码图片(微信扫https链接即开连接页), 新增 qrcode+@types/qrcode(纯UI依赖)
- DecodeConfig: nil config map 当空map解码(不报错), 否则 pending账号(空config)构建被跳过→未注册→登录端点404
- 测试更新(DecodeConfigNil/admin QR端点断言 qrUrl+qrCode)
- 另有 weixinAccountFor 裸weixin兜底(此前提交 d3b0921) 保证 accountId 命中
- 实测: login-qr 200{waiting, qrUrl=89}, 前端能看到可扫二维码
build/vet/test 全绿, 已部署.
2026-09-07 21:32:19 +08:00
Aska e037fab7d0 feat(weixin): 微信iLink扫码登录——面板触发+二维码显示+状态轮询+确认热连接
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
适配器: login_admin.go(StartLogin 幂等取二维码/LoginStatus idle-waiting-confirmed-failed);
       login.go 重写 Connect 委托 StartLogin+等待,后台 runLogin 轮询,completeLogin/failLogin
       (锁序 loginMu->a.mu 不嵌套反向无死锁); adapter.go 加登录会话字段
网关: admin_channels_weixin.go(2 端点 login-qr/login-status owner+审计, confirmed 合并写回
       channels.json 保留 base_url/cdn/黑白名单 + Reload 热重载连接; qrImage best-effort Base64,
       token 掩码) + server.go 路由
前端: WeixinLogin.tsx(token空→扫码按钮→二维码→1.5s轮询→confirmed提示已登录+显示bot_id),
       AdapterDetailPage 渲染, api/types 补类型
必需偏离(最小化): 允许空token的weixin账号被构建/持久化(channels.go+runtimeconfig移出
       tokenRequiringPlatforms),否则空token账号无法注册调用StartLogin; 空token保持断开(configured
       仍要求token非空),确认后才持久化连接——守红线。
测试: login_admin/admin端点用例; 后端 build/vet/test 全绿 + 前端 build 101模块绿.
2026-09-07 20:50:28 +08:00
Aska 817f1e6355 feat(chat): 动作/旁白格式统一——兼容星号(*…*/*…) + 人设强制 XML
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
模型常漂移成 *动作:弯起眼睛*(星号),前端/后端只认 <action>/<narration>,导致星号版
没被剥成灰斜体注记/没从 IM 剥除→裸出在气泡、上下文不连贯。
- parseContent.ts(新): 把 XML <action>/<narration>、全角*…*(带'动作/旁白/内心/神态/轻声'
  关键词或整段≤40字)、半角*词…*(仅关键词前缀)统一解析成 ContentPart,剥出正文进 BubbleNotes
  灰斜体注记(*动作:…*); 超长无关键词*…*保留为文本; <p>拆气泡不变
- sanitize.go: stripNarration 同样剥星号动作(与 XML 一致); splitBubbles 不变
- cyrene.yaml: 新增格式铁律——动作/旁白必须用 <action>/<narration>,禁用*/Markdown等
验收: 后端 build/vet/test 全绿 + 前端 build 绿 + Node parseContent/splitBubble 实测(5组)
2026-09-07 20:29:47 +08:00
Aska 44e7a5c2c5 feat(flow): 实时全链路流程可视化 P1——trace→graph_update→前端全链路流程页(design/19)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
后端: trace/graph.go(RunGraph 图构建器,kind/status 映射,父子优先连线,脱敏白名单+截断);
       loop/flow.go(FlowPublisher 按会话增量发布 ws.graph_update,仅主人web会话); loop span
       start/finish 折入图; run.go StartRound/EndRound; wire.go 组装+注入.
前端: Flow.tsx(全链路流程页:FlowGraphView+会话/节点/开始/耗时卡片+状态计数+节点点开日志);
       FlowGraph 组件加 onNodeClick; types/wsParse 扩展; router/sections/AdminApp 注册 flow;
       api-client.md §3.5 graph_update 契约.
验证: 后端 build/vet/test 全绿+flow_test.go 集成(span→graph→ws.graph_update主干); 前端 build 绿.
红线: 单二进制零新依赖; 工具参数/结果脱敏; 仅主人web会话; 身份靠actor元数据; 只读不虚构.
P2(并行子代理分支/泳道/节点实时日志)后置.
2026-09-07 19:10:57 +08:00
Aska 7a81071ec8 feat(backthink): 后台思考页接 WS 实时——ws.ts 处理 backthink 事件头插 store
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
后端每次思考落库发 ws.backthink(bus→hub→WS),此前 ws.ts 无 case、addBackthink 是死方法。
新增 case `backthink`→parseBackthinkItem→s.addBackthink 头插;parseBackthinkItem 兼容
Go默认字段(ID/Trigger/At/Conclusion/ShouldPush/PushResult)与admin camelCase。
配合页面(行key=id)实现增量插入、不整页重渲。build 99模块绿。
2026-09-07 18:53:26 +08:00
Aska 3386679d45 feat(channels): 适配器日志接 WS 实时推送(落库即秒推, channel_persisted)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
后端: persistIsolated 由 _ = full(不广播)改为 notifyPersisted(full); BroadcastPersisted 按
sessionId 分流——main/web:<uuid> → message_persisted(Web聊天同步), 隔离 sess-xxx → channel_persisted
(适配器日志专用, 永不写主会话 web, 红线). payload data:{message:historyMessage}(strip thinking).
前端: ws.ts 新增 channel_persisted case→parseAdminChannelMessage→pushChannelEvent; wsParse.ts 纯函数;
useAppStore 新增 channelEvents(最新在前,按id去重,cap200,不持久化); channelLogList 订阅过滤
(单adapter按adapterId/总览取adapterId非空)merge进列表(仅追加、id去重、不整页重载),保留拉历史+10s兜底.
Docs/api-client.md §3.4 补 channel_persisted 契约.
验收: 后端 build/vet/test 全绿+windows/darwin交叉编译绿; 前端 npm run build 99模块绿.
注: 偏离=web:<uuid> 归 message_persisted(保Web副会话同步), 隔离永不带web前缀红线仍守.
2026-09-07 18:51:00 +08:00
Aska 0a645b7212 feat(backthink): 后台思考面板并入已存记录——不再只读WS实时事件
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
后台思考页此前只读 /ws/chat 的 backthink/thinking WS 实时事件(后台任务完成才有),DB里
270 条 backthink_records 看不到。新增 adminBackthink() 拉 GET /api/v1/admin/backthink +
useAutoReload(10s),与 WS 事件按 id 去重、按 at 倒序展示;空态/数据源说明更新。
验收: npm run build 99模块全绿
2026-09-07 18:44:58 +08:00
Aska 5ec4c9814d feat(kook): P2 KOOK 专属页+后端 admin 端点(design/17 §2/§4)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
后端(KOOK REST, 复用 httpclient WithAuthScheme(Bot), token不打印):
- kook/admin.go(新): ListFriends/HandleFriendRequest/DeleteFriend/BlockFriend/
  ListUserChats/CreateUserChat/ListDirectMessages
- kook/admin_guild.go(新): ListGuilds/ListGuildChannels/ListGuildUsers/ListChannelMsgs/SendTestMessage
- gateway/admin_channels_platform.go(新): kookAdmin(反射解包namedAdapter命中内嵌PlatformAdapter)
  + 4 handler + adminKookView聚合(子项失败记errors不伪造)
- server.go 注册 4 条 ownerAuth 路由: /view /friends /friend/handle /message/test
- admin.go/admin_write_channel_config.go: AdminChannelAccount 加 Capabilities
前端(KOOK 专属页):
- KookPanel.tsx(新): 好友&申请/服务器/频道/成员/私信会话/发消息测试卡片
- AdapterDetailPage.tsx: platform==='kook' 渲染 KookPanel, 否则通用
- types.ts/api.ts: KOOK 类型 + adminChannelPlatformView/Friends/FriendHandle/MessageTest
文档: Docs/api-client.md 新增4端点契约(owner-only)+capabilities+v0.17
验收: go build/vet/test ./... 全绿 + npm run build 97模块全绿; 零新依赖
注: api.ts/types.ts 集中契约文件>500行属既有结构(未新增违规); KOOK其余REST方法留能力面待用
2026-09-07 18:19:31 +08:00
Aska 2e044d1d19 feat(channels): 管理面板消息日志——chat_messages 加 adapter_id + 配置级/平台/总览三粒度端点
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
后端:
- 迁移 0007:chat_messages 加 adapter_id 列 + 索引
- history.Message 加 AdapterID;persistToMain/persistIsolated 传适配器名(a.Name())
- channelbridge: 4 个持久化点 + registerSilenced 传 a;light.go registerSilenced 签名加 a
- Store 新增 ListAdapterLog(?adapter=, 不排除主会话)/ListAllLog(adapter_id!='', 总览);ListPlatformLog 保留
- 新端点 GET /api/v1/admin/channels/messages:?adapter= 配置级 / ?platform= 平台 / 无参=总览,historyMessage 加 adapterId
- 测试:ListAdapterLog/ListAllLog 过滤用例 + 端点粒度用例 + 桥接持久化断言

前端:渠道管理每配置(账号)「消息日志」按钮 + 页顶「适配器总览日志」入口 + ChannelLogPanel 弹窗(总览/配置级),Miuix 风格,build 绿。
2026-09-07 17:25:23 +08:00
Aska e9df928072 feat(web): 定时拉取优化——静默刷新不闪loading + AdminTable稳定排序/键控不重排
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- useAsyncData: dataRef跟踪,首次setLoading(骨架),已有data时不设loading(静默后台拉),成功setData/失败保留旧data
- AdminTable: rows 按 rowKey 升序稳定排序(useMemo,同批数据顺序稳定不跳),稳定key diff复用DOM不整页重绘,error&&!hasRows才显示错误(保留旧表)
- 受益: 所有useAsyncData/AdminTable面板页(会话/记忆/渠道/IoT/插件/人格/用户/RAG/LLM/自动化/可观测/仪表盘)
- npm run build绿(83模块)
2026-09-07 16:27:49 +08:00
Aska 65091f6497 feat: KOOK自动获取bot身份 + action/narration剥出气泡 + 渠道配置表单回填
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
agent-116 KOOK token即用+自动获取:
- kook/identity.go: Connect 调 GET /user/me 拿 bot 身份(bot_id/bot_username/bot_nickname), 失败容错
- 渠道列表 enrichAccountsWithBot 附 bot 身份; base_url空用默认/receive_mode默认ws(只填token可跑)

agent-117 action/narration 剥出气泡(主人需求: 动作/旁白不进气泡,按位置上/下):
- parseContent.splitBubble(content)->{body,head,tail}: body=纯文本(去标签), head=开头/中间action/narr(气泡上), tail=结尾(气泡下)
- renderContent 只渲染text(去内联灰斜体); chat.tsx BubbleNotes 泡外 *动作/旁白* 灰斜体小字(气泡外依附), SplitChatBubble 先剥splitBubble再splitParagraphs(body), <p>/\n\n/毛玻璃/SourceLabel不破坏
- 注: 非chat mode renderContent 现在丢弃action/narr(可接受)

Channels 配置表单回填(修save后输入框空):
- openConfig 从 data.accounts[0].config 回填 token(掩码提示)/base_url/平台字段/黑白名单/限流, 不再硬清空
全仓 build/vet/test绿+前端build绿
2026-09-07 15:31:14 +08:00
Aska 1ebc82fffd feat: JWT过期自动重置 + 用户端登录页 + 系统设置前三个真实实现
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
agent-111 JWT过期重置+系统设置去占位:
- ws.ts 识别401/过期 markAuthExpired(清token+停重连+expired态),isTokenExpired;wsParse.ts拆出压行371;scheduleReconnect有token未过期才重连
- api.ts REST 401→auth_expired+清token+引导重登;login走skipAuthExpired密码错不误清
- types.ts WsStatus加expired;TopBar/Nav expired显示登录过期;System.tsx去alert占位改4张事实卡+合并Notice

agent-113 用户端登录页:
- components/Login.tsx Miuix登录卡(用户名/密码→login()→setAuthToken);App !getAuthToken()→<Login>;AdminApp LoginGate指向

agent-112 系统设置前三个(owner+审计):
- auth.APIKey.RevokeAll(吊销全部key);auth.JWTService.RotateSecret(≥32校验+并发安全+新密钥不回显)
- gateway admin_system.go: POST revoke-keys/rotate-jwt/backup(VACUUM INTO)/restore(防路径穿越+恢复前自动备份+原子替换+需重启)
- wire.go 传DatabasePath;全仓 build/vet/test绿+交叉编译;api-client v0.17系统设置契约

实机验证: 登录(role=owner)+revoke-keys 200+渠道列表含kook; 全仓绿+前端build绿; .env密码仅登录验证不打印
2026-09-07 13:57:36 +08:00
Aska aedae2190b feat(config): 运行时配置体系②——渠道配置落 channels.json + 面板落盘 + 热更新
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- runtimeconfig/channels.go: channels.json 承载 map[platform][]ChannelAccount(token/baseURL/黑白名单/群聊限流), LoadChannels 优先文件/回退env, SaveChannels(0600+tmp原子写), Upsert/Delete/Masked脱敏
- channelbridge/reload.go: adapterManager 热替换——工厂重建新adapter先连接, 再原子断旧adapter(独立readCtx/进行中不中断); Bridge.Reload(platform) 逐账号增删
- 面板 PUT/DELETE /admin/channels/{platform}/config(owner+审计) 落盘channels.json+Reload热更新; GET /admin/channels 附账号掩码不泄裸token
- 前端 Channels.tsx 配置表单(id/token/baseURL/黑白名单/限流+config JSON)+保存热更新提示+掩码展示/删除
- .gitignore 加 channels.json; .env 退兜底(.env.example注明); token不打印/Config()脱敏
- channelbridge.go 拆 logic→reload.go(742→731); 全仓 go build/vet/test绿+前端build绿
- 未做真token端到端(需渠道凭据,不读.env)——如实标注待凭据
2026-09-07 13:29:41 +08:00
Aska 2d7151f979 feat(config): 运行时配置体系①——LLM 多厂商独立组落 models.json + 面板落盘 + 热更新
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- runtimeconfig/models.go: models.json 承载 [{id,provider,baseUrl,apiKey,model,fallback?,multimodal?}] 多厂商独立组(首项=生效)
- LoadModels 优先文件/回退env(GroupFromEnv), SaveModels(0600+tmp原子写), Activate/Upsert/MaskedKey脱敏
- 面板 POST /admin/llm 落盘 models.json(取代temporary内存) + GET 列组(脱敏)
- runtime/model/runtime.go: RuntimeLLM(adapter+router) atomic快照可热替换, Reload 重建不中断进行中请求; per-role路由用接口
- wire 用 NewRuntimeLLM(adapter+router), 保留 a.modelAdapter(=runtime stack, 审查模型随热更新)
- .env 退兜底(.env.example注明); apiKey不打印/Config()脱敏/热更新不中断
- 全仓 go build/vet/test 绿(54包)+交叉编译+前端build绿(79模块); api-client v0.15已同步
- 遗留: vision ModelInfo 仍读静态env(后续纳入); 保存组=生效组(第一版语义)
2026-09-07 13:07:58 +08:00
Aska 9c2a37c4ac feat: 管理面板补齐(RAG导入/记忆添加/会话接history/诚实表述) + design/16 §4.6 IM多会话隔离+第三方身份+黑白名单
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
agent-98 面板批次:
- 会话管理面板改接 history.ListSessions(主web+次级) + 新建次级会话按钮
- 记忆面板手动添加入口 POST /admin/memories(owner)
- 知识库真正实现 IndexDocument(分块+落projectindex) + POST /admin/rag 导入端点
- 三面板空态诚实表述(去除'后端M10+提供')
- RAG嵌入降级到keyword/line(无直属embedder,不伪造语义,符合红线)

agent-99 design/16 §4.6:
- model.Message.SenderName + 迁移0006 sender_name 列
- 第三方身份边界: session.ResolveActor判定(非LLM猜) + [第三方·昵称]前缀(不改源content)
- 群聊/陌生人落独立sess-xxx(persistIsolated),不写主会话,不广播
- 黑/白名单(allowGroups/denyGroups/allowUsers/denyUsers)最前拦截,不进LLM
- 多账号 CHANNELS_JSON 配置 + 每平台多实例
- 管理只读 GET /admin/channels/{platform}/messages(该平台非主人消息流)

实机验证(JWT): 会话管理返回主会话web / 记忆添加成功 / RAG导入documents非空+Cyrene命中; 后端build/vet/test全绿 + 前端build绿
2026-09-07 05:13:36 +08:00
Aska 37e98ec584 feat: IM平台列 + deviceID标识 + 会话持久化完善
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- agent-96: chat_messages 加 platform 列(迁移0004) + IM主人私聊落主会话web(带platform) + 前端按平台过滤契约 + message_persisted 带 platform(复用 BroadcastPersisted)
- agent-97: chat_messages 加 device_id 列(迁移0005) + history.Message.DeviceID + Web发消息带deviceId(localStorage getClientId) + IM persistToMain 带 deviceID + 前端气泡展示 SourceLabel + 修主会话基础2个bug(fn scanMessage语法/DDL缺列)
- design/16 §4.4(平台) + §4.5(deviceID) 已入档
- 实机: POST /chat 带 deviceId 读回 user/assistant 均带 deviceId+platform; 后端 build/vet/test 绿 + 前端 build 绿
- 红线: 身份靠 actor 元数据; 禁止 shell 读 .env(JWT冒烟由主会话跑)
2026-09-07 04:51:41 +08:00
Aska 1bf60c1ae4 feat: IM式跨端实时同步——message_persisted 广播 + 前端按id去重追加
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- history.Store 新增 AppendFull(返回含 id/createdAt 的完整消息),Append 签名不变
- session_orchestrator 加可空 OnPersisted;persistUserMessages/persistAssistantReply 落库后回调广播
- server.go newOrchestrator 接 OnPersisted → hub.broadcast message_persisted(thinking 剥除)
- 前端 ws.ts 加 message_persisted case(仅 activeSessionId 匹配才处理);appendOrUpdateMessage 升级为 id 精确upsert+内容/时间归一
- 实测:双 WS,A stream 发消息,B 免刷新收到 user+assistant 各1条(count=2 PASS)
- 红线: 身份仍靠 actor 元数据,不靠提示词;用户/助手消息、本端/异端统一路径
2026-09-07 04:16:29 +08:00
Aska bcc53d68f3 feat(web): 前端接会话持久化——拉历史热分页 + 侧栏会话列表
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- store: 消息真源移到后端(sessions元数据map + activeSessionId,partialize 移除 messages 改存会话元数据,version:2 migrate 清旧数据)
- api: fetchSessions/createSubSession/fetchMessages(热分页before游标)/deleteSession + MessageDto→toChatMessage
- Nav: 侧栏「会话」区——主会话置顶 + 次级列表 + +新建会话(Miuix)
- 新增 HistoryList: 顶部「加载更早」向上分页 + 保守虚拟化(>200只渲染最近200)
- useChat: send 用 activeSessionId;App: token 后 fetchSessions→激活主会话→拉近50条
- Docs/api-client: v0.10 补 WS sessionId + history 回放事件契约
2026-09-07 03:52:50 +08:00
Aska 4ad1e465da feat(web): 聊天背景渲染 + 思维链/工具卡富化
- persona.ts: 新增 personaChatBackground(p, orientation),只取本角色对应方向的图
- ChatShell.tsx: 按横/竖屏渲染角色聊天背景(衬底+scrim),null/无图回退纯 Miuix 面
- chat.tsx: 思维链块加图标 chip+spinner+收起预览;工具卡加状态色 chip+ok/fail Tag
- 红线: 绝不 fallback 昔涟/其它角色;TemplateCard detail 折叠判定等行为不变
2026-09-07 02:57:37 +08:00
Aska 7455d09d05 feat: 角色视觉体系(头像按角色取)+ 时间注入(loop 每轮当前时间)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
【角色视觉体系(红线:每个角色自己的头像/背景,绝不串用昔涟)】
- persona.go:Persona 加 Visual{avatar, chatBackground{landscape,portrait}} + DefaultAvatar;每个角色各自配。
- cyrene.yaml:昔涟配 avatar(3F-Q-Happy-1) + chatBackground(横/竖屏)。
- PersonaStore 加 Persona(id);PersonaSummary 加 avatar/chatBackground;collectPersonas 按角色取
  Persona(id) 视觉(无视觉→空,前端回退默认占位,绝不串角色)。
- 前端:types PersonaRecord 加 avatar/chatBackground;persona.ts personaAvatar(p)=p?.avatar||默认占位
  (殊无昔涟 fallback);store 加 currentPersona;App 挂载 fetchPersonas 取默认角色;
  TopBar/chat 头像改 personaAvatar(currentPersona)(写死昔涟头像已清除)。

【时间注入(她自然知道现在几点,深夜催睡交给人格/capacity)】
- options.go Options 加 Timezone;loop.go Loop 加 timeLocation/timeZoneName + New 解析 + loadTimezone;
  time.go currentTimeBlock()(当前时间+周几+时区,每轮刷新);memory.go assembleContext 在「工作记忆」
  前注入时间 system(keyed 在 timeLocation!=nil,无时区不注入不破坏测试);wire.go Timezone=a.cfg.Timezone。

go build/vet/test 全绿(gateway/loop/persona);前端 tsc/vite build 75模块绿。红线无写死昔涟头像。
2026-09-07 02:46:40 +08:00
Aska 33eeadfc38 fix(backthink): 后台思考静默广播——不再把内部推理泄到聊天思维链 + XML 动作/旁白解析
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
【静默广播修复(bug:思维链露出 backthink 推理)】
- 根因:LoopThinker.Think 复用同一 loop.Loop 且 loop 全局带 OnStream,backthink 后台思考时
  把 [background autonomous reflection] 的 thinking/流式事件广播到前端,被当聊天思维链显示。
- loop/mute_ctx.go:WithMutedBroadcast(ctx) + isMutedBroadcast(ctx)——context 上静默标志。
- loop 四处广播抑制(stream.go 流式 / step.go 静默走非流式 agentStep / request.go capacity 事件 /
  tools.go tool_execution),静默时跳过 UI 广播,推理照常返回结论。
- thinker.go LoopThinker.Think 用 loop.WithMutedBroadcast(ctx),backthink 不再泄 thinking。

【XML 动作/旁白结构化解析】
- cyrene.yaml systemPrompt 加「表达方式:动作与旁白」——动作 <action>…</action>、
  旁白 <narration>…</narration>;克制≤1-2个/段、贴合唤醒态、重要信息不加、朗读正文忽略标签。
- 前端 parseContent.ts:ContentPart[](text/action/narration),非贪婪+反向引用、跨行、非法/
  未闭合兜底纯文本不崩;summarizeContent 供思维导图/状态。
- 前端 renderContent.tsx:action/narration → 灰斜体(mu-text-lo italic)句中原位渲染。
- 应用到 chat.tsx UserBubble/AssistantBubble + messages 各 mode body。

go build/vet/test(loop/backthink)绿 + 前端 tsc/vite 绿。
2026-09-06 22:09:51 +08:00
Aska 6dbb4a2e18 feat: 唤醒式架构批次——capacity/L4/会话编排/管理面板写CRUD/前端集成(77-81)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
【capacity 唤醒式核心(77)】internal/runtime/capacity:(Decider L1启发式+L2上下文+人格覆盖→三态静息/唤醒/全能→允许工具集+capacity_awaken事件)。loop 外围允许集过滤(不硬阻断=能力≠边界红线)。config 加 Capacity(Enabled/MinConfidence/ToolSets)。wire buildCapacity 接入 loop。

【L4 记忆驱动意图(80)】recall.go:从记忆召回用户习惯(搞一下xx=办事)→唤醒L1/L2漏掉/升置信;群聊陌生人不读owner习惯(隔离红线);RecordIntent闭环(判定写回记忆越用越准);默认保守静息。

【会话消息编排(78)】gateway/session_orchestrator.go:每会话(模式/pending有界5/tail上下文尾巴20);Submit非阻塞(idle立即/busy入队ack/满拒绝);完成回调按序续接(tail+新消息合并增量注入非全量重放);Interrupt中断;REST 202/409+WS session_busy/pending_ack事件;不重造任务引擎复用loop。

【前端集成(79)】ws.ts 加 capacity_awaken/session_busy/pending_ack 解析;store 加 awakenState/sessionBusy;TopBar/ChatShell 加唤醒态徽标+忙态提示(不阻塞输入框);状态组件 status.tsx;Miuix风格。

【管理面板写CRUD(81)】20个写端点(POST/PUT/DELETE /admin/*,owner+审计落库):personas(真持久化YAML)/users apikey(签发掩码+撤销)/iot控制(真下发)/automations(建/触发/删)/llm(test真调用+临时)/channels(connect/close/身份测试actor白名单)/plugins(卸载)/memories(search真检索)/sessions(export)。无存储如实501不伪造。拆4文件满足≤500红线。前端9模块接真写。

【wire收口】buildCapacity接入loop+OnCapacity事件;server.go newOrchestrator接hub。

实机验证:iot ac.living control 200 真实改变 on:true;observability/metrics 200、health ok;全仓 build/vet/test 47包绿+前端tsc/vite。
2026-09-06 21:54:40 +08:00
Aska e0a543cc37 feat(observability): 管理面板可观测性接真实数据——metrics/trace/audit 三端点 + 审计持久化
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- observability.go/observability_metrics.go/observability_trace.go/observability_audit.go:
  拆分保证 ≤500行/函数≤80。metrics 并发安全 MetricsCollector(方法/路径/状态计数、平均/最大延迟、
  近1s QPS窗口);trace 并发安全 RingBuffer(默认512, newest-first)+traceSink+MultiTraceWriter;
  audit AuditStore 接口+内存回退+SQLite 持久化(NewSQLiteAuditStore 参数化 SQL+audit_logs 表)。
- server.go:Deps.AuditStore + Server.obs + 3 路由 GET /admin/observability/{metrics,trace,audit};
  ObserveSpan/TraceSink 注入点;middleware logging recordMetric;audit 落库(仅 slog→Append)。
- 前端 Obs.tsx:metrics 接 4 张真实 StatCard+请求分布、trace 接 span 列表(展开 props/events)、
  audit 从后端拉(前端内存审计作回退);api.ts/types.ts 加 obs 端点/类型(AdminObservabilityMetrics/
  AdminTraceSpan/AuditRecord.id 放宽)。成本指标不伪造(保留'—'+注明)。
- wire.go 收口:Deps.AuditStore 注入 gateway.NewSQLiteAuditStore(ctx, a.db)(审计真落库),
  未注入回退内存。
- Docs/api-client.md §2/v0.6。

实机验证:三端点 200,metrics 返回 totalRequests:4/qps:4/perPath/statusCounts:{200:4}。
go build/vet/test 全绿 + 前端 tsc。trace 数据源对接(gw.TraceSink→loop tracer)因 gw/tracer
构造顺序留作可选后置(端点已就绪, 未对接 span 空)。
2026-09-06 21:02:46 +08:00
Aska dbcf3df8a3 feat: RAG 知识库真实数据 + 渠道端到端接线(并行∦wire.go)+ 主会话收口
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
【渠道端到端·接线(agent-72)】
- 新建 internal/services/channelbridge/:桥接服务(Start 对配置渠道 Connect(10s超时/warn)+SetMessageHandler+ReadMessages;
  入站 UnifiedMessage→sessions.GetOrCreate(ResolveActor 白名单结构性识别)→loop.Run→SendMessage 回执,chat 文本)。
- cmd/cyrene/channels.go:从 CHANNEL_* env 读 4 渠道凭据(telegram/qq_obv11/weixin_ilink/webhook)。
- wire.go:app 加 channelBridge 字段,wireChannels 构造适配器+bridge.Start(),close() 收尾。
- 无真凭据降级:无 CHANNEL_* → configured()false 跳过不 dial;Connect 失败 Warn 不阻启动;
  webhook 仅入站(回执 ErrUnsupported 记 debug)。身份识别绝不靠提示词。收发端到端待凭据验证。

【RAG 知识库(agent-71)】
- internal/runtime/knowledge/:真实数据源(doc=资料/记忆=经历 分离 design/03 §3③)。
  ListDocuments 走 projectindex.ListProjects(+ListChapters)、Search 走 projectindex.Search(标题/描述+章节
  命中行+上下文)+retriever.Retrieve(配 vector 真语义,命中标 semantic:true)。
- gateway/server.go:RagStore 接口+Deps.RAG 可空+3 路由(GET /admin/rag、POST /admin/rag/query、/delete)。
- admin.go:adminListRag/adminSearchRag(空 query 400)/adminDeleteRag(写 501 not_implemented,M10)。
- projectindex/store.go:ListProjects/ListChapters。
- 前端 Rag.tsx:docs 从 GET /admin/rag 拉、检索走 POST /admin/rag/query、删除调真端点(501 显示 Notice),
  上传/分块/嵌入显示 M10 Notice;api.ts/types.ts 加 adminListRag/adminSearchRag/adminDeleteRag。

【主会话收口 wire.go】projStore 提到 app struct+wireMemory 赋值;knowledge.New(...) 注入 gateway.Deps.RAG。

实机验证:admin/rag 200(documents[] 空表非壳)、channels 枚举 4 渠道、health ok。
go build/vet/test 全绿 + 前端 tsc。wire.go 567 行。

遗留(记录):① 群聊/陌生人 MemWritable 记忆隔离未接 loop(AGENTS.md 红线,待修) ② webhook InboundHandler
需 gateway 挂载 ③ RAG 语义路径 persona-scoped(project 记忆其他 persona 不浮现)。
2026-09-06 20:09:09 +08:00
Aska 518bd0a230 feat: admin 端点补齐 + 视觉真推理 + 语音链路 + wire.go 收口(A+B+第3步)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
批次A admin 端点(原本 404 变 200 真实数据):
- GET /admin/llm:读 s.cfg.LLM 组 openai+anthropic 两 provider(enabled=当前 Provider、multimodal=配 VisionModel),APIKey 不进 wire 零泄露。
- GET /admin/automations:*automations.Service.List()(reminders+event rules+cron schedules,cron 加只读登记)。
- GET /admin/users:cfg.AdminUser + *auth.APIKey.List()(密钥掩码);无用户存储,恒先返回当前 admin 账号。
- GET /admin/backthink:*backthink.Backthink.List(ctx,50)。均只读、owner/admin RBAC、{data} 信封。

批次B 视觉真推理 + 语音:
- rest.go chatRequest 加 Image?;流式 publishChatStream 带 image;userChatMessages 构造 ImageMessage(model.go:71)。
- loop/vision.go:ImageResolver 可注入(MVP 先看图再对话);run.go Run 开头 resolveImages,无 resolver 透传直交主模型。
- vision/resolver.go:MessageResolver 调 vision.Router.Route——KindMain 保留图片交主模型多模态、KindVisionTool/OCRTool 经 dispatcher.Invoke 折叠成 [图片内容] 文本、KindUnsupported 记日志保留原图不崩。
- gateway/voice.go:VoiceService 接口 + SetVoice 注入点 + handleVoiceInput(未注入回 error 不崩)+ runVoiceTurn 异步 STT→loop chat→TTS→定向 voice_output 帧。
- ws_hub/ws_route:voice_input 接 handleVoiceInput;前端 ws.ts decodeBase64/playVoiceAudio/case voice_output。

第3步 wire.go 收口(唯一碰 wire.go 的一步):
- Deps 补传 Automations:a.automation / Backthink:a.backthink / Users:auth.NewAPIKey(a.cfg.Auth)(*auth.APIKey 原生满足 UserStore,避免 admin 重复的复合类型)。
- gw.SetVoice(a.voice);loop.Options.Vision = vision.NewMessageResolver(router, info, dispatcher.Invoke)(router=NewRouter(WithVisionTool/WithOCRTool)、info=cfg.LLM.VisionModel)。

实机验证:四 admin 端点 200 真实数据(llm 双 provider 脱敏、users=admin,yeij0942,owner);WS 握手正常。go build/vet/test 全绿 + 前端 tsc。wire.go 557 行。
2026-09-06 18:54:05 +08:00
Aska 2248ddce15 feat(web): 用户侧体验补齐——思维链/工具卡数据源 + 图片附件 + 语音上行 + home/vision/voice 真表现
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 打通 thinking/tool_call 运行时数据源:openai 发 thinking_*(reasoning_content)/tool_call_*
  (delta.tool_calls 累积重新组装 Args 非 JSON 串);anthropic_stream 发 thinking_*(content_block
  thinking start/delta/stop)。ws_bridge 已映射 thinking.*/tool_call.*,前端渲染活。
- 前端消息模型 + 附件:ChatMessage 加 image?;ChatInput 加附件按钮(file→base64)、预览/移除、
  image-aware onSend(text,image);VisionMessageBody 升级图像卡+识别 chip;VoiceMessageBody
  升级通话控制卡(live2D预留/波形/静音/挂断);HomeMessageBody 读真实 deviceUpdates(去掉
  sampleDevices 猜)。
- 激活 voice_input:ChatShell onVoice 不再 no-op → sendUp voice_input + 切 voice mode。
- addTool 改按工具名 upsert(修复 tool_call.start/end 重复卡);ws_mode_switch 应用 agent 驱动
  mode;addUserMessage/beginAssistant 带 image/mode;chatStream/useChat.send 带 image。
- 新增 image/phone 图标。

已知限制(标注):图片仅前端收集(后端 chatRequest 无 image 字段未接真推理);流式工具卡无真实
工具名(StreamEvent 只带 ID,回退 tool_<id前缀>);mode 由 agent 驱动但后端未逐消息下发 mode
(mode_switch 回显+默认当前 mode 兜底);voice 为 UI+voice_input 上行(真实通话后置)。
go build/vet/test + 前端 tsc 绿。
2026-09-06 17:43:03 +08:00
Aska 24d5924cee feat(model): Top5#1 结构化流事件 + WS 事件体系(对齐 OpenClaw AssistantMessageEvent)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 新增 model/stream.go:StreamKind(text/thinking/tool_call 各 start/delta/end + tool_execution)
  + StreamEvent{Kind,Delta,Index,ID}。
- ChatStream 签名 onChunk func(delta string)→onEvent func(StreamEvent);loop OnStream 同改;
  streamStep 转发结构化事件。
- openai:text_delta + text_start/text_end(正文三段式);anthropic:文本块 text_*/tool_call_*
  按块 Index(content_block_stop 分支)真分段;fallback:有事件即交付。
- ws_hub:wsEvent 壳补 turnId/seq;新增 broadcastStream;streamChat 每帧打 turnId+seq;
  stream.go 把事件 publish 到 bus ws.stream。
- ws_bridge:streamEventData 映射 text_*→message.start/delta/end、thinking_*→thinking.*、
  tool_call_*→tool_call.*、tool_execution_update→tool_execution.update,未知回退 stream_chunk。
- 前端 ws.ts:解析 message.start/delta/end、thinking.start/delta/end(pendingThinking)、
  tool_call.start/end→addTool、tool_execution.update;保留旧 stream_chunk/thinking/tool_used 兼容;
  types.ts 补 turnId/seq。Docs/api-client.md 增 §3.1 v0.4。

已知限制(注释/文档标注):turnId 在 OnStream→bus→relay 路径暂为空(StreamEvent 无 turnId 字段,
bus ws.stream 载荷不带 turn);OpenAI adapter 未解析 tool_call 段;thinking 段两 adapter 暂不发;
tool_execution.update 是保留项(随工具循环钩子后置)。go build/vet/test + 前端 tsc 全绿。
2026-09-06 16:31:28 +08:00
Aska 77f75b0d99 refactor(web): 前端单页收敛修正——导航式侧边栏 + 去输入模式 chip,mode 由后端自切
按设计/01 §3 + 主人要求:行为模式切换由后端/agent 自切(热切换),前端不再提供
手动切换的行为模式按钮列表。
- 侧边栏改为导航式(连接状态 / 设置 / 管理面板 / 主题),不再列行为模式按钮;
  App.tsx 还原 <Sidebar/> 布局。
- ChatInput 去掉行为模式 chip 切换条(模式不由用户手选)。
- useChat.send/chatStream 不再传 mode;消息 mode 由后端在回复时决定,
  MessageBubble 仍按 message.mode 渲染。
- ChatShell onVoice 为占位(语音处理在 agent)。
2026-09-06 14:04:46 +08:00
Aska 4aab0f501a feat(web): 前端收敛为「共享消息流 + 按消息 mode 渲染」,并补全 emoji→MD3 图标
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
架构变更(主人要求,design/07 §1/§2 已改定稿):把「9 个行为模式 = 9 个独立页面」改为
「一个共享页面 + 每条消息绑 mode,消息框按对应 mode 渲染」。
- ChatMessage 增 mode?(types.ts);useAppStore addUserMessage/beginAssistant 带 mode;
  useSendChat.send(text, mode) / chatStream body 带 mode(通知后端按 mode 回复)。
- MessageBubble 按 message.mode 分发到 components/messages/ 各形态渲染器
  (chat 气泡 / code 等宽代码块 / home 设备卡 / docs 文档卡 / work 任务卡 / vision 视觉卡)。
- ChatInput 顶部加「行为模式」chip 切换下一条消息的 mode(默认 chat);输入框上方显示当前模式。
- ModeRouter 收敛为只渲染 ChatShell;删除 9 个旧独立 mode 页面;Nav/TopBar 的 mode 改为
  「输入模式」语义;settings 归管理面板(design/10)。

同时补全上一轮 emoji→MD3 图标(约 23 文件):新增 Icon.tsx(MD3 SVG、IconName、零依赖、
离线优先),全部界面 emoji 替换为 <Icon name=... />;正文说明箭头保留。

npm run build 绿(tsc 0 错,79→71 模块,JS 284KB/gzip 86KB)。
2026-09-06 13:32:44 +08:00
Aska f43eb17030 feat(frontend/admin): M10 后台管理面板(/admin hash 路由 + 15 大模块 + RBAC(owner/admin/viewer) + 审计 + Miuix);Docs/api-client.md v0.3 契约补全;tsc+vite build 通过 2026-09-06 07:55:04 +08:00