From d43d30eeeb4cac6f0c1c7c7b3ffa4be83d3b100d Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sun, 24 May 2026 12:54:08 +0700 Subject: [PATCH] fix(server): log each provider fallback during metadata generation --- .../server/agent/agent-metadata-generator.ts | 18 +++++-------- .../src/server/agent/agent-response-loop.ts | 27 +++++++++++++++++++ .../server/worktree-branch-name-generator.ts | 17 ++++++------ 3 files changed, 42 insertions(+), 20 deletions(-) diff --git a/packages/server/src/server/agent/agent-metadata-generator.ts b/packages/server/src/server/agent/agent-metadata-generator.ts index f71da3348..ae687ab8f 100644 --- a/packages/server/src/server/agent/agent-metadata-generator.ts +++ b/packages/server/src/server/agent/agent-metadata-generator.ts @@ -132,25 +132,19 @@ export async function generateAndApplyAgentMetadata( maxRetries: 2, providers: DEFAULT_STRUCTURED_GENERATION_PROVIDERS, persistSession: false, + logger: options.logger, agentConfigOverrides: { title: "Agent metadata generator", internal: true, }, }); } catch (error) { - if ( - error instanceof StructuredAgentResponseError || - error instanceof StructuredAgentFallbackError - ) { - options.logger.warn( - { err: error, agentId: options.agentId }, - "Structured metadata generation failed", - ); - return; - } + const attempts = error instanceof StructuredAgentFallbackError ? error.attempts : undefined; options.logger.error( - { err: error, agentId: options.agentId }, - "Agent metadata generation failed", + { err: error, agentId: options.agentId, attempts }, + error instanceof StructuredAgentResponseError || error instanceof StructuredAgentFallbackError + ? "Structured metadata generation failed" + : "Agent metadata generation failed", ); return; } diff --git a/packages/server/src/server/agent/agent-response-loop.ts b/packages/server/src/server/agent/agent-response-loop.ts index b54b1bd99..1f85b2ece 100644 --- a/packages/server/src/server/agent/agent-response-loop.ts +++ b/packages/server/src/server/agent/agent-response-loop.ts @@ -5,6 +5,11 @@ import type { AgentProvider, AgentSessionConfig } from "./agent-sdk-types.js"; import type { AgentManager } from "./agent-manager.js"; import { getAgentProviderDefinition } from "./provider-manifest.js"; +export interface StructuredGenerationLogger { + info: (obj: object, msg?: string) => void; + warn: (obj: object, msg?: string) => void; +} + export type JsonSchema = Record; export type AgentCaller = (prompt: string) => Promise; @@ -90,6 +95,7 @@ export interface StructuredAgentGenerationWithFallbackOptions { persistSession?: boolean; maxRetries?: number; schemaName?: string; + logger?: StructuredGenerationLogger; runner?: (options: StructuredAgentGenerationOptions) => Promise; } @@ -397,6 +403,7 @@ export async function generateStructuredAgentResponseWithFallback( persistSession, maxRetries, schemaName, + logger, runner, } = options; @@ -414,12 +421,17 @@ export async function generateStructuredAgentResponseWithFallback( for (const candidate of providers) { const availabilityEntry = availabilityByProvider.get(candidate.provider); if (availabilityEntry && !availabilityEntry.available) { + const reason = availabilityEntry.error ?? "unavailable"; attempts.push({ provider: candidate.provider, model: candidate.model ?? null, available: false, error: availabilityEntry.error ?? null, }); + logger?.warn( + { provider: candidate.provider, model: candidate.model, schemaName, reason }, + "Structured generation: skipping unavailable provider", + ); continue; } @@ -439,6 +451,17 @@ export async function generateStructuredAgentResponseWithFallback( ...(candidate.thinkingOptionId ? { thinkingOptionId: candidate.thinkingOptionId } : {}), }, }); + if (attempts.length > 0) { + logger?.info( + { + provider: candidate.provider, + model: candidate.model, + schemaName, + priorAttempts: attempts, + }, + "Structured generation: succeeded after fallback", + ); + } return result; } catch (error) { attempts.push({ @@ -447,6 +470,10 @@ export async function generateStructuredAgentResponseWithFallback( available: true, error: errorMessage(error), }); + logger?.warn( + { err: error, provider: candidate.provider, model: candidate.model, schemaName }, + "Structured generation: provider failed, trying next", + ); } } diff --git a/packages/server/src/server/worktree-branch-name-generator.ts b/packages/server/src/server/worktree-branch-name-generator.ts index 378dd54f3..fe06ef18c 100644 --- a/packages/server/src/server/worktree-branch-name-generator.ts +++ b/packages/server/src/server/worktree-branch-name-generator.ts @@ -12,6 +12,7 @@ import { buildMetadataPrompt } from "../utils/build-metadata-prompt.js"; import type { WorkspaceGitService } from "./workspace-git-service.js"; interface BranchNameGeneratorLogger { + info: (obj: object, msg?: string) => void; warn: (obj: object, msg?: string) => void; error: (obj: object, msg?: string) => void; } @@ -77,6 +78,7 @@ export async function generateBranchNameFromFirstAgentContext( maxRetries: 2, providers: DEFAULT_STRUCTURED_GENERATION_PROVIDERS, persistSession: false, + logger: options.logger, agentConfigOverrides: { title: "Branch name generator", internal: true, @@ -84,14 +86,13 @@ export async function generateBranchNameFromFirstAgentContext( }); return result.branch.trim() || null; } catch (error) { - if ( - error instanceof StructuredAgentResponseError || - error instanceof StructuredAgentFallbackError - ) { - options.logger.warn({ err: error }, "Structured branch name generation failed"); - return null; - } - options.logger.error({ err: error }, "Branch name generation failed"); + const attempts = error instanceof StructuredAgentFallbackError ? error.attempts : undefined; + options.logger.error( + { err: error, attempts }, + error instanceof StructuredAgentResponseError || error instanceof StructuredAgentFallbackError + ? "Structured branch name generation failed" + : "Branch name generation failed", + ); return null; } }