@@ -5,13 +5,20 @@ import Popover from '~/components/ui/Popover';
55import { workbenchStore } from '~/lib/stores/workbench' ;
66import { WORK_DIR } from '~/utils/constants' ;
77import WithTooltip from '~/components/ui/Tooltip' ;
8+ import type { Message } from 'ai' ;
9+ import type { ProviderInfo } from '~/types/model' ;
810
911interface AssistantMessageProps {
1012 content : string ;
1113 annotations ?: JSONValue [ ] ;
1214 messageId ?: string ;
1315 onRewind ?: ( messageId : string ) => void ;
1416 onFork ?: ( messageId : string ) => void ;
17+ append ?: ( message : Message ) => void ;
18+ chatMode ?: 'discuss' | 'build' ;
19+ setChatMode ?: ( mode : 'discuss' | 'build' ) => void ;
20+ model ?: string ;
21+ provider ?: ProviderInfo ;
1522}
1623
1724function openArtifactInWorkbench ( filePath : string ) {
@@ -38,104 +45,120 @@ function normalizedFilePath(path: string) {
3845 return normalizedPath ;
3946}
4047
41- export const AssistantMessage = memo ( ( { content, annotations, messageId, onRewind, onFork } : AssistantMessageProps ) => {
42- const filteredAnnotations = ( annotations ?. filter (
43- ( annotation : JSONValue ) => annotation && typeof annotation === 'object' && Object . keys ( annotation ) . includes ( 'type' ) ,
44- ) || [ ] ) as { type : string ; value : any } & { [ key : string ] : any } [ ] ;
48+ export const AssistantMessage = memo (
49+ ( {
50+ content,
51+ annotations,
52+ messageId,
53+ onRewind,
54+ onFork,
55+ append,
56+ chatMode,
57+ setChatMode,
58+ model,
59+ provider,
60+ } : AssistantMessageProps ) => {
61+ const filteredAnnotations = ( annotations ?. filter (
62+ ( annotation : JSONValue ) =>
63+ annotation && typeof annotation === 'object' && Object . keys ( annotation ) . includes ( 'type' ) ,
64+ ) || [ ] ) as { type : string ; value : any } & { [ key : string ] : any } [ ] ;
4565
46- let chatSummary : string | undefined = undefined ;
66+ let chatSummary : string | undefined = undefined ;
4767
48- if ( filteredAnnotations . find ( ( annotation ) => annotation . type === 'chatSummary' ) ) {
49- chatSummary = filteredAnnotations . find ( ( annotation ) => annotation . type === 'chatSummary' ) ?. summary ;
50- }
68+ if ( filteredAnnotations . find ( ( annotation ) => annotation . type === 'chatSummary' ) ) {
69+ chatSummary = filteredAnnotations . find ( ( annotation ) => annotation . type === 'chatSummary' ) ?. summary ;
70+ }
5171
52- let codeContext : string [ ] | undefined = undefined ;
72+ let codeContext : string [ ] | undefined = undefined ;
5373
54- if ( filteredAnnotations . find ( ( annotation ) => annotation . type === 'codeContext' ) ) {
55- codeContext = filteredAnnotations . find ( ( annotation ) => annotation . type === 'codeContext' ) ?. files ;
56- }
74+ if ( filteredAnnotations . find ( ( annotation ) => annotation . type === 'codeContext' ) ) {
75+ codeContext = filteredAnnotations . find ( ( annotation ) => annotation . type === 'codeContext' ) ?. files ;
76+ }
5777
58- const usage : {
59- completionTokens : number ;
60- promptTokens : number ;
61- totalTokens : number ;
62- } = filteredAnnotations . find ( ( annotation ) => annotation . type === 'usage' ) ?. value ;
78+ const usage : {
79+ completionTokens : number ;
80+ promptTokens : number ;
81+ totalTokens : number ;
82+ } = filteredAnnotations . find ( ( annotation ) => annotation . type === 'usage' ) ?. value ;
6383
64- return (
65- < div className = "overflow-hidden w-full" >
66- < >
67- < div className = " flex gap-2 items-center text-sm text-bolt-elements-textSecondary mb-2" >
68- { ( codeContext || chatSummary ) && (
69- < Popover side = "right" align = "start" trigger = { < div className = "i-ph:info" /> } >
70- { chatSummary && (
71- < div className = "max-w-chat" >
72- < div className = "summary max-h-96 flex flex-col" >
73- < h2 className = "border border-bolt-elements-borderColor rounded-md p4" > Summary</ h2 >
74- < div style = { { zoom : 0.7 } } className = "overflow-y-auto m4" >
75- < Markdown > { chatSummary } </ Markdown >
76- </ div >
77- </ div >
78- { codeContext && (
79- < div className = "code-context flex flex-col p4 border border-bolt-elements-borderColor rounded-md" >
80- < h2 > Context</ h2 >
81- < div className = "flex gap-4 mt-4 bolt" style = { { zoom : 0.6 } } >
82- { codeContext . map ( ( x ) => {
83- const normalized = normalizedFilePath ( x ) ;
84- return (
85- < Fragment key = { normalized } >
86- < code
87- className = "bg-bolt-elements-artifacts-inlineCode-background text-bolt-elements-artifacts-inlineCode-text px-1.5 py-1 rounded-md text-bolt-elements-item-contentAccent hover:underline cursor-pointer"
88- onClick = { ( e ) => {
89- e . preventDefault ( ) ;
90- e . stopPropagation ( ) ;
91- openArtifactInWorkbench ( normalized ) ;
92- } }
93- >
94- { normalized }
95- </ code >
96- </ Fragment >
97- ) ;
98- } ) }
84+ return (
85+ < div className = "overflow-hidden w-full" >
86+ < >
87+ < div className = " flex gap-2 items-center text-sm text-bolt-elements-textSecondary mb-2" >
88+ { ( codeContext || chatSummary ) && (
89+ < Popover side = "right" align = "start" trigger = { < div className = "i-ph:info" /> } >
90+ { chatSummary && (
91+ < div className = "max-w-chat" >
92+ < div className = "summary max-h-96 flex flex-col" >
93+ < h2 className = "border border-bolt-elements-borderColor rounded-md p4" > Summary</ h2 >
94+ < div style = { { zoom : 0.7 } } className = "overflow-y-auto m4" >
95+ < Markdown > { chatSummary } </ Markdown >
9996 </ div >
10097 </ div >
98+ { codeContext && (
99+ < div className = "code-context flex flex-col p4 border border-bolt-elements-borderColor rounded-md" >
100+ < h2 > Context</ h2 >
101+ < div className = "flex gap-4 mt-4 bolt" style = { { zoom : 0.6 } } >
102+ { codeContext . map ( ( x ) => {
103+ const normalized = normalizedFilePath ( x ) ;
104+ return (
105+ < Fragment key = { normalized } >
106+ < code
107+ className = "bg-bolt-elements-artifacts-inlineCode-background text-bolt-elements-artifacts-inlineCode-text px-1.5 py-1 rounded-md text-bolt-elements-item-contentAccent hover:underline cursor-pointer"
108+ onClick = { ( e ) => {
109+ e . preventDefault ( ) ;
110+ e . stopPropagation ( ) ;
111+ openArtifactInWorkbench ( normalized ) ;
112+ } }
113+ >
114+ { normalized }
115+ </ code >
116+ </ Fragment >
117+ ) ;
118+ } ) }
119+ </ div >
120+ </ div >
121+ ) }
122+ </ div >
123+ ) }
124+ < div className = "context" > </ div >
125+ </ Popover >
126+ ) }
127+ < div className = "flex w-full items-center justify-between" >
128+ { usage && (
129+ < div >
130+ Tokens: { usage . totalTokens } (prompt: { usage . promptTokens } , completion: { usage . completionTokens } )
131+ </ div >
132+ ) }
133+ { ( onRewind || onFork ) && messageId && (
134+ < div className = "flex gap-2 flex-col lg:flex-row ml-auto" >
135+ { onRewind && (
136+ < WithTooltip tooltip = "Revert to this message" >
137+ < button
138+ onClick = { ( ) => onRewind ( messageId ) }
139+ key = "i-ph:arrow-u-up-left"
140+ className = "i-ph:arrow-u-up-left text-xl text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary transition-colors"
141+ />
142+ </ WithTooltip >
143+ ) }
144+ { onFork && (
145+ < WithTooltip tooltip = "Fork chat from this message" >
146+ < button
147+ onClick = { ( ) => onFork ( messageId ) }
148+ key = "i-ph:git-fork"
149+ className = "i-ph:git-fork text-xl text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary transition-colors"
150+ />
151+ </ WithTooltip >
101152 ) }
102153 </ div >
103154 ) }
104- < div className = "context" > </ div >
105- </ Popover >
106- ) }
107- < div className = "flex w-full items-center justify-between" >
108- { usage && (
109- < div >
110- Tokens: { usage . totalTokens } (prompt: { usage . promptTokens } , completion: { usage . completionTokens } )
111- </ div >
112- ) }
113- { ( onRewind || onFork ) && messageId && (
114- < div className = "flex gap-2 flex-col lg:flex-row ml-auto" >
115- { onRewind && (
116- < WithTooltip tooltip = "Revert to this message" >
117- < button
118- onClick = { ( ) => onRewind ( messageId ) }
119- key = "i-ph:arrow-u-up-left"
120- className = "i-ph:arrow-u-up-left text-xl text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary transition-colors"
121- />
122- </ WithTooltip >
123- ) }
124- { onFork && (
125- < WithTooltip tooltip = "Fork chat from this message" >
126- < button
127- onClick = { ( ) => onFork ( messageId ) }
128- key = "i-ph:git-fork"
129- className = "i-ph:git-fork text-xl text-bolt-elements-textSecondary hover:text-bolt-elements-textPrimary transition-colors"
130- />
131- </ WithTooltip >
132- ) }
133- </ div >
134- ) }
155+ </ div >
135156 </ div >
136- </ div >
137- </ >
138- < Markdown html > { content } </ Markdown >
139- </ div >
140- ) ;
141- } ) ;
157+ </ >
158+ < Markdown append = { append } chatMode = { chatMode } setChatMode = { setChatMode } model = { model } provider = { provider } html >
159+ { content }
160+ </ Markdown >
161+ </ div >
162+ ) ;
163+ } ,
164+ ) ;
0 commit comments