AskaEth
|
f91a83ff81
|
feat(urgency): 通用紧急度通道(Declarer/Level + 只抬不压折算)+ IoT 首个生产者 + 她自己的结论走结构化标记穿透安静时段
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 13:11:04 +08:00 |
|
AskaEth
|
4a2d276881
|
feat(capability): 转码能力包(vendor 纯 Go AMR-NB 解码器 + 黄金向量逐样本对照 + 8 哨兵 + 注册面)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 13:02:28 +08:00 |
|
AskaEth
|
89715d1813
|
feat(channels): 受限车道回合补自身会话历史(群聊/陌生人能连贯理解一段对话;复用共享 transcript,拒绝主会话 id)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:58:01 +08:00 |
|
AskaEth
|
be6e5f5780
|
docs(api): 契约升 v0.67(契约先行登记:media 播放端点 + voice DTO + 渠道事件查询面 + accountOnline;三批未实现已如实标注)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:53:35 +08:00 |
|
AskaEth
|
b82870f41e
|
fix(channels): QQ 适配器接上注入 logger(帧取证复活)+ 兜底不再静默降级(Warn 说明 Debug 会被丢)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:53:17 +08:00 |
|
AskaEth
|
e1bd7c3009
|
fix(channels): 探活失败不再静默 + 回执信封校验(杜绝把失败谎报成账号离线)+ echo 唯一化
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:29:34 +08:00 |
|
AskaEth
|
8f6a75b7d7
|
feat(channels): IM 车道生成并写入真实 turn_id(user/assistant 成对 + 同源 WithTurnID;群聊隔离与静默语义不变)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:22:44 +08:00 |
|
AskaEth
|
ba1974038a
|
feat(gateway): 并行提示接线(第二路 + 串行续跑路;OtherMessageID/Queued 取自另一在途路,无其它在途路则不挂)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:21:24 +08:00 |
|
AskaEth
|
20160c66d8
|
feat(security): 代审口径 A 落地(仅子代理发起的敏感调用做实质判定 + fail-closed + 理由进审计与小字)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:12:31 +08:00 |
|
AskaEth
|
fa850f9599
|
feat(loop): 落地 design/15 §2.5.6 并行提示(结构化 ParallelNotice + 独立 system 行,杜绝一题多答/跨端串话)
|
2026-10-05 12:12:23 +08:00 |
|
AskaEth
|
a79fe9684e
|
feat(channels): QQ 账号 get_status 主动探活(复用既有 action 通道 / 状态变化才记日志 / AccountStatus 与 WS 连通分开)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:10:34 +08:00 |
|
AskaEth
|
f44114301e
|
feat(channels): 微信入站媒体脱敏取证日志(形状行记 ref 来源+host、结局行记 err_kind;不记 URL/query/密钥)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 12:07:18 +08:00 |
|
AskaEth
|
5139945bfe
|
feat(channels): 非消息事件接入(notice 归一化 + 传入前审查,fail-safe 静默)与入站脱敏帧日志/日志轮转
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- notice:adapter 归一化 seam + 结构化分类 + 净化(ANSI/控制/零宽/双向字符、200 runes 截断)
+ fail-safe 写死为「静默」(未装配审查/超时/失败 ⇒ 仅登记、不驱动 loop)
- 身份面零改动:notice 发送者恒 RoleSystem + SenderID=system
- 复用策略四的同一个审查模型(Options.Review),未另造第二套
- 入站帧脱敏 DEBUG(post_type/message_type/sub_type/self_id/user_id/sender_id/group_id/段类型/at 目标)
- ctrl.bat 启动前归档轮转(保留 20 份)+ bash 侧改追加(不再重启即截断)
|
2026-10-05 11:55:05 +08:00 |
|
AskaEth
|
85abb90067
|
feat(security): 敏感清单补齐 design/11 §4 的 7 类(写数据/对外发消息/访问密钥/改配置,结构化判据)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:53:17 +08:00 |
|
AskaEth
|
509dc412eb
|
feat(memory): 记忆 P2(项目索引物化 / decay 回写 / 作用域写规则 / 静默吞点 + loop 级只读红线测试)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:47:39 +08:00 |
|
AskaEth
|
9b903a89bc
|
feat(runtime): IM 主人私聊补历史转录(与 Web 主会话同源:抽共享 transcript 包 + OwnerEnvFor 单入口)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:36:18 +08:00 |
|
AskaEth
|
df8fc660c0
|
docs(agents): §10 补铁律——提交一律逐文件 git add(实测吞过别人在途文件)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:31:24 +08:00 |
|
AskaEth
|
2b6750b821
|
docs(channels): 再修 3 处注释里的 design/08 引用(其中 -14 口径无对应节 ⇒ 改指对照清单)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:31:14 +08:00 |
|
AskaEth
|
eeb5f26668
|
fix(memory): 堵住 knowledge 工具绕过群聊/陌生人过滤的 P0 / owner 召回 hits 如实上报 / 静默吞点补来源日志
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:30:51 +08:00 |
|
AskaEth
|
e792baa316
|
docs(channels): 修正 6 处指向已不存在 design/08 节号的注释(只改注释)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:29:54 +08:00 |
|
AskaEth
|
91a3209c9b
|
feat(memory): 记忆整理 v1(design/23)——低峰定期扫描 + 事实包含判定 + 规则否决 + 只产建议队列(不自动应用)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:29:36 +08:00 |
|
AskaEth
|
012e9f3ad4
|
feat(web): 前端 P0 收尾(多路忙态收口 / 握手 history 落 store / 清理幽灵键)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:29:17 +08:00 |
|
AskaEth
|
e852e60af9
|
docs(channels): media_key 注释指向修正(design/08 §3.3 已不存在 → §4 weixin-ilink 条目)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:26:02 +08:00 |
|
AskaEth
|
afd56ffd99
|
docs(agents): §10 补两条铁律(换二进制前先确认前端变更 / 裁定必须带完成状态)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 11:22:27 +08:00 |
|
AskaEth
|
1e0f2c9ec8
|
docs(api): v0.66 补充说明——chat.image 体积上限按形态写清(描述性更正,不升版本号)
|
2026-10-05 11:22:26 +08:00 |
|
AskaEth
|
b73a1276c6
|
feat(channels): IM 入站图片接线(纯图片不再被丢 / data URI 进模型视图 / 诚实提示 / 来源白名单)
|
2026-10-05 11:22:26 +08:00 |
|
AskaEth
|
0cbc9ff886
|
docs(api): 契约升 v0.66(帧层 + turn_id + 渠道配置 + 修正未实现清单 + 思考流口径更正)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 登记 turn_begin / steer_ack 帧壳 turnId / interrupt.turnId(仅 scope=current)/ 帧序按实现
(session_busy → message_persisted(user) → turn_begin)/ activeTurns / cancelledTurns /
pending_ack.reason=parallel_limit / session_idle 并行时收紧
- chat_messages.turn_id:历史 DTO、PATCH 响应、admin 渠道日志、message_persisted /
channel_persisted / message_edited、握手回放均增可选 turnId(空则键省略)
- 渠道配置:open|close 可选 accountId + resolved/accountId;DELETE config 显式 empty=1 + removed/empty;
GET /admin/channels 的 accounts[].connected
- 语音:VOICE_STT_TIMEOUT_SEC;IM 入站附件引用落库(行为变更)
- 修正 v0.65 的「未实现」清单(那 5 项都已实现并上线)
- 思考流口径更正:历史 thinking 恒缺席(全仓无写入者),思维链唯一出口是实时 thinking.* 帧
|
2026-10-05 11:15:25 +08:00 |
|
AskaEth
|
eaada3af5d
|
feat(web): 前端与后端同步一批(帧壳 turnId / 并行六态与两级分桶 / documents 渲染 / System 键名 / 主人档案分组)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- 帧壳 `turnId` 在 socket 层不再被丢(`lib/ws.ts` 的 dispatchFrame 补 turnId/seq)—— 按路分桶的前提
- 并行帧组接入:`turn_begin` / `steer_ack` / `pending_ack` / `pending_drain` / `pending_full` /
`chat_duplicate` ⇒ 六态 + 灰态 + `(sessionId, turnId)` 两级分桶;`appendChunk` 不再永远写尾气泡
- 多路忙态:`session_interrupted` 不再无条件当空闲(看 mode/activeTurns);`stream_end` 不再只按会话过滤
- `documents` 渲染(含 status/chars/truncated 与**逐字中文 reason**);`turnId` 历史行分组小标
- `System.tsx` 键名改正(真键 HOST/PORT/ADMIN_USERNAME/ADMIN_PASSWORD,避免照抄静默失效)
- 主人档案**按平台分组** + 平台下拉 + 账号候选;**写盘仍展平数组**(后端契约不变)
- 验证:tsc --noEmit ✅、npm run build ✅、22 个前端测试文件全通过(本次新增 3 文件 108 条断言)
- 未做(如实):握手 history handler 与断线补拉、上行 interrupt 按钮、proactive_message/subagent_result
等帧落点、文档上传入口与图片预检、voice 管线、System 的 env 读端点
|
2026-10-05 11:09:24 +08:00 |
|
AskaEth
|
6a545badbd
|
feat(channels): IM 入站图片采集层(图片白名单 + 微信图片来源 + 复用 vision 内联入口)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- mediafetch 新增**图片白名单**(扩展名 + **字节嗅探兜底**;与文档/音频**三份名单互不污染**),
取回/裁决/上限全部走既有 Fetch(**来源白名单 deny-by-default** + 逐跳重定向校验 + 边读边限 + 超时)
⇒ 没有新造第四份取回实现
- 微信:给图片 URL 配来源白名单(沿用该渠道 CDN 根口径)
- vision 的 `data:` URI 内联入口为**只读复用**(未改 vision 一行)
- **行为变更**:图片现在**会**被尝试取回(**字节嗅探是唯一裁决权** —— 不是图片字节就不写 `Data`);
其它渠道尚无图片来源白名单 ⇒ 由 deny-by-default 拒绝(**安全**,只是暂读不到,走诚实降级)——
故同步更新了 kook 的既有测试(原断言「图片保持既有路径 = 不取回」已随口径演进)
- ⚠️ **`channelbridge` 一个字没碰**(接线点在切片报告 §7),等监工接线 + 补其它渠道白名单
- 测试:3 个新文件;变异 5 条
|
2026-10-05 11:04:41 +08:00 |
|
AskaEth
|
5de708a560
|
fix(gateway,channelbridge,turnreply): p 标签半包写入侧规整(修「整条塌成一段」)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
裁定(已发安卓):**能修**,走**写入侧规整** —— 不指望模型输出、不动客户端。
- 新增 internal/runtime/turnreply/paragraph.go 的 NormalizeParagraphs:
把未被 <p> 包裹的段落补上 <p>(按空行分段;<action>/<narration> 段也包进 <p>,
与正确形态 <p><action>…</action>…</p> 一致)
- **幂等**守门断言:已完全包裹的文本逐字不变(防二次加工)
- 落点覆盖 Web 与 IM 两条落库路径(gateway/session_turn_reply.go、channelbridge/turnreply.go、
proactive.go)⇒ 两边共用同一份规整文本 ⇒ **历史一次性变好、两个客户端零改动**、渲染口径不分叉
(测试与变异详见切片报告)
|
2026-10-05 10:56:39 +08:00 |
|
AskaEth
|
d532eb3fcd
|
fix(session,qq-obv11): 修「判主好了、会话车道没跟上」(QQ 私聊没镜像进主会话)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
真因(agent-221 用三条独立证据推翻了「SenderID 为空」的假设):ev.UserID 有值;
owner.yaml 的 qq 条目是 10:37:57 才加的(此前那几条判陌生人属**正确的 fail-closed**);
而热重载成功后仍不对 —— 因为 internal/channel/session/manager.go 的 GetOrCreate
对**已绑定的渠道直接返回缓存会话**:判主门槛用新 actor 会过(所以她会回话),
但**车道用的是缓存的旧会话**(Owner=false ⇒ 不镜像进 Web 主会话、MemWritable=false、
落盘 actor_role 永不更新)。
修:缓存命中但 ActorRole 与本次解析不一致 ⇒ rebindLocked 刷新车道 + 同步落盘
(updateActorRoleSQL);persist 的 INSERT OR IGNORE 后读回落盘车道、不一致就地纠正
(覆盖上一轮进程留下的旧行);落盘失败只 WARN(不因记账失败丢主人消息);
**身份变化不搬家、不换 session id**;车道只来自 ResolveActor 的结构化白名单判定。
QQ 适配器(防御加固,非本次真机 bug 的修复):senderIDOf 兜底链 顶层 user_id →
sender.user_id;并用完整论证钉住「**群聊绝不能用 ChannelID 兜底**」(否则群里任何人
可顶群号冒充主人);顺手体检:自己发的消息(post_type=message_sent)与 meta_event
已被 handlePayload 过滤。为守 ≤500 行把 id/字符串小工具拆到 ids.go。
测试:session/ownerlane_test + qq/ownerlane_test 新增用例(含「群号等于主人号时
陌生人不得借群号冒充」「群聊发送者 id 缺失时 SenderID 必须为空而非群号」「白名单
热重载后车道立刻刷新且 session id 不变」「白名单移除后立即退回,不是单向提权」
「跨进程继承的旧行被就地纠正」)。
变异 5 条(去 sender.user_id 兜底 / 群聊用群号当 SenderID / 命中却判 unknown /
还原缓存直返 / 去掉旧行纠正),每条先确认可编译、贴红行、还原复绿(md5 逐字节校验)。
|
2026-10-05 10:53:05 +08:00 |
|
AskaEth
|
b16ab2c5e8
|
chore(config): 主人档案新增 qq-obv11 账号(主人经面板添加,保留)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 10:37:57 +08:00 |
|
AskaEth
|
42279b7124
|
feat(channels): 按账号连接/断开 + 可删空 id 条目(修主人真机踩的两个缺口)
缺口①:「连接」是按平台连、且恒打第一条账号(channelActionRequest 只有 name)⇒ 主人有两条
qq-obv11 时点到的是 mode=server 的历史条目,报 server mode requires listenAddr,而正确的
client 条目轮不到。缺口②:空 id 条目既删不掉(DELETE 要求 id 非空)也改不了(UpsertChannel
空 id = 新建),越改越多。
后端:
- POST /admin/channels/open|close 请求体新增可选 accountId(缺省逐字兼容,老客户端零影响);
按该账号驱动;未知 id ⇒ 404 且零连接(不静默回落第一条);已配置未注册 ⇒ 409
- DELETE /admin/channels/{platform}/config 新增显式 empty=1(id 与 empty=1 互斥 ⇒ 400;
无可删 ⇒ 404);语义严格 —— 只删空 id 条目,绝不把「id 为空」默认解释成删空 id
- 响应新增:open/close 的 resolved(实际驱动的适配器名)与 accountId;delete 的 removed/empty;
GET /admin/channels 的 accounts[].connected(可选 bool,缺省 = 未知)
- 审计动作名不变(channel.open/close/delete),日志行新增 accountId 字段
前端:每条账号一行「连接/断开」(带 accountId);按钮旁明确「会连哪一条」;空 id 行显著标注
+ 删除入口;channelActionBody 携带 accountId;新增 action 测试 33 checks + 空 id 行渲染 31 checks。
测试:后端 14 个用例(真实 HTTP 路由 + JWT + 真注册表 + spy 适配器,断言「哪一条被驱动、
另一条一次都没被碰」)。
变异 6 条(accountId 被忽略 / id 为空当删空 id / 找不到静默回落 / 前端丢 accountId /
删空 id 退化成 ?id= / 空 id 行按普通行渲染)。
|
2026-10-05 10:37:56 +08:00 |
|
AskaEth
|
c4ea02a887
|
feat(web): 渠道配置面板重做(按模式动态显隐 + 下拉 + 真鉴权键 + 掩码不回填)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
新增:channelFieldRules.ts(纯函数规则层:选择器归一化 / 按 transport×mode 显隐与必填 /
写回补丁 / 模式提示文案)、channelConnFields.tsx(「连接配置」区:只渲染当前组合生效的字段,
逐字段「谁连谁」说明 + 必填/可选标记 + 掩码清除开关)、channelAccountId.tsx(账号 id 与
「覆盖/新建」状态 Tag)、channelPersonaField.tsx(从表单抽出,逻辑逐字保留)。
qq-obv11:transport / mode 改下拉;remote_url 仅 ws+client 显示且必填;listen_addr 按
server / http+client 条件显示;api_base_url 仅 http(http+client 必填);report_path 仅 http;
access_token 掩码;self_id 仅记录。每种组合顶部一句 modeHints;保存前拦截必填缺失并红框点名。
⚠️ 修掉一处数据毁伤:后端把 access_token 掩码成 ****abcd 下发,旧代码回填进表单 ⇒
「打开就保存」会把掩码写成真 token。现在掩码不回填、只记 configuredKeys,并提示
「已配置,留空 = 不改动」;要清空必须显式打开「清除已配置的 access_token」开关
(顺带给掩码秘密补上了以前没有的「清除」能力)。可见字段清空发 ""、隐藏字段不进补丁(缺位 = 保留)。
Token 误导修掉:PLATFORM_GUIDE.authKey 声明平台真正读取的键 —— qq-obv11 不再渲染 bot_token
输入框、不再标必填(改指向 access_token);渠道列表与只读配置卡的凭据行同步改用真实 authKey。
空 id:结论是后端契约(UpsertChannel 空 id = 新建),前端不碰后端修好:记住 savedId
(留空 = 覆盖当前条目)+ 改新 id 时内联二次确认 + 保存后用返回的 accountId 刷新 + 状态 Tag。
测试:新增真组件 SSR 渲染测试(68 checks)+ 规则单测(58 checks);17 个前端测试文件逐跑全绿;
tsc --noEmit 与 npm run build 通过(产物 index-CK_2RXKo.js)。
|
2026-10-05 10:15:19 +08:00 |
|
AskaEth
|
8c437866e7
|
feat(qq-obv11): client 模式首连失败不再致命(复用既有重连循环 + 指数退避)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
痛点:mode=client 时首次拨号失败会让 Connect 直接返回 error ⇒ 渠道起不来;
而「连上后再断」本来就有重连。⇒ 把 readLoop 的入口条件放宽为「conn==nil 也算」,
**不新造第二套循环**。
新增 reconnect.go:退避 2s → ×2 → 上限 60s、抖动 ±25%(具名常量),失败计数跨
Connect 与 readLoop 共享。
ws_client:新增 connectFirstClient —— 可重试失败只记 WARN 并返回 nil;
配置缺失(remote_url 空)仍致命(闸门口径不变)。
connected 语义不许撒谎:始终由真实连接决定;HealthCheck 未连上返回 ErrNotConnected;
仅 http 传输保留「已装配即可服务」旧口径(逐字未改)。
ctx 感知等待(sleepCtx)+ 等待后复查 ctx ⇒ Disconnect 能立即中止,不泄漏 goroutine。
server 模式与 http 三端行为逐字不变(既有用例零改动全绿 + TestServerModeUnaffectedByClientRetry)。
测试:client_retry_test.go(428) + reconnect_test.go(83),用可注入 dialer + gate 通道造确定性时序。
变异 5 条(首连 fail-fast / 退避无上限 / 取消失效 / 未连上就报已连 / 抖动未接线)。
诚实边界:60s 上限对聊天渠道可能偏慢(改 30s 是一行常量);仓库内仍存第二份指数退避
(wsutil.Backoff 无抖动能力,收敛需改 internal/**,本切片禁碰)。
|
2026-10-05 10:12:23 +08:00 |
|
AskaEth
|
d804c4e675
|
feat(gateway): 接线 chat_messages.turn_id 写入(A–D 四点齐)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
A 新起一路:publishLegStart 在 persistUserMessages 之前 withTurnID(ctx, leg.turnID)
(该行随 ef3dcb6 已进 HEAD)。
B 队首续跑路:completeTurn 在 o.mu.Unlock() 之后 assignTurnID(sessionID, runLeg.turnID, next.persisted)。
C 被 steer 吃进:consumePending 认领成功后 assignTurnID(sessionID, s.turnID, steerRows(candidates))。
D 助手回复:persistTurnReply 增 turnID 形参,completeTurn 传 leg.turnID —— 刻意**不用** turnIDOfLeg:
interrupt scope=all 会清空 st.legs,而被打断那一路已产出的正文仍要照原样落库(内容是真的),
按 gen 回查只能拿到空串 ⇒ 配对丢失。
删掉 history_turnid_test.go 的 t.Skip:TestSubmitWiresTurnIDForBothRows 真跑并通过。
新增 session_turnid_wiring_test.go(真 SQLite 内存存储 + 真编排器 + 可逐路放行 runner):
单路两条同值 / 并行两路各自同值且两两不同 / 续跑补写(先钉「补写前为空」)/ steer 补写(用该路自己的转向源)/
TestAssistantTurnIDSurvivesInterruptAll(钉住 D 的取值来源)。
变异 5 条(A/B/C/D 各自 + D′ 改回 turnIDOfLeg —— 只有那条守门用例红,证明它守的正是这个取舍)。
诚实边界:turnIDOfLeg 现无生产调用方(保留为兜底);先到先得竞态未构造对抗用例;
IM 渠道桥不走本编排器 ⇒ 其行 turn_id 留空属预期(契约里键缺席)。
|
2026-10-05 10:00:17 +08:00 |
|
AskaEth
|
3589f4b14f
|
feat(tools): 真实工具声明文件目标(让文件级互斥真正生效)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
新增 plugins/tools/io/file_targets.go:fileTool 与 cropTool 实现 tool.FileTargeter
(编译期钉住 var _ tool.FileTargeter,声明集中一处可审计)。
file:read/list/search ⇒ 读;其余(含 delete / 未知 / 缺失 action)⇒ 写(保守侧,宁可多挡一次)。
路径取沙箱解析前的声明值(绝对、clean、已确认在 roots 内,纯词法不触盘);沙箱会拒的路径不声明。
search 的缺省 base 与执行路径共用 f.searchBase(避免声明目录 ≠ 实际走查目录)。
image-crop:仅本地路径声明为读(URL/data URI 不落盘);分类与 load 共用一份。
体检清单:file ✅ / image-crop ✅ / document-read ❌(sidecar 走「临时文件 + rename」原子替换,
无撕读风险;且布局属未导出的第二份真相)/ basic、http、knowledge 等不碰盘;
vision·ocr(internal 越界)、terminal(cmd 越界 + 目标不可知)、MCP 外部工具 未做 —— 如实登记为遗留。
测试:单元(action→Op 全表 / 路径归一 / 不声明场景)+ 机制层 6 条(真插件 + 真 Dispatcher + 真占用表,
用闸门工具把并发变确定性事件,不靠 sleep)。
变异 5 条(一切按写 / 未知按读 / 用原始相对串 / crop 不声明 / file 声明被抹掉)。
注:本切片声明正确但生效依赖 ef3dcb6(网关给每条在途路挂互斥身份)。
|
2026-10-05 09:55:29 +08:00 |
|
AskaEth
|
ef3dcb699b
|
fix(gateway,loop,tool): 解耦「工具互斥身份」与「checkpoint 归属」(修普通回合不受保护)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
缺口:「1 普通回合 + 1 并行路」时普通回合既不登记也不被检查 —— 因为互斥身份取自
loop.ParallelLegFrom,而网关只给 parallel=true 那一路盖它。直接给普通回合盖 WithParallelLeg
会把它的 checkpoint 键从 sess 变成 sess#turn-x(改崩溃恢复语义),故改为两条独立通道:
- 工具互斥身份:loop.WithToolLegID / ToolLegIDFrom(新增),网关在 beginLegLocked 内【无条件】盖,
取值 = 本路 turnID ⇒ 普通回合 / 队首续跑路 / 并行路 三条路都覆盖
- checkpoint 归属:WithParallelLeg 一行未改,仍只有真并行路 ⇒ 恢复语义零变化
守门断言 TestCheckpointOwnerIgnoresToolLegID:普通回合 ctx 下 AgentID 必须逐字仍是 sess。
变异 3 条:互斥身份回退只认 ParallelLegFrom(判忙失效)/ 顺手把 checkpoint 改读新通道
(守门断言红,证明确实解耦)/ 普通回合不盖身份(判忙失效)。
另修 race:-race -count=2 三包全绿;诚实边界含一个既有竞态(同一路并发登记共享,建议后续小切片)。
|
2026-10-05 09:53:08 +08:00 |
|
AskaEth
|
d64b26d499
|
feat(chat): chat_messages.turn_id 列 + DTO(写入接线留待下一步)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
迁移 0018:ALTER TABLE chat_messages ADD COLUMN turn_id TEXT NOT NULL DEFAULT ''
(与 persona_id / client_msg_id / document 同族:不用 NULL,空串 = 不属于任何已知回合 ⇒ 旧行零迁移、键省略)。
存储层全链路带 turn_id(列清单唯一一份 ⇒ List/ListAfter/Recent/Search/FindByClientMsgID 自动同源);
新增 history/turn_id.go:ensureTurnIDColumn(既有库幂等前滚)+ SetMessagesTurnID
(第二段补写:单事务参数化、先到先得 WHERE turn_id = ''、幂等、未知 id 忽略)。
DTO:historyMessage.TurnID(json turnId,omitempty)⇒ REST 列表 / admin 渠道日志 / WS 握手回放 /
message_persisted / channel_persisted / message_edited 一次全覆盖。
写入面:persistUserMessages 读 ctx 回合标识;persistAssistantReply 增可选尾参(既有调用点零改动);
withTurnID / turnIDFrom / assignTurnID / turnIDOfLeg。
⚠️ 编排器把 turnId 交给落库的 4 处(新起一路 / 续跑路 / 被 steer 吃进 / 助手回复)尚未接线
(那些文件当时被另一路占用);当前生产行为 turn_id 仍为 ''。清单已在切片报告里精确到文件:行。
13 新用例 + 5 条变异(INSERT 不带列 / DTO 不回填 / 去掉 omitempty / 去掉先到先得 / 不回滚前滚)。
为守 session_persist.go ≤500 行,turnId 一节拆到新文件 session_turn_id.go。
|
2026-10-05 09:46:10 +08:00 |
|
AskaEth
|
354b08a45f
|
feat(tool): 写类工具文件级互斥(读共享 / 写独占)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
新增 tool/fileclaims.go:FileTargeter 可选接口,由工具声明本次调用要碰的文件
(动态声明、不猜正文 —— 同一工具的 path 在读/写语义不同)。
语义:读共享 / 写独占;两个读允许并行(主人「优先性能」口径);未知操作/裸路径按写处理(保守)。
占用键含操作类别(read/write,NUL 分隔),路径 Abs+Clean+Windows 大小写折叠;随最后占用者离场删键(有界)。
Dispatcher 默认装配进程内占用表(无需 cmd 侧接线);Invoke 登记 + defer 释放(成功/报错/超时/panic 四条路径)。
loop/tools.go 唯一接线:tool.WithLegID(ParallelLegFrom(ctx)) 桥接网关路标识。
判忙不阻塞、不排队死等;显式文案回灌(含文件名与状态)让 LLM 稍后重试。
测试 3 个新文件(占用表语义 / 接线确定性并发 / loop 桥与端到端);变异 5 条,另揪出并修一个
真隐患(空串既当「无人占用」哨兵又是合法路标识 ⇒ 改 (leg,busy) 返回)。
诚实边界:①「1 普通回合 + 1 并行路」时普通回合不受保护(网关只给 parallel 路盖 legID;
修法须与 checkpoint 归属一起裁决);② 目前无真实工具实现 FileTargeter ⇒ 机制就绪但占用表恒空,
真实保护待下一片给 file 等工具加声明。
|
2026-10-05 09:38:12 +08:00 |
|
AskaEth
|
c0dc435770
|
feat(gateway): 忙时并行帧层(turn_begin + steer_ack.turnId + interrupt.turnId)
新下行帧 turn_begin:编排器每启动一路恰好一帧(单路 kind:"turn" / 并行路 "parallel"),
data{kind, messageIds, leg, activeTurns};角色门 fail-closed 仅 owner+admin,未进 frameReachesAll。
steer_ack 增帧壳 turnId(与该路 turn_begin 同源)—— 并行下没有它配不上正确的 turn.end。
上行 interrupt.turnId(仅 scope:"current" 生效):精确停某一路;目标不存在 ⇒ 定向
{type:"error",data:{code:"bad_request"}},不广播、不动任何会话;省略 turnId = v0.65 原口径(全部在途路)。
帧序按实现:session_busy / pending_drain → message_persisted(user) → turn_begin
(规范草案 §2.9 的时序图需按实现更正:messageIds 必须是已落库的权威 id,故只能在落库之后)。
测试:编排器侧 + 真 WS/JWT 端到端;变异 5 条(每路一帧 / 帧壳 turnId / 目标化打断 / 取消筛选)。
Docs 待升 v0.66(由监工登记)。
|
2026-10-05 09:38:11 +08:00 |
|
AskaEth
|
e5cc9c6054
|
docs(api): 重写 api-client.md(61 KB / 701 行,比归档版缩小 85%)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
以代码为唯一真源重写:概览认证 / 用户侧 REST 表 / 管理侧表+权限矩阵 / WS 协议(握手+回放+上行+下行+角色门)/
契约细节(错误码·游标·幂等·消息 DTO·文档图片语音·忙时并行·interrupt)/ env 与模型配置 /
变更记录(只留 v0.60 起,更早指向 Docs/archive/)。
相对归档 v0.65 的修正(以 routes.go 等代码为准):
1. 管理侧权限矩阵计数错(归档 61 且自相矛盾)⇒ 实测 12 viewer + 11 owner/admin + 40 owner-only = 63
2. WS 握手实际也接受 ?token=<JWT>(仅不接受 X-API-Key)
3. limit>200 是钳到 200,不是 400(非数字/<1 才 400)
4. voice_output 的 sessionId 在 data 里(帧壳没有)
5. WS_MAX_CONNECTIONS 疑似解析未接线(标未确证)
6. 未确证清单 6 条已写入 §7.4
|
2026-10-05 09:34:08 +08:00 |
|
AskaEth
|
2ba1baf6d0
|
docs(api): 归档 v0.65 旧版 api-client / api-reference(准备以代码为真源重写干净版)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
旧版积了 v0.28→v0.65 的历史条目、「契约版本」标题并列、双变更记录、mtime 落后等结构性问题;
归档保留完整历史(含 §5 变更记录),新文件将从零重写,只留最近若干版并指向本归档。
|
2026-10-05 09:29:33 +08:00 |
|
AskaEth
|
879669cc59
|
docs(api): 契约 v0.65(忙时并行基础管线 + 六条登记)+ 修三条过期陈述
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
升 v0.65(依据 design/15 §2.5 与 commit 89e13cf),一并登记 679cee0(IM 入站附件引用落库)
/ 59a1ac4(llm_usage.session_id 接线)/ a918819(IM 各渠道语音可被读到),
cb564fe / 15181e7 / 7d2ff74 为纯内部修(无契约变化)。
三档:纯增量 = chat.parallel / activeTurns / cancelledTurns / pending_ack.reason /
两条 REST 应答形状 / VOICE_STT_TIMEOUT_SEC;行为变更 = IM 附件引用落库(无新字段)/
IM 语音进上下文 / session_idle 时点收紧(仅并行时);破坏性 = 无。
修正(客户端抓到的三条,属实):① session_id 「恒为 NULL」→ 已接线(端点仍不按会话过滤/分组)
② 「契约版本」标题并列三处 → v0.65 唯一,其余降为「上一版」
③ 按提交逐个核对补齐(mtime 落后问题)。
未实现项写明:turn_begin / steer_ack 帧壳 turnId / interrupt.turnId / chat_messages.turn_id /
graph_update 按路分桶 / 写类工具文件级互斥(tool/legfile.go 仅定死形状,无实现无接线)/ 第二路 system 摘要。
env CHAT_MAX_PARALLEL_TURNS 如实标注「未接线,生产恒为默认 2」。
|
2026-10-05 09:23:46 +08:00 |
|
AskaEth
|
89e13cf53d
|
feat(gateway,loop): 忙时并行回合基础管线(I1′ 有条件放宽)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
- turnId 由编排器生成、loop Run 复用(硬前提:否则 turn_begin 与流帧各铸一个,客户端两级分桶立即失配)
- StateSink 增带 turnId 的变体(未接线时退化为现签名,不丢状态帧)
- 上行 chat.parallel(WS chat 帧 + REST 三入口同形;省略 = 逐字不变)
- 单会话额度默认 2 / 硬上限 3 / <2 关闭;额度满或未声明 ⇒ 落回既有排队语义
- I1′:checkpoint 归属、历史配对、忙态计数三处从会话级单例升为路级
- session_idle 收紧为「所有在途路收尾且 pending 空」(仅并行时生效;单路逐字不变)
- 预留接口(形状定死、无实现无接线):tool/legfile.go 的 FileClaimer / ErrFileBusy / WithLegID
- 顺手修一个真 bug:并行路 ctx 派生自提交请求作用域,REST 同步入口一写响应就把它连坐杀死(改 context.WithoutCancel 派生)
- 23 个新用例(含 -race -count=3);变异 6 条(turnId 复用 / idle 时点 / 并行升级 / checkpoint 键 / 编排器交 id / pending_ack reason)
- 契约变更点 10 条待监工升 v0.65(本人未改 Docs/**)
|
2026-10-05 09:18:50 +08:00 |
|
AskaEth
|
7d2ff74cfc
|
test(telegram): 补语音内联回归测试(上一条语音切片提交时被 grep 过滤漏掉)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
|
2026-10-05 08:37:23 +08:00 |
|
AskaEth
|
a918819878
|
feat(channels,voice): IM 各渠道语音消息可被读到(全渠道云端 ASR + 临时熔断)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
采集面:mediafetch 新增 inline_voice.go(音频白名单,与 documents.ExtAllowed 互不污染;
复用既有来源白名单 / 逐跳校验 / 边读边限 / 超时);四个适配器零改动。
消费面:channelbridge 在流水线最前端把「语音字节 → 文本」归一并写回 msg.Content;
inbound.go 的丢空判据放宽为「无文本且无可用媒体」。
微信优先平台自带转写(Content 非空 ⇒ 不调 ASR,不重复付费)。
降级(主人定的两层):新增 voice/outcome.go 的 STTOutcome 识破静默档位;
errors.go 分类鉴权失败/欠费/限流(CircuitWorthy);voice_breaker.go 临时熔断 + 退避(TTL 恢复);
无论是否熔断,消息面都落一行中文诚实提示(绝不静默、绝不留空消息)。
独立短超时:VOICE_STT_TIMEOUT_SEC(默认 20s,同步 .env.example)。
kook 不再把 CDN 地址写进 Content(地址仍在 Media[].URL)。
设计先行:design/06 §1.1/§1.2、design/08 §4.1、design/24 §1.3/§4.2、开源对照清单。
变异 5 条(静默档位不带 Cause / Transcribed 误判 / 熔断恒放行 / ChatText 退化 / 平台文字判据取反)。
诚实边界:实施时官方音频规格尚未抓到 ⇒ MaxVoiceBytes 自定 5 MiB(保守)、采样率仍 16 kHz;
官方规格随后已抓到(10 MB / 5 min;格式含 amr、无 silk),对齐留待下次改动。
|
2026-10-05 08:32:37 +08:00 |
|
AskaEth
|
679cee04f7
|
fix(channelbridge): IM 入站附件引用写进落库的用户消息(安卓报的 P0)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
根因:摄取结果只挂到「内存里的模型可见消息」(inbound.go 的 attachInboundAttachments),
落库时只传了 text、history.Message 没有 Document 字段 ⇒ 该列恒空 ⇒ 读侧 omitempty
导致 documents 键整个缺席 ⇒ 任何客户端只看到一条空消息。Web 侧不这样,是因为
gateway/session_persist.go 有 messageTextImageDocument 把 ContentTypeDocument 部件编码进该列
—— IM 路径缺的就是同一步。
修法:inboundAttachments.documentColumn() 复用 history.EncodeDocuments 同一口径写出该列;
persistToMain/persistIsolated 增 document 参数并返回刚落库的消息;新增两段式第二段
persistTurnDocumentStatus 按 id 回写抽取结论(只补结论、按存储名匹配、匹配不到原样留),
与 gateway/session_document_status.go 逐字对齐。
契约零扩张:无新端点/帧/字段;0 附件 ⇒ 列空 ⇒ 键省略;形状即 web 的同一结构体。
测试 6 条(含元素 JSON 逐字断言、unreadable 带 reason、被拒不编造芯片、群聊隔离分支、
真循环端到端);变异两条(还原挂载 / 关闭结论回写)⇒ 各 4 条红。
|
2026-10-05 08:10:21 +08:00 |
|
AskaEth
|
f8f2e9c54c
|
feat(weixin_ilink): 出站媒体走通(主人已批的三项)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
按官方包 @tencent-weixin/openclaw-weixin 2.4.9 源码对齐:
① 上传由 PUT 改 POST;② 上传凭据读响应头 x-encrypted-param;
③ nativeMediaItem 改为官方 *_item.media.encrypt_query_param 嵌套形状(含 aes_key,
图片优先 image_item.aeskey)。
配合前一版已修的两点(入站按条密钥、媒体失败不阻断文本),机器人现在可主动发出文件/图片。
(逐项测试、变异红行与诚实边界见该切片报告)
|
2026-10-05 08:04:50 +08:00 |
|
AskaEth
|
59a1ac4056
|
feat(model): llm_usage.session_id 真正落库(补完 U1 缺口)
通道:新增 model/session_ctx.go 的 WithSessionID / SessionIDFrom(与 tool.WithTurnPersona
同族的 ctx 范式,避开 model 反向 import loop 的环),loop 在 Run 顶部播种;适配器
record(ctx,...) 接会话;usageSessionArg 空串映射为 NULL。
兼容:sink 未注入或会话未播种时行为逐字不变;既有 model 测试零断言改动即全绿。
文件:model/{session_ctx.go(新), usage.go, usage_store.go, openai.go, anthropic.go,
usage_session_test.go(新)} + loop/{run.go, usage_session_test.go(新)}。
变异三处:去 loop 打标 / 写侧不绑会话 / 适配器不读 ctx ⇒ 各自红行,还原复绿。
契约与日志字段集未动;读侧不按 session 过滤,面板汇总口径不变。
|
2026-10-05 08:04:49 +08:00 |
|