fix(addressing)!: 寻址不按工作区筛 + 联系人地址不再从垃圾 from_workspace 拼
用户:「任意 agent 的寻址是任意的,而不是按工作区区分,去落实吧」。 ① 拆掉两处"按工作区收窄"(那是我把**寻址**当成了**权限**): · AgentListContacts 不再走 ListContactsInWorkspace ⇒ 列表 = 我参与过的会话(事实,不是授权); · AgentSuggestAddress 的会话候选不再走 SuggestSessionCandidatesInWorkspace。 两个 InWorkspace 变体(连同钉旧口径的用例)一并删除,避免死代码。 生产实测:pi 的联系人从"只剩同工作区"变成 5 条,横跨 TrueAgent/agentmail/其它工作区。 agentScope 仍调用(校验 session_id 格式 + 未声明时告警),只是它的工作区不再当过滤器。 ② 联系人地址的 path 取自**会话**,不再取第一封邮件的 from_workspace: `COALESCE(NULLIF(s.workspace,''), NULLIF(m.to_workspace,''), '')`。 那条老路把地址拼成 `zcode@zcode.<别名>` —— 正是用户预言的"感染":一个可被复制出去的 错误地址。from_workspace 与"对方在哪"无关,只用 to_*。 ③ **清除感染源(数据)**:658 行 from_workspace = from_name(pi 406 / dsh 137 / zcode 89 / homeagent 17 / opencode 9)已清空。带去重前备份(/root/gotmp/agentmail-pre-fromws-purge-*.db) 与回滚脚本,回滚**在副本库上真跑过**(恢复 658 行)才敢落地。
This commit is contained in:
@ -127,20 +127,18 @@ func AgentListContacts(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
scope, ok := agentScope(w, r, agentName)
|
||||
if !ok {
|
||||
// 仍走 agentScope:它负责校验 session_id 格式、并在未声明时记一条警告。
|
||||
// 但它的返回值**不再是过滤器** —— 列表与寻址都不再按工作区收窄(见下)。
|
||||
if _, ok := agentScope(w, r, agentName); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
archived := r.URL.Query().Get("archived") == "true"
|
||||
var contacts []repo.Contact
|
||||
var err error
|
||||
if scope == nil {
|
||||
contacts, err = repo.ListContactsFor(r.Context(), agentName, archived)
|
||||
} else {
|
||||
contacts, err = repo.ListContactsInWorkspace(
|
||||
r.Context(), agentName, repo.SessionWorkspaceOf(r.Context(), *scope), archived)
|
||||
}
|
||||
// ★ 2026-09-15 用户:「任意 agent 的寻址是任意的,而不是按工作区区分,去落实吧」。
|
||||
// 列表 = **我参与过的会话**(这是事实,不是授权),不再按工作区收窄。
|
||||
// 旧口径让一个 agent 只看得见"同工作区的会话标题",zcode 2026-09-15 正是据此
|
||||
// 认定"那五位 agent 不存在"。工作区那条轴只留给 cwd/沙箱。
|
||||
contacts, err := repo.ListContactsFor(r.Context(), agentName, archived)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "Failed to list contacts")
|
||||
return
|
||||
@ -243,23 +241,15 @@ func AgentSuggestAddress(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// 可见性传自己的名字:只提示自己参与过的会话。
|
||||
// 传空会把别人的私下线索也列出来,那是越权。
|
||||
//
|
||||
// 声明了 `session_id` 时额外要求这些会话与调用方**同工作区**:参与过不等于
|
||||
// 该看 —— 一个 Agent 同时服务所有工作区(见 repo.AgentMayReadSession)。
|
||||
// 跨工作区寻址本身仍然可行(`new` 总在最后,paths 候选也不收窄),
|
||||
// 收窄的只是"浏览别的会话的标题/别名"。
|
||||
scope, ok := agentScope(w, r, agentName)
|
||||
if !ok {
|
||||
// ★ 2026-09-15 用户:「任意 agent 的寻址是任意的,而不是按工作区区分,去落实吧」。
|
||||
// 原先这里"声明了 session_id 就只列同工作区的会话"——那是把**寻址**当成**权限**了:
|
||||
// 寻址就该是任意的(谁都能给谁发),工作区只决定 cwd/沙箱。
|
||||
if _, ok := agentScope(w, r, agentName); !ok {
|
||||
return
|
||||
}
|
||||
var sessions []repo.SessionCandidate
|
||||
var err error
|
||||
if scope == nil {
|
||||
sessions, err = repo.SuggestSessionCandidates(r.Context(), agentName, name, path)
|
||||
} else {
|
||||
sessions, err = repo.SuggestSessionCandidatesInWorkspace(
|
||||
r.Context(), agentName, name, path, repo.SessionWorkspaceOf(r.Context(), *scope))
|
||||
}
|
||||
// 候选会话只按"我参与过 + 与这个 name/path 匹配"来列。 —— 候选会话只按"我参与过 + 与这个名字/路径匹配"来列,
|
||||
// 这样 zcode 那种"想给别的 agent 发信"的场景才能拿到真实的候选。
|
||||
sessions, err := repo.SuggestSessionCandidates(r.Context(), agentName, name, path)
|
||||
if err != nil {
|
||||
Error(w, http.StatusInternalServerError, "Failed to suggest sessions")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user