@@ -101,6 +101,7 @@ func (b *Builder) WithToolsets(toolsetIDs []string) *Builder {
101101// WithTools specifies additional tools that bypass toolset filtering.
102102// These tools are additive - they will be included even if their toolset is not enabled.
103103// Read-only filtering still applies to these tools.
104+ // Input is cleaned (trimmed, deduplicated) during Build().
104105// Deprecated tool aliases are automatically resolved to their canonical names during Build().
105106// Returns self for chaining.
106107func (b * Builder ) WithTools (toolNames []string ) * Builder {
@@ -127,6 +128,24 @@ func (b *Builder) WithFilter(filter ToolFilter) *Builder {
127128 return b
128129}
129130
131+ // cleanTools trims whitespace and removes duplicates from tool names.
132+ // Empty strings after trimming are excluded.
133+ func cleanTools (tools []string ) []string {
134+ seen := make (map [string ]bool )
135+ var cleaned []string
136+ for _ , name := range tools {
137+ trimmed := strings .TrimSpace (name )
138+ if trimmed == "" {
139+ continue
140+ }
141+ if ! seen [trimmed ] {
142+ seen [trimmed ] = true
143+ cleaned = append (cleaned , trimmed )
144+ }
145+ }
146+ return cleaned
147+ }
148+
130149// Build creates the final Inventory with all configuration applied.
131150// This processes toolset filtering, tool name resolution, and sets up
132151// the inventory for use. The returned Inventory is ready for use with
@@ -151,12 +170,13 @@ func (b *Builder) Build() *Inventory {
151170 validToolNames [b .tools [i ].Tool .Name ] = true
152171 }
153172
154- // Process additional tools (resolve aliases and track unrecognized)
155- // Note: input is expected to be pre-cleaned (trimmed, deduped) via CleanTools
173+ // Process additional tools (clean, resolve aliases, and track unrecognized)
156174 if len (b .additionalTools ) > 0 {
157- r .additionalTools = make (map [string ]bool , len (b .additionalTools ))
175+ cleanedTools := cleanTools (b .additionalTools )
176+
177+ r .additionalTools = make (map [string ]bool , len (cleanedTools ))
158178 var unrecognizedTools []string
159- for _ , name := range b . additionalTools {
179+ for _ , name := range cleanedTools {
160180 // Always include the original name - this handles the case where
161181 // the tool exists but is controlled by a feature flag that's OFF.
162182 r .additionalTools [name ] = true
0 commit comments