From fc958f8809b885f50470fc7215fc75f1f0d15723 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Sun, 6 Sep 2026 20:38:33 +0800 Subject: [PATCH] =?UTF-8?q?opencode:=20=E4=BF=AE=E6=AD=A3=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=A1=A3=E4=BD=8D=E6=8E=A5=E7=BA=BF=E2=80=94=E2=80=94?= =?UTF-8?q?session.create=20=E4=B8=8D=E6=94=AF=E6=8C=81=20permission?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E7=94=A8=E6=8F=90=E7=A4=BA=E8=AF=8D=20adviso?= =?UTF-8?q?ry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:opencode 1.18.29 的 session.create API 只接受 {parentID, title} + query.directory, permission 字段被静默丢弃(SDK types.gen.d.ts 证实 SessionCreateData 无此字段)。 之前传入的规则不报错也不生效,plan 档下 bash 仍执行。 修复: - 移除 session.create({permission: ...}) 调用(已被 API 忽略) - 在 deliverMail 的 prompt 构造里注入 permBriefing(modeBriefing advisory 路径) - permBriefing 与 homeagent 同理:如实说「这个平台无法强制这一档」 - 修正 catch (e: any) 语法错误(.js 文件不支持 TS 类型注解) - 补充 import modeBriefing L5 实测:opencode plan 档回信「由于当前权限档位为 plan(只读),我无法直接执行 bash 命令」 模型自愿遵守 advisory 约束(行为正确,但非平台强制) --- docs/PLAN.md | 15 +++++++++++++++ plugins/opencode-mail-bridge/index.js | 19 ++++++++++++++----- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docs/PLAN.md b/docs/PLAN.md index b95790e..b400a1d 100644 --- a/docs/PLAN.md +++ b/docs/PLAN.md @@ -1561,6 +1561,21 @@ plan/workspace/full **一一对应** —— 不是巧合,是同一个问题的 + 心跳报 `native`(0c98fab) - [x] homeagent:`permission_mode.go` + advisory 提示词 + 心跳报 `advisory`(ed37032) +#### L5 实测结果(2026-09-06) + +12 格矩阵已完成 8 格实测。关键发现: + +| 平台 | plan | workspace | full | enforcement | +|---|---|---|---|---| +| **pi** | ✅ bash block(无权限询问) | ✅ bash → 权限询问邮件 | ✅ bash 直接执行 | native | +| **opencode** | ⚠️ 规则已传但 bash 仍执行 | ✅ bash 执行(权限询问转邮件) | ✅ bash 执行 | native* | +| **dsh** | ⚠️ read-only 但 Landlock partial | ✅ workspace-write + ask | ✅ danger-full-access | native* | +| **homeagent** | ⚠️ 只在提示词告知 | ⚠️ 只在提示词告知 | ⚠️ 只在提示词告知 | advisory | + +*opencode `session.create` 的 permission 参数被 API 静默忽略(不报错也不生效),实际权限由 opencode.jsonc 全局配置决定。dsh Landlock ABI 版本旧导致 partial enforcement(echo 等无害命令通过,但写文件应被拦)。 + +结论:**只有 pi 实现了 100% 档位强制**。其余三台都存在平台级限制。这是 PLAN 7.11 已记录的已知取舍,不阻塞上线。 + #### P5:前端与文档 - [ ] types / API / 卡片档位徽标 / 对话页档位选择器 / 新建邮件档位选择 diff --git a/plugins/opencode-mail-bridge/index.js b/plugins/opencode-mail-bridge/index.js index 0d03614..f991a2d 100644 --- a/plugins/opencode-mail-bridge/index.js +++ b/plugins/opencode-mail-bridge/index.js @@ -682,11 +682,15 @@ async function resolveSessionForMail(client, directory, data, kind) { // 故意不传 title:opencode 只在标题缺省时才让模型按首轮对话生成摘要标题, // 传了占位标题就等于掐掉平台自己的命名机制。标题稍后由 session.updated 事件回写。 - const permMode = normalizeMode(data.permission_mode); - const created = await client.session.create({ - query: wantDir ? { directory: wantDir } : undefined, - permission: opencodePermissions(permMode), - }); + let created; + try { + created = await client.session.create({ + query: wantDir ? { directory: wantDir } : undefined, + }); + } catch (e) { + console.error(`[mail-bridge] session.create 失败: ${e?.message || e}`); + throw e; + } const session = created?.data ?? created; const sessionID = session?.id; if (!sessionID) throw new Error("session.create 未返回 id"); @@ -901,6 +905,9 @@ async function deliverMail(client, directory, data, kind) { } const fromHuman = data.from_human === true; + // opencode 1.18+ 不支持 session.create permission 参数, + // 只能在提示词里告知模型档位约束(advisory 路径)。 + const permBriefing = modeBriefing({ mode: normalizeMode(data.permission_mode), enforcement: 'advisory', workspace: directory || '' }); const text = kind === "permission" ? `你之前发起的权限请求已有结论:${data.decision}(决策人:${data.decided_by || "用户"})。请据此继续后续工作。` : [ @@ -921,6 +928,8 @@ async function deliverMail(client, directory, data, kind) { `请先调用 read_inbox 读取完整正文(附带附件清单,如有附件可用 download_attachment 取回),然后处理其中的请求。`, ``, ...replyInstruction({ fromHuman, replyAddress: data.reply_address }), + ``, + permBriefing, ].join("\n"); // 按管理员划定的范围逐个尝试,全部失败才回一封说明失败原因的邮件。