Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompts/node/panel/notebookVariables.tsx
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { BasePromptElementProps, PromptElement, PromptElementProps, PromptSizing, TextChunk, TokenLimit } from '@vscode/prompt-tsx';
7
import type * as vscode from 'vscode';
8
import { ILogService } from '../../../../platform/log/common/logService';
9
import { parseAndCleanStack } from '../../../../platform/notebook/common/helpers';
10
import { INotebookService, VariablesResult } from '../../../../platform/notebook/common/notebookService';
11
import { IPromptPathRepresentationService } from '../../../../platform/prompts/common/promptPathRepresentationService';
12
import { IWorkspaceService } from '../../../../platform/workspace/common/workspaceService';
13
import { getNotebookCellOutput, isJupyterNotebookUri } from '../../../../util/common/notebooks';
14
import { URI } from '../../../../util/vs/base/common/uri';
15
import { IPromptEndpoint } from '../base/promptRenderer';
16
import { Tag } from '../base/tag';
17
import { getCharLimit } from '../inline/summarizedDocument/summarizeDocumentHelpers';
18
import { Image } from './image';
19
20
type NotebookVariablesPromptProps = PromptElementProps<{
21
notebook: vscode.NotebookDocument;
22
}>;
23
24
interface InlineChatNotebookRuntimeState {
25
variables: VariablesResult[];
26
}
27
28
export class NotebookVariables extends PromptElement<NotebookVariablesPromptProps, InlineChatNotebookRuntimeState> {
29
constructor(
30
props: NotebookVariablesPromptProps,
31
@INotebookService private readonly notebookService: INotebookService,
32
@IPromptPathRepresentationService private readonly _promptPathRepresentationService: IPromptPathRepresentationService,
33
@ILogService private readonly logger: ILogService,
34
) {
35
super(props);
36
}
37
38
override async prepare(): Promise<InlineChatNotebookRuntimeState> {
39
try {
40
this.logger.trace(`Fetching notebook variables for ${this.props.notebook.uri.toString()}`);
41
const variables = await this.notebookService.getVariables(this.props.notebook.uri);
42
return { variables };
43
} catch (error) {
44
this.logger.error(`Failed to get notebook variables for ${this.props.notebook.uri.toString()}: ${error}`);
45
return { variables: [] };
46
}
47
}
48
49
render(state: InlineChatNotebookRuntimeState) {
50
const filePath = this._promptPathRepresentationService.getFilePath(this.props.notebook.uri);
51
const isJupyterNotebook = isJupyterNotebookUri(this.props.notebook.uri);
52
const notebookType = isJupyterNotebook ? 'Jupyter Notebook' : 'Notebook';
53
if (state.variables.length === 0) {
54
return (<></>);
55
}
56
57
return (
58
<TokenLimit max={16384}>
59
&lt;notebook-kernel-variables&gt;<br />
60
{state.variables.length !== 0 &&
61
<>
62
The following variables are present in the {notebookType} {filePath}:
63
{
64
state.variables.map((variable) => (
65
<>
66
<TextChunk>
67
Name: {variable.variable.name}<br />
68
{variable.variable.type && <>Type: {variable.variable.type}</>}<br />
69
</TextChunk>
70
</>
71
))
72
73
}
74
</>}
75
&lt;/notebook-kernel-variables&gt;<br />
76
</TokenLimit>
77
);
78
}
79
}
80
81
82
export interface INotebookCellOutputProps extends BasePromptElementProps {
83
outputUri: URI;
84
}
85
86
87
export class NotebookCellOutputVariable extends PromptElement<INotebookCellOutputProps> {
88
constructor(
89
props: PromptElementProps<INotebookCellOutputProps>,
90
@IWorkspaceService private readonly workspaceService: IWorkspaceService,
91
@IPromptPathRepresentationService private readonly promptPathRepresentationService: IPromptPathRepresentationService,
92
@IPromptEndpoint private readonly promptEndpoint: IPromptEndpoint
93
) {
94
super(props);
95
}
96
97
render(state: void, sizing: PromptSizing) {
98
const outputUri = this.props.outputUri;
99
const outputInfo = getNotebookCellOutput(outputUri, this.workspaceService.notebookDocuments);
100
if (!outputInfo) {
101
return;
102
}
103
const [notebook, cell, notebookCellOutput] = outputInfo;
104
const outputIndex = cell.outputs.indexOf(notebookCellOutput);
105
106
const allowedTextMimeTypes = ['text/plain', 'text/html', 'text/markdown', 'application/vnd.code.notebook.stdout', 'application/vnd.code.notebook.error', 'application/vnd.code.notebook.stderr'];
107
const item = notebookCellOutput.items.length ? notebookCellOutput.items[0] : undefined;
108
if (!item || (!allowedTextMimeTypes.includes(item.mime) && !item.mime.startsWith('image/'))) {
109
return <></>;
110
}
111
let text;
112
const cellIndex = cell.index;
113
const notebookPath = this.promptPathRepresentationService.getFilePath(notebook.uri);
114
if (item.mime === 'image/png') {
115
if (this.promptEndpoint.supportsVision) {
116
text = (
117
<>
118
<br />
119
<Tag name={`cell-output`} attrs={{ mimeType: item.mime, outputIndex, cellIndex, notebookPath }}>
120
<Image variableName={`cell-output-image-${outputIndex}`} variableValue={item.data} />
121
</Tag>
122
123
</>
124
);
125
} else {
126
text = (<>
127
<br />
128
The user attempted to attach an image which is the output from the cell with index: {cellIndex} of the notebook {notebookPath} but
129
images cannot be sent to this endpoint at this time and is therefore not attached. <br />
130
<br />
131
</>);
132
}
133
} else {
134
// force 1/4 of the token budget for text
135
const textSize = getCharLimit(sizing.tokenBudget / 4);
136
let textChunk = item.data.toString();
137
if (item.mime === 'application/vnd.code.notebook.stderr' || item.mime === 'application/vnd.code.notebook.error') {
138
textChunk = parseAndCleanStack(textChunk);
139
}
140
if (textChunk.length > textSize) {
141
textChunk = textChunk.substring(0, textSize);
142
}
143
text = (
144
<>
145
<br />
146
<Tag name={`notebook-cell-output`} attrs={{ mimeType: item.mime, outputIndex, cellIndex, notebookPath }}>
147
{textChunk}
148
</Tag>
149
</>
150
);
151
}
152
return text;
153
}
154
}
155
156
//#endregion
157
158