@@ -4,12 +4,10 @@ import { getOwner, setOwner } from '@ember/owner';
4
4
5
5
import { inject as service } from '@ember/service' ;
6
6
7
- import {
8
- LooseSingleCardDocument ,
9
- sanitizeHtml ,
10
- } from '@cardstack/runtime-common' ;
7
+ import { LooseSingleCardDocument } from '@cardstack/runtime-common' ;
11
8
12
9
import {
10
+ APP_BOXEL_COMMAND_REQUESTS_KEY ,
13
11
APP_BOXEL_COMMAND_RESULT_EVENT_TYPE ,
14
12
APP_BOXEL_COMMAND_RESULT_WITH_OUTPUT_MSGTYPE ,
15
13
APP_BOXEL_MESSAGE_MSGTYPE ,
@@ -40,7 +38,7 @@ const ErrorMessage: Record<string, string> = {
40
38
41
39
export default class MessageBuilder {
42
40
constructor (
43
- private event : MessageEvent | CommandEvent | CardMessageEvent ,
41
+ private event : MessageEvent | CardMessageEvent ,
44
42
owner : Owner ,
45
43
private builderContext : {
46
44
roomId : string ;
@@ -127,28 +125,18 @@ export default class MessageBuilder {
127
125
return errorMessage ;
128
126
}
129
127
130
- private get formattedMessageForCommand ( ) {
131
- return `<p data-test-command-message class="command-message">${ sanitizeHtml (
132
- this . event . content . formatted_body ,
133
- ) } </p>`;
134
- }
135
-
136
128
buildMessage ( ) : Message {
137
129
let { event } = this ;
138
130
let message = this . coreMessageArgs ;
139
131
message . errorMessage = this . errorMessage ;
140
132
if ( event . content . msgtype === APP_BOXEL_MESSAGE_MSGTYPE ) {
141
133
message . clientGeneratedId = this . clientGeneratedId ;
142
134
message . attachedCardIds = this . attachedCardIds ;
135
+ if ( event . content [ APP_BOXEL_COMMAND_REQUESTS_KEY ] ) {
136
+ message . command = this . buildMessageCommand ( message ) ;
137
+ }
143
138
} else if ( event . content . msgtype === 'm.text' ) {
144
139
message . isStreamingFinished = ! ! event . content . isStreamingFinished ; // Indicates whether streaming (message updating while AI bot is sending more content into the message) has finished
145
- } else if (
146
- event . content . msgtype === APP_BOXEL_COMMAND_MSGTYPE &&
147
- event . content . data . toolCall
148
- ) {
149
- message . formattedMessage = this . formattedMessageForCommand ;
150
- message . command = this . buildMessageCommand ( message ) ;
151
- message . isStreamingFinished = true ;
152
140
}
153
141
return message ;
154
142
}
@@ -171,17 +159,15 @@ export default class MessageBuilder {
171
159
: undefined ;
172
160
message . updated = new Date ( ) ;
173
161
174
- if ( this . event . content . msgtype === APP_BOXEL_COMMAND_MSGTYPE ) {
175
- if ( ! message . command ) {
162
+ let commandRequest = ( this . event . content as CardMessageContent ) [
163
+ APP_BOXEL_COMMAND_REQUESTS_KEY
164
+ ] ?. [ 0 ] ; // TODO: handle multiple commands
165
+ if ( commandRequest ) {
166
+ if ( message . command ) {
167
+ message . command . commandRequest = commandRequest ;
168
+ } else {
176
169
message . command = this . buildMessageCommand ( message ) ;
177
170
}
178
-
179
- message . isStreamingFinished = true ;
180
- message . formattedMessage = this . formattedMessageForCommand ;
181
-
182
- let command = this . event . content . data . toolCall ;
183
- message . command . name = command . name ;
184
- message . command . payload = command . arguments ;
185
171
}
186
172
}
187
173
@@ -192,36 +178,38 @@ export default class MessageBuilder {
192
178
193
179
if ( this . builderContext . commandResultEvent ) {
194
180
let event = this . builderContext . commandResultEvent ;
195
- message . command . commandStatus = event . content [ 'm.relates_to' ]
181
+ message . command ! . commandStatus = event . content [ 'm.relates_to' ]
196
182
. key as CommandStatus ;
197
- message . command . commandResultCardEventId =
183
+ message . command ! . commandResultCardEventId =
198
184
event . content . msgtype === APP_BOXEL_COMMAND_RESULT_WITH_OUTPUT_MSGTYPE
199
185
? event . content . data . cardEventId
200
186
: undefined ;
201
187
}
202
188
}
203
189
204
190
private buildMessageCommand ( message : Message ) {
205
- let event = this . event as CommandEvent ;
191
+ let eventContent = this . event . content as CardMessageContent ;
192
+ let commandRequests = eventContent [ APP_BOXEL_COMMAND_REQUESTS_KEY ] ;
193
+ if ( ! commandRequests ) {
194
+ return ;
195
+ }
196
+ let commandRequest = commandRequests [ 0 ] ; // TODO: handle multiple commands
206
197
let commandResultEvent =
207
198
this . builderContext . commandResultEvent ??
208
199
( this . builderContext . events . find ( ( e : any ) => {
209
200
let r = e . content [ 'm.relates_to' ] ;
210
201
return (
211
202
e . type === APP_BOXEL_COMMAND_RESULT_EVENT_TYPE &&
212
203
r . rel_type === 'm.annotation' &&
213
- ( r . event_id === event ! . content . data . eventId ||
214
- r . event_id === event ! . event_id ||
215
- r . event_id === this . builderContext . effectiveEventId )
204
+ ( r . event_id === this . event . event_id ||
205
+ r . event_id === this . builderContext . effectiveEventId ) &&
206
+ r . data . commandRequestId === commandRequest . id
216
207
) ;
217
208
} ) as CommandResultEvent | undefined ) ;
218
209
219
- let command = event . content . data . toolCall ;
220
210
let messageCommand = new MessageCommand (
221
211
message ,
222
- command . id ,
223
- command . name ,
224
- command . arguments ,
212
+ commandRequest ,
225
213
this . builderContext . effectiveEventId ,
226
214
( commandResultEvent ?. content [ 'm.relates_to' ] ?. key ||
227
215
'ready' ) as CommandStatus ,
0 commit comments