@@ -40,6 +40,7 @@ export type ConversationState =
40
40
| {
41
41
state : "error" ;
42
42
error : Error ;
43
+ lastAssistantMessage ?: Message . Model ;
43
44
} ;
44
45
45
46
export type Model = {
@@ -98,6 +99,10 @@ export type Msg =
98
99
}
99
100
| {
100
101
type : "show-message-debug-info" ;
102
+ }
103
+ | {
104
+ type : "sidebar-setup-resubmit" ;
105
+ lastUserMessage : string ;
101
106
} ;
102
107
103
108
export function init ( { nvim, lsp } : { nvim : Nvim ; lsp : Lsp } ) {
@@ -173,28 +178,67 @@ export function init({ nvim, lsp }: { nvim: Nvim; lsp: Lsp }) {
173
178
174
179
case "conversation-state" : {
175
180
model . conversation = msg . conversation ;
176
- if ( msg . conversation . state == "stopped" ) {
177
- const lastMessage = model . messages [ model . messages . length - 1 ] ;
178
- if ( lastMessage ?. role === "assistant" ) {
179
- lastMessage . parts . push ( {
180
- type : "stop-msg" ,
181
- stopReason : msg . conversation . stopReason ,
182
- usage : msg . conversation . usage ,
183
- } ) ;
181
+
182
+ switch ( msg . conversation . state ) {
183
+ case "stopped" : {
184
+ const lastMessage = model . messages [ model . messages . length - 1 ] ;
185
+ if ( lastMessage ?. role === "assistant" ) {
186
+ lastMessage . parts . push ( {
187
+ type : "stop-msg" ,
188
+ stopReason : msg . conversation . stopReason ,
189
+ usage : msg . conversation . usage ,
190
+ } ) ;
191
+ }
192
+ return [ model , maybeAutorespond ( model ) ] ;
184
193
}
185
- }
186
194
187
- if ( msg . conversation . state == "error" ) {
188
- const lastMessage = model . messages [ model . messages . length - 1 ] ;
189
- if ( lastMessage ?. role == "assistant" ) {
190
- // get rid of the latest assistant message so we can re-submit.
191
- model . messages . pop ( ) ;
195
+ case "error" : {
196
+ const lastAssistantMessage =
197
+ model . messages [ model . messages . length - 1 ] ;
198
+ if ( lastAssistantMessage ?. role == "assistant" ) {
199
+ model . messages . pop ( ) ;
200
+
201
+ // save the last message so we can show a nicer error message.
202
+ (
203
+ model . conversation as Extract <
204
+ ConversationState ,
205
+ { state : "error" }
206
+ >
207
+ ) . lastAssistantMessage = lastAssistantMessage ;
208
+ }
209
+
210
+ const lastUserMessage = model . messages [ model . messages . length - 1 ] ;
211
+ if ( lastUserMessage ?. role == "user" ) {
212
+ model . messages . pop ( ) ;
213
+ const sidebarResubmitSetupThunk : Thunk < Msg > = ( dispatch ) =>
214
+ new Promise ( ( resolve ) => {
215
+ dispatch ( {
216
+ type : "sidebar-setup-resubmit" ,
217
+ lastUserMessage : lastUserMessage . parts
218
+ . map ( ( p ) => ( p . type == "text" ? p . text : "" ) )
219
+ . join ( "" ) ,
220
+ } ) ;
221
+ resolve ( ) ;
222
+ } ) ;
223
+
224
+ return [ model , sidebarResubmitSetupThunk ] ;
225
+ }
226
+ return [ model ] ;
192
227
}
193
- }
194
228
195
- return [ model , maybeAutorespond ( model ) ] ;
229
+ case "message-in-flight" :
230
+ return [ model ] ;
231
+
232
+ default :
233
+ return assertUnreachable ( msg . conversation ) ;
234
+ }
196
235
}
197
236
237
+ case "sidebar-setup-resubmit" :
238
+ // this action is really just there so the parent (magenta app) can observe it and manipulate the sidebar
239
+ // accordingly
240
+ return [ model ] ;
241
+
198
242
case "send-message" : {
199
243
const lastMessage = model . messages [ model . messages . length - 1 ] ;
200
244
if ( lastMessage && lastMessage . role == "user" ) {
@@ -504,7 +548,8 @@ export function init({ nvim, lsp }: { nvim: Nvim; lsp: Lsp }) {
504
548
} ) => {
505
549
if (
506
550
model . messages . length == 0 &&
507
- Object . keys ( model . contextManager . files ) . length == 0
551
+ Object . keys ( model . contextManager . files ) . length == 0 &&
552
+ model . conversation . state == "stopped"
508
553
) {
509
554
return d `${ LOGO } ` ;
510
555
}
@@ -532,7 +577,16 @@ export function init({ nvim, lsp }: { nvim: Nvim; lsp: Lsp }) {
532
577
? withBindings ( d `Stopped (${ model . conversation . stopReason } )` , {
533
578
"<CR>" : ( ) => dispatch ( { type : "show-message-debug-info" } ) ,
534
579
} )
535
- : d `Error ${ model . conversation . error . message } ${ model . conversation . error . stack ? "\n" + model . conversation . error . stack : "" } `
580
+ : d `Error ${ model . conversation . error . message } ${ model . conversation . error . stack ? "\n" + model . conversation . error . stack : "" } ${
581
+ model . conversation . lastAssistantMessage
582
+ ? "\n\nLast assistant message:\n" +
583
+ JSON . stringify (
584
+ model . conversation . lastAssistantMessage ,
585
+ null ,
586
+ 2 ,
587
+ )
588
+ : ""
589
+ } `
536
590
} ${
537
591
model . conversation . state != "message-in-flight" &&
538
592
! contextManagerModel . isContextEmpty ( model . contextManager )
0 commit comments