From 8cddf012573e62a31b4b394585591e173904d039 Mon Sep 17 00:00:00 2001 From: USO Status Date: Tue, 27 Jan 2026 08:36:31 +0100 Subject: [PATCH] feat(status): Include model name in intermittent 'Sending query' status --- src/agents/pi-embedded-runner/run.ts | 5 ++ .../reply/status-updates-integration.ts | 3 +- src/auto-reply/reply/status-updates.ts | 46 ++++++++----------- 3 files changed, 25 insertions(+), 29 deletions(-) diff --git a/src/agents/pi-embedded-runner/run.ts b/src/agents/pi-embedded-runner/run.ts index adbe6ad49..4746a5c94 100644 --- a/src/agents/pi-embedded-runner/run.ts +++ b/src/agents/pi-embedded-runner/run.ts @@ -300,6 +300,11 @@ export async function runEmbeddedPiAgent( const prompt = provider === "anthropic" ? scrubAnthropicRefusalMagic(params.prompt) : params.prompt; + params.onAgentEvent?.({ + stream: "lifecycle", + data: { phase: "model_call_start", provider, model: modelId }, + }); + const attempt = await runEmbeddedAttempt({ sessionId: params.sessionId, sessionKey: params.sessionKey, diff --git a/src/auto-reply/reply/status-updates-integration.ts b/src/auto-reply/reply/status-updates-integration.ts index 34ee4dc73..7bf48b6ed 100644 --- a/src/auto-reply/reply/status-updates-integration.ts +++ b/src/auto-reply/reply/status-updates-integration.ts @@ -87,6 +87,7 @@ export function mapAgentEventToPhase(event: { const phase = typeof data.phase === "string" ? data.phase : ""; if (stream === "lifecycle") { + if (phase === "model_call_start") return "sending_query_model_resolved"; if (phase === "start") return "sending_query"; if (phase === "end") return "complete"; } @@ -162,7 +163,7 @@ export async function handleAgentEventForStatus( if (phase && phase !== ctx.currentPhase) { log.debug(`Status phase change: ${ctx.currentPhase} -> ${phase}`); ctx.currentPhase = phase; - await ctx.controller.setPhase(phase); + await ctx.controller.setPhase(phase, event.data); } } diff --git a/src/auto-reply/reply/status-updates.ts b/src/auto-reply/reply/status-updates.ts index 1bed4ea20..e7d0a85db 100644 --- a/src/auto-reply/reply/status-updates.ts +++ b/src/auto-reply/reply/status-updates.ts @@ -17,6 +17,7 @@ const log = createSubsystemLogger("status-updates"); export type StatusPhase = | "sending_query" + | "sending_query_model_resolved" | "receiving_reasoning" | "processing_tools" | "generating_response" @@ -59,6 +60,8 @@ export type StatusUpdateState = { lastUpdateAt: number; elapsedSeconds: number; isComplete: boolean; + providerUsed?: string; + modelUsed?: string; }; const DEFAULT_CONFIG: Required = { @@ -73,6 +76,7 @@ const DEFAULT_CONFIG: Required = { const PHASE_MESSAGES: Record = { sending_query: "Sending query to AI model", + sending_query_model_resolved: "Sending query to AI model", receiving_reasoning: "Processing reasoning data", processing_tools: "Executing tools", generating_response: "Generating response", @@ -81,6 +85,7 @@ const PHASE_MESSAGES: Record = { const PHASE_EMOJI: Record = { sending_query: "⏳", + sending_query_model_resolved: "⏳", receiving_reasoning: "🧠", processing_tools: "🔧", generating_response: "✍️", @@ -104,15 +109,21 @@ function formatElapsedTime(seconds: number): string { } function formatStatusMessage( - phase: StatusPhase, - elapsedSeconds: number, + state: StatusUpdateState, config: Required, ): string { const parts: string[] = []; + const phase = state.phase; + const elapsedSeconds = state.elapsedSeconds; if (config.showPhases) { const emoji = PHASE_EMOJI[phase]; - const message = PHASE_MESSAGES[phase]; + let message = PHASE_MESSAGES[phase]; + + if (phase === "sending_query_model_resolved" && state.providerUsed && state.modelUsed) { + message = `Sending request to ${state.providerUsed}/${state.modelUsed}`; + } + parts.push(`${emoji} ${message}`); } @@ -174,13 +185,15 @@ export class StatusUpdateController { } } - async setPhase(phase: StatusPhase): Promise { + async setPhase(phase: StatusPhase, data?: { provider?: string; model?: string }): Promise { if (!this.isEnabled() || this.stopped || this.state.isComplete) return; if (phase === this.state.phase) return; log.debug(`Status phase: ${this.state.phase} -> ${phase}`); this.state.phase = phase; + if (data?.provider) this.state.providerUsed = data.provider; + if (data?.model) this.state.modelUsed = data.model; if (phase === "complete") { this.state.isComplete = true; @@ -191,29 +204,6 @@ export class StatusUpdateController { await this.sendUpdate(); } - async complete(finalText?: string): Promise { - if (this.stopped) return undefined; - - this.state.isComplete = true; - this.stopUpdateTimer(); - this.stopped = true; - - if (!this.isEnabled()) return finalText; - - // The final message is returned, relying on message deletion/cleanup. - - // Clean up status message if it exists and we're not editing - if (this.state.statusMessageId && this.callbacks.deleteStatus) { - try { - await this.callbacks.deleteStatus(this.state.statusMessageId); - } catch (err) { - log.debug(`Failed to delete status message: ${String(err)}`); - } - } - - return finalText; - } - async cleanup(): Promise { this.stopUpdateTimer(); this.stopped = true; @@ -235,7 +225,7 @@ export class StatusUpdateController { this.state.elapsedSeconds = Math.floor((now - this.state.startedAt) / 1000); this.state.lastUpdateAt = now; - const text = formatStatusMessage(this.state.phase, this.state.elapsedSeconds, this.config); + const text = formatStatusMessage(this.state, this.config); try { if (this.config.mode === "edit" && this.supportsEdit() && this.state.statusMessageId) {