package permission // tool_use_id 去重机制. // // 精妙之处(CLEVER): 在 SDK/HTTP 场景中,权限响应可能被重传. // 如果同一个 tool_use_id 被处理两次,API 会报 400 错误 // "tool_use ids must be unique".用固定大小的 set 记录已处理的 ID. // 最大 1000 条,超过后淘汰最早的. // // 历史包袱(LEGACY): 虽然变量名叫 "dedup",但它不是通用去重-- // 它专门针对权限响应的重复处理.通用去重应该在更上层做. // // 精妙之处(CLEVER): 用 FIFO 而不是 LRU. // 原因:tool_use_id 是一次性的,处理完就不会再被"访问", // 所以 LRU 的"最近访问"语义毫无意义.FIFO 更简单,更准确. // 替代方案:LRU(更通用但增加不必要的复杂度,tool_use_id 不会被重复访问). import ( "sync" ) // 默认去重集合最大容量. const defaultDedupMaxSize = 1000 // PermissionDedup 防止同一个 tool_use_id 的权限响应被重复处理. // // 精妙之处(CLEVER): 用 FIFO 而不是 LRU-- // tool_use_id 是一次性的,不会被"再次访问",FIFO 就够了. // 替代方案:LRU(更通用但多余,tool_use_id 不存在重复访问模式). type PermissionDedup struct { mu sync.Mutex resolved map[string]bool // 已处理的 tool_use_id order []string // FIFO 顺序 maxSize int // 最大容量(默认 1000) } // NewPermissionDedup 创建去重器. // // maxSize 指定最大容量,传入 0 使用默认值(1000 条). func NewPermissionDedup(maxSize int) *PermissionDedup { if maxSize <= 0 { maxSize = defaultDedupMaxSize } return &PermissionDedup{ resolved: make(map[string]bool), order: make([]string, 0), maxSize: maxSize, } } // IsResolved 检查指定的 tool_use_id 是否已被处理. func (d *PermissionDedup) IsResolved(toolUseID string) bool { d.mu.Lock() defer d.mu.Unlock() return d.resolved[toolUseID] } // MarkResolved 标记指定的 tool_use_id 为已处理. // // 如果已标记过,不会重复添加. // 如果超过 maxSize,按 FIFO 淘汰最早的条目. func (d *PermissionDedup) MarkResolved(toolUseID string) { d.mu.Lock() defer d.mu.Unlock() if d.resolved[toolUseID] { return // 已标记 } // 超过容量,淘汰最早的 if len(d.order) >= d.maxSize { oldest := d.order[0] d.order = d.order[1:] delete(d.resolved, oldest) } d.resolved[toolUseID] = true d.order = append(d.order, toolUseID) } // Size 返回当前已记录的 tool_use_id 数量. func (d *PermissionDedup) Size() int { d.mu.Lock() defer d.mu.Unlock() return len(d.resolved) }