homeagent: advisory 档位提示词 + 心跳报 advisory + permission_mode.go
- 新建 permission_mode.go:NormalizeMode / ModeBriefing(advisory 版本) homeagent 无工具拦截点,档位只能在提示词里告知模型,措辞如实说 「这个平台无法强制这一档」—— 假装强制会让模型以为越界会被拦 - mailEvent 加 PermissionMode 字段(从 SSE new_mail payload 读入) - handleNewMail 提示词追加 ModeBriefing(plan/workspace/full 三档说明) - 心跳上报 mode_enforcement: 'advisory' - go vet + 68 测试全过
This commit is contained in:
53
plugins/homeagent-mail-bridge/permission_mode.go
Normal file
53
plugins/homeagent-mail-bridge/permission_mode.go
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// permission_mode.go — 权限档位的本地翻译(advisory:仅提示词告知模型)
|
||||||
|
//
|
||||||
|
// homeagent 没有任何工具调用拦截点(没有 tool_call hook、没有沙箱),
|
||||||
|
// 档位在这里是 advisory —— 只能在提示词里告诉模型「请遵守」。
|
||||||
|
// 假装是强制的更危险:模型会以为越界会被拦,于是不必自己小心,
|
||||||
|
// 那比做不到本身更危险。
|
||||||
|
|
||||||
|
const (
|
||||||
|
ModePlan = "plan"
|
||||||
|
ModeWorkspace = "workspace"
|
||||||
|
ModeFull = "full"
|
||||||
|
)
|
||||||
|
|
||||||
|
var validModes = map[string]bool{
|
||||||
|
ModePlan: true, ModeWorkspace: true, ModeFull: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeMode 把外部输入收敛成合法档位。
|
||||||
|
// 非法值回落到默认档(workspace),不是 full。
|
||||||
|
func NormalizeMode(m string) string {
|
||||||
|
if validModes[m] {
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
return ModeWorkspace
|
||||||
|
}
|
||||||
|
|
||||||
|
// ModeBriefing 生成给模型看的档位说明,放进提示词。
|
||||||
|
//
|
||||||
|
// homeagent 永远是 advisory(无法强制),所以措辞必须如实说
|
||||||
|
// 「这个平台无法强制这一档」—— 假装强制会让模型以为越界会被拦,
|
||||||
|
// 于是不必自己小心,那比做不到本身更危险。
|
||||||
|
func ModeBriefing(mode, enforcement string) string {
|
||||||
|
m := NormalizeMode(mode)
|
||||||
|
|
||||||
|
if m == ModeFull {
|
||||||
|
return "本任务权限档位:full(全权)。工具调用不需要额外授权。"
|
||||||
|
}
|
||||||
|
|
||||||
|
if m == ModePlan {
|
||||||
|
return "本任务权限档位:plan(只读)。" +
|
||||||
|
"**这个平台无法强制这一档**,所以约束靠你自己遵守:" +
|
||||||
|
"请不要写文件、改文件或执行命令。" +
|
||||||
|
"请把结论、方案、需要人工执行的步骤写在回信里。" +
|
||||||
|
"需要动手请让发件人把档位改成 workspace。"
|
||||||
|
}
|
||||||
|
|
||||||
|
// workspace
|
||||||
|
return "本任务权限档位:workspace。请把改动限制在本任务的工作目录内。" +
|
||||||
|
"**这个平台无法强制这一档**,所以边界靠你自己遵守:" +
|
||||||
|
"需要改该目录之外的东西时,不要直接动手,先在回信里说明。"
|
||||||
|
}
|
||||||
@ -501,6 +501,7 @@ func (p *Plugin) register() error {
|
|||||||
|
|
||||||
func (p *Plugin) heartbeat() error {
|
func (p *Plugin) heartbeat() error {
|
||||||
payload := map[string]interface{}{}
|
payload := map[string]interface{}{}
|
||||||
|
payload["mode_enforcement"] = "advisory" // homeagent 无沙箱,档位只在提示词里告知
|
||||||
|
|
||||||
// B-2.3:带上模型目录
|
// B-2.3:带上模型目录
|
||||||
if len(p.modelCatalog) > 0 {
|
if len(p.modelCatalog) > 0 {
|
||||||
@ -698,6 +699,9 @@ type mailEvent struct {
|
|||||||
FromHuman bool `json:"from_human"`
|
FromHuman bool `json:"from_human"`
|
||||||
// InReplyTo 非空 = 这封是对本方某封信的回复,不是新派的活。
|
// InReplyTo 非空 = 这封是对本方某封信的回复,不是新派的活。
|
||||||
InReplyTo string `json:"in_reply_to"`
|
InReplyTo string `json:"in_reply_to"`
|
||||||
|
// PermissionMode 是会话的权限档位(plan / workspace / full)。
|
||||||
|
// homeagent 无法强制执行任何档位(advisory),只能在提示词里告知模型。
|
||||||
|
PermissionMode string `json:"permission_mode"`
|
||||||
// Decision / DecidedBy 只在 permission_decision 事件上有值。
|
// Decision / DecidedBy 只在 permission_decision 事件上有值。
|
||||||
Decision string `json:"decision"`
|
Decision string `json:"decision"`
|
||||||
DecidedBy string `json:"decided_by"`
|
DecidedBy string `json:"decided_by"`
|
||||||
@ -970,10 +974,11 @@ func (p *Plugin) handleNewMail(evt mailEvent, resumed bool) {
|
|||||||
"%s\n\n"+
|
"%s\n\n"+
|
||||||
"发件人:%s\n主题:%s\n邮件 ID:%s\n%s身份:你是 %s\n%s\n"+
|
"发件人:%s\n主题:%s\n邮件 ID:%s\n%s身份:你是 %s\n%s\n"+
|
||||||
"请先调用 read_inbox 读取完整正文,然后处理其中的请求。\n\n"+
|
"请先调用 read_inbox 读取完整正文,然后处理其中的请求。\n\n"+
|
||||||
"%s",
|
"%s\n%s",
|
||||||
inboundHeadline(evt.InReplyTo, evt.FromHuman, false),
|
inboundHeadline(evt.InReplyTo, evt.FromHuman, false),
|
||||||
evt.FromName, evt.Subject, evt.MailID, replyLine, p.agentName, addrLine,
|
evt.FromName, evt.Subject, evt.MailID, replyLine, p.agentName, addrLine,
|
||||||
replyInstruction(evt.FromHuman, evt.ReplyAddr),
|
replyInstruction(evt.FromHuman, evt.ReplyAddr),
|
||||||
|
ModeBriefing(evt.PermissionMode, "advisory"),
|
||||||
)
|
)
|
||||||
|
|
||||||
// InjectInputSync 阻塞等待 agent 处理完毕,返回最终回复文本。
|
// InjectInputSync 阻塞等待 agent 处理完毕,返回最终回复文本。
|
||||||
|
|||||||
Reference in New Issue
Block a user