From c465616a86aeae45e5508b1d0ea0426c9fe7de1d Mon Sep 17 00:00:00 2001 From: Copilot Date: Sun, 19 Jul 2026 11:32:38 -0400 Subject: [PATCH] refactor: optimize filter-map chains into single-pass operations --- packages/@ant/computer-use-mcp/src/toolCalls.ts | 5 ++++- .../src/tools/TaskListTool/TaskListTool.ts | 5 ++++- src/commands/plugin/ManagePlugins.tsx | 5 ++++- src/components/Spinner.tsx | 5 ++++- src/components/TaskListV2.tsx | 15 ++++++++++++--- src/components/agents/AgentsList.tsx | 8 ++++++-- src/components/memory/MemoryFileSelector.tsx | 5 ++++- .../messages/CollapsedReadSearchContent.tsx | 5 ++++- .../permissions/rules/PermissionRuleList.tsx | 5 ++++- src/hooks/useTaskListWatcher.ts | 5 ++++- src/services/autoDream/consolidationLock.ts | 5 ++++- src/skills/bundled/ultracode.ts | 5 ++++- src/utils/groupToolUses.ts | 5 ++++- src/utils/messages.ts | 5 ++++- src/utils/pipeRegistry.ts | 5 ++++- src/utils/plugins/dependencyResolver.ts | 10 ++++++++-- src/utils/plugins/pluginDirectories.ts | 5 ++++- src/utils/swarm/inProcessRunner.ts | 5 ++++- src/utils/tasks.ts | 10 ++++++++-- 19 files changed, 94 insertions(+), 24 deletions(-) diff --git a/packages/@ant/computer-use-mcp/src/toolCalls.ts b/packages/@ant/computer-use-mcp/src/toolCalls.ts index 404c38cd2c..6a972e1d9a 100644 --- a/packages/@ant/computer-use-mcp/src/toolCalls.ts +++ b/packages/@ant/computer-use-mcp/src/toolCalls.ts @@ -1262,7 +1262,10 @@ async function buildAccessRequest( // resolved goes in the exempt set. const exemptForPreview = [ ...allowedApps.map(a => a.bundleId), - ...surviving.filter(r => r.resolved).map(r => r.resolved!.bundleId), + ...surviving.reduce((acc: string[], r) => { + if (r.resolved) acc.push(r.resolved.bundleId); + return acc; + }, []), ] const willHide = await adapter.executor.previewHideSet( exemptForPreview, diff --git a/packages/builtin-tools/src/tools/TaskListTool/TaskListTool.ts b/packages/builtin-tools/src/tools/TaskListTool/TaskListTool.ts index 128f731432..7d8e50f5b3 100644 --- a/packages/builtin-tools/src/tools/TaskListTool/TaskListTool.ts +++ b/packages/builtin-tools/src/tools/TaskListTool/TaskListTool.ts @@ -71,7 +71,10 @@ export const TaskListTool = buildTool({ // Build a set of resolved task IDs for filtering const resolvedTaskIds = new Set( - allTasks.filter(t => t.status === 'completed').map(t => t.id), + allTasks.reduce((acc: string[], t) => { + if (t.status === 'completed') acc.push(t.id); + return acc; + }, []) ) const tasks = allTasks.map(task => ({ diff --git a/src/commands/plugin/ManagePlugins.tsx b/src/commands/plugin/ManagePlugins.tsx index 3230cef983..4897e6604a 100644 --- a/src/commands/plugin/ManagePlugins.tsx +++ b/src/commands/plugin/ManagePlugins.tsx @@ -855,7 +855,10 @@ export function ManagePlugins({ // Mark flagged plugins as seen when the Installed view renders them. // After 48 hours from seenAt, they auto-clear on next load. const flaggedIds = useMemo( - () => unifiedItems.filter(item => item.type === 'flagged-plugin').map(item => item.id), + () => unifiedItems.reduce((acc: string[], item) => { + if (item.type === 'flagged-plugin') acc.push(item.id); + return acc; + }, []), [unifiedItems], ); useEffect(() => { diff --git a/src/components/Spinner.tsx b/src/components/Spinner.tsx index 419eb00871..034b98c5d8 100644 --- a/src/components/Spinner.tsx +++ b/src/components/Spinner.tsx @@ -550,6 +550,9 @@ function findNextPendingTask(tasks: Task[] | undefined): Task | undefined { if (pendingTasks.length === 0) { return undefined; } - const unresolvedIds = new Set(tasks.filter(t => t.status !== 'completed').map(t => t.id)); + const unresolvedIds = new Set(tasks.reduce((acc: string[], t) => { + if (t.status !== 'completed') acc.push(t.id); + return acc; + }, [])); return pendingTasks.find(t => !t.blockedBy.some(id => unresolvedIds.has(id))) ?? pendingTasks[0]; } diff --git a/src/components/TaskListV2.tsx b/src/components/TaskListV2.tsx index 9f92b4ff70..6769632759 100644 --- a/src/components/TaskListV2.tsx +++ b/src/components/TaskListV2.tsx @@ -42,12 +42,18 @@ export function TaskListV2({ tasks, isStandalone = false }: Props): React.ReactN const completionTimestampsRef = React.useRef(new Map()); const previousCompletedIdsRef = React.useRef | null>(null); if (previousCompletedIdsRef.current === null) { - previousCompletedIdsRef.current = new Set(tasks.filter(t => t.status === 'completed').map(t => t.id)); + previousCompletedIdsRef.current = new Set(tasks.reduce((acc: string[], t) => { + if (t.status === 'completed') acc.push(t.id); + return acc; + }, [])); } const maxDisplay = rows <= 10 ? 0 : Math.min(10, Math.max(3, rows - 14)); // Update completion timestamps: reset when a task transitions to completed - const currentCompletedIds = new Set(tasks.filter(t => t.status === 'completed').map(t => t.id)); + const currentCompletedIds = new Set(tasks.reduce((acc: string[], t) => { + if (t.status === 'completed') acc.push(t.id); + return acc; + }, [])); const now = Date.now(); for (const id of currentCompletedIds) { if (!previousCompletedIdsRef.current.has(id)) { @@ -136,7 +142,10 @@ export function TaskListV2({ tasks, isStandalone = false }: Props): React.ReactN const pendingCount = count(tasks, t => t.status === 'pending'); const inProgressCount = tasks.length - completedCount - pendingCount; // Unresolved tasks (open or in_progress) block dependent tasks - const unresolvedTaskIds = new Set(tasks.filter(t => t.status !== 'completed').map(t => t.id)); + const unresolvedTaskIds = new Set(tasks.reduce((acc: string[], t) => { + if (t.status !== 'completed') acc.push(t.id); + return acc; + }, [])); // Check if we need to truncate const needsTruncation = tasks.length > maxDisplay; diff --git a/src/components/agents/AgentsList.tsx b/src/components/agents/AgentsList.tsx index 04e7240b2b..689a4cd10c 100644 --- a/src/components/agents/AgentsList.tsx +++ b/src/components/agents/AgentsList.tsx @@ -242,7 +242,9 @@ export function AgentsList({ source, agents, onBack, onSelect, onCreateNew, chan {onCreateNew && {renderCreateNewOption()}} {source === 'all' ? ( <> - {AGENT_SOURCE_GROUPS.filter(g => g.source !== 'built-in').map(({ label, source: groupSource }) => ( + {AGENT_SOURCE_GROUPS.flatMap(g => + g.source !== 'built-in' ? [{label: g.label, source: g.source}] : [] + ).map(({ label, source: groupSource }) => ( {renderAgentGroup( label, @@ -270,7 +272,9 @@ export function AgentsList({ source, agents, onBack, onSelect, onCreateNew, chan ) : ( <> - {sortedAgents.filter(a => a.source !== 'built-in').map(agent => renderAgent(agent))} + {sortedAgents.flatMap(agent => + agent.source !== 'built-in' ? [agent] : [] + ).map(agent => renderAgent(agent))} {sortedAgents.some(a => a.source === 'built-in') && ( <> diff --git a/src/components/memory/MemoryFileSelector.tsx b/src/components/memory/MemoryFileSelector.tsx index 90a5beca8f..0acda4cd52 100644 --- a/src/components/memory/MemoryFileSelector.tsx +++ b/src/components/memory/MemoryFileSelector.tsx @@ -59,7 +59,10 @@ export function MemoryFileSelector({ onSelect, onCancel }: Props): React.ReactNo // /memory already surfaces "Open auto-memory folder" / "Open team memory // folder" options below. Listing the entrypoint file separately is redundant. const allMemoryFiles: ExtendedMemoryFileInfo[] = [ - ...existingMemoryFiles.filter(f => f.type !== 'AutoMem' && f.type !== 'TeamMem').map(f => ({ ...f, exists: true })), + ...existingMemoryFiles.reduce((acc: ExtendedMemoryFileInfo[], f) => { + if (f.type !== 'AutoMem' && f.type !== 'TeamMem') acc.push({ ...f, exists: true }); + return acc; + }, []), // Add User memory if it doesn't exist ...(hasUserMemory ? [] diff --git a/src/components/messages/CollapsedReadSearchContent.tsx b/src/components/messages/CollapsedReadSearchContent.tsx index 9209a109a6..5527174464 100644 --- a/src/components/messages/CollapsedReadSearchContent.tsx +++ b/src/components/messages/CollapsedReadSearchContent.tsx @@ -309,7 +309,10 @@ export function CollapsedReadSearchContent({ 'cherry-picked': 'cherry-picked', }; for (const kind of ['committed', 'amended', 'cherry-picked'] as const) { - const shas = message.commits.filter(c => c.kind === kind).map(c => c.sha); + const shas = message.commits.reduce((acc: string[], c) => { + if (c.kind === kind) acc.push(c.sha); + return acc; + }, []); if (shas.length) { pushPart(kind, byKind[kind], {shas.join(', ')}); } diff --git a/src/components/permissions/rules/PermissionRuleList.tsx b/src/components/permissions/rules/PermissionRuleList.tsx index d02d9c6014..190bca503c 100644 --- a/src/components/permissions/rules/PermissionRuleList.tsx +++ b/src/components/permissions/rules/PermissionRuleList.tsx @@ -508,7 +508,10 @@ export function PermissionRuleList({ onExit, initialTab, onRetryDenials }: Props // Find the adjacent rule to focus on after deletion const { options } = getRulesOptions(selectedRule.ruleBehavior as TabType); const selectedKey = jsonStringify(selectedRule); - const ruleKeys = options.filter(opt => opt.value !== 'add-new-rule').map(opt => opt.value); + const ruleKeys = options.reduce((acc: string[], opt) => { + if (opt.value !== 'add-new-rule') acc.push(opt.value as string); + return acc; + }, []); const currentIndex = ruleKeys.indexOf(selectedKey); // Try to focus on the next rule, or the previous if deleting the last one diff --git a/src/hooks/useTaskListWatcher.ts b/src/hooks/useTaskListWatcher.ts index 1fa3b9093b..d30e36fa0d 100644 --- a/src/hooks/useTaskListWatcher.ts +++ b/src/hooks/useTaskListWatcher.ts @@ -196,7 +196,10 @@ export function useTaskListWatcher({ */ function findAvailableTask(tasks: Task[]): Task | undefined { const unresolvedTaskIds = new Set( - tasks.filter(t => t.status !== 'completed').map(t => t.id), + tasks.reduce((acc: string[], t) => { + if (t.status !== 'completed') acc.push(t.id); + return acc; + }, []) ) return tasks.find(task => { diff --git a/src/services/autoDream/consolidationLock.ts b/src/services/autoDream/consolidationLock.ts index 621232bb82..8bfeecf0e6 100644 --- a/src/services/autoDream/consolidationLock.ts +++ b/src/services/autoDream/consolidationLock.ts @@ -120,7 +120,10 @@ export async function listSessionsTouchedSince( ): Promise { const dir = getProjectDir(getOriginalCwd()) const candidates = await listCandidates(dir, true) - return candidates.filter(c => c.mtime > sinceMs).map(c => c.sessionId) + return candidates.reduce((acc: string[], c) => { + if (c.mtime > sinceMs) acc.push(c.sessionId); + return acc; + }, []) } /** diff --git a/src/skills/bundled/ultracode.ts b/src/skills/bundled/ultracode.ts index e47ed22953..7fcf6b68c3 100644 --- a/src/skills/bundled/ultracode.ts +++ b/src/skills/bundled/ultracode.ts @@ -182,7 +182,10 @@ while (dry < 2) { // loop-until-dry parallel(['correctness','security','repro'].map(lens => () => // ...each by 3 distinct lenses agent(\`Judge "\${b.desc}" via the \${lens} lens — real?\`, {phase: 'Verify', schema: VERDICT}))) .then(vs => ({ b, real: vs.filter(Boolean).filter(v => v.real).length >= 2 })))) - confirmed.push(...judged.filter(v => v.real).map(v => v.b)) + confirmed.push(...judged.reduce((acc: typeof judged, v) => { + if (v.real) acc.push(v); + return acc; + }, []).map(v => v.b)) } return confirmed // dedup vs \`seen\`, NOT \`confirmed\` — else judge-rejected findings reappear every round and it never converges. diff --git a/src/utils/groupToolUses.ts b/src/utils/groupToolUses.ts index 333d9c5a8e..fe0abf6413 100644 --- a/src/utils/groupToolUses.ts +++ b/src/utils/groupToolUses.ts @@ -28,7 +28,10 @@ const GROUPING_CACHE = new WeakMap>() function getToolsWithGrouping(tools: Tools): Set { let cached = GROUPING_CACHE.get(tools) if (!cached) { - cached = new Set(tools.filter(t => t.renderGroupedToolUse).map(t => t.name)) + cached = new Set(tools.reduce((acc: string[], t) => { + if (t.renderGroupedToolUse) acc.push(t.name); + return acc; + }, [])) GROUPING_CACHE.set(tools, cached) } return cached diff --git a/src/utils/messages.ts b/src/utils/messages.ts index 51884e8041..4ae402cd0b 100644 --- a/src/utils/messages.ts +++ b/src/utils/messages.ts @@ -2199,7 +2199,10 @@ function sanitizeErrorToolResultContent( if (!Array.isArray(trContent)) return b if (trContent.every(c => c.type === 'text')) return b changed = true - const texts = trContent.filter(c => c.type === 'text').map(c => c.text) + const texts = trContent.reduce((acc: string[], c) => { + if (c.type === 'text') acc.push(c.text); + return acc; + }, []) const textOnly: TextBlockParam[] = texts.length > 0 ? [{ type: 'text', text: texts.join('\n\n') }] : [] return { ...b, content: textOnly } diff --git a/src/utils/pipeRegistry.ts b/src/utils/pipeRegistry.ts index da2b07a5f7..2daca5700b 100644 --- a/src/utils/pipeRegistry.ts +++ b/src/utils/pipeRegistry.ts @@ -420,7 +420,10 @@ export async function cleanupStaleEntries(): Promise { } const deadNames = new Set( - subResults.filter(r => !r.alive).map(r => r.sub.pipeName), + subResults.reduce((acc: string[], r) => { + if (!r.alive) acc.push(r.sub.pipeName); + return acc; + }, []) ) const aliveSubs = fresh.subs.filter(s => !deadNames.has(s.pipeName)) if (aliveSubs.length !== fresh.subs.length) { diff --git a/src/utils/plugins/dependencyResolver.ts b/src/utils/plugins/dependencyResolver.ts index 5575c8c017..5d3d3f5604 100644 --- a/src/utils/plugins/dependencyResolver.ts +++ b/src/utils/plugins/dependencyResolver.ts @@ -179,7 +179,10 @@ export function verifyAndDemote(plugins: readonly LoadedPlugin[]): { errors: PluginError[] } { const known = new Set(plugins.map(p => p.source)) - const enabled = new Set(plugins.filter(p => p.enabled).map(p => p.source)) + const enabled = new Set(plugins.reduce((acc: string[], p) => { + if (p.enabled) acc.push(p.source); + return acc; + }, [])) // Name-only indexes for bare deps from --plugin-dir (@inline) plugins: // the real marketplace is unknown, so match "B" against any enabled "B@*". // enabledByName is a multiset: if B@epic AND B@other are both enabled, @@ -228,7 +231,10 @@ export function verifyAndDemote(plugins: readonly LoadedPlugin[]): { } const demoted = new Set( - plugins.filter(p => p.enabled && !enabled.has(p.source)).map(p => p.source), + plugins.reduce((acc: string[], p) => { + if (p.enabled && !enabled.has(p.source)) acc.push(p.source); + return acc; + }, []) ) return { demoted, errors } } diff --git a/src/utils/plugins/pluginDirectories.ts b/src/utils/plugins/pluginDirectories.ts index 0bb6701935..f8d77b3679 100644 --- a/src/utils/plugins/pluginDirectories.ts +++ b/src/utils/plugins/pluginDirectories.ts @@ -86,7 +86,10 @@ export function getPluginSeedDirs(): string[] { // Same tilde-expansion rationale as getPluginsDirectory (gh-30794). const raw = process.env.CLAUDE_CODE_PLUGIN_SEED_DIR if (!raw) return [] - return raw.split(delimiter).filter(Boolean).map(expandTilde) + return raw.split(delimiter).reduce((acc: string[], p) => { + if (p) acc.push(expandTilde(p)); + return acc; + }, []) } function sanitizePluginId(pluginId: string): string { diff --git a/src/utils/swarm/inProcessRunner.ts b/src/utils/swarm/inProcessRunner.ts index 4d2c7e605b..61c2271a60 100644 --- a/src/utils/swarm/inProcessRunner.ts +++ b/src/utils/swarm/inProcessRunner.ts @@ -603,7 +603,10 @@ async function sendIdleNotification( */ function findAvailableTask(tasks: Task[]): Task | undefined { const unresolvedTaskIds = new Set( - tasks.filter(t => t.status !== 'completed').map(t => t.id), + tasks.reduce((acc: string[], t) => { + if (t.status !== 'completed') acc.push(t.id); + return acc; + }, []) ) return tasks.find(task => { diff --git a/src/utils/tasks.ts b/src/utils/tasks.ts index 90e50e72f8..423b8ebe36 100644 --- a/src/utils/tasks.ts +++ b/src/utils/tasks.ts @@ -584,7 +584,10 @@ export async function claimTask( // Check for unresolved blockers (open or in_progress tasks block) const allTasks = await listTasks(taskListId) const unresolvedTaskIds = new Set( - allTasks.filter(t => t.status !== 'completed').map(t => t.id), + allTasks.reduce((acc: string[], t) => { + if (t.status !== 'completed') acc.push(t.id); + return acc; + }, []) ) const blockedByTasks = task.blockedBy.filter(id => unresolvedTaskIds.has(id), @@ -648,7 +651,10 @@ async function claimTaskWithBusyCheck( // Check for unresolved blockers (open or in_progress tasks block) const unresolvedTaskIds = new Set( - allTasks.filter(t => t.status !== 'completed').map(t => t.id), + allTasks.reduce((acc: string[], t) => { + if (t.status !== 'completed') acc.push(t.id); + return acc; + }, []) ) const blockedByTasks = task.blockedBy.filter(id => unresolvedTaskIds.has(id),