@kispace-io/extension-monaco-editor 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +21 -0
- package/src/i18n.json +11 -0
- package/src/index.ts +16 -0
- package/src/js-programming-prompt.txt +20 -0
- package/src/k-monaco-editor.ts +342 -0
- package/src/monaco-editor-extension.ts +72 -0
- package/src/py-programming-prompt.txt +15 -0
- package/tsconfig.json +12 -0
package/package.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kispace-io/extension-monaco-editor",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./src/index.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./src/index.ts",
|
|
9
|
+
"types": "./src/index.ts"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@kispace-io/core": "*",
|
|
14
|
+
"@kispace-io/extension-python-runtime": "*",
|
|
15
|
+
"@kispace-io/extension-ai-system": "*",
|
|
16
|
+
"monaco-editor": "0.55.1"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"typescript": "^5.9.3"
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/i18n.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"namespace": "extensions",
|
|
3
|
+
"en": {
|
|
4
|
+
"EXT_MONACO_NAME": "Monaco Code Editor",
|
|
5
|
+
"EXT_MONACO_DESC": "Code editor with syntax highlighting, code completion, and Python execution support"
|
|
6
|
+
},
|
|
7
|
+
"de": {
|
|
8
|
+
"EXT_MONACO_NAME": "Monaco-Code-Editor",
|
|
9
|
+
"EXT_MONACO_DESC": "Code-Editor mit Syntaxhervorhebung, Code-Vervollständigung und Python-Ausführungsunterstützung"
|
|
10
|
+
}
|
|
11
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { extensionRegistry, i18nLazy, contributionRegistry, SYSTEM_LANGUAGE_BUNDLES } from '@kispace-io/core';
|
|
2
|
+
import bundle from './i18n.json';
|
|
3
|
+
|
|
4
|
+
contributionRegistry.registerContribution(SYSTEM_LANGUAGE_BUNDLES, bundle as any);
|
|
5
|
+
|
|
6
|
+
const t = i18nLazy('extensions');
|
|
7
|
+
|
|
8
|
+
extensionRegistry.registerExtension({
|
|
9
|
+
id: "system.monaco",
|
|
10
|
+
name: t('EXT_MONACO_NAME'),
|
|
11
|
+
description: t('EXT_MONACO_DESC'),
|
|
12
|
+
loader: () => import("./monaco-editor-extension"),
|
|
13
|
+
icon: "file-pen",
|
|
14
|
+
|
|
15
|
+
dependencies: ["system.pythonruntime"],
|
|
16
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
**JavaScript Programming Assistant:**
|
|
2
|
+
|
|
3
|
+
You are helping with JavaScript code. JavaScript code is executed in a worker.
|
|
4
|
+
|
|
5
|
+
**JavaScript-Specific Focus:**
|
|
6
|
+
- Help with JavaScript, OpenLayers usage, and module patterns
|
|
7
|
+
- When a user requests a starter module, provide this template:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
export default function ({ map, env, render, html, style, when, ref, createRef, events, settings }) {
|
|
11
|
+
const state = {};
|
|
12
|
+
return () => html`
|
|
13
|
+
<div>
|
|
14
|
+
<h3>Hello!</h3>
|
|
15
|
+
<button @click=${() => {}}>Click me</button>
|
|
16
|
+
</div>
|
|
17
|
+
`;
|
|
18
|
+
}
|
|
19
|
+
```
|
|
20
|
+
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import * as monaco from 'monaco-editor';
|
|
2
|
+
import styles from "monaco-editor/min/vs/editor/editor.main.css?raw";
|
|
3
|
+
import {customElement, property, state} from "lit/decorators.js";
|
|
4
|
+
import {KPart} from "@kispace-io/core";
|
|
5
|
+
import {css, html} from "lit";
|
|
6
|
+
import {createRef, ref} from "lit/directives/ref.js";
|
|
7
|
+
import {EditorInput, EditorContentProvider} from "@kispace-io/core";
|
|
8
|
+
import {styleMap} from "lit/directives/style-map.js";
|
|
9
|
+
import { PyEnv, pythonPackageManagerService } from "@kispace-io/extension-python-runtime";
|
|
10
|
+
import { workspaceService } from "@kispace-io/core";
|
|
11
|
+
import { logger } from '@kispace-io/core';
|
|
12
|
+
|
|
13
|
+
const workerMap: Record<string, string> = {
|
|
14
|
+
'json': new URL('monaco-editor/esm/vs/language/json/json.worker.js', import.meta.url).href,
|
|
15
|
+
'css': new URL('monaco-editor/esm/vs/language/css/css.worker.js', import.meta.url).href,
|
|
16
|
+
'scss': new URL('monaco-editor/esm/vs/language/css/css.worker.js', import.meta.url).href,
|
|
17
|
+
'less': new URL('monaco-editor/esm/vs/language/css/css.worker.js', import.meta.url).href,
|
|
18
|
+
'html': new URL('monaco-editor/esm/vs/language/html/html.worker.js', import.meta.url).href,
|
|
19
|
+
'handlebars': new URL('monaco-editor/esm/vs/language/html/html.worker.js', import.meta.url).href,
|
|
20
|
+
'razor': new URL('monaco-editor/esm/vs/language/html/html.worker.js', import.meta.url).href,
|
|
21
|
+
'typescript': new URL('monaco-editor/esm/vs/language/typescript/ts.worker.js', import.meta.url).href,
|
|
22
|
+
'javascript': new URL('monaco-editor/esm/vs/language/typescript/ts.worker.js', import.meta.url).href,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
self.MonacoEnvironment = {
|
|
26
|
+
getWorkerUrl(_: any, label: string) {
|
|
27
|
+
return workerMap[label] || new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url).href;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
@customElement('k-monaco-editor')
|
|
32
|
+
export class KMonacoEditor extends KPart implements EditorContentProvider {
|
|
33
|
+
@property({attribute: false})
|
|
34
|
+
public input?: EditorInput;
|
|
35
|
+
@property()
|
|
36
|
+
public readOnly: boolean = false;
|
|
37
|
+
|
|
38
|
+
private editorRef = createRef();
|
|
39
|
+
private editor?: any;
|
|
40
|
+
private model?: any;
|
|
41
|
+
|
|
42
|
+
@state()
|
|
43
|
+
private canExecute: boolean = false;
|
|
44
|
+
|
|
45
|
+
@state()
|
|
46
|
+
private pyenv?: PyEnv;
|
|
47
|
+
|
|
48
|
+
@state()
|
|
49
|
+
private requiredPackages: string[] = [];
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
protected doBeforeUI() {
|
|
53
|
+
const file = this.input!.data
|
|
54
|
+
this.canExecute = file.getName().endsWith(".py")
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
protected updated(changedProperties: Map<string, any>) {
|
|
58
|
+
super.updated(changedProperties);
|
|
59
|
+
|
|
60
|
+
if (changedProperties.has('canExecute') || changedProperties.has('pyenv')) {
|
|
61
|
+
this.updateToolbar();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
protected async doInitUI() {
|
|
66
|
+
const file = this.input!.data
|
|
67
|
+
const textContents = await file.getContents()
|
|
68
|
+
const container = this.editorRef.value as HTMLElement
|
|
69
|
+
const uri = monaco.Uri.file(file.getName())
|
|
70
|
+
this.model = monaco.editor.createModel(textContents, undefined, uri)
|
|
71
|
+
this.editor = monaco.editor.create(container, {
|
|
72
|
+
theme: 'vs-dark',
|
|
73
|
+
automaticLayout: false,
|
|
74
|
+
})
|
|
75
|
+
this.model.onDidChangeContent((_event: Event) => {
|
|
76
|
+
if (this.readOnly) {
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
this.markDirty(true)
|
|
80
|
+
})
|
|
81
|
+
this.editor.setModel(this.model)
|
|
82
|
+
|
|
83
|
+
if (this.canExecute) {
|
|
84
|
+
this.requiredPackages = this.parsePackagesFromContent(textContents as string)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
public getEditor() {
|
|
89
|
+
return this.editor
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
save(): void {
|
|
93
|
+
const value = this.model.getValue()
|
|
94
|
+
this.input?.data.saveContents(value)
|
|
95
|
+
this.markDirty(false)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
protected doClose() {
|
|
99
|
+
this.model?.dispose();
|
|
100
|
+
this.editor?.dispose()
|
|
101
|
+
this.model = undefined
|
|
102
|
+
this.editor = undefined
|
|
103
|
+
this.pyenv?.close()
|
|
104
|
+
this.pyenv = undefined
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private async onRunCode() {
|
|
108
|
+
if (!this.canExecute) {
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
if (!this.pyenv) {
|
|
112
|
+
await this.toggleConnection();
|
|
113
|
+
}
|
|
114
|
+
this.pyenv?.execCode(this.model.getValue())
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
public getLanguage() {
|
|
118
|
+
return this.model?.getLanguageId()?.toLowerCase() || null
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public getContent(): string | null {
|
|
122
|
+
if (!this.model) {
|
|
123
|
+
return null
|
|
124
|
+
}
|
|
125
|
+
return this.model.getValue()
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
public getSelection(): string | null {
|
|
129
|
+
if (!this.editor || !this.model) {
|
|
130
|
+
return null
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
const selection = this.editor.getSelection()
|
|
134
|
+
if (!selection || selection.isEmpty()) {
|
|
135
|
+
return null
|
|
136
|
+
}
|
|
137
|
+
return this.model.getValueInRange(selection) || null
|
|
138
|
+
} catch (err) {
|
|
139
|
+
return null
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
public getSnippet(lines: number = 5): { snippet: string; cursorLine: number } | null {
|
|
144
|
+
if (!this.editor || !this.model) {
|
|
145
|
+
return null
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const position = this.editor.getPosition()
|
|
149
|
+
if (!position) {
|
|
150
|
+
return null
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (isNaN(lines) || lines < 0) {
|
|
154
|
+
lines = 5
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const cursorLineNumber = position.lineNumber
|
|
158
|
+
const totalLines = this.model.getLineCount()
|
|
159
|
+
|
|
160
|
+
const startLine = Math.max(1, cursorLineNumber - lines)
|
|
161
|
+
const endLine = Math.min(totalLines, cursorLineNumber + lines)
|
|
162
|
+
|
|
163
|
+
const snippet = this.model.getValueInRange({
|
|
164
|
+
startLineNumber: startLine,
|
|
165
|
+
startColumn: 1,
|
|
166
|
+
endLineNumber: endLine,
|
|
167
|
+
endColumn: this.model.getLineMaxColumn(endLine)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
snippet,
|
|
172
|
+
cursorLine: cursorLineNumber
|
|
173
|
+
}
|
|
174
|
+
} catch (err) {
|
|
175
|
+
return null
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public getFilePath(): string | null {
|
|
180
|
+
return this.input?.data?.getWorkspacePath() || null
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
protected renderToolbar() {
|
|
184
|
+
if (!this.canExecute) {
|
|
185
|
+
return html``;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return html`
|
|
189
|
+
<wa-button @click=${() => this.onRunCode()} title="Run code"
|
|
190
|
+
?disabled="${!this.canExecute}" appearance="plain" size="small">
|
|
191
|
+
<wa-icon name="play" label="Run code"></wa-icon>
|
|
192
|
+
</wa-button>
|
|
193
|
+
<wa-button @click=${() => this.toggleConnection()}
|
|
194
|
+
style="${styleMap({color: this.pyenv ? "var(--wa-color-success-fill-loud)" : "var(--wa-color-danger-fill-loud)"})}"
|
|
195
|
+
title="(Re)Connect to execution environment"
|
|
196
|
+
?disabled="${!this.canExecute}"
|
|
197
|
+
appearance="plain" size="small">
|
|
198
|
+
<wa-icon name="circle" label="Connection status"></wa-icon>
|
|
199
|
+
</wa-button>
|
|
200
|
+
<wa-button
|
|
201
|
+
size="small"
|
|
202
|
+
appearance="plain"
|
|
203
|
+
@click=${() => this.openPackageManager()}
|
|
204
|
+
title="Manage required Python packages">
|
|
205
|
+
<wa-icon name="box" label="Packages"></wa-icon>
|
|
206
|
+
Packages
|
|
207
|
+
</wa-button>
|
|
208
|
+
`;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private async toggleConnection() {
|
|
212
|
+
if (this.pyenv) {
|
|
213
|
+
this.pyenv.close()
|
|
214
|
+
this.pyenv = undefined
|
|
215
|
+
}
|
|
216
|
+
if (this.model.getLanguageId() !== "python") {
|
|
217
|
+
logger.error("Language not supported: " + this.model.getLanguageId());
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
this.pyenv = new PyEnv()
|
|
221
|
+
const workspace = await workspaceService.getWorkspace()
|
|
222
|
+
await this.pyenv.init(workspace!)
|
|
223
|
+
|
|
224
|
+
if (this.requiredPackages.length > 0) {
|
|
225
|
+
try {
|
|
226
|
+
await this.pyenv.loadPackages(this.requiredPackages)
|
|
227
|
+
} catch (error) {
|
|
228
|
+
logger.error("Failed to load required packages: " + String(error))
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private parsePackagesFromContent(content: string): string[] {
|
|
234
|
+
const lines = content.split('\n')
|
|
235
|
+
const magicCommentRegex = /^#\s*@gs-packages:\s*(.+)$/i
|
|
236
|
+
|
|
237
|
+
for (const line of lines) {
|
|
238
|
+
const match = line.match(magicCommentRegex)
|
|
239
|
+
if (match) {
|
|
240
|
+
return match[1]
|
|
241
|
+
.split(',')
|
|
242
|
+
.map(pkg => pkg.trim())
|
|
243
|
+
.filter(pkg => pkg.length > 0)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return []
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
private updatePackagesInContent(): void {
|
|
251
|
+
if (!this.model) return
|
|
252
|
+
|
|
253
|
+
const content = this.model.getValue()
|
|
254
|
+
const lines = content.split('\n')
|
|
255
|
+
const magicCommentRegex = /^#\s*@gs-packages:/i
|
|
256
|
+
|
|
257
|
+
let magicCommentLineIndex = -1
|
|
258
|
+
for (let i = 0; i < lines.length; i++) {
|
|
259
|
+
if (magicCommentRegex.test(lines[i])) {
|
|
260
|
+
magicCommentLineIndex = i
|
|
261
|
+
break
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const newMagicComment = this.requiredPackages.length > 0
|
|
266
|
+
? `# @gs-packages: ${this.requiredPackages.join(', ')}`
|
|
267
|
+
: null
|
|
268
|
+
|
|
269
|
+
if (newMagicComment) {
|
|
270
|
+
if (magicCommentLineIndex >= 0) {
|
|
271
|
+
lines[magicCommentLineIndex] = newMagicComment
|
|
272
|
+
} else {
|
|
273
|
+
const insertIndex = lines[0]?.startsWith('#!') ? 1 : 0
|
|
274
|
+
lines.splice(insertIndex, 0, newMagicComment)
|
|
275
|
+
}
|
|
276
|
+
} else if (magicCommentLineIndex >= 0) {
|
|
277
|
+
lines.splice(magicCommentLineIndex, 1)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const newContent = lines.join('\n')
|
|
281
|
+
if (newContent !== content) {
|
|
282
|
+
this.model.setValue(newContent)
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private openPackageManager() {
|
|
287
|
+
pythonPackageManagerService.showPackageManager({
|
|
288
|
+
packages: this.requiredPackages,
|
|
289
|
+
pyenv: this.pyenv,
|
|
290
|
+
onPackageAdded: (packageName: string) => {
|
|
291
|
+
if (!this.requiredPackages.includes(packageName)) {
|
|
292
|
+
this.requiredPackages = [...this.requiredPackages, packageName]
|
|
293
|
+
this.updatePackagesInContent()
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
onPackageRemoved: (packageName: string) => {
|
|
297
|
+
this.requiredPackages = this.requiredPackages.filter(pkg => pkg !== packageName)
|
|
298
|
+
this.updatePackagesInContent()
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
render() {
|
|
304
|
+
return html`
|
|
305
|
+
<style>
|
|
306
|
+
${styles}
|
|
307
|
+
</style>
|
|
308
|
+
<div class="monaco-editor-container" ${ref(this.editorRef)}>
|
|
309
|
+
</div>
|
|
310
|
+
`
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
static styles = css`
|
|
314
|
+
:host {
|
|
315
|
+
display: flex;
|
|
316
|
+
flex-direction: column;
|
|
317
|
+
position: relative;
|
|
318
|
+
width: 100%;
|
|
319
|
+
height: 100%;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
input.prompt {
|
|
323
|
+
flex: 1;
|
|
324
|
+
font-size: large;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
div.monaco-editor-container {
|
|
328
|
+
position: absolute;
|
|
329
|
+
top: 0;
|
|
330
|
+
left: 0;
|
|
331
|
+
right: 0;
|
|
332
|
+
bottom: 0;
|
|
333
|
+
}
|
|
334
|
+
`;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
declare global {
|
|
338
|
+
interface HTMLElementTagNameMap {
|
|
339
|
+
'k-monaco-editor': KMonacoEditor
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import {html} from "lit";
|
|
2
|
+
import {EditorInput, editorRegistry} from "@kispace-io/core";
|
|
3
|
+
import {File} from "@kispace-io/core";
|
|
4
|
+
import {contributionRegistry} from "@kispace-io/core";
|
|
5
|
+
import {CID_PROMPT_ENHANCERS, type PromptEnhancer, type PromptEnhancerContribution} from "@kispace-io/extension-ai-system";
|
|
6
|
+
import type {ExecutionContext} from "@kispace-io/core";
|
|
7
|
+
import PYTHON_PROMPT from "./py-programming-prompt.txt?raw";
|
|
8
|
+
import JAVASCRIPT_PROMPT from "./js-programming-prompt.txt?raw";
|
|
9
|
+
|
|
10
|
+
editorRegistry.registerEditorInputHandler({
|
|
11
|
+
lazyInit: async () => {
|
|
12
|
+
await import('./k-monaco-editor');
|
|
13
|
+
},
|
|
14
|
+
canHandle: input => input instanceof File,
|
|
15
|
+
handle: async (input: File) => {
|
|
16
|
+
const editorInput = {
|
|
17
|
+
title: input.getName(),
|
|
18
|
+
data: input,
|
|
19
|
+
key: input.getName(),
|
|
20
|
+
editorId: "monaco-editor",
|
|
21
|
+
icon: "file-pen",
|
|
22
|
+
noOverflow: false,
|
|
23
|
+
state: {},
|
|
24
|
+
} as EditorInput
|
|
25
|
+
editorInput.widgetFactory = () => html`
|
|
26
|
+
<k-monaco-editor .input=${editorInput}></k-monaco-editor>`
|
|
27
|
+
return editorInput;
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
// Helper to check if active editor is a Monaco editor with specific language
|
|
32
|
+
function isMonacoEditorWithLanguage(context: ExecutionContext, language: string): boolean {
|
|
33
|
+
const activeEditor = context.activeEditor as any;
|
|
34
|
+
return activeEditor &&
|
|
35
|
+
typeof activeEditor.getEditor === 'function' &&
|
|
36
|
+
typeof activeEditor.getLanguage === 'function' &&
|
|
37
|
+
activeEditor.getLanguage() === language;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Python programming prompt enhancer
|
|
41
|
+
const pythonPromptEnhancer: PromptEnhancer = {
|
|
42
|
+
priority: 50,
|
|
43
|
+
enhance: async (prompt: string, context: ExecutionContext) => {
|
|
44
|
+
if (!isMonacoEditorWithLanguage(context, 'python')) {
|
|
45
|
+
return prompt;
|
|
46
|
+
}
|
|
47
|
+
return `${prompt}\n\n${PYTHON_PROMPT}`;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// JavaScript programming prompt enhancer
|
|
52
|
+
const javascriptPromptEnhancer: PromptEnhancer = {
|
|
53
|
+
priority: 50,
|
|
54
|
+
enhance: async (prompt: string, context: ExecutionContext) => {
|
|
55
|
+
if (!isMonacoEditorWithLanguage(context, 'javascript')) {
|
|
56
|
+
return prompt;
|
|
57
|
+
}
|
|
58
|
+
return `${prompt}\n\n${JAVASCRIPT_PROMPT}`;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Register prompt enhancers for programming languages
|
|
63
|
+
contributionRegistry.registerContribution(CID_PROMPT_ENHANCERS, {
|
|
64
|
+
label: "Python Programming Enhancer",
|
|
65
|
+
enhancer: pythonPromptEnhancer
|
|
66
|
+
} as PromptEnhancerContribution);
|
|
67
|
+
|
|
68
|
+
contributionRegistry.registerContribution(CID_PROMPT_ENHANCERS, {
|
|
69
|
+
label: "JavaScript Programming Enhancer",
|
|
70
|
+
enhancer: javascriptPromptEnhancer
|
|
71
|
+
} as PromptEnhancerContribution);
|
|
72
|
+
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
**Python Programming Assistant:**
|
|
2
|
+
|
|
3
|
+
You are helping with Python code. Python code is executed in the browser using Pyodide.
|
|
4
|
+
|
|
5
|
+
**Python-Specific Responsibilities:**
|
|
6
|
+
- Explain Python code and help debug Python errors
|
|
7
|
+
- Help with `js` module interaction: calling JavaScript functions from Python and passing data between Python and JavaScript
|
|
8
|
+
- Provide Python code examples
|
|
9
|
+
- Remember code runs in a browser environment (Pyodide) - be mindful of browser limitations
|
|
10
|
+
|
|
11
|
+
**Python Environment:**
|
|
12
|
+
- Working directory is `/workspace` (linked to user's local file system)
|
|
13
|
+
- Install packages by adding them to `requirements.txt` in the workspace
|
|
14
|
+
- Packages in `requirements.txt` are automatically installed before code execution
|
|
15
|
+
|