feat: 修复审计落差 #1/#2/#3/#6 + 管理面板移动端适配
#1 工具布尔标记生效(agent-106, 安全红线): loop toolSchemas/runToolCalls 加 allow-set 安全门 restrictSchemas/applyToolSecurityGate——群聊/陌生人只暴露允许工具(默认关), 被拒not_allowed软提示+AuditEvent, owner全工具不变; 身份靠 ActorEnv(非提示词) #2 checkpoint 恢复(agent-109): run.go LoadLatest + resumableStopReason门控(只恢复in-flight工具循环,不出答案不续跑), 幂等不重放副作用, 新会话不误恢复; resume_test 4用例 #3 tool_result(agent-108, 协议层): Anthropic 原生tool_result块(tool_use_id/is_error)非user纯文本 + OpenAI tool消息补tool_call_id; Content加ToolCallID/IsError等; (loop接线层2处留待,见备注) #6 capacity_awaken推送(agent-107): onCapacity从只Debug改推WS hub(BroadcastCapacityAwaken, sessionId定向+payload对齐前端AwakenPayload) 管理面板移动端(agent-110): AdminApp 汉堡菜单+抽屉侧栏+标题truncate防换行, RBAC守卫不受影响 全仓 build/vet/test绿 + 前端build绿; 前端无涉差异已对齐 备注: #3 loop接线层2处(assistant工具轮append历史 + Message.ToolCallID/IsError)留给后续; #4代审/#5子代理触发/#7拆文件后置(主人说后三不急)
This commit is contained in:
1 parent
aedae2190b
commit
7e39153a69
24 files changed
+1286
-56
No files matched your search
@@ -36,17 +36,36 @@ const (
|
||||
ContentTypeText ContentType = "text"
|
||||
// ContentTypeImage is an image content part.
|
||||
ContentTypeImage ContentType = "image_url"
|
||||
// ContentTypeToolCall is an assistant-originated tool invocation part
|
||||
// (Anthropic tool_use / OpenAI tool_calls), carried on a RoleAssistant turn.
|
||||
ContentTypeToolCall ContentType = "tool_call"
|
||||
// ContentTypeToolResult is a tool execution result part, carried on a RoleTool
|
||||
// turn and encoded natively (Anthropic tool_result / OpenAI tool message).
|
||||
ContentTypeToolResult ContentType = "tool_result"
|
||||
)
|
||||
|
||||
// Content is a single, possibly multimodal, part of a message.
|
||||
type Content struct {
|
||||
// Type distinguishes a text part from an image part.
|
||||
// Type distinguishes a text part from an image / tool part.
|
||||
Type ContentType
|
||||
// Text is the text payload when Type == ContentTypeText.
|
||||
// Text is the text payload when Type == ContentTypeText, or the result body
|
||||
// when Type == ContentTypeToolResult.
|
||||
Text string
|
||||
// ImageURL is the image source when Type == ContentTypeImage. It may be a
|
||||
// data: URI or an http(s):// URL.
|
||||
ImageURL string
|
||||
// ToolCallID correlates the part to a provider tool_use/tool_call id: the call
|
||||
// id for ContentTypeToolCall, or the tool_use_id being answered for
|
||||
// ContentTypeToolResult.
|
||||
ToolCallID string
|
||||
// ToolCallName is the invoked tool name when Type == ContentTypeToolCall.
|
||||
ToolCallName string
|
||||
// ToolArgs is the structured argument object when Type == ContentTypeToolCall.
|
||||
// It is never a JSON-encoded string.
|
||||
ToolArgs map[string]any
|
||||
// IsError marks a ContentTypeToolResult part as an execution failure so the
|
||||
// provider's tool_result.is_error / error flag is set natively.
|
||||
IsError bool
|
||||
}
|
||||
|
||||
// Message is a single conversation turn, normalized across providers.
|
||||
@@ -62,8 +81,11 @@ type Message struct {
|
||||
// channel layer. Empty means the sender is unlabeled (the owner, or an
|
||||
// unknown/unresolved sender), and callers may leave it unset.
|
||||
SenderName string
|
||||
// ToolCallID and ToolCallName are reserved as interface-level placeholders
|
||||
// for the M2 tool loop; they are ignored by current adapters.
|
||||
// ToolCallID correlates a RoleTool turn to the provider tool_use/tool_call id
|
||||
// it answers, and ToolCallName is the invoked tool name carried as a
|
||||
// convenience for callers that render the result. Both are set by the tool
|
||||
// loop when it feeds a result back, and consumed by the adapters to emit
|
||||
// native tool_result / tool-message blocks.
|
||||
ToolCallID string
|
||||
ToolCallName string
|
||||
}
|
||||
@@ -84,6 +106,25 @@ func ImageMessage(role Role, text, imageURL string) Message {
|
||||
return Message{Role: role, Content: parts}
|
||||
}
|
||||
|
||||
// ToolResultMessage builds a RoleTool turn carrying the native result of one tool
|
||||
// call. toolUseID must equal the provider id of the tool_use block this result
|
||||
// answers; isError marks an execution failure; text is the result body.
|
||||
func ToolResultMessage(toolUseID, text string, isError bool) Message {
|
||||
return Message{Role: RoleTool, ToolCallID: toolUseID,
|
||||
Content: []Content{{Type: ContentTypeToolResult, Text: text, ToolCallID: toolUseID, IsError: isError}}}
|
||||
}
|
||||
|
||||
// AssistantToolCallMessage builds a RoleAssistant turn advertising the tool calls
|
||||
// the model requested, so a subsequent RoleTool turn can be correlated to them by
|
||||
// the provider (OpenAI tool_call_id / Anthropic tool_use_id).
|
||||
func AssistantToolCallMessage(calls []ToolCall) Message {
|
||||
parts := make([]Content, 0, len(calls))
|
||||
for _, c := range calls {
|
||||
parts = append(parts, Content{Type: ContentTypeToolCall, ToolCallID: c.ID, ToolCallName: c.Name, ToolArgs: c.Args})
|
||||
}
|
||||
return Message{Role: RoleAssistant, Content: parts}
|
||||
}
|
||||
|
||||
// ToolSpec is an interface-level placeholder for a tool/function schema. The
|
||||
// full tool loop (registration, argument binding, result re-feed) is M2; here
|
||||
// it only lets a request advertise tools to the provider in the wire contract.
|
||||
@@ -99,6 +140,10 @@ type ToolSpec struct {
|
||||
// (never a serialized JSON string), so a tool loop can bind it directly without
|
||||
// re-parsing.
|
||||
type ToolCall struct {
|
||||
// ID is the provider tool_use/tool_call id, so a tool loop can correlate the
|
||||
// resulting RoleTool message to the exact call (Anthropic tool_use_id / OpenAI
|
||||
// tool_call_id). Empty when the provider emitted no id.
|
||||
ID string
|
||||
// Name is the tool being invoked.
|
||||
Name string
|
||||
// Args are the tool arguments, decoded from the provider's structured
|
||||
|
||||
Reference in new issue
Block a user