@@ -89,6 +89,7 @@ import {
8989 getStoredLogEventPosition ,
9090 getUserShellExecutesSinceLastPrompt ,
9191 hasSessionPromptEvent ,
92+ hasSessionPromptEventForTaskRun ,
9293 isTurnCompleteEvent ,
9394 normalizePromptToBlocks ,
9495 promptReferencesAbsoluteFolder ,
@@ -6222,27 +6223,34 @@ export class SessionService {
62226223 ) ;
62236224 }
62246225 }
6225- const hasUserPrompt = events . some (
6226- ( e : AcpMessage ) =>
6227- isJsonRpcRequest ( e . message ) && e . message . method === "session/prompt" ,
6226+ const hasCurrentRunUserPrompt = isResumeRun
6227+ ? hasSessionPromptEventForTaskRun ( events , taskRunId )
6228+ : hasSessionPromptEvent ( events ) ;
6229+
6230+ // A reload loses the in-memory placeholder; restore it from the resume
6231+ // state or initial task description until the active run records its prompt.
6232+ const seedContent = isResumeRun
6233+ ? typeof runState ?. pending_user_message === "string"
6234+ ? runState . pending_user_message
6235+ : undefined
6236+ : ( this . initialCloudOptimisticPrompt . get ( taskId ) ?? taskDescription ) ;
6237+ const hasOptimisticUserPrompt = session . optimisticItems . some (
6238+ ( item ) => item . type === "user_message" ,
62286239 ) ;
6229-
6230- // Seed the optimistic user-message bubble whenever the agent has
6231- // not yet recorded an initial `session/prompt` request — covers the
6232- // brand-new task case as well as "agent has emitted lifecycle
6233- // notifications but hasn't received its first prompt yet". Prefer the
6234- // stashed initial prompt (which carries the channel CONTEXT.md block, so
6235- // its chip renders right away) over the bare task description.
6236- const seedContent =
6237- this . initialCloudOptimisticPrompt . get ( taskId ) ?? taskDescription ;
6238- if ( ! isTerminalRun && ! hasUserPrompt && seedContent ?. trim ( ) ) {
6240+ if (
6241+ ! isTerminalRun &&
6242+ ! hasCurrentRunUserPrompt &&
6243+ ! hasOptimisticUserPrompt &&
6244+ seedContent ?. trim ( )
6245+ ) {
62396246 this . d . store . appendOptimisticItem ( taskRunId , {
62406247 type : "user_message" ,
62416248 content : seedContent ,
62426249 timestamp : Date . now ( ) ,
6250+ ...( isResumeRun ? { pinToTop : false } : { } ) ,
62436251 } ) ;
62446252 }
6245- if ( hasUserPrompt || isTerminalRun ) {
6253+ if ( hasCurrentRunUserPrompt || isTerminalRun ) {
62466254 // The stash is no longer needed once the real prompt lands - and a
62476255 // finished run gets no further echoes, so leftover optimistic items
62486256 // would otherwise linger as phantom tail items on the final transcript.
0 commit comments