JianFeeeee
24f7ed99fc
fix(dsh)★★: idle 时取不到 assistant 文本 —— 重试而非当场判「空回复」
## 用户报「dsh 插件还是没有正确回复邮件」
第一版修复(519bdf7)改对了 `lastAssistantText` 本身,但生产仍复现。取证后定位
到**第二层原因**:不是取错事件,而是**取的时候那条还没到**。
## 证据(生产 22:56 那次,磁盘 session.v4.jsonl.zstd 解压)
那一轮的事件是:
seq=50 step/start
seq=51 assistant/message 块=['text'] ← 模型确实写了完整文本
seq=52 step/end seq=53 turn/end
按修复后的逻辑(从后往前找第一条带 text 的 assistant)**必然会取到 seq=51**,
可它仍被判成空回复。
⇒ 唯一解释:`agent/status: idle` 触发的那一刻,`agent.session.events` 里
**还没有 seq=51** —— 宿主在最后一条 assistant 消息落入内存**之前**就发了 idle。
旁证:投影缓存 `/root/.dsh/storages/session_projcache/sessions/<id>.json`
只有 `{identity, rows}`,**没有 events** ⇒ 它不是从投影读的,确属内存对象。
## 修法:idle 时取不到就短暂重试
重试 3 次 × 250ms(合计 750ms)。远小于一轮模型思考的量级,不拖慢链路;
而 seq=51 落盘只需几毫秒,三次足够覆盖。
顺带把诊断日志改成打出**重试后**的 events 长度与末尾类型(附「第 N 次重试才拿到」)
——下一次复现就能直接验证这个推断是否成立,而不是再靠推测。
## 一条被推翻的推断(记下来)
我一度判定「根因是 resume 路径」,理由是新会话那次通过、resume 那次失败。
**这是错的**:那两次的差异其实在更早一步 ——
`shouldSkipAutoRelay`(模型已主动 send_mail 就早退)。C-1 新会话与 C-2 resume
都因为 dsh 主动回信而早退,压根没走到取文本那段,所以两者都「正常」。
⇒ resume 与本问题**无关**,此前把差异归因于它是观察不足。
## 一条设定更正(用户指出)
我曾说「Agent 间通信不自动转发」是不可协商的约定,并据此说「pi 发信会早退,
拿不到诊断日志」。用户更正:agent→agent 只是**消耗额度**,而额度会随时间恢复
——那是成本权衡,不是禁止。该约定来自 784192d(2026-09-04),四个桥共用同一份
relay-policy.js,它**没有随额度恢复机制一起更新**。
⚠ 该约定是否要改属成本策略,未擅自改动。但它确实挡在诊断路径前面,是本轮
多花一轮的直接原因。
## 验证状态(诚实标注)
- tsc 零错 · dsh 435 格全绿 · 部署成功(current → 20261004-073447)
- **最终行为验证未完成**:需要一次**真人发信**(`from_human=true`)才能走到
取文本那段。我的所有身份都是 Agent,会被「不自动转发」早退。
⇒ 诊断日志已就位,待真人复现时可直接读出 events 的真实内容。
2026-10-04 07:35:23 +08:00
..
2026-10-03 22:24:32 +08:00
2026-10-04 07:35:23 +08:00
2026-10-03 22:24:32 +08:00
2026-09-14 08:38:33 +08:00
2026-09-02 20:05:51 +08:00
2026-10-03 00:25:28 +08:00
2026-09-11 10:47:30 +08:00