FilterAllowedTools filters tools based on the given allow/denylists. Filtering acts on tool names, and uses tool IDs for tracking. The denylist supersedes the allowlist in the case of any conflicts. If an allowlist is provided, tools must match it to be allowed. If only a denylist is provided, tools
(logger slog.Logger, tools map[string]*Tool, allowlist *regexp.Regexp, denylist *regexp.Regexp)
| 122 | // If an allowlist is provided, tools must match it to be allowed. |
| 123 | // If only a denylist is provided, tools are allowed unless explicitly denied. |
| 124 | func FilterAllowedTools(logger slog.Logger, tools map[string]*Tool, allowlist *regexp.Regexp, denylist *regexp.Regexp) map[string]*Tool { |
| 125 | if len(tools) == 0 { |
| 126 | return tools |
| 127 | } |
| 128 | |
| 129 | if allowlist == nil && denylist == nil { |
| 130 | return tools |
| 131 | } |
| 132 | |
| 133 | allowed := make(map[string]*Tool, len(tools)) |
| 134 | for id, tool := range tools { |
| 135 | if tool == nil { |
| 136 | continue |
| 137 | } |
| 138 | |
| 139 | // Check denylist first since it can override allowlist. |
| 140 | if denylist != nil && denylist.MatchString(tool.Name) { |
| 141 | // Log conflict if also in allowlist. |
| 142 | if allowlist != nil && allowlist.MatchString(tool.Name) { |
| 143 | logger.Warn(context.Background(), "tool filtering conflict; marking tool disallowed", slog.F("name", tool.Name)) |
| 144 | } |
| 145 | continue // Not allowed. |
| 146 | } |
| 147 | |
| 148 | // Check allowlist if present. |
| 149 | if allowlist != nil { |
| 150 | if !allowlist.MatchString(tool.Name) { |
| 151 | continue // Not allowed. |
| 152 | } |
| 153 | } |
| 154 | |
| 155 | // Tool is allowed. |
| 156 | allowed[id] = tool |
| 157 | } |
| 158 | |
| 159 | return allowed |
| 160 | } |
no outgoing calls