@@ -46,6 +46,7 @@ import {
4646import { useIssues , useIssueQueue } from '@/hooks/useIssues' ;
4747import { useTerminalGridStore , selectTerminalGridFocusedPaneId } from '@/stores/terminalGridStore' ;
4848import { useWorkflowStore , selectProjectPath } from '@/stores/workflowStore' ;
49+ import { toast } from '@/stores/notificationStore' ;
4950import { CliConfigModal , type CliSessionConfig } from './CliConfigModal' ;
5051
5152// ========== Types ==========
@@ -79,6 +80,7 @@ const LAYOUT_PRESETS = [
7980] ;
8081
8182type LaunchMode = 'default' | 'yolo' ;
83+ type ShellKind = 'bash' | 'pwsh' | 'cmd' ;
8284
8385const CLI_TOOLS = [ 'claude' , 'gemini' , 'qwen' , 'codex' , 'opencode' ] as const ;
8486type CliTool = ( typeof CLI_TOOLS ) [ number ] ;
@@ -124,6 +126,9 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
124126 const [ isCreating , setIsCreating ] = useState ( false ) ;
125127 const [ selectedTool , setSelectedTool ] = useState < CliTool > ( 'gemini' ) ;
126128 const [ launchMode , setLaunchMode ] = useState < LaunchMode > ( 'yolo' ) ;
129+ const [ selectedShell , setSelectedShell ] = useState < ShellKind > (
130+ typeof navigator !== 'undefined' && navigator . platform . toLowerCase ( ) . includes ( 'win' ) ? 'cmd' : 'bash'
131+ ) ;
127132 const [ isConfigOpen , setIsConfigOpen ] = useState ( false ) ;
128133
129134 // Helper to get or create a focused pane
@@ -140,18 +145,29 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
140145 setIsCreating ( true ) ;
141146 try {
142147 const targetPaneId = getOrCreateFocusedPane ( ) ;
143- if ( ! targetPaneId ) return ;
148+ if ( ! targetPaneId ) {
149+ toast . error ( '无法创建会话' , '未能获取或创建窗格' ) ;
150+ return ;
151+ }
144152
145153 await createSessionAndAssign ( targetPaneId , {
146154 workingDir : projectPath ,
147- preferredShell : 'bash' ,
155+ preferredShell : selectedShell ,
148156 tool : selectedTool ,
149157 launchMode,
150158 } , projectPath ) ;
159+ } catch ( error : unknown ) {
160+ // Handle both Error instances and ApiError-like objects
161+ const message = error instanceof Error
162+ ? error . message
163+ : ( error as { message ?: string } ) ?. message
164+ ? ( error as { message : string } ) . message
165+ : String ( error ) ;
166+ toast . error ( `CLI 会话创建失败 (${ selectedTool } )` , message ) ;
151167 } finally {
152168 setIsCreating ( false ) ;
153169 }
154- } , [ projectPath , createSessionAndAssign , selectedTool , launchMode , getOrCreateFocusedPane ] ) ;
170+ } , [ projectPath , createSessionAndAssign , selectedTool , selectedShell , launchMode , getOrCreateFocusedPane ] ) ;
155171
156172 const handleConfigure = useCallback ( ( ) => {
157173 setIsConfigOpen ( true ) ;
@@ -164,7 +180,7 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
164180 const targetPaneId = getOrCreateFocusedPane ( ) ;
165181 if ( ! targetPaneId ) throw new Error ( 'Failed to create pane' ) ;
166182
167- const created = await createSessionAndAssign (
183+ await createSessionAndAssign (
168184 targetPaneId ,
169185 {
170186 workingDir : config . workingDir || projectPath ,
@@ -175,8 +191,15 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
175191 } ,
176192 projectPath
177193 ) ;
178-
179- if ( ! created ?. session ?. sessionKey ) throw new Error ( 'createSessionAndAssign failed' ) ;
194+ } catch ( error : unknown ) {
195+ // Handle both Error instances and ApiError-like objects
196+ const message = error instanceof Error
197+ ? error . message
198+ : ( error as { message ?: string } ) ?. message
199+ ? ( error as { message : string } ) . message
200+ : String ( error ) ;
201+ toast . error ( `CLI 会话创建失败 (${ config . tool } )` , message ) ;
202+ throw error ;
180203 } finally {
181204 setIsCreating ( false ) ;
182205 }
@@ -249,6 +272,31 @@ export function DashboardToolbar({ activePanel, onTogglePanel, isFileSidebarOpen
249272 </ DropdownMenuSubContent >
250273 </ DropdownMenuSub >
251274
275+ < DropdownMenuSub >
276+ < DropdownMenuSubTrigger className = "gap-2" >
277+ < span > { formatMessage ( { id : 'terminalDashboard.toolbar.shell' } ) } </ span >
278+ < span className = "text-xs text-muted-foreground" >
279+ { selectedShell === 'cmd' ? 'cmd' : selectedShell === 'pwsh' ? 'pwsh' : 'bash' }
280+ </ span >
281+ </ DropdownMenuSubTrigger >
282+ < DropdownMenuSubContent >
283+ < DropdownMenuRadioGroup
284+ value = { selectedShell }
285+ onValueChange = { ( v ) => setSelectedShell ( v as ShellKind ) }
286+ >
287+ < DropdownMenuRadioItem value = "cmd" >
288+ cmd { formatMessage ( { id : 'terminalDashboard.toolbar.shellCmdDesc' } ) }
289+ </ DropdownMenuRadioItem >
290+ < DropdownMenuRadioItem value = "bash" >
291+ bash (Git Bash/WSL)
292+ </ DropdownMenuRadioItem >
293+ < DropdownMenuRadioItem value = "pwsh" >
294+ pwsh (PowerShell)
295+ </ DropdownMenuRadioItem >
296+ </ DropdownMenuRadioGroup >
297+ </ DropdownMenuSubContent >
298+ </ DropdownMenuSub >
299+
252300 < DropdownMenuSeparator />
253301 < DropdownMenuItem
254302 onClick = { handleQuickCreate }
0 commit comments