@@ -14,7 +14,7 @@ import { Keybind } from "@/util/keybind"
1414import { usePromptHistory , type PromptInfo } from "./history"
1515import { type AutocompleteRef , Autocomplete } from "./autocomplete"
1616import { useCommandDialog } from "../dialog-command"
17- import { useRenderer } from "@opentui/solid"
17+ import { useRenderer , useTerminalDimensions } from "@opentui/solid"
1818import { Editor } from "@tui/util/editor"
1919import { useExit } from "../../context/exit"
2020import { Clipboard } from "../../util/clipboard"
@@ -120,6 +120,9 @@ export function Prompt(props: PromptProps) {
120120 const history = usePromptHistory ( )
121121 const command = useCommandDialog ( )
122122 const renderer = useRenderer ( )
123+ const dimensions = useTerminalDimensions ( )
124+ const tall = createMemo ( ( ) => dimensions ( ) . height > 40 )
125+ const wide = createMemo ( ( ) => dimensions ( ) . width > 120 )
123126 const { theme, syntax } = useTheme ( )
124127
125128 function promptModelWarning ( ) {
@@ -881,19 +884,21 @@ export function Prompt(props: PromptProps) {
881884 cursorColor = { theme . text }
882885 syntaxStyle = { syntax ( ) }
883886 />
884- < box flexDirection = "row" flexShrink = { 0 } paddingTop = { 1 } gap = { 1 } >
885- < text fg = { highlight ( ) } >
886- { store . mode === "shell" ? "Shell" : Locale . titlecase ( local . agent . current ( ) . name ) } { " " }
887- </ text >
888- < Show when = { store . mode === "normal" } >
889- < box flexDirection = "row" gap = { 1 } >
890- < text flexShrink = { 0 } fg = { keybind . leader ? theme . textMuted : theme . text } >
891- { local . model . parsed ( ) . model }
892- </ text >
893- < text fg = { theme . textMuted } > { local . model . parsed ( ) . provider } </ text >
894- </ box >
895- </ Show >
896- </ box >
887+ < Show when = { tall ( ) } >
888+ < box flexDirection = "row" flexShrink = { 0 } paddingTop = { 1 } gap = { 1 } >
889+ < text fg = { highlight ( ) } >
890+ { store . mode === "shell" ? "Shell" : Locale . titlecase ( local . agent . current ( ) . name ) } { " " }
891+ </ text >
892+ < Show when = { store . mode === "normal" } >
893+ < box flexDirection = "row" gap = { 1 } >
894+ < text flexShrink = { 0 } fg = { keybind . leader ? theme . textMuted : theme . text } >
895+ { local . model . parsed ( ) . model }
896+ </ text >
897+ < text fg = { theme . textMuted } > { local . model . parsed ( ) . provider } </ text >
898+ </ box >
899+ </ Show >
900+ </ box >
901+ </ Show >
897902 </ box >
898903 </ box >
899904 < box
@@ -923,101 +928,123 @@ export function Prompt(props: PromptProps) {
923928 />
924929 </ box >
925930 < box flexDirection = "row" justifyContent = "space-between" >
926- < Show when = { status ( ) . type !== "idle" } fallback = { < text /> } >
927- < box
928- flexDirection = "row"
929- gap = { 1 }
930- flexGrow = { 1 }
931- justifyContent = { status ( ) . type === "retry" ? "space-between" : "flex-start" }
932- >
933- < box flexShrink = { 0 } flexDirection = "row" gap = { 1 } >
934- { /* @ts -ignore // SpinnerOptions doesn't support marginLeft */ }
935- < spinner marginLeft = { 1 } color = { spinnerDef ( ) . color } frames = { spinnerDef ( ) . frames } interval = { 40 } />
936- < box flexDirection = "row" gap = { 1 } flexShrink = { 0 } >
937- { ( ( ) => {
938- const retry = createMemo ( ( ) => {
939- const s = status ( )
940- if ( s . type !== "retry" ) return
941- return s
942- } )
943- const message = createMemo ( ( ) => {
944- const r = retry ( )
945- if ( ! r ) return
946- if ( r . message . includes ( "exceeded your current quota" ) && r . message . includes ( "gemini" ) )
947- return "gemini is way too hot right now"
948- if ( r . message . length > 80 ) return r . message . slice ( 0 , 80 ) + "..."
949- return r . message
950- } )
951- const isTruncated = createMemo ( ( ) => {
952- const r = retry ( )
953- if ( ! r ) return false
954- return r . message . length > 120
955- } )
956- const [ seconds , setSeconds ] = createSignal ( 0 )
957- onMount ( ( ) => {
958- const timer = setInterval ( ( ) => {
959- const next = retry ( ) ?. next
960- if ( next ) setSeconds ( Math . round ( ( next - Date . now ( ) ) / 1000 ) )
961- } , 1000 )
962-
963- onCleanup ( ( ) => {
964- clearInterval ( timer )
931+ < Switch >
932+ < Match when = { status ( ) . type !== "idle" } >
933+ < box
934+ flexDirection = "row"
935+ gap = { 1 }
936+ flexGrow = { 1 }
937+ justifyContent = { status ( ) . type === "retry" ? "space-between" : "flex-start" }
938+ >
939+ < box flexShrink = { 0 } flexDirection = "row" gap = { 1 } >
940+ { /* @ts -ignore // SpinnerOptions doesn't support marginLeft */ }
941+ < spinner marginLeft = { 1 } color = { spinnerDef ( ) . color } frames = { spinnerDef ( ) . frames } interval = { 40 } />
942+ < box flexDirection = "row" gap = { 1 } flexShrink = { 0 } >
943+ { ( ( ) => {
944+ const retry = createMemo ( ( ) => {
945+ const s = status ( )
946+ if ( s . type !== "retry" ) return
947+ return s
965948 } )
966- } )
967- const handleMessageClick = ( ) => {
968- const r = retry ( )
969- if ( ! r ) return
970- if ( isTruncated ( ) ) {
971- DialogAlert . show ( dialog , "Retry Error" , r . message )
949+ const message = createMemo ( ( ) => {
950+ const r = retry ( )
951+ if ( ! r ) return
952+ if ( r . message . includes ( "exceeded your current quota" ) && r . message . includes ( "gemini" ) )
953+ return "gemini is way too hot right now"
954+ if ( r . message . length > 80 ) return r . message . slice ( 0 , 80 ) + "..."
955+ return r . message
956+ } )
957+ const isTruncated = createMemo ( ( ) => {
958+ const r = retry ( )
959+ if ( ! r ) return false
960+ return r . message . length > 120
961+ } )
962+ const [ seconds , setSeconds ] = createSignal ( 0 )
963+ onMount ( ( ) => {
964+ const timer = setInterval ( ( ) => {
965+ const next = retry ( ) ?. next
966+ if ( next ) setSeconds ( Math . round ( ( next - Date . now ( ) ) / 1000 ) )
967+ } , 1000 )
968+
969+ onCleanup ( ( ) => {
970+ clearTimeout ( timer )
971+ } )
972+ } )
973+ const handleMessageClick = ( ) => {
974+ const r = retry ( )
975+ if ( ! r ) return
976+ if ( isTruncated ( ) ) {
977+ DialogAlert . show ( dialog , "Retry Error" , r . message )
978+ }
972979 }
973- }
974980
975- const retryText = ( ) => {
976- const r = retry ( )
977- if ( ! r ) return ""
978- const baseMessage = message ( )
979- const truncatedHint = isTruncated ( ) ? " (click to expand)" : ""
980- const retryInfo = ` [retrying ${ seconds ( ) > 0 ? `in ${ seconds ( ) } s ` : "" } attempt #${ r . attempt } ]`
981- return baseMessage + truncatedHint + retryInfo
982- }
981+ const retryText = ( ) => {
982+ const r = retry ( )
983+ if ( ! r ) return ""
984+ const baseMessage = message ( )
985+ const truncatedHint = isTruncated ( ) ? " (click to expand)" : ""
986+ const retryInfo = ` [retrying ${ seconds ( ) > 0 ? `in ${ seconds ( ) } s ` : "" } attempt #${ r . attempt } ]`
987+ return baseMessage + truncatedHint + retryInfo
988+ }
983989
984- return (
985- < Show when = { retry ( ) } >
986- < box onMouseUp = { handleMessageClick } >
987- < text fg = { theme . error } > { retryText ( ) } </ text >
988- </ box >
989- </ Show >
990- )
991- } ) ( ) }
990+ return (
991+ < Show when = { retry ( ) } >
992+ < box onMouseUp = { handleMessageClick } >
993+ < text fg = { theme . error } > { retryText ( ) } </ text >
994+ </ box >
995+ </ Show >
996+ )
997+ } ) ( ) }
998+ </ box >
992999 </ box >
1000+ < text fg = { store . interrupt > 0 ? theme . primary : theme . text } >
1001+ esc{ " " }
1002+ < span style = { { fg : store . interrupt > 0 ? theme . primary : theme . textMuted } } >
1003+ { store . interrupt > 0 ? "again to interrupt" : "interrupt" }
1004+ </ span >
1005+ </ text >
9931006 </ box >
994- < text fg = { store . interrupt > 0 ? theme . primary : theme . text } >
995- esc{ " " }
996- < span style = { { fg : store . interrupt > 0 ? theme . primary : theme . textMuted } } >
997- { store . interrupt > 0 ? "again to interrupt" : "interrupt" }
998- </ span >
999- </ text >
1000- </ box >
1001- </ Show >
1002- < Show when = { status ( ) . type !== "retry" } >
1003- < box gap = { 2 } flexDirection = "row" >
1004- < Switch >
1005- < Match when = { store . mode === "normal" } >
1007+ </ Match >
1008+ < Match when = { ! tall ( ) } >
1009+ < box flexDirection = "row" gap = { 1 } >
1010+ < text fg = { highlight ( ) } >
1011+ { store . mode === "shell" ? "Shell" : Locale . titlecase ( local . agent . current ( ) . name ) } { " " }
1012+ </ text >
1013+ < Show when = { store . mode === "normal" } >
1014+ < box flexDirection = "row" gap = { 1 } >
1015+ < text flexShrink = { 0 } fg = { keybind . leader ? theme . textMuted : theme . text } >
1016+ { local . model . parsed ( ) . model }
1017+ </ text >
1018+ < text fg = { theme . textMuted } > { local . model . parsed ( ) . provider } </ text >
1019+ </ box >
1020+ </ Show >
1021+ </ box >
1022+ </ Match >
1023+ </ Switch >
1024+ < box gap = { 2 } flexDirection = "row" marginLeft = "auto" >
1025+ < Switch >
1026+ < Match when = { store . mode === "normal" } >
1027+ < Show when = { wide ( ) } >
10061028 < text fg = { theme . text } >
10071029 { keybind . print ( "agent_cycle" ) } < span style = { { fg : theme . textMuted } } > switch agent</ span >
10081030 </ text >
1031+ </ Show >
1032+ < Show when = { ! wide ( ) } >
10091033 < text fg = { theme . text } >
1010- { keybind . print ( "command_list" ) } < span style = { { fg : theme . textMuted } } > commands</ span >
1011- </ text >
1012- </ Match >
1013- < Match when = { store . mode === "shell" } >
1014- < text fg = { theme . text } >
1015- esc < span style = { { fg : theme . textMuted } } > exit shell mode</ span >
1034+ { keybind . print ( "sidebar_toggle" ) } < span style = { { fg : theme . textMuted } } > sidebar</ span >
10161035 </ text >
1017- </ Match >
1018- </ Switch >
1019- </ box >
1020- </ Show >
1036+ </ Show >
1037+ < text fg = { theme . text } >
1038+ { keybind . print ( "command_list" ) } < span style = { { fg : theme . textMuted } } > commands</ span >
1039+ </ text >
1040+ </ Match >
1041+ < Match when = { store . mode === "shell" } >
1042+ < text fg = { theme . text } >
1043+ esc < span style = { { fg : theme . textMuted } } > exit shell mode</ span >
1044+ </ text >
1045+ </ Match >
1046+ </ Switch >
1047+ </ box >
10211048 </ box >
10221049 </ box >
10231050 </ >
0 commit comments