Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions packages/ai-bot/lib/code-patch-correctness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ import {
APP_BOXEL_CODE_PATCH_CORRECTNESS_REL_TYPE,
} from '@cardstack/runtime-common/matrix-constants';
import {
encodeCommandRequests,
type CommandRequest,
encodeToolRequests,
type ToolRequest,
} from '@cardstack/runtime-common/commands';
import { MAX_CORRECTNESS_FIX_ATTEMPTS } from '@cardstack/runtime-common/ai/correctness-constants';

export const CHECK_CORRECTNESS_COMMAND_NAME = 'checkCorrectness';
export const CHECK_CORRECTNESS_TOOL_NAME = 'checkCorrectness';

export async function publishCodePatchCorrectnessMessage(
summary: PendingCodePatchCorrectnessCheck,
client: MatrixClient,
) {
let body = '';
let commandRequests = buildCheckCorrectnessCommandRequests(summary);
let toolRequests = buildCheckCorrectnessToolRequests(summary);
let baseContent = {
Comment thread
lukemelia marked this conversation as resolved.
body,
msgtype: APP_BOXEL_CODE_PATCH_CORRECTNESS_MSGTYPE,
Expand All @@ -46,17 +46,16 @@ export async function publishCodePatchCorrectnessMessage(
if (Object.keys(data).length > 0) {
content.data = data;
}
if (commandRequests.length) {
content[APP_BOXEL_TOOL_REQUESTS_KEY] =
encodeCommandRequests(commandRequests);
if (toolRequests.length) {
content[APP_BOXEL_TOOL_REQUESTS_KEY] = encodeToolRequests(toolRequests);
}
await client.sendEvent(summary.roomId, 'm.room.message', content);
}

export function buildCheckCorrectnessCommandRequests(
export function buildCheckCorrectnessToolRequests(
summary: PendingCodePatchCorrectnessCheck,
): Partial<CommandRequest>[] {
let requests: Partial<CommandRequest>[] = [];
): Partial<ToolRequest>[] {
let requests: Partial<ToolRequest>[] = [];
let attemptsByTargetKey = summary.attemptsByTargetKey ?? {};
for (let file of summary.files) {
let sourceRef = file.sourceUrl || file.displayName;
Expand All @@ -70,7 +69,7 @@ export function buildCheckCorrectnessCommandRequests(
let lintIssues = file.lintIssues;
requests.push({
id: `check-${uuidv4()}`,
name: CHECK_CORRECTNESS_COMMAND_NAME,
name: CHECK_CORRECTNESS_TOOL_NAME,
arguments: {
description: `Check correctness of ${file.displayName}`,
attributes: {
Expand All @@ -94,7 +93,7 @@ export function buildCheckCorrectnessCommandRequests(
}
requests.push({
id: `check-${uuidv4()}`,
name: CHECK_CORRECTNESS_COMMAND_NAME,
name: CHECK_CORRECTNESS_TOOL_NAME,
arguments: {
description: `Check correctness of ${card.cardId}`,
attributes: {
Expand Down
6 changes: 3 additions & 3 deletions packages/ai-bot/lib/matrix/response-publisher.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ChatCompletionMessageFunctionToolCall } from 'openai/resources/chat/completions';
import type { CommandRequest } from '@cardstack/runtime-common/commands';
import type { ToolRequest } from '@cardstack/runtime-common/commands';
import { AI_BOT_EXECUTOR } from '@cardstack/runtime-common/commands';
import {
READ_REALM_FILE_TOOL_NAME,
Expand All @@ -21,9 +21,9 @@ let log = logger('ai-bot');

function toCommandRequest(
toolCall: ChatCompletionMessageFunctionToolCall,
): Partial<CommandRequest> {
): Partial<ToolRequest> {
let { id, function: f } = toolCall;
let result = {} as Partial<CommandRequest>;
let result = {} as Partial<ToolRequest>;
if (id) {
result['id'] = id;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/ai-bot/lib/responder.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { logger } from '@cardstack/runtime-common';
import { APP_BOXEL_CODE_PATCH_CORRECTNESS_MSGTYPE } from '@cardstack/runtime-common/matrix-constants';
import { isCommandOrCodePatchResult } from '@cardstack/runtime-common/ai';
import { isToolOrCodePatchResult } from '@cardstack/runtime-common/ai';

import { errorReporter } from './sentry.ts';
import type { OpenAIError } from 'openai/error';
Expand Down Expand Up @@ -35,7 +35,7 @@ export class Responder {
}

// If it's a command result or a code patch result, we might respond
if (isCommandOrCodePatchResult(event)) {
if (isToolOrCodePatchResult(event)) {
return true;
}

Expand All @@ -45,7 +45,7 @@ export class Responder {

static eventWillDefinitelyTriggerResponse(event: DiscreteMatrixEvent) {
return (
this.eventMayTriggerResponse(event) && !isCommandOrCodePatchResult(event)
this.eventMayTriggerResponse(event) && !isToolOrCodePatchResult(event)
);
}

Expand Down
34 changes: 15 additions & 19 deletions packages/ai-bot/lib/set-title.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import type OpenAI from 'openai';
import type { MatrixClient, IRoomEvent } from 'matrix-js-sdk';
import type {
MatrixEvent as DiscreteMatrixEvent,
CommandResultWithOutputContent,
CommandResultWithNoOutputContent,
EncodedCommandRequest,
ToolResultWithOutputContent,
ToolResultWithNoOutputContent,
EncodedToolRequest,
CodePatchResultContent,
CardMessageContent,
} from 'https://cardstack.com/base/matrix-event';
import type { ChatCompletionMessageParam } from 'openai/resources';
import {
type OpenAIPromptMessage,
isCodePatchResultStatusApplied,
isCommandResultStatusApplied,
isToolResultStatusApplied,
attachedCardsToMessage,
getRelevantCards,
} from '@cardstack/runtime-common/ai';
Expand Down Expand Up @@ -106,8 +106,8 @@ export const getLatestResultMessage = (
return [];
}
let eventContent = event.getContent() as
| CommandResultWithOutputContent
| CommandResultWithNoOutputContent
| ToolResultWithOutputContent
| ToolResultWithNoOutputContent
| CodePatchResultContent;
let messageRelation: IEventRelation | undefined =
eventContent['m.relates_to'];
Expand All @@ -122,27 +122,23 @@ export const getLatestResultMessage = (
);

let commandRequestId = (
eventContent as
| CommandResultWithOutputContent
| CommandResultWithNoOutputContent
eventContent as ToolResultWithOutputContent | ToolResultWithNoOutputContent
).commandRequestId;
if (commandRequestId) {
let commandRequests = getToolRequests<Partial<EncodedCommandRequest>>(
let toolRequests = getToolRequests<Partial<EncodedToolRequest>>(
resultSourceEvent.content as CardMessageContent,
);
if (commandRequests) {
let commandRequest = commandRequests.find(
(cr: Partial<EncodedCommandRequest>) => {
return cr.id === commandRequestId;
},
);
if (!commandRequest) {
if (toolRequests) {
let toolRequest = toolRequests.find((cr: Partial<EncodedToolRequest>) => {
return cr.id === commandRequestId;
});
if (!toolRequest) {
return [];
}
return [
{
role: 'user',
content: `Applying tool call ${commandRequest.name} with args ${commandRequest.arguments}. Cards shared are: ${attachedCardsToMessage(
content: `Applying tool call ${toolRequest.name} with args ${toolRequest.arguments}. Cards shared are: ${attachedCardsToMessage(
mostRecentlyAttachedCard,
attachedCards,
)}`,
Expand Down Expand Up @@ -190,7 +186,7 @@ export function shouldSetRoomTitle(
event?: MatrixEvent,
) {
return (
(isCommandResultStatusApplied(event) ||
(isToolResultStatusApplied(event) ||
isCodePatchResultStatusApplied(event) ||
userAlreadyHasSentNMessages(rawEventLog, aiBotUserId)) &&
!roomTitleAlreadySet(rawEventLog)
Expand Down
4 changes: 2 additions & 2 deletions packages/ai-bot/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
isRecognisedDebugCommand,
getPromptParts,
isInDebugMode,
isCommandResultStatusApplied,
isToolResultStatusApplied,
getRoomEvents,
sendPromptAsDebugMessage,
constructHistory,
Expand Down Expand Up @@ -827,7 +827,7 @@ Common issues are:
if (
event.event.origin_server_ts! < startTime ||
!room ||
!isCommandResultStatusApplied(event)
!isToolResultStatusApplied(event)
) {
return;
}
Expand Down
16 changes: 8 additions & 8 deletions packages/ai-bot/tests/chat-titling-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ module('getLatestResultMessage', (hooks) => {
);

// Create a command result event that references the command request
const commandResultEvent = {
const toolResultEvent = {
getContent: () => ({
'm.relates_to': {
event_id: testEventId,
Expand All @@ -600,7 +600,7 @@ module('getLatestResultMessage', (hooks) => {
const result = getLatestResultMessage(
history,
'@aibot:localhost',
commandResultEvent,
toolResultEvent,
);

// Verify the function returns the expected message
Expand Down Expand Up @@ -649,7 +649,7 @@ module('getLatestResultMessage', (hooks) => {
];

// Create a command result event that references a non-existent command request
const commandResultEvent = {
const toolResultEvent = {
getContent: () => ({
'm.relates_to': {
event_id: 'test-event-id',
Expand All @@ -665,7 +665,7 @@ module('getLatestResultMessage', (hooks) => {
const result = getLatestResultMessage(
history,
'@aibot:localhost',
commandResultEvent,
toolResultEvent,
);

// Function should gracefully handle the missing command request and return an empty array
Expand Down Expand Up @@ -724,7 +724,7 @@ module('getLatestResultMessage', (hooks) => {
];

// Create a command result event that references the second command request
const commandResultEvent = {
const toolResultEvent = {
getContent: () => ({
'm.relates_to': {
event_id: testEventId,
Expand All @@ -740,7 +740,7 @@ module('getLatestResultMessage', (hooks) => {
const result = getLatestResultMessage(
history,
'@aibot:localhost',
commandResultEvent,
toolResultEvent,
);

// Verify the function returns the expected message based on the correct command
Expand Down Expand Up @@ -847,7 +847,7 @@ module('setTitle', () => {
];

// Create command result event
const commandResultEvent = {
const toolResultEvent = {
getContent: () => ({
'm.relates_to': {
event_id: testEventId,
Expand All @@ -866,7 +866,7 @@ module('setTitle', () => {
'test-room-id',
history,
'@aibot:localhost',
commandResultEvent,
toolResultEvent,
);
// The assertions are inside the mock matrixClient.setRoomName function
});
Expand Down
16 changes: 8 additions & 8 deletions packages/ai-bot/tests/code-patch-correctness-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
APP_BOXEL_TOOL_REQUESTS_KEY,
} from '@cardstack/runtime-common/matrix-constants';
import {
decodeCommandRequest,
type CommandRequest,
decodeToolRequest,
type ToolRequest,
} from '@cardstack/runtime-common/commands';

module('code patch correctness helpers', () => {
Expand Down Expand Up @@ -82,10 +82,10 @@ module('code patch correctness helpers', () => {
'Should request correctness checks for each file and card',
);
let decodedRequests = encodedRequests.map((request: any) =>
decodeCommandRequest(request),
decodeToolRequest(request),
);
let fileRequest = decodedRequests.find(
(request: Partial<CommandRequest>) =>
(request: Partial<ToolRequest>) =>
request.arguments?.attributes?.targetType === 'file',
);
assert.ok(fileRequest, 'Should include a file correctness request');
Expand All @@ -109,7 +109,7 @@ module('code patch correctness helpers', () => {
'File correctness check request should describe the file that changed',
);
let cardRequest = decodedRequests.find(
(request: Partial<CommandRequest>) =>
(request: Partial<ToolRequest>) =>
request.arguments?.attributes?.targetType === 'card',
);
assert.ok(cardRequest, 'Should include a card correctness request');
Expand Down Expand Up @@ -152,11 +152,11 @@ module('code patch correctness helpers', () => {
let [event] = client.getSentEvents();
let encodedRequests = event.content[APP_BOXEL_TOOL_REQUESTS_KEY];
let decodedRequests = encodedRequests.map((request: any) =>
decodeCommandRequest(request),
decodeToolRequest(request),
);

let fileRequest = decodedRequests.find(
(request: Partial<CommandRequest>) =>
(request: Partial<ToolRequest>) =>
request.arguments?.attributes?.targetType === 'file',
);
assert.strictEqual(
Expand All @@ -171,7 +171,7 @@ module('code patch correctness helpers', () => {
);

let cardRequest = decodedRequests.find(
(request: Partial<CommandRequest>) =>
(request: Partial<ToolRequest>) =>
request.arguments?.attributes?.targetType === 'card',
);
assert.strictEqual(
Expand Down
Loading
Loading