@@ -11,7 +11,7 @@ import {
11
11
import { d , type View } from "../tea/view.ts" ;
12
12
import * as ToolManager from "../tools/toolManager.ts" ;
13
13
import { type Result } from "../utils/result.ts" ;
14
- import { IdCounter } from "../utils/uniqueId.ts" ;
14
+ import { Counter } from "../utils/uniqueId.ts" ;
15
15
import type { Nvim } from "bunvim" ;
16
16
import type { Lsp } from "../lsp.ts" ;
17
17
import {
@@ -37,6 +37,7 @@ export type ConversationState =
37
37
} ;
38
38
39
39
export type Model = {
40
+ lastUserMessageId : Message . MessageId ;
40
41
activeProvider : ProviderName ;
41
42
options : MagentaOptions ;
42
43
conversation : ConversationState ;
@@ -58,6 +59,11 @@ export type Msg =
58
59
type : "context-manager-msg" ;
59
60
msg : ContextManager . Msg ;
60
61
}
62
+ | {
63
+ type : "add-file-context" ;
64
+ absFilePath : string ;
65
+ relFilePath : string ;
66
+ }
61
67
| {
62
68
type : "add-message" ;
63
69
role : Role ;
@@ -98,14 +104,15 @@ export type Msg =
98
104
} ;
99
105
100
106
export function init ( { nvim, lsp } : { nvim : Nvim ; lsp : Lsp } ) {
101
- const idCounter = new IdCounter ( "message_" ) ;
107
+ const counter = new Counter ( ) ;
102
108
const partModel = Part . init ( { nvim, lsp } ) ;
103
109
const toolManagerModel = ToolManager . init ( { nvim, lsp } ) ;
104
110
const contextManagerModel = ContextManager . init ( { nvim } ) ;
105
111
const messageModel = Message . init ( { nvim, lsp } ) ;
106
112
107
113
function initModel ( ) : Model {
108
114
return {
115
+ lastUserMessageId : counter . last ( ) as Message . MessageId ,
109
116
options : DEFAULT_OPTIONS ,
110
117
activeProvider : "anthropic" ,
111
118
conversation : { state : "stopped" , stopReason : "end_turn" } ,
@@ -134,12 +141,16 @@ export function init({ nvim, lsp }: { nvim: Nvim; lsp: Lsp }) {
134
141
return [ { ...model , activeProvider : msg . provider } ] ;
135
142
case "add-message" : {
136
143
let message : Message . Model = {
137
- id : idCounter . get ( ) as Message . MessageId ,
144
+ id : counter . get ( ) as Message . MessageId ,
138
145
role : msg . role ,
139
146
parts : [ ] ,
140
147
edits : { } ,
141
148
} ;
142
149
150
+ if ( message . role == "user" ) {
151
+ model . lastUserMessageId = message . id ;
152
+ }
153
+
143
154
let messageThunk ;
144
155
if ( msg . content ) {
145
156
const [ next , thunk ] = messageModel . update (
@@ -231,7 +242,7 @@ export function init({ nvim, lsp }: { nvim: Nvim; lsp: Lsp }) {
231
242
const lastMessage = model . messages [ model . messages . length - 1 ] ;
232
243
if ( lastMessage ?. role !== "assistant" ) {
233
244
model . messages . push ( {
234
- id : idCounter . get ( ) as Message . MessageId ,
245
+ id : counter . get ( ) as Message . MessageId ,
235
246
role : "assistant" ,
236
247
parts : [ ] ,
237
248
edits : { } ,
@@ -255,7 +266,7 @@ export function init({ nvim, lsp }: { nvim: Nvim; lsp: Lsp }) {
255
266
const lastMessage = model . messages [ model . messages . length - 1 ] ;
256
267
if ( lastMessage ?. role !== "assistant" ) {
257
268
model . messages . push ( {
258
- id : idCounter . get ( ) as Message . MessageId ,
269
+ id : counter . get ( ) as Message . MessageId ,
259
270
role : "assistant" ,
260
271
parts : [ ] ,
261
272
edits : { } ,
@@ -283,7 +294,7 @@ ${msg.error.stack}`,
283
294
const lastMessage = model . messages [ model . messages . length - 1 ] ;
284
295
if ( lastMessage ?. role !== "assistant" ) {
285
296
model . messages . push ( {
286
- id : idCounter . get ( ) as Message . MessageId ,
297
+ id : counter . get ( ) as Message . MessageId ,
287
298
role : "assistant" ,
288
299
parts : [ ] ,
289
300
edits : { } ,
@@ -363,6 +374,24 @@ ${msg.error.stack}`,
363
374
] ;
364
375
}
365
376
377
+ case "add-file-context" : {
378
+ const [ nextContextManager , contextManagerThunk ] =
379
+ contextManagerModel . update (
380
+ {
381
+ type : "add-file-context" ,
382
+ absFilePath : msg . absFilePath ,
383
+ relFilePath : msg . relFilePath ,
384
+ messageId : model . lastUserMessageId ,
385
+ } ,
386
+ model . contextManager ,
387
+ ) ;
388
+ model . contextManager = nextContextManager ;
389
+ return [
390
+ model ,
391
+ parallelThunks ( wrapThunk ( "context-manager-msg" , contextManagerThunk ) ) ,
392
+ ] ;
393
+ }
394
+
366
395
case "clear" : {
367
396
return [ initModel ( ) ] ;
368
397
}
@@ -519,19 +548,7 @@ ${msg.error.stack}`,
519
548
} ;
520
549
521
550
async function getMessages ( model : Model ) : Promise < ProviderMessage [ ] > {
522
- const messages = [ ] ;
523
- const contextMessage = await contextManagerModel . getContextMessage (
524
- model . contextManager ,
525
- ) ;
526
-
527
- if ( contextMessage ) {
528
- nvim . logger ?. debug (
529
- `Got context message: ${ JSON . stringify ( contextMessage ) } ` ,
530
- ) ;
531
- messages . push ( contextMessage ) ;
532
- }
533
-
534
- const rest = model . messages . flatMap ( ( msg ) => {
551
+ const messages = model . messages . flatMap ( ( msg ) => {
535
552
const messageContent : ProviderMessageContent [ ] = [ ] ;
536
553
const toolResponseContent : ProviderMessageContent [ ] = [ ] ;
537
554
@@ -580,11 +597,35 @@ ${msg.error.stack}`,
580
597
} ) ;
581
598
}
582
599
583
- return out ;
600
+ return out . map ( ( m ) => ( {
601
+ message : m ,
602
+ messageId : msg . id ,
603
+ } ) ) ;
584
604
} ) ;
585
605
586
- messages . push ( ...rest ) ;
587
- return messages ;
606
+ const contextMessages = await contextManagerModel . getContextMessages (
607
+ counter . last ( ) as Message . MessageId ,
608
+ model . contextManager ,
609
+ ) ;
610
+
611
+ if ( contextMessages ) {
612
+ nvim . logger ?. debug (
613
+ `Got context messages: ${ JSON . stringify ( contextMessages ) } ` ,
614
+ ) ;
615
+
616
+ for ( const contextMessage of contextMessages ) {
617
+ // we want to insert the contextMessage before the corresponding user message
618
+ let idx = messages . findIndex (
619
+ ( m ) => m . messageId >= contextMessage . messageId ,
620
+ ) ;
621
+ if ( idx == - 1 ) {
622
+ idx = messages . length ;
623
+ }
624
+ messages . splice ( idx , 0 , contextMessage ) ;
625
+ }
626
+ }
627
+
628
+ return messages . map ( ( m ) => m . message ) ;
588
629
}
589
630
590
631
return {
0 commit comments