fix(dsh): agents.get() 返回 agent 本体,当 handle 用缺一层 .agent

## 症状(上一版修复后暴露的新错)

    会话 mail-515c0c70… 已在运行,直接 followup(不重复 resume)
    new_mail 处理失败: Cannot read properties of undefined (reading 'followup')

去重生效了(不再撞 flock),但下一步炸。

## 根因:两个来源返回的不是同一种东西

    ctx.agents.get(id)   → **agent 本体**(.followup / .session 直接在上面)
    startAgent()         → handle,agent 在 **handle.agent**

证据在同文件 findLiveDshSession(约 1059 行)——它自己也要包一层:

    const live = ctx.agents.get(bound.dshSessionId);
    if (live) return { id: bound.dshSessionId, agent: live };

而去重那段把 `get()` 的返回值**直接赋给 handle** ⇒ `handle.agent` 是 undefined
⇒ 一取 followup 就炸。

⇒ 两条路径拿的是同一个对象,只是用法不同:一个包了一层、一个没包。

## 修法

`handle = { agent: alreadyLive }`。

## 判据(+2 格)

钉「从 `agents.get()` 取到的东西,必须包成 `{ agent: … }` 才能当 handle 用」。

★ 写这格时又被自己的两个假设绊住:
  1. 先写的是「看 `handle = …` 那一行有没有 `agents.get`」——
     实际代码是**两步**(先绑变量 `alreadyLive`,再 `handle = { agent: alreadyLive }`),
     赋值式里根本没有 `get(` 字样 ⇒ 判据报「应至少有一处…」而自己红了。
     改成**追变量来源**。
  2. 追来源时正则先匹配到接管路径的 `live`(它的用法本来就对),
     于是抓不到新加的那处 ⇒ 收紧成只匹配**双可选链** `?.get?.(` 那一处。

dsh 444 格全绿 · tsc 零错 · 部署成功(current → 20261004-094533)· 心跳正常。
变异:去掉 `{ agent }` 包装 → 红 2 格。
This commit is contained in:
2026-10-04 09:45:55 +08:00
parent 3673019ec4
commit caffe2f9fe
2 changed files with 91 additions and 1 deletions

View File

@ -1341,10 +1341,19 @@ export function apply(ctx: any, config: PluginConfig): void {
//
// 1187 行的接管路径早有这段去重,注释写得很清楚(同一条会话两个 handle
// 会各自往日志里写、replay 校验不过)。同一个陷阱漏在普通路径上。
// `ctx.agents.get()` 返回的是 **agent 本体**(见下方 `{ agent }` 处的注释)
const alreadyLive = ctx.agents?.get?.(attemptSessionId);
if (alreadyLive) {
handle = alreadyLive;
// ★ 必须包一层 `{ agent }`:`ctx.agents.get()` 返回的是 **agent 本体**
// (证据:findLiveDshSession 第 1059 行 `ctx.agents.get(id)` 之后
// 紧接着 `return { id, agent: live }` —— 它自己也要包)。
// 而 `startAgent` 返回的 handle 上才有 `.agent`,后续全部按
// `handle.agent.session` / `handle.agent.followup` 取值。
// 直接把 agent 当 handle 塞进去 ⇒ `handle.agent` 是 undefined ⇒
// 实测报 `Cannot read properties of undefined (reading 'followup')`。
handle = { agent: alreadyLive };
console.error(
`[dsh-mail-bridge] 会话 ${attemptSessionId} 已在运行,直接 followup(不重复 resume)`,
);