fix(agent)★★: 会话作用域拒绝文案不再拼出「你当前在会话 。」
2026-10-05,比对 MCP 与插件接入能力时实测发现。
## 症状
独立 MCP 宿主读自己刚收到的那封信,得到:
这封信不在你当前所在的那条会话里:…你当前在会话 。要读它,…
`你当前在会话 。` 中间是空的。
## 根因:一个 reason 值管三种拒绝,文案却只有一句
`AgentMayReadSession` 用**同一个 `reason`** 覆盖三种情形:
① 没声明 session_id(scope == nil)
② 声明了别人的会话
③ 声明了但**不是参与方**(session_id 由请求方提供,自述不是事实)
而 `canReadSession` 无条件拼 `"你当前在会话 " + self + "。"`,
于是 ① 拼出那句残缺文案。
★ 为什么这句残缺文案比「不说」更糟:模型读到「你当前在会话 。」
会以为自己在一个**无名会话**里,于是转去猜/去搜 ——
而正确做法(从 new_mail 事件取 session_id)就在同一句话的后半段,
它却读不到前半段。
## 修法
按 `scope` 有无分句,**不给空值留位置**:
① → 「你当前**没有**声明自己所在的那条会话,所以无从判断这封信是不是你的。」
② → 「你当前在会话 00000000-…」(仍只报自己声明的那条)
②③ 故意不拆开:`session_workspace.go:171` 已经警告过「新增 reason 还要同步改
handler 的 switch,漏改就是 500」,而两者给模型的指引**完全相同**
(都是"去那条会话读"),拆开只增加分支不增加信息。
## 实测(真实请求,部署后)
① 不声明 → 「你当前**没有**声明自己所在的那条会话…」 无残缺 ✓
② 声明他人 → 「你当前在会话 00000000-…」(自己声明的那条)✓
★ 「会话 。」残缺句已消失
## 判据
`TestSessionScopeHintNeverLeavesEmptySessionSlot` —— 盯**结构**而非文案本身:
- 禁止再出现 `"你当前在会话 "+self+"。` 这种无条件拼接
- 要求按 `scope != nil` 分句
- 要求存在「未声明会话」那一句
两个变异都转红:退回无条件拼接 / 删掉「未声明」那句。
## 顺带确认:MCP 与插件的工具面已对齐
实测 `tools/list`(11 个)与 4 个插件的真实注册项做集合比对:
MCP 有、插件没有: 无
插件有、MCP 没有: 无
⚠️ 中途差点误判:grep 到插件里有 `permission_decision` 等 3 个词,
以为 MCP 缺 3 个工具。查下去 `permission_decision` 是 **mail_type**
(收到授权请求邮件后转给 worker),另两个只存在于 `src/pool.mjs`
和测试里,**从不暴露给模型**。
This commit is contained in:
@ -98,13 +98,21 @@ func canReadSession(w http.ResponseWriter, r *http.Request, agentName string, sc
|
||||
// 记忆是隔离的」。所以**不再拿工作区当理由**(旧文案就是 cross-workspace,
|
||||
// 它让 zcode 推断出"那五位 agent 不存在",把错误结论写进了给人看的信里)。
|
||||
// 报出"我当前在哪条会话"是安全的(那是调用方自己的);**不报**目标会话在哪。
|
||||
self := ""
|
||||
//
|
||||
// ★ 2026-10-05:`reason` 是**一个值管三种拒绝**(没声明 / 声明了别人的 /
|
||||
// 不是参与方),而「你当前在会话 <self>」在 self 为空时会拼出
|
||||
// 「你当前在会话 。」—— 实测(独立 MCP 宿主读自己那封信)确实读到这句,
|
||||
// 残缺的话会让模型以为自己在一个无名会话里,转而去猜。
|
||||
// 所以先按 self 有无分句,**不给空值留位置**。
|
||||
var where string
|
||||
if scope != nil {
|
||||
self = (*scope).String()
|
||||
where = "你当前在会话 " + (*scope).String() + "。"
|
||||
} else {
|
||||
where = "你当前**没有**声明自己所在的那条会话,所以无从判断这封信是不是你的。"
|
||||
}
|
||||
Error(w, http.StatusForbidden,
|
||||
"这封信不在你当前所在的那条会话里:每个会话各有各的收件箱(会话之间的记忆是隔离的)。"+
|
||||
"你当前在会话 "+self+"。要读它,就在它那条会话里读 —— 每封来信都会把 worker 唤醒到"+
|
||||
where+"要读它,就在它那条会话里读 —— 每封来信都会把 worker 唤醒到"+
|
||||
"它自己那条会话上,那时你看到的就是那条会话的收件箱。"+
|
||||
// ★ 2026-10-04 补:调用方多半是**拿不到**目标会话 id,而不是
|
||||
// 「知道却不传」。原来那句「就在它那条会话里读」只说了去哪读,
|
||||
|
||||
Reference in New Issue
Block a user