@@ -7,7 +7,7 @@ import { ChatArea } from "./components/chat-area.js"
77import { CommandPalette , type CmdItem } from "./components/command-palette.js"
88import { PromptBar } from "./prompt-bar.js"
99import { Tips } from "./tips.js"
10- import { genId , getMessageBlocks } from "./utils.js"
10+ import { genId , getMessageBlocks , titlecase } from "./utils.js"
1111import type { ChatMessage , ContentBlock } from "./types.js"
1212import { SessionStore } from "../services/session-store.js"
1313import { SnapshotManager } from "../services/snapshot-manager.js"
@@ -19,7 +19,11 @@ import { ModelSwitcher } from "./ui/model-switcher.js"
1919import { ManageProvidersDialog } from "./ui/manage-providers-dialog.js"
2020import { DoctorDialog } from "./ui/doctor-dialog.js"
2121import { AboutDialog } from "./ui/about-dialog.js"
22- import { cycleEffort , getProviderEfforts } from "./variant-cycle.js"
22+ import { AgentSwitcher } from "./ui/agent-switcher.js"
23+ import { ThinkingEffortDialog } from "./ui/thinking-effort-dialog.js"
24+ import { McpToggleDialog } from "./ui/mcp-toggle-dialog.js"
25+ import { DebugDialog } from "./ui/debug-dialog.js"
26+ import { cycleEffort } from "./variant-cycle.js"
2327import { MessageControls } from "./ui/message-controls.js"
2428import { ToastContainer , showToast } from "./components/toast.js"
2529import clipboard from "clipboardy"
@@ -91,7 +95,7 @@ export function App({ renderer }: { renderer: CliRenderer }) {
9195 const [ copiedMsg , setCopiedMsg ] = useState ( false )
9296 const [ selectedAgent , setSelectedAgent ] = useState ( "build" )
9397 const [ submitKey , setSubmitKey ] = useState ( 0 )
94- const [ dialogStep , setDialogStep ] = useState < { type : "provider" } | { type : "session-list" ; mode ?: "delete" | "rename" } | { type : "switch-model" } | { type : "manage-providers" } | { type : "doctor" ; result : any } | { type : "about" } | null > ( null )
98+ const [ dialogStep , setDialogStep ] = useState < { type : "provider" } | { type : "session-list" ; mode ?: "delete" | "rename" } | { type : "switch-model" } | { type : "manage-providers" } | { type : "doctor" ; result : any } | { type : "about" } | { type : "switch-agent" } | { type : "thinking-effort" } | { type : "toggle-mcp" } | { type : "debug" } | null > ( null )
9599 const [ placeholderIdx , setPlaceholderIdx ] = useState ( 0 )
96100 const [ promptHistory , setPromptHistory ] = useState < string [ ] > ( [ ] )
97101 const [ historyIdx , setHistoryIdx ] = useState ( - 1 )
@@ -620,11 +624,12 @@ export function App({ renderer }: { renderer: CliRenderer }) {
620624 setRoute, setMessages, setStatus, setElapsedMs, setTokPerSec, setTokenUsage, setShowThinking, setShowToolCalls, setHomeKey, setNavKey, setDialogStep,
621625 onCycleVariant : handleCycleVariant ,
622626 currentEffort : thinkingEffort ,
623- } ) , [ renderer , hasModel , selectedModel , provider , mcpCount , customProviderCount , messages . length , showThinking , showToolCalls , handleCycleVariant , thinkingEffort ] )
627+ selectedAgent,
628+ } ) , [ renderer , hasModel , selectedModel , provider , mcpCount , customProviderCount , messages . length , showThinking , showToolCalls , handleCycleVariant , thinkingEffort , selectedAgent ] )
624629
625630 const cmdFiltered = useMemo ( ( ) => {
626631 const q = cmdFilter . toLowerCase ( )
627- return ! q ? cmdItems : cmdItems . filter ( ( i ) => i . label . includes ( q ) || i . desc . includes ( q ) || ( i . cat && i . cat . toLowerCase ( ) . includes ( q ) ) )
632+ return ! q ? cmdItems : cmdItems . filter ( ( i ) => i . label . toLowerCase ( ) . includes ( q ) || i . desc . toLowerCase ( ) . includes ( q ) || ( i . cat && i . cat . toLowerCase ( ) . includes ( q ) ) )
628633 } , [ cmdItems , cmdFilter ] )
629634 const execCmd = useCallback ( ( item : any ) => { item . action ( ) ; setShowCmd ( false ) } , [ ] )
630635 useEffect ( ( ) => { if ( cmdSelected >= cmdFiltered . length && cmdFiltered . length > 0 ) setCmdSelected ( cmdFiltered . length - 1 ) } , [ cmdSelected , cmdFiltered . length ] )
@@ -667,8 +672,8 @@ export function App({ renderer }: { renderer: CliRenderer }) {
667672 < box height = { 1 } />
668673 < box flexDirection = "row" justifyContent = "flex-end" width = { Math . min ( 68 , termWidth - 8 ) } >
669674 < box flexDirection = "row" gap = { 2 } >
670- < box flexDirection = "row" > < text fg = { c . text } > tab</ text > < text fg = { c . dim } > agents </ text > </ box >
671- < box flexDirection = "row" > < text fg = { c . text } > ctrl+t</ text > < text fg = { c . dim } > variant </ text > </ box >
675+ < box flexDirection = "row" > < text fg = { c . text } > tab</ text > < text fg = { c . dim } > agent </ text > </ box >
676+ < box flexDirection = "row" > < text fg = { c . text } > ctrl+t</ text > < text fg = { c . dim } > effort </ text > </ box >
672677 < box flexDirection = "row" > < text fg = { c . text } > ctrl+p</ text > < text fg = { c . dim } > commands</ text > </ box >
673678 </ box >
674679 </ box >
@@ -865,6 +870,46 @@ export function App({ renderer }: { renderer: CliRenderer }) {
865870 onClose = { ( ) => setDialogStep ( null ) }
866871 registerHandler = { ( fn : any ) => { dialogKeyHandler . current = fn } } />
867872 ) }
873+ { dialogStep ?. type === "switch-agent" && (
874+ < AgentSwitcher currentAgent = { selectedAgent } termWidth = { termWidth } termHeight = { termHeight }
875+ onAgentSelected = { ( agent ) => {
876+ setSelectedAgent ( agent )
877+ agentRef . current = null
878+ setDialogStep ( null )
879+ showToast ( `Switched to ${ titlecase ( agent ) } agent` , "info" )
880+ } }
881+ onClose = { ( ) => setDialogStep ( null ) }
882+ registerHandler = { ( fn ) => { dialogKeyHandler . current = fn } }
883+ />
884+ ) }
885+ { dialogStep ?. type === "thinking-effort" && (
886+ < ThinkingEffortDialog provider = { provider } currentEffort = { thinkingEffort }
887+ termWidth = { termWidth } termHeight = { termHeight }
888+ onEffortSelected = { ( effort ) => {
889+ setThinkingEffort ( effort )
890+ agentRef . current = null
891+ setDialogStep ( null )
892+ showToast ( effort === "none" ? "Thinking: off" : `Thinking: ${ effort } ` , "info" )
893+ } }
894+ onClose = { ( ) => setDialogStep ( null ) }
895+ registerHandler = { ( fn ) => { dialogKeyHandler . current = fn } }
896+ />
897+ ) }
898+ { dialogStep ?. type === "toggle-mcp" && (
899+ < McpToggleDialog termWidth = { termWidth } termHeight = { termHeight }
900+ onClose = { ( ) => setDialogStep ( null ) }
901+ registerHandler = { ( fn ) => { dialogKeyHandler . current = fn } }
902+ />
903+ ) }
904+ { dialogStep ?. type === "debug" && (
905+ < DebugDialog termWidth = { termWidth } termHeight = { termHeight }
906+ selectedModel = { selectedModel } provider = { provider }
907+ selectedAgent = { selectedAgent } thinkingEffort = { thinkingEffort }
908+ sessionStore = { sessionStore . current } mcpCount = { mcpCount }
909+ onClose = { ( ) => setDialogStep ( null ) }
910+ registerHandler = { ( fn : any ) => { dialogKeyHandler . current = fn } }
911+ />
912+ ) }
868913 { msgControls && sessionId . current && (
869914 < MessageControls
870915 message = { msgControls }
0 commit comments