@@ -47,7 +47,6 @@ export type PromptRef = {
4747 reset ( ) : void
4848 blur ( ) : void
4949 focus ( ) : void
50- submit ( ) : void
5150}
5251
5352const PLACEHOLDERS = [ "Fix a TODO in the codebase" , "What is the tech stack of this project?" , "Fix broken tests" ]
@@ -119,7 +118,7 @@ export function Prompt(props: PromptProps) {
119118 const sync = useSync ( )
120119 const dialog = useDialog ( )
121120 const toast = useToast ( )
122- const status = createMemo ( ( ) => sync . data . session_status ?. [ props . sessionID ?? "" ] ?? { type : "idle" } )
121+ const status = createMemo ( ( ) => sync . data . session_status [ props . sessionID ?? "" ] ?? { type : "idle" } )
123122 const history = usePromptHistory ( )
124123 const command = useCommandDialog ( )
125124 const renderer = useRenderer ( )
@@ -350,93 +349,10 @@ export function Prompt(props: PromptProps) {
350349 promptPartTypeId = input . extmarks . registerType ( "prompt-part" )
351350 } )
352351
353- // Track IDE selection extmark so we can update/remove it
354- let ideSelectionExtmarkId : number | null = null
355-
356- function removeExtmark ( extmarkId : number ) {
357- const allExtmarks = input . extmarks . getAllForTypeId ( promptPartTypeId )
358- const extmark = allExtmarks . find ( ( e ) => e . id === extmarkId )
359- const partIndex = store . extmarkToPartIndex . get ( extmarkId )
360-
361- if ( partIndex !== undefined ) {
362- setStore (
363- produce ( ( draft ) => {
364- draft . prompt . parts . splice ( partIndex , 1 )
365- draft . extmarkToPartIndex . delete ( extmarkId )
366- const newMap = new Map < number , number > ( )
367- for ( const [ id , idx ] of draft . extmarkToPartIndex ) {
368- newMap . set ( id , idx > partIndex ? idx - 1 : idx )
369- }
370- draft . extmarkToPartIndex = newMap
371- } ) ,
372- )
373- }
374-
375- if ( extmark ) {
376- const savedOffset = input . cursorOffset
377- input . cursorOffset = extmark . start
378- const start = { ...input . logicalCursor }
379- input . cursorOffset = extmark . end + 1
380- input . deleteRange ( start . row , start . col , input . logicalCursor . row , input . logicalCursor . col )
381- input . cursorOffset =
382- savedOffset > extmark . start
383- ? Math . max ( extmark . start , savedOffset - ( extmark . end + 1 - extmark . start ) )
384- : savedOffset
385- }
386-
387- input . extmarks . delete ( extmarkId )
388- }
389-
390- function updateIdeSelection ( selection : Ide . Selection | null ) {
391- if ( ! input || promptPartTypeId === undefined ) return
392-
393- if ( ideSelectionExtmarkId !== null ) {
394- removeExtmark ( ideSelectionExtmarkId )
395- ideSelectionExtmarkId = null
396- }
397-
398- // Ignore empty selections (just a cursor position)
399- if ( ! selection || ! selection . text ) return
400-
401- const { filePath, text } = selection
402- const filename = filePath . split ( "/" ) . pop ( ) || filePath
403- const start = selection . selection . start . line + 1
404- const end = selection . selection . end . line + 1
405- const lines = text . split ( "\n" ) . length
406-
407- const previewText = `[${ filename } :${ start } -${ end } ~${ lines } lines]`
408- const contextText = `\`\`\`\n# ${ filePath } :${ start } -${ end } \n${ text } \n\`\`\`\n\n`
409-
410- const extmarkStart = input . visualCursor . offset
411- const extmarkEnd = extmarkStart + previewText . length
412-
413- input . insertText ( previewText + " " )
414-
415- ideSelectionExtmarkId = input . extmarks . create ( {
416- start : extmarkStart ,
417- end : extmarkEnd ,
418- virtual : true ,
419- styleId : pasteStyleId ,
420- typeId : promptPartTypeId ,
421- } )
422-
423- setStore (
424- produce ( ( draft ) => {
425- const partIndex = draft . prompt . parts . length
426- draft . prompt . parts . push ( {
427- type : "text" as const ,
428- text : contextText ,
429- source : {
430- text : {
431- start : extmarkStart ,
432- end : extmarkEnd ,
433- value : previewText ,
434- } ,
435- } ,
436- } )
437- draft . extmarkToPartIndex . set ( ideSelectionExtmarkId ! , partIndex )
438- } ) ,
439- )
352+ function updateIdeSelection ( _selection : Ide . Selection | null ) {
353+ // Selection is now displayed in footer via local.selection
354+ // No visual insertion in the input needed
355+ // Content will be included at submit time from local.selection
440356 }
441357
442358 function restoreExtmarksFromParts ( parts : PromptInfo [ "parts" ] ) {
@@ -545,14 +461,11 @@ export function Prompt(props: PromptProps) {
545461 } )
546462 setStore ( "extmarkToPartIndex" , new Map ( ) )
547463 } ,
548- submit ( ) {
549- submit ( )
550- } ,
551464 } )
552465
553466 async function submit ( ) {
554467 if ( props . disabled ) return
555- if ( autocomplete ? .visible ) return
468+ if ( autocomplete . visible ) return
556469 if ( ! store . prompt . input ) return
557470 const trimmed = store . prompt . input . trim ( )
558471 if ( trimmed === "exit" || trimmed === "quit" || trimmed === ":q" ) {
@@ -573,6 +486,8 @@ export function Prompt(props: PromptProps) {
573486 const messageID = Identifier . ascending ( "message" )
574487 let inputText = store . prompt . input
575488
489+ // IDE selection is displayed in footer only - not injected into message
490+
576491 // Expand pasted text inline before submitting
577492 const allExtmarks = input . extmarks . getAllForTypeId ( promptPartTypeId )
578493 const sortedExtmarks = allExtmarks . sort ( ( a : { start : number } , b : { start : number } ) => b . start - a . start )
@@ -592,9 +507,6 @@ export function Prompt(props: PromptProps) {
592507 // Filter out text parts (pasted content) since they're now expanded inline
593508 const nonTextParts = store . prompt . parts . filter ( ( part ) => part . type !== "text" )
594509
595- // Capture mode before it gets reset
596- const currentMode = store . mode
597-
598510 if ( store . mode === "shell" ) {
599511 sdk . client . session . shell ( {
600512 sessionID,
@@ -637,24 +549,35 @@ export function Prompt(props: PromptProps) {
637549 type : "text" ,
638550 text : inputText ,
639551 } ,
552+ ...( local . selection . current ( ) ?. text
553+ ? [
554+ {
555+ id : Identifier . ascending ( "part" ) ,
556+ type : "text" as const ,
557+ text : `\n\n[IDE Selection: ${
558+ local . selection
559+ . current ( ) !
560+ . filePath . split ( / [ \/ \\ ] / )
561+ . pop ( ) || local . selection . current ( ) ! . filePath
562+ } :${ local . selection . current ( ) ! . selection . start . line + 1 } -${ local . selection . current ( ) ! . selection . end . line + 1 } ]\n\`\`\`\n${ local . selection . current ( ) ! . text } \n\`\`\``,
563+ synthetic : true ,
564+ } ,
565+ ]
566+ : [ ] ) ,
640567 ...nonTextParts . map ( ( x ) => ( {
641568 id : Identifier . ascending ( "part" ) ,
642569 ...x ,
643570 } ) ) ,
644571 ] ,
645572 } )
646573 }
647- history . append ( {
648- ...store . prompt ,
649- mode : currentMode ,
650- } )
574+ history . append ( store . prompt )
651575 input . extmarks . clear ( )
652576 setStore ( "prompt" , {
653577 input : "" ,
654578 parts : [ ] ,
655579 } )
656580 setStore ( "extmarkToPartIndex" , new Map ( ) )
657- ideSelectionExtmarkId = null
658581 props . onSubmit ?.( )
659582
660583 // temporary hack to make sure the message is sent
@@ -830,8 +753,8 @@ export function Prompt(props: PromptProps) {
830753 >
831754 < textarea
832755 placeholder = { props . sessionID ? undefined : `Ask anything... "${ PLACEHOLDERS [ store . placeholder ] } "` }
833- textColor = { keybind . leader ? theme . textMuted : theme . text }
834- focusedTextColor = { keybind . leader ? theme . textMuted : theme . text }
756+ textColor = { theme . text }
757+ focusedTextColor = { theme . text }
835758 minHeight = { 1 }
836759 maxHeight = { 6 }
837760 onContentChange = { ( ) => {
@@ -889,7 +812,6 @@ export function Prompt(props: PromptProps) {
889812 if ( item ) {
890813 input . setText ( item . input )
891814 setStore ( "prompt" , item )
892- setStore ( "mode" , item . mode ?? "normal" )
893815 restoreExtmarksFromParts ( item . parts )
894816 e . preventDefault ( )
895817 if ( direction === - 1 ) input . cursorOffset = 0
@@ -981,7 +903,7 @@ export function Prompt(props: PromptProps) {
981903 </ text >
982904 < Show when = { store . mode === "normal" } >
983905 < box flexDirection = "row" gap = { 1 } >
984- < text flexShrink = { 0 } fg = { keybind . leader ? theme . textMuted : theme . text } >
906+ < text flexShrink = { 0 } fg = { theme . text } >
985907 { local . model . parsed ( ) . model }
986908 </ text >
987909 < text fg = { theme . textMuted } > { local . model . parsed ( ) . provider } </ text >
@@ -996,15 +918,16 @@ export function Prompt(props: PromptProps) {
996918 borderColor = { highlight ( ) }
997919 customBorderChars = { {
998920 ...EmptyBorder ,
999- vertical : theme . backgroundElement . a !== 0 ? "╹" : " " ,
921+ // when the background is transparent, don't draw the vertical line
922+ vertical : theme . background . a != 0 ? "╹" : " " ,
1000923 } }
1001924 >
1002925 < box
1003926 height = { 1 }
1004927 border = { [ "bottom" ] }
1005928 borderColor = { theme . backgroundElement }
1006929 customBorderChars = {
1007- theme . backgroundElement . a != = 0
930+ theme . background . a != 0
1008931 ? {
1009932 ...EmptyBorder ,
1010933 horizontal : "▀" ,
0 commit comments