Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
25 changes: 25 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@
"dark": "images/dark/play.svg"
}
},
{
"command": "mdb.exportCodeToPlayground",
"title": "Export Code to Playground"
},
{
"command": "mdb.exportToPython",
"title": "MongoDB: Export To Python 3"
Expand Down Expand Up @@ -747,6 +751,17 @@
"when": "mdb.isPlayground == true"
}
],
"mdb.copilot": [
{
"command": "mdb.exportCodeToPlayground"
}
],
"editor/context": [
{
"submenu": "mdb.copilot",
"group": "1_main@2"
}
],
"commandPalette": [
{
"command": "mdb.selectDatabaseWithParticipant",
Expand Down Expand Up @@ -948,6 +963,10 @@
"command": "mdb.runPlayground",
"when": "false"
},
{
"command": "mdb.exportCodeToPlayground",
"when": "false"
},
{
"command": "mdb.createIndexFromTreeView",
"when": "false"
Expand Down Expand Up @@ -994,6 +1013,12 @@
}
]
},
"submenus": [
{
"id": "mdb.copilot",
"label": "MongoDB Copilot"
}
],
"keybindings": [
{
"command": "mdb.runSelectedPlaygroundBlocks",
Expand Down
1 change: 1 addition & 0 deletions src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ enum EXTENSION_COMMANDS {
MDB_RUN_SELECTED_PLAYGROUND_BLOCKS = 'mdb.runSelectedPlaygroundBlocks',
MDB_RUN_ALL_PLAYGROUND_BLOCKS = 'mdb.runAllPlaygroundBlocks',
MDB_RUN_ALL_OR_SELECTED_PLAYGROUND_BLOCKS = 'mdb.runPlayground',
MDB_EXPORT_CODE_TO_PLAYGROUND = 'mdb.exportCodeToPlayground',

MDB_FIX_THIS_INVALID_INTERACTIVE_SYNTAX = 'mdb.fixThisInvalidInteractiveSyntax',
MDB_FIX_ALL_INVALID_INTERACTIVE_SYNTAX = 'mdb.fixAllInvalidInteractiveSyntax',
Expand Down
34 changes: 17 additions & 17 deletions src/editors/playgroundController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -492,33 +492,33 @@ export default class PlaygroundController {
}

try {
const progressResult = await vscode.window.withProgress(
return await vscode.window.withProgress(
{
location: ProgressLocation.Notification,
title: 'Running MongoDB playground...',
cancellable: true,
},
async (progress, token) => {
token.onCancellationRequested(() => {
// If a user clicked the cancel button terminate all playground scripts.
this._languageServerController.cancelAll();

return { result: undefined };
async (progress, token): Promise<ShellEvaluateResult> => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
return new Promise(async (resolve, reject) => {
token.onCancellationRequested(() => {
// If a user clicked the cancel button terminate all playground scripts.
this._languageServerController.cancelAll();
return resolve({ result: undefined });
});

try {
// Run all playground scripts.
const result = await this._evaluate(codeToEvaluate);
return resolve(result);
} catch (error) {
return reject(error);
}
});

// Run all playground scripts.
const result: ShellEvaluateResult = await this._evaluate(
codeToEvaluate
);

return result;
}
);

return progressResult;
} catch (error) {
log.error('Evaluating playground with cancel modal failed', error);

return { result: undefined };
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/mdbExtensionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ export default class MDBExtensionController implements vscode.Disposable {
EXTENSION_COMMANDS.MDB_RUN_ALL_OR_SELECTED_PLAYGROUND_BLOCKS,
() => this._playgroundController.runAllOrSelectedPlaygroundBlocks()
);
this.registerCommand(EXTENSION_COMMANDS.MDB_EXPORT_CODE_TO_PLAYGROUND, () =>
this._participantController.exportCodeToPlayground()
);

this.registerCommand(
EXTENSION_COMMANDS.MDB_FIX_THIS_INVALID_INTERACTIVE_SYNTAX,
Expand Down
84 changes: 80 additions & 4 deletions src/participant/participant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import EXTENSION_COMMANDS from '../commands';
import type { StorageController } from '../storage';
import { StorageVariables } from '../storage';
import { GenericPrompt, isPromptEmpty } from './prompts/generic';
import { ExportToPlaygroundPrompt } from './prompts/exportToPlayground';
import type { ChatResult } from './constants';
import {
askToConnectChatResult,
Expand Down Expand Up @@ -42,6 +43,7 @@ import {
} from '../telemetry/telemetryService';
import { DocsChatbotAIService } from './docsChatbotAIService';
import type TelemetryService from '../telemetry/telemetryService';
import formatError from '../utils/formatError';

const log = createLogger('participant');

Expand Down Expand Up @@ -132,7 +134,7 @@ export default class ParticipantController {
return this._participant;
}

handleError(err: any, command: string): never {
handleError(err: any, command: string): void {
let errorCode: string | undefined;
let errorName: ParticipantErrorTypes;
// Making the chat request might fail because
Expand Down Expand Up @@ -168,9 +170,6 @@ export default class ParticipantController {
error_name: errorName,
}
);

// Re-throw other errors so they show up in the UI.
throw err;
}

/**
Expand Down Expand Up @@ -1201,6 +1200,81 @@ export default class ParticipantController {
});
}

async exportCodeToPlayground(): Promise<boolean> {
const activeTextEditor = vscode.window.activeTextEditor;
if (!activeTextEditor) {
await vscode.window.showErrorMessage('Active editor not found.');
return Promise.resolve(false);
}

const sortedSelections = Array.from(activeTextEditor.selections).sort(
(a, b) => a.start.compareTo(b.start)
);
const selectedText = sortedSelections
.map((selection) => activeTextEditor.document.getText(selection))
.join('\n');
const code =
selectedText || activeTextEditor.document.getText().trim() || '';
try {
const progressResult = await vscode.window.withProgress(
{
location: vscode.ProgressLocation.Notification,
title: 'Exporting code to a playground...',
cancellable: true,
},
async (progress, token): Promise<string | undefined> => {
// eslint-disable-next-line @typescript-eslint/no-misused-promises
return new Promise(async (resolve, reject) => {
token.onCancellationRequested(() => {
void vscode.window.showInformationMessage(
'The running export to a playground operation was canceled.'
);
return reject();
});

const messages = ExportToPlaygroundPrompt.buildMessages(code);
try {
const responseContent = await this.getChatResponseContent({
messages,
token,
});
return resolve(responseContent);
} catch (error) {
return reject(error);
}
});
}
);

if (progressResult?.includes("Sorry, I can't assist with that.")) {
void vscode.window.showErrorMessage("Sorry, I can't assist with that.");
return Promise.resolve(false);
}

if (progressResult) {
const runnableContent = getRunnableContentFromString(progressResult);
if (runnableContent) {
await vscode.commands.executeCommand(
EXTENSION_COMMANDS.OPEN_PARTICIPANT_QUERY_IN_PLAYGROUND,
{
runnableContent,
}
);
}
}

return Promise.resolve(true);
} catch (error) {
this.handleError(error, 'exportToPlayground');
await vscode.window.showErrorMessage(
`An error occurred exporting to a playground: ${
formatError(error).message
}`
);
return Promise.resolve(false);
}
}

async chatHandler(
...args: [
vscode.ChatRequest,
Expand Down Expand Up @@ -1249,6 +1323,8 @@ Please see our [FAQ](https://www.mongodb.com/docs/generative-ai-faq/) for more i
}
} catch (e) {
this.handleError(e, request.command || 'generic');
// Re-throw other errors so they show up in the UI.
throw e;
}
}

Expand Down
31 changes: 31 additions & 0 deletions src/participant/prompts/exportToPlayground.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import * as vscode from 'vscode';

export class ExportToPlaygroundPrompt {
static getAssistantPrompt(): vscode.LanguageModelChatMessage {
const prompt = `You are a MongoDB expert.
Your task is to help the user build MongoDB queries and aggregation pipelines that perform their task.
You convert user's code written in any programming language to the MongoDB Shell syntax.
Take a user promt as an input string and translate it to the MongoDB Shell language.
Keep your response concise.
You should suggest queries that are performant and correct.
Respond with markdown, suggest code in a Markdown code block that begins with \`\`\`javascript and ends with \`\`\`.
Respond in MongoDB shell syntax using the \`\`\`javascript code block syntax.`;

// eslint-disable-next-line new-cap
return vscode.LanguageModelChatMessage.Assistant(prompt);
}

static getUserPrompt(prompt: string): vscode.LanguageModelChatMessage {
// eslint-disable-next-line new-cap
return vscode.LanguageModelChatMessage.User(prompt);
}

static buildMessages(prompt: string): vscode.LanguageModelChatMessage[] {
const messages = [
ExportToPlaygroundPrompt.getAssistantPrompt(),
ExportToPlaygroundPrompt.getUserPrompt(prompt),
];

return messages;
}
}
Loading