Skip to content

Commit 0e33530

Browse files
Handle bad slash commands as warnings (#1649)
* Handle unsupported slash commands with helpful warning instead of error - Added special handling for InvalidPromptError with 'Unknown command:' messages - Shows user-friendly warning dialog instead of scary error dialog with stack traces - Made error type check case-insensitive for robustness - Added tests for the new behavior - Updated changelog * Remove enable_deep_plan from test mocks after merge with main * Revert package-lock.json changes * Fix regex to specifically match slash commands with forward slash --------- Co-authored-by: teg-atlassian <tzewdie@atlassian.com>
1 parent 04a9374 commit 0e33530

File tree

3 files changed

+91
-0
lines changed

3 files changed

+91
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
- **RovoDev**: Fixed JSON parsing errors in ToolReturnMessage handling - added type checking before JSON.parse() to prevent "Input data should be a String" and invalid JSON errors
3636
- Added comprehensive test coverage for parseToolReturnMessage with both string and pre-parsed object inputs
37+
- Rovo Dev: Unsupported slash commands now show a helpful warning instead of an error dialog
3738

3839
## What's new in 4.0.22
3940

src/rovo-dev/rovoDevChatProvider.test.ts

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,5 +974,74 @@ describe('RovoDevChatProvider', () => {
974974
}),
975975
);
976976
});
977+
978+
it('should show warning instead of error for unsupported slash commands', async () => {
979+
const mockPrompt: RovoDevPrompt = {
980+
text: '/model',
981+
context: [],
982+
};
983+
984+
// Create a stream that returns an InvalidPromptError exception for unknown command
985+
const mockReadableStream = new ReadableStream({
986+
start(controller) {
987+
controller.enqueue(
988+
new TextEncoder().encode(
989+
'event: exception\ndata: {"message":"Unknown command: /model","type":"InvalidPromptError"}\n\n',
990+
),
991+
);
992+
controller.enqueue(new TextEncoder().encode('event: close\ndata: \n\n'));
993+
controller.close();
994+
},
995+
});
996+
const mockResponse = { body: mockReadableStream } as Response;
997+
mockApiClient.chat.mockResolvedValue(mockResponse);
998+
999+
await chatProvider.executeChat(mockPrompt, []);
1000+
1001+
// Should show warning dialog, not error
1002+
expect(mockWebview.postMessage).toHaveBeenCalledWith(
1003+
expect.objectContaining({
1004+
type: RovoDevProviderMessageType.ShowDialog,
1005+
message: expect.objectContaining({
1006+
event_kind: '_RovoDevDialog',
1007+
type: 'warning',
1008+
title: 'Unsupported Command',
1009+
text: 'The command /model is not supported.',
1010+
}),
1011+
}),
1012+
);
1013+
});
1014+
1015+
it('should extract command name from InvalidPromptError message', async () => {
1016+
const mockPrompt: RovoDevPrompt = {
1017+
text: '/unknowncommand',
1018+
context: [],
1019+
};
1020+
1021+
const mockReadableStream = new ReadableStream({
1022+
start(controller) {
1023+
controller.enqueue(
1024+
new TextEncoder().encode(
1025+
'event: exception\ndata: {"message":"Unknown command: /unknowncommand","type":"InvalidPromptError"}\n\n',
1026+
),
1027+
);
1028+
controller.enqueue(new TextEncoder().encode('event: close\ndata: \n\n'));
1029+
controller.close();
1030+
},
1031+
});
1032+
const mockResponse = { body: mockReadableStream } as Response;
1033+
mockApiClient.chat.mockResolvedValue(mockResponse);
1034+
1035+
await chatProvider.executeChat(mockPrompt, []);
1036+
1037+
expect(mockWebview.postMessage).toHaveBeenCalledWith(
1038+
expect.objectContaining({
1039+
type: RovoDevProviderMessageType.ShowDialog,
1040+
message: expect.objectContaining({
1041+
text: 'The command /unknowncommand is not supported.',
1042+
}),
1043+
}),
1044+
);
1045+
});
9771046
});
9781047
});

src/rovo-dev/rovoDevChatProvider.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,27 @@ export class RovoDevChatProvider {
549549
break;
550550

551551
case 'exception': {
552+
// Handle InvalidPromptError for unsupported slash commands as a warning instead of an error
553+
if (
554+
response.type.toLowerCase().includes('invalidprompt') &&
555+
response.message.includes('Unknown command:')
556+
) {
557+
// Extract the command name from the message (e.g., "Unknown command: /model" -> "/model")
558+
const commandMatch = response.message.match(/Unknown command:\s*(\/\S+)/);
559+
const command = commandMatch ? commandMatch[1] : 'the command you entered';
560+
561+
await webview.postMessage({
562+
type: RovoDevProviderMessageType.ShowDialog,
563+
message: {
564+
event_kind: '_RovoDevDialog',
565+
type: 'warning',
566+
title: 'Unsupported Command',
567+
text: `The command ${command} is not supported.`,
568+
},
569+
});
570+
break;
571+
}
572+
552573
RovoDevTelemetryProvider.logError(
553574
new Error(`${response.type} ${response.message}`),
554575
response.title || undefined,

0 commit comments

Comments
 (0)