perf: eliminate redundant agent fetches during startup (#1466)

This commit is contained in:
Kian Jones
2026-03-23 14:56:59 -07:00
committed by GitHub
parent 1971362a23
commit f1087c1b5c
2 changed files with 73 additions and 31 deletions

View File

@@ -3159,9 +3159,15 @@ export default function App({
const fetchConfig = async () => { const fetchConfig = async () => {
try { try {
// Use pre-loaded agent state if available, otherwise fetch
const { getClient } = await import("../agent/client"); const { getClient } = await import("../agent/client");
const client = await getClient(); const client = await getClient();
const agent = await client.agents.retrieve(agentId); let agent: AgentState;
if (initialAgentState && initialAgentState.id === agentId) {
agent = initialAgentState;
} else {
agent = await client.agents.retrieve(agentId);
}
setAgentState(agent); setAgentState(agent);
setLlmConfig(agent.llm_config); setLlmConfig(agent.llm_config);
@@ -3307,7 +3313,7 @@ export default function App({
cancelled = true; cancelled = true;
}; };
} }
}, [loadingState, agentId]); }, [loadingState, agentId, initialAgentState]);
// Keep effective model state in sync with the active conversation override. // Keep effective model state in sync with the active conversation override.
// biome-ignore lint/correctness/useExhaustiveDependencies: ref.current is intentionally read dynamically // biome-ignore lint/correctness/useExhaustiveDependencies: ref.current is intentionally read dynamically

View File

@@ -267,7 +267,7 @@ function getModelForToolLoading(
*/ */
async function resolveAgentByName( async function resolveAgentByName(
name: string, name: string,
): Promise<{ id: string; name: string } | null> { ): Promise<{ id: string; name: string; agent: AgentState } | null> {
const client = await getClient(); const client = await getClient();
// Get all pinned agents (local first, then global, deduplicated) // Get all pinned agents (local first, then global, deduplicated)
@@ -280,7 +280,7 @@ async function resolveAgentByName(
} }
// Fetch names for all pinned agents and find matches // Fetch names for all pinned agents and find matches
const matches: { id: string; name: string }[] = []; const matches: { id: string; name: string; agent: AgentState }[] = [];
const normalizedSearchName = name.toLowerCase(); const normalizedSearchName = name.toLowerCase();
await Promise.all( await Promise.all(
@@ -288,7 +288,7 @@ async function resolveAgentByName(
try { try {
const agent = await client.agents.retrieve(id); const agent = await client.agents.retrieve(id);
if (agent.name?.toLowerCase() === normalizedSearchName) { if (agent.name?.toLowerCase() === normalizedSearchName) {
matches.push({ id, name: agent.name }); matches.push({ id, name: agent.name, agent });
} }
} catch { } catch {
// Agent not found or error, skip // Agent not found or error, skip
@@ -731,6 +731,7 @@ async function main(): Promise<void> {
} }
// Validate --name flag // Validate --name flag
let nameResolvedAgent: AgentState | null = null;
if (specifiedAgentName) { if (specifiedAgentName) {
if (specifiedAgentId) { if (specifiedAgentId) {
console.error("Error: --name cannot be used with --agent"); console.error("Error: --name cannot be used with --agent");
@@ -848,6 +849,7 @@ async function main(): Promise<void> {
process.exit(1); process.exit(1);
} }
specifiedAgentId = resolved.id; specifiedAgentId = resolved.id;
nameResolvedAgent = resolved.agent;
} }
// Set tool filter if provided (controls which tools are loaded) // Set tool filter if provided (controls which tools are loaded)
@@ -950,6 +952,7 @@ async function main(): Promise<void> {
initBlocks, initBlocks,
baseTools, baseTools,
agentIdArg, agentIdArg,
preResolvedAgent,
model, model,
systemPromptPreset, systemPromptPreset,
toolset, toolset,
@@ -961,6 +964,7 @@ async function main(): Promise<void> {
initBlocks?: string[]; initBlocks?: string[];
baseTools?: string[]; baseTools?: string[];
agentIdArg: string | null; agentIdArg: string | null;
preResolvedAgent?: AgentState | null;
model?: string; model?: string;
systemPromptPreset?: string; systemPromptPreset?: string;
toolset?: "auto" | "codex" | "default" | "gemini"; toolset?: "auto" | "codex" | "default" | "gemini";
@@ -995,7 +999,7 @@ async function main(): Promise<void> {
>(null); >(null);
// Cache agent object from Phase 1 validation to avoid redundant re-fetch in Phase 2 // Cache agent object from Phase 1 validation to avoid redundant re-fetch in Phase 2
const [validatedAgent, setValidatedAgent] = useState<AgentState | null>( const [validatedAgent, setValidatedAgent] = useState<AgentState | null>(
null, preResolvedAgent ?? null,
); );
// Track agent and conversation for conversation selector (--resume flag) // Track agent and conversation for conversation selector (--resume flag)
const [resumeAgentId, setResumeAgentId] = useState<string | null>(null); const [resumeAgentId, setResumeAgentId] = useState<string | null>(null);
@@ -1274,31 +1278,50 @@ async function main(): Promise<void> {
// Step 1: Check local project LRU (session helpers centralize legacy fallback) // Step 1: Check local project LRU (session helpers centralize legacy fallback)
// Cache the retrieved agent to avoid redundant re-fetch in init() // Cache the retrieved agent to avoid redundant re-fetch in init()
const localAgentId = settingsManager.getLocalLastAgentId(process.cwd()); const localAgentId = settingsManager.getLocalLastAgentId(process.cwd());
const globalAgentId = settingsManager.getGlobalLastAgentId();
// Fetch local + global LRU agents in parallel
let localAgentExists = false; let localAgentExists = false;
let globalAgentExists = false;
let cachedAgent: AgentState | null = null; let cachedAgent: AgentState | null = null;
if (localAgentId) {
try { if (globalAgentId && globalAgentId === localAgentId) {
cachedAgent = await client.agents.retrieve(localAgentId); // Same agent — only need one fetch
if (localAgentId) {
try {
cachedAgent = await client.agents.retrieve(localAgentId);
localAgentExists = true;
} catch {
setFailedAgentMessage(
`Unable to locate recently used agent ${localAgentId}`,
);
}
}
globalAgentExists = localAgentExists;
} else {
// Different agents — fetch in parallel
const [localResult, globalResult] = await Promise.allSettled([
localAgentId
? client.agents.retrieve(localAgentId)
: Promise.reject(new Error("no local")),
globalAgentId
? client.agents.retrieve(globalAgentId)
: Promise.reject(new Error("no global")),
]);
if (localResult.status === "fulfilled") {
localAgentExists = true; localAgentExists = true;
} catch { cachedAgent = localResult.value;
} else if (localAgentId) {
setFailedAgentMessage( setFailedAgentMessage(
`Unable to locate recently used agent ${localAgentId}`, `Unable to locate recently used agent ${localAgentId}`,
); );
} }
}
// Step 2: Check global LRU (covers directory-switching case) if (globalResult.status === "fulfilled") {
const globalAgentId = settingsManager.getGlobalLastAgentId();
let globalAgentExists = false;
if (globalAgentId && globalAgentId !== localAgentId) {
try {
cachedAgent = await client.agents.retrieve(globalAgentId);
globalAgentExists = true; globalAgentExists = true;
} catch { cachedAgent = globalResult.value;
// Global agent doesn't exist either
} }
} else if (globalAgentId && globalAgentId === localAgentId) {
globalAgentExists = localAgentExists;
} }
// Step 3: Resolve startup target using pure decision logic // Step 3: Resolve startup target using pure decision logic
@@ -1379,11 +1402,17 @@ async function main(): Promise<void> {
// Priority 1: --agent flag // Priority 1: --agent flag
if (agentIdArg) { if (agentIdArg) {
try { // Use cached agent from name resolution if available
await client.agents.retrieve(agentIdArg); if (validatedAgent && validatedAgent.id === agentIdArg) {
resumingAgentId = agentIdArg; resumingAgentId = agentIdArg;
} catch { } else {
// Agent doesn't exist, will create new later try {
const agent = await client.agents.retrieve(agentIdArg);
setValidatedAgent(agent);
resumingAgentId = agentIdArg;
} catch {
// Agent doesn't exist, will create new later
}
} }
} }
@@ -1396,13 +1425,19 @@ async function main(): Promise<void> {
// This takes precedence over stale LRU since user explicitly chose it // This takes precedence over stale LRU since user explicitly chose it
const shouldCreateNew = forceNew || userRequestedNewAgent; const shouldCreateNew = forceNew || userRequestedNewAgent;
if (!resumingAgentId && !shouldCreateNew && selectedGlobalAgentId) { if (!resumingAgentId && !shouldCreateNew && selectedGlobalAgentId) {
try { // Use cached agent from Phase 1 validation if available
await client.agents.retrieve(selectedGlobalAgentId); if (validatedAgent && validatedAgent.id === selectedGlobalAgentId) {
resumingAgentId = selectedGlobalAgentId; resumingAgentId = selectedGlobalAgentId;
} catch { } else {
// Selected agent doesn't exist - show selector again try {
setLoadingState("selecting_global"); const agent = await client.agents.retrieve(selectedGlobalAgentId);
return; setValidatedAgent(agent);
resumingAgentId = selectedGlobalAgentId;
} catch {
// Selected agent doesn't exist - show selector again
setLoadingState("selecting_global");
return;
}
} }
} }
@@ -2032,6 +2067,7 @@ async function main(): Promise<void> {
initBlocks: initBlocks, initBlocks: initBlocks,
baseTools: baseTools, baseTools: baseTools,
agentIdArg: specifiedAgentId, agentIdArg: specifiedAgentId,
preResolvedAgent: nameResolvedAgent,
model: specifiedModel, model: specifiedModel,
systemPromptPreset: systemPromptPreset, systemPromptPreset: systemPromptPreset,
toolset: specifiedToolset as toolset: specifiedToolset as