6d0f09d75f
- 跨实例 Resolve 通过 Redis reply channel 接收 owning 实例的 ack (ok / not_found / tenant_mismatch / user_mismatch / already_resolved), HTTP 不再静默 200,超时退化为 NotFound。 - PendingRequest 增加 UserID,Resolve 校验会话所有者,避免同租户 其他用户越权批准/篡改参数。 - 新增 ErrAlreadyResolved,timer/ctx 命中后再次 Resolve 返回 400 而 不是静默成功;waiter.deliver 暴露胜出语义。 - NeedsApproval 默认 fail-close(DB 故障要求审批),可经 WEKNORA_AGENT_TOOL_APPROVAL_FAIL_OPEN=true 回退。 - Pub/Sub 增加 OriginID 自过滤、退避重连、namespace 后缀,避免自回 环噪声与多部署串扰。 - 工具执行超时常量统一通过 ToolExecContext.ExecTimeout 注入, mcp_tool.go 不再硬编码 60s。 - handler 修正 path 二次解码、错误用 errors.Is、modified_args=null 的 静默清空、ListMCPToolApprovals 的 404/500 误判。 - repository 用 clause.OnConflict 做原子 upsert,消除并发 500。 - 增加 NotFound / TenantMismatch / UserMismatch / AlreadyResolved / Race 等用例。
48 lines
1.6 KiB
Go
48 lines
1.6 KiB
Go
package tools
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/Tencent/WeKnora/internal/event"
|
|
)
|
|
|
|
type execCtxKey struct{}
|
|
|
|
// ToolExecContext is attached to context during agent tool execution (per tool call).
|
|
type ToolExecContext struct {
|
|
SessionID string
|
|
AssistantMessageID string
|
|
RequestID string
|
|
ToolCallID string
|
|
UserID string // owner of the originating session; used by HITL gates for authorization (issue #1173)
|
|
EventBus *event.EventBus
|
|
// ApprovalCtx is the parent ctx WITHOUT defaultToolExecTimeout; used when the tool
|
|
// must wait for human approval that may exceed normal tool exec timeout (issue #1173).
|
|
// Falls back to the per-tool execCtx when nil.
|
|
ApprovalCtx context.Context
|
|
// ExecTimeout mirrors the per-tool exec timeout the engine applied to the
|
|
// outer ctx. Tools that legitimately consume that ctx (e.g. MCP human
|
|
// approval) can re-derive a fresh timeout from ApprovalCtx using this
|
|
// value instead of hard-coding a duration. Zero means "fallback to 60s".
|
|
ExecTimeout time.Duration
|
|
}
|
|
|
|
// WithToolExecContext returns ctx that carries ToolExecContext for MCP approval and similar features.
|
|
func WithToolExecContext(ctx context.Context, meta *ToolExecContext) context.Context {
|
|
if meta == nil {
|
|
return ctx
|
|
}
|
|
return context.WithValue(ctx, execCtxKey{}, meta)
|
|
}
|
|
|
|
// ToolExecFromContext returns metadata attached by the agent engine, if any.
|
|
func ToolExecFromContext(ctx context.Context) (*ToolExecContext, bool) {
|
|
v := ctx.Value(execCtxKey{})
|
|
if v == nil {
|
|
return nil, false
|
|
}
|
|
meta, ok := v.(*ToolExecContext)
|
|
return meta, ok && meta != nil
|
|
}
|