( currentAgentMode?: AgentMode, )
| 242 | * User's local agents from .agents/ are always included regardless of mode. |
| 243 | */ |
| 244 | export const loadLocalAgents = ( |
| 245 | currentAgentMode?: AgentMode, |
| 246 | ): LocalAgentInfo[] => { |
| 247 | const selectedFreebuffModel = IS_FREEBUFF ? getSelectedFreebuffModel() : null |
| 248 | const cacheKey = selectedFreebuffModel |
| 249 | ? `${currentAgentMode ?? 'all'}:${selectedFreebuffModel}` |
| 250 | : (currentAgentMode ?? 'all') |
| 251 | const cached = cachedAgentsByMode.get(cacheKey) |
| 252 | if (cached) { |
| 253 | return cached |
| 254 | } |
| 255 | |
| 256 | // Get bundled agents - these are the default Codebuff agents |
| 257 | // compiled into the CLI binary at build time |
| 258 | const bundledAgentsInfo = getBundledAgentsAsLocalInfo() |
| 259 | const bundledAgents = getBundledAgents() |
| 260 | |
| 261 | // Filter bundled agents to only include subagents of the current mode's agent |
| 262 | let filteredBundledAgents: LocalAgentInfo[] |
| 263 | if (currentAgentMode) { |
| 264 | const currentAgentId = getAgentIdForMode(currentAgentMode) |
| 265 | const currentAgentDef = bundledAgents[currentAgentId] |
| 266 | ? bundledAgents[currentAgentId] |
| 267 | : undefined |
| 268 | const spawnableAgentIds = new Set(currentAgentDef?.spawnableAgents ?? []) |
| 269 | |
| 270 | // Only include bundled agents that are in the spawnableAgents list |
| 271 | filteredBundledAgents = bundledAgentsInfo.filter((agent) => |
| 272 | spawnableAgentIds.has(agent.id), |
| 273 | ) |
| 274 | } else { |
| 275 | filteredBundledAgents = bundledAgentsInfo |
| 276 | } |
| 277 | |
| 278 | const results: LocalAgentInfo[] = [...filteredBundledAgents] |
| 279 | const includedIds = new Set(filteredBundledAgents.map((a) => a.id)) |
| 280 | |
| 281 | // Get user agents from the SDK-loaded cache |
| 282 | // User agents are always included (not filtered by mode) and can override bundled agents |
| 283 | const userAgents = getUserAgentsAsLocalInfo() |
| 284 | |
| 285 | // Merge user agents - they override bundled agents with same ID |
| 286 | // and are always included regardless of mode filtering |
| 287 | for (const userAgent of userAgents) { |
| 288 | if (includedIds.has(userAgent.id)) { |
| 289 | // Replace bundled agent with user's version |
| 290 | const idx = results.findIndex((a) => a.id === userAgent.id) |
| 291 | if (idx !== -1) { |
| 292 | results[idx] = userAgent |
| 293 | } |
| 294 | } else { |
| 295 | results.push(userAgent) |
| 296 | includedIds.add(userAgent.id) |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | const sorted = results.sort((a, b) => |
| 301 | a.displayName.localeCompare(b.displayName, 'en'), |
no test coverage detected