@@ -17,6 +17,7 @@ import { AtPicker } from './AtPicker.js';
1717import { MobileDpad , DPAD_ARROW_SEQUENCES } from './MobileDpad.js' ;
1818import { P2pConfigPanel , buildP2pWorkflowLaunchEnvelopeFromConfig } from './P2pConfigPanel.js' ;
1919import { useExecutionRouting } from '../hooks/useExecutionRouting.js' ;
20+ import { buildExecutionTemplateLabel } from '../execution-template-label.js' ;
2021import {
2122 OpenSpecAutoDeliverCurrentRunEntry ,
2223 OpenSpecAutoDeliverDetailsPanel ,
@@ -160,6 +161,10 @@ interface Props {
160161 parentSession ?: string | null ;
161162 executionCloneKind ?: string | null ;
162163 parentRunId ?: string | null ;
164+ qwenModel ?: string | null ;
165+ requestedModel ?: string | null ;
166+ activeModel ?: string | null ;
167+ modelDisplay ?: string | null ;
163168 executionTemplateEligible ?: boolean ;
164169 executionTemplateIneligibleReason ?: string ;
165170 } > ;
@@ -198,8 +203,13 @@ const OPENSPEC_EXEC_EXCLUDED_TYPES = new Set(['shell', 'script']);
198203
199204/** OpenSpec Execute candidate label: session short name + SDK (agent type) +
200205 * preset name, so identical-looking workers (w2…wN) are distinguishable. */
201- function formatExecLabel ( shortName : string , sdk ?: string | null , preset ?: string | null ) : string {
202- return [ shortName , sdk || null , preset || null ] . filter ( Boolean ) . join ( ' · ' ) ;
206+ function formatExecLabel ( shortName : string , sdk ?: string | null , preset ?: string | null , model ?: string | null ) : string {
207+ return buildExecutionTemplateLabel ( {
208+ shortName,
209+ agentType : sdk ,
210+ ccPreset : preset ,
211+ modelDisplay : model ,
212+ } ) ;
203213}
204214
205215type OpenSpecTaskStatsSummary = {
@@ -2045,7 +2055,15 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
20452055 const executionSessionDisplayName = useMemo ( ( ) => {
20462056 if ( ! configuredExecutionSession ) return null ;
20472057 const sub = ( subSessions ?? [ ] ) . find ( ( s ) => s . sessionName === configuredExecutionSession ) ;
2048- if ( sub && ! isExecutionCloneTemplateLike ( sub ) ) return sub . label || sub . sessionName . split ( '_' ) . pop ( ) || sub . sessionName ;
2058+ if ( sub && ! isExecutionCloneTemplateLike ( sub ) ) return buildExecutionTemplateLabel ( {
2059+ shortName : sub . label || sub . sessionName . split ( '_' ) . pop ( ) || sub . sessionName ,
2060+ agentType : sub . type ,
2061+ ccPreset : sub . ccPresetId ,
2062+ qwenModel : sub . qwenModel ,
2063+ requestedModel : sub . requestedModel ,
2064+ activeModel : sub . activeModel ,
2065+ modelDisplay : sub . modelDisplay ,
2066+ } ) ;
20492067 return null ;
20502068 } , [ configuredExecutionSession , subSessions ] ) ;
20512069 const hasValidExecutionDefault = Boolean (
@@ -2068,12 +2086,12 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
20682086 // the UI renders the flag and never recomputes eligibility client-side. This
20692087 // mirrors the P2pConfigPanel template scan.
20702088 const openSpecExecutionTemplateScan = useMemo ( ( ) => {
2071- const eligible : Array < { sessionName : string ; shortName : string ; sdk : string ; preset : string | null } > = [ ] ;
2089+ const eligible : Array < { sessionName : string ; shortName : string ; sdk : string ; preset : string | null ; model : string | null } > = [ ] ;
20722090 const seen = new Set < string > ( ) ;
2073- const push = ( sessionName : string , shortName : string , sdk : string , preset : string | null ) => {
2091+ const push = ( sessionName : string , shortName : string , sdk : string , preset : string | null , model : string | null ) => {
20742092 if ( seen . has ( sessionName ) ) return ;
20752093 seen . add ( sessionName ) ;
2076- eligible . push ( { sessionName, shortName, sdk, preset } ) ;
2094+ eligible . push ( { sessionName, shortName, sdk, preset, model } ) ;
20772095 } ;
20782096 // GROUP-SCOPED: execution targets are attached non-main sub-sessions only.
20792097 // Main sessions (brain/orchestrator/worker `wN`) are not execution templates.
@@ -2085,7 +2103,13 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
20852103 if ( ! rootSession || s . parentSession !== rootSession ) continue ;
20862104 if ( isExecutionCloneTemplateLike ( s ) ) continue ;
20872105 if ( s . executionTemplateEligible === false ) continue ;
2088- push ( s . sessionName , s . label || s . sessionName . split ( '_' ) . pop ( ) || s . sessionName , s . type , s . ccPresetId ?? null ) ;
2106+ push (
2107+ s . sessionName ,
2108+ s . label || s . sessionName . split ( '_' ) . pop ( ) || s . sessionName ,
2109+ s . type ,
2110+ s . ccPresetId ?? null ,
2111+ resolveEffectiveSessionModel ( s ) ?? null ,
2112+ ) ;
20892113 }
20902114 return eligible ;
20912115 } , [ subSessions , activeSession ?. name , rootSession ] ) ;
@@ -2098,9 +2122,10 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
20982122 if ( ! sub || isExecutionCloneTemplateLike ( sub ) ) return null ;
20992123 return {
21002124 sessionName : configuredExecutionSession ,
2101- shortName : executionSessionDisplayName ,
2125+ shortName : sub . label || sub . sessionName . split ( '_' ) . pop ( ) || sub . sessionName ,
21022126 sdk : sub . type ,
21032127 preset : sub . ccPresetId ?? null ,
2128+ model : resolveEffectiveSessionModel ( sub ) ?? null ,
21042129 } ;
21052130 } , [ hasValidExecutionDefault , configuredExecutionSession , executionSessionDisplayName , subSessions ] ) ;
21062131
@@ -2139,7 +2164,7 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
21392164 } }
21402165 >
21412166 < span aria-hidden = "true" > ★ </ span >
2142- { t ( 'openspec.execute.dispatch_to' , { name : formatExecLabel ( openSpecPinnedExecutionSession . shortName , openSpecPinnedExecutionSession . sdk , openSpecPinnedExecutionSession . preset ) } ) }
2167+ { t ( 'openspec.execute.dispatch_to' , { name : formatExecLabel ( openSpecPinnedExecutionSession . shortName , openSpecPinnedExecutionSession . sdk , openSpecPinnedExecutionSession . preset , openSpecPinnedExecutionSession . model ) } ) }
21432168 </ button >
21442169 ) }
21452170 { openSpecExecutionCandidates . map ( ( candidate ) => (
@@ -2155,7 +2180,7 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
21552180 setOpenSpecOpen ( false ) ;
21562181 } }
21572182 >
2158- { t ( 'openspec.execute.dispatch_to' , { name : formatExecLabel ( candidate . shortName , candidate . sdk , candidate . preset ) } ) }
2183+ { t ( 'openspec.execute.dispatch_to' , { name : formatExecLabel ( candidate . shortName , candidate . sdk , candidate . preset , candidate . model ) } ) }
21592184 </ button >
21602185 ) ) }
21612186 { ! openSpecPinnedExecutionSession && openSpecExecutionCandidates . length === 0 && (
@@ -2177,7 +2202,7 @@ export function SessionControls({ ws, activeSession, inputRef, onAfterAction, on
21772202 setOpenSpecExecuteMenu ( null ) ;
21782203 } }
21792204 >
2180- { t ( 'openspec.execute.set_default' , { name : formatExecLabel ( candidate . shortName , candidate . sdk , candidate . preset ) } ) }
2205+ { t ( 'openspec.execute.set_default' , { name : formatExecLabel ( candidate . shortName , candidate . sdk , candidate . preset , candidate . model ) } ) }
21812206 </ button >
21822207 ) ) }
21832208 { openSpecPinnedExecutionSession && (
0 commit comments