Skip to content

Commit b762a09

Browse files
committed
WIP Update host types for changes to how command requests are encoded
1 parent b40c860 commit b762a09

File tree

9 files changed

+209
-233
lines changed

9 files changed

+209
-233
lines changed

packages/host/app/components/matrix/room-message-command.gts

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export default class RoomMessageCommand extends Component<Signature> {
7474
};
7575

7676
private get previewCommandCode() {
77-
let { name, payload } = this.args.messageCommand;
77+
let { name, arguments: payload } = this.args.messageCommand;
7878
return JSON.stringify({ name, payload }, null, 2);
7979
}
8080

packages/host/app/lib/matrix-classes/message-builder.ts

+25-37
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,10 @@ import { getOwner, setOwner } from '@ember/owner';
44

55
import { inject as service } from '@ember/service';
66

7-
import {
8-
LooseSingleCardDocument,
9-
sanitizeHtml,
10-
} from '@cardstack/runtime-common';
7+
import { LooseSingleCardDocument } from '@cardstack/runtime-common';
118

129
import {
10+
APP_BOXEL_COMMAND_REQUESTS_KEY,
1311
APP_BOXEL_COMMAND_RESULT_EVENT_TYPE,
1412
APP_BOXEL_COMMAND_RESULT_WITH_OUTPUT_MSGTYPE,
1513
APP_BOXEL_MESSAGE_MSGTYPE,
@@ -40,7 +38,7 @@ const ErrorMessage: Record<string, string> = {
4038

4139
export default class MessageBuilder {
4240
constructor(
43-
private event: MessageEvent | CommandEvent | CardMessageEvent,
41+
private event: MessageEvent | CardMessageEvent,
4442
owner: Owner,
4543
private builderContext: {
4644
roomId: string;
@@ -127,28 +125,18 @@ export default class MessageBuilder {
127125
return errorMessage;
128126
}
129127

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-
136128
buildMessage(): Message {
137129
let { event } = this;
138130
let message = this.coreMessageArgs;
139131
message.errorMessage = this.errorMessage;
140132
if (event.content.msgtype === APP_BOXEL_MESSAGE_MSGTYPE) {
141133
message.clientGeneratedId = this.clientGeneratedId;
142134
message.attachedCardIds = this.attachedCardIds;
135+
if (event.content[APP_BOXEL_COMMAND_REQUESTS_KEY]) {
136+
message.command = this.buildMessageCommand(message);
137+
}
143138
} else if (event.content.msgtype === 'm.text') {
144139
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;
152140
}
153141
return message;
154142
}
@@ -171,17 +159,15 @@ export default class MessageBuilder {
171159
: undefined;
172160
message.updated = new Date();
173161

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 {
176169
message.command = this.buildMessageCommand(message);
177170
}
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;
185171
}
186172
}
187173

@@ -192,36 +178,38 @@ export default class MessageBuilder {
192178

193179
if (this.builderContext.commandResultEvent) {
194180
let event = this.builderContext.commandResultEvent;
195-
message.command.commandStatus = event.content['m.relates_to']
181+
message.command!.commandStatus = event.content['m.relates_to']
196182
.key as CommandStatus;
197-
message.command.commandResultCardEventId =
183+
message.command!.commandResultCardEventId =
198184
event.content.msgtype === APP_BOXEL_COMMAND_RESULT_WITH_OUTPUT_MSGTYPE
199185
? event.content.data.cardEventId
200186
: undefined;
201187
}
202188
}
203189

204190
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
206197
let commandResultEvent =
207198
this.builderContext.commandResultEvent ??
208199
(this.builderContext.events.find((e: any) => {
209200
let r = e.content['m.relates_to'];
210201
return (
211202
e.type === APP_BOXEL_COMMAND_RESULT_EVENT_TYPE &&
212203
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
216207
);
217208
}) as CommandResultEvent | undefined);
218209

219-
let command = event.content.data.toolCall;
220210
let messageCommand = new MessageCommand(
221211
message,
222-
command.id,
223-
command.name,
224-
command.arguments,
212+
commandRequest,
225213
this.builderContext.effectiveEventId,
226214
(commandResultEvent?.content['m.relates_to']?.key ||
227215
'ready') as CommandStatus,

packages/host/app/lib/matrix-classes/message-command.ts

+17-7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { inject as service } from '@ember/service';
44

55
import { tracked } from '@glimmer/tracking';
66

7+
import { CommandRequestContent } from '@cardstack/runtime-common/helpers/ai';
8+
79
import type CardService from '@cardstack/host/services/card-service';
810
import type CommandService from '@cardstack/host/services/command-service';
911
import type MatrixService from '@cardstack/host/services/matrix-service';
@@ -15,25 +17,21 @@ import { Message } from './message';
1517
type CommandStatus = 'applied' | 'ready' | 'applying';
1618

1719
export default class MessageCommand {
18-
@tracked name: string;
19-
@tracked payload: any;
20+
@tracked commandRequest: Partial<CommandRequestContent>;
2021
@tracked commandStatus?: CommandStatus;
2122
@tracked commandResultCardEventId?: string;
2223

2324
constructor(
2425
public message: Message,
25-
public toolCallId: string,
26-
name: string,
27-
payload: any, //arguments of toolCall. Its not called arguments due to lint
26+
commandRequest: Partial<CommandRequestContent>,
2827
public eventId: string,
2928
commandStatus: CommandStatus,
3029
commandResultCardEventId: string | undefined,
3130
owner: Owner,
3231
) {
3332
setOwner(this, owner);
3433

35-
this.name = name;
36-
this.payload = payload;
34+
this.commandRequest = commandRequest;
3735
this.commandStatus = commandStatus;
3836
this.commandResultCardEventId = commandResultCardEventId;
3937
}
@@ -42,6 +40,18 @@ export default class MessageCommand {
4240
@service declare matrixService: MatrixService;
4341
@service declare cardService: CardService;
4442

43+
get id() {
44+
return this.commandRequest.id;
45+
}
46+
47+
get name() {
48+
return this.commandRequest.name;
49+
}
50+
51+
get arguments() {
52+
return this.commandRequest.arguments;
53+
}
54+
4555
get status() {
4656
if (
4757
this.commandService.currentlyExecutingCommandEventIds.has(this.eventId)

packages/host/app/resources/room.ts

+21-18
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,13 @@ import { type LooseSingleCardDocument } from '@cardstack/runtime-common';
1111

1212
import {
1313
APP_BOXEL_CARDFRAGMENT_MSGTYPE,
14-
APP_BOXEL_COMMAND_MSGTYPE,
14+
APP_BOXEL_COMMAND_REQUESTS_KEY,
1515
APP_BOXEL_COMMAND_RESULT_EVENT_TYPE,
1616
DEFAULT_LLM,
1717
} from '@cardstack/runtime-common/matrix-constants';
1818

1919
import type {
2020
CardFragmentContent,
21-
CommandEvent,
2221
MatrixEvent as DiscreteMatrixEvent,
2322
RoomCreateEvent,
2423
RoomNameEvent,
@@ -294,7 +293,7 @@ export class RoomResource extends Resource<Args> {
294293
index,
295294
}: {
296295
roomId: string;
297-
event: MessageEvent | CommandEvent | CardMessageEvent;
296+
event: MessageEvent | CardMessageEvent;
298297
index: number;
299298
}) {
300299
if (event.content.msgtype === APP_BOXEL_CARDFRAGMENT_MSGTYPE) {
@@ -311,7 +310,7 @@ export class RoomResource extends Resource<Args> {
311310
index,
312311
}: {
313312
roomId: string;
314-
event: MessageEvent | CommandEvent | CardMessageEvent;
313+
event: MessageEvent | CardMessageEvent;
315314
index: number;
316315
}) {
317316
let effectiveEventId = this.getEffectiveEventId(event);
@@ -351,35 +350,39 @@ export class RoomResource extends Resource<Args> {
351350
index: number;
352351
}) {
353352
let effectiveEventId = this.getEffectiveEventId(event);
354-
let commandEvent = this.events.find(
353+
let messageEventWithCommand = this.events.find(
355354
(e: any) =>
356355
e.type === 'm.room.message' &&
357-
e.content.msgtype === APP_BOXEL_COMMAND_MSGTYPE &&
356+
e.content[APP_BOXEL_COMMAND_REQUESTS_KEY]?.length &&
358357
e.content['m.relates_to']?.event_id === effectiveEventId,
359-
)! as CommandEvent | undefined;
358+
)! as CardMessageEvent | undefined;
360359
let message = this._messageCache.get(effectiveEventId);
361-
if (!message || !commandEvent) {
360+
if (!message || !messageEventWithCommand) {
362361
return;
363362
}
364363

365364
let author = this.upsertRoomMember({
366365
roomId,
367366
userId: event.sender,
368367
});
369-
let messageBuilder = new MessageBuilder(commandEvent, getOwner(this)!, {
370-
roomId,
371-
effectiveEventId,
372-
author,
373-
index,
374-
serializedCardFromFragments: this.serializedCardFromFragments,
375-
events: this.events,
376-
commandResultEvent: event,
377-
});
368+
let messageBuilder = new MessageBuilder(
369+
messageEventWithCommand,
370+
getOwner(this)!,
371+
{
372+
roomId,
373+
effectiveEventId,
374+
author,
375+
index,
376+
serializedCardFromFragments: this.serializedCardFromFragments,
377+
events: this.events,
378+
commandResultEvent: event,
379+
},
380+
);
378381
messageBuilder.updateMessageCommandResult(message);
379382
}
380383

381384
private getEffectiveEventId(
382-
event: MessageEvent | CommandEvent | CardMessageEvent | CommandResultEvent,
385+
event: MessageEvent | CardMessageEvent | CommandResultEvent,
383386
) {
384387
return event.content['m.relates_to']?.rel_type === 'm.replace' ||
385388
event.content['m.relates_to']?.rel_type === 'm.annotation'

packages/host/app/services/command-service.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export default class CommandService extends Service {
104104
await this.matrixService.sendCommandResultEvent(
105105
event.room_id!,
106106
eventId,
107+
toolCall.id,
107108
resultCard,
108109
);
109110
} finally {
@@ -122,14 +123,14 @@ export default class CommandService extends Service {
122123

123124
//TODO: Convert to non-EC async method after fixing CS-6987
124125
run = task(async (command: MessageCommand) => {
125-
let { payload, eventId } = command;
126+
let { arguments: payload, eventId, id: toolCallId } = command;
126127
let resultCard: CardDef | undefined;
127128
try {
128129
this.matrixService.failedCommandState.delete(eventId);
129130
this.currentlyExecutingCommandEventIds.add(eventId);
130131

131132
// lookup command
132-
let { command: commandToRun } = this.commands.get(command.name) ?? {};
133+
let { command: commandToRun } = this.commands.get(command.name!) ?? {};
133134

134135
if (commandToRun) {
135136
// Get the input type and validate/construct the payload
@@ -139,8 +140,8 @@ export default class CommandService extends Service {
139140
let typedInput;
140141
if (InputType) {
141142
typedInput = new InputType({
142-
...payload.attributes,
143-
...payload.relationships,
143+
...payload!.attributes,
144+
...payload!.relationships,
144145
});
145146
} else {
146147
typedInput = undefined;
@@ -183,6 +184,7 @@ export default class CommandService extends Service {
183184
await this.matrixService.sendCommandResultEvent(
184185
command.message.roomId,
185186
eventId,
187+
toolCallId!,
186188
resultCard,
187189
);
188190
} catch (e) {

0 commit comments

Comments
 (0)