diff --git a/extensions/copilot/src/extension/tools/node/editNotebookTool.tsx b/extensions/copilot/src/extension/tools/node/editNotebookTool.tsx index 69455d8a5f0..348ddabfa3f 100644 --- a/extensions/copilot/src/extension/tools/node/editNotebookTool.tsx +++ b/extensions/copilot/src/extension/tools/node/editNotebookTool.tsx @@ -18,7 +18,7 @@ import { IPromptPathRepresentationService } from '../../../platform/prompts/comm import { ITelemetryService } from '../../../platform/telemetry/common/telemetry'; import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService'; import { createSha256Hash } from '../../../util/common/crypto'; -import { findCell, findNotebook } from '../../../util/common/notebooks'; +import { findCell, findNotebook, isJupyterNotebook } from '../../../util/common/notebooks'; import { findLast } from '../../../util/vs/base/common/arraysFind'; import { raceCancellation, StatefulPromise } from '../../../util/vs/base/common/async'; import { isCancellationError } from '../../../util/vs/base/common/errors'; @@ -317,6 +317,13 @@ export class EditNotebookTool implements ICopilotTool { if (newCode === undefined) { throw new ErrorWithTelemetrySafeReason('None of the edits were applied as newCode is required for insert operation', 'missingNewCode'); } + if (newCode.length && isJupyterNotebook(notebook)) { + if (newCode.startsWith('{') && newCode.includes('"cell_type') && newCode.includes('"source') && newCode.endsWith('}')) { + // Possible the entire notebook JSON was provided as newCode. + // This is not supported. + throw new ErrorWithTelemetrySafeReason('When inserting cell(s) do NOT provide the entire notebook JSON as newCode. Provide the code (as plain text) for the cell instead.', 'gotEntireNotebookJson'); + } + } break; case 'delete': if (!id) { diff --git a/extensions/copilot/src/util/common/notebooks.ts b/extensions/copilot/src/util/common/notebooks.ts index d62272b566c..c06231f2738 100644 --- a/extensions/copilot/src/util/common/notebooks.ts +++ b/extensions/copilot/src/util/common/notebooks.ts @@ -115,6 +115,10 @@ export function isJupyterNotebookUri(uri: vscode.Uri): boolean { return uri.path.endsWith('.ipynb'); } +export function isJupyterNotebook(notebook: vscode.NotebookDocument): boolean { + return notebook.notebookType === 'jupyter-notebook'; +} + export function serializeNotebookDocument(document: vscode.NotebookDocument, features: { cell_uri_fragment?: boolean } = {}): string { return JSON.stringify({