From 9af0a0df2bbf4d4a592ceee501eced45677c460c Mon Sep 17 00:00:00 2001 From: 777genius Date: Thu, 28 May 2026 23:13:26 +0300 Subject: [PATCH] perf(team): cache runtime command parsing --- .../team/TeamRuntimeLivenessResolver.ts | 49 ++++++++++++++++++- ...timeLivenessResolverCommandParsing.test.ts | 24 +++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 test/main/services/team/TeamRuntimeLivenessResolverCommandParsing.test.ts diff --git a/src/main/services/team/TeamRuntimeLivenessResolver.ts b/src/main/services/team/TeamRuntimeLivenessResolver.ts index 558ffb0c..b1d7fa80 100644 --- a/src/main/services/team/TeamRuntimeLivenessResolver.ts +++ b/src/main/services/team/TeamRuntimeLivenessResolver.ts @@ -45,6 +45,11 @@ export interface ResolvedTeamMemberRuntimeLiveness { const SHELL_COMMAND_NAMES = new Set(['sh', 'bash', 'zsh', 'fish', 'dash', 'login', 'tmux']); const SECRET_FLAG_PATTERN = /(--(?:api-key|token|password|secret|authorization|auth-token)(?:=|\s+))("[^"]*"|'[^']*'|\S+)/gi; +const MAX_CLI_ARG_CACHE_ENTRIES = 2_000; +const CLI_ARG_CACHE_KEY_SEPARATOR = '\u0000'; + +const cliArgValuesCache = new Map(); +const commandArgEqualsCache = new Map(); function basenameCommand(command: string | undefined): string { const firstToken = command?.trim().split(/\s+/, 1)[0] ?? ''; @@ -68,7 +73,37 @@ function escapeRegexLiteral(value: string): string { return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } +function buildCliArgCacheKey(...parts: readonly string[]): string { + return parts.join(CLI_ARG_CACHE_KEY_SEPARATOR); +} + +function getCachedValue(cache: Map, key: string): T | undefined { + if (!cache.has(key)) { + return undefined; + } + const value = cache.get(key) as T; + cache.delete(key); + cache.set(key, value); + return value; +} + +function setCachedValue(cache: Map, key: string, value: T): void { + if (!cache.has(key) && cache.size >= MAX_CLI_ARG_CACHE_ENTRIES) { + const oldestKey = cache.keys().next().value; + if (oldestKey !== undefined) { + cache.delete(oldestKey); + } + } + cache.set(key, value); +} + export function extractCliArgValues(command: string, argName: string): string[] { + const cacheKey = buildCliArgCacheKey(command, argName); + const cached = getCachedValue(cliArgValuesCache, cacheKey); + if (cached) { + return cached.slice(); + } + const escapedArg = escapeRegexLiteral(argName); const pattern = new RegExp( `(?:^|\\s)${escapedArg}(?:=|\\s+)("([^"]*)"|'([^']*)'|([^\\s]+))`, @@ -80,7 +115,8 @@ export function extractCliArgValues(command: string, argName: string): string[] const value = (match[2] ?? match[3] ?? match[4] ?? '').trim(); if (value) values.push(value); } - return values; + setCachedValue(cliArgValuesCache, cacheKey, values); + return values.slice(); } export function commandArgEquals( @@ -90,7 +126,16 @@ export function commandArgEquals( ): boolean { const normalizedExpected = expected?.trim(); if (!normalizedExpected) return false; - return extractCliArgValues(command, argName).some((value) => value === normalizedExpected); + const cacheKey = buildCliArgCacheKey(command, argName, normalizedExpected); + const cached = getCachedValue(commandArgEqualsCache, cacheKey); + if (cached !== undefined) { + return cached; + } + const result = extractCliArgValues(command, argName).some( + (value) => value === normalizedExpected + ); + setCachedValue(commandArgEqualsCache, cacheKey, result); + return result; } function collectDescendants( diff --git a/test/main/services/team/TeamRuntimeLivenessResolverCommandParsing.test.ts b/test/main/services/team/TeamRuntimeLivenessResolverCommandParsing.test.ts new file mode 100644 index 00000000..f82b2746 --- /dev/null +++ b/test/main/services/team/TeamRuntimeLivenessResolverCommandParsing.test.ts @@ -0,0 +1,24 @@ +import { + commandArgEquals, + extractCliArgValues, +} from '@main/services/team/TeamRuntimeLivenessResolver'; +import { describe, expect, it } from 'vitest'; + +describe('team runtime liveness command parsing', () => { + it('keeps cached extracted values isolated from caller mutation', () => { + const command = 'node runtime --team-name demo --agent-id agent-alice'; + + const firstValues = extractCliArgValues(command, '--agent-id'); + firstValues.push('mutated-agent'); + + expect(extractCliArgValues(command, '--agent-id')).toEqual(['agent-alice']); + }); + + it('caches command arg equality without changing quoted value matching', () => { + const command = 'node runtime --team-name "demo team" --agent-id agent-alice'; + + expect(commandArgEquals(command, '--team-name', 'demo team')).toBe(true); + expect(commandArgEquals(command, '--team-name', 'other team')).toBe(false); + expect(commandArgEquals(command, '--agent-id', 'agent-alice')).toBe(true); + }); +});