@kispace-io/extension-monaco-editor 0.8.0 → 0.8.2

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.
@@ -1,4 +1,4 @@
1
- {
1
+ declare const _default: {
2
2
  "namespace": "extensions",
3
3
  "en": {
4
4
  "EXT_MONACO_NAME": "Monaco Code Editor",
@@ -8,4 +8,6 @@
8
8
  "EXT_MONACO_NAME": "Monaco-Code-Editor",
9
9
  "EXT_MONACO_DESC": "Code-Editor mit Syntaxhervorhebung, Code-Vervollständigung und Python-Ausführungsunterstützung"
10
10
  }
11
- }
11
+ };
12
+
13
+ export default _default;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ import { contributionRegistry, SYSTEM_LANGUAGE_BUNDLES, i18nLazy, extensionRegistry } from "@kispace-io/core";
2
+ const namespace = "extensions";
3
+ const en = { "EXT_MONACO_NAME": "Monaco Code Editor", "EXT_MONACO_DESC": "Code editor with syntax highlighting, code completion, and Python execution support" };
4
+ const de = { "EXT_MONACO_NAME": "Monaco-Code-Editor", "EXT_MONACO_DESC": "Code-Editor mit Syntaxhervorhebung, Code-Vervollständigung und Python-Ausführungsunterstützung" };
5
+ const bundle = {
6
+ namespace,
7
+ en,
8
+ de
9
+ };
10
+ contributionRegistry.registerContribution(SYSTEM_LANGUAGE_BUNDLES, bundle);
11
+ const t = i18nLazy("extensions");
12
+ extensionRegistry.registerExtension({
13
+ id: "system.monaco",
14
+ name: t("EXT_MONACO_NAME"),
15
+ description: t("EXT_MONACO_DESC"),
16
+ loader: () => import("./monaco-editor-extension-B5XEGKAr.js"),
17
+ icon: "file-pen",
18
+ dependencies: ["system.pythonruntime"]
19
+ });
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["import { extensionRegistry, i18nLazy, contributionRegistry, SYSTEM_LANGUAGE_BUNDLES } from '@kispace-io/core';\nimport bundle from './i18n.json';\n\ncontributionRegistry.registerContribution(SYSTEM_LANGUAGE_BUNDLES, bundle as any);\n\nconst t = i18nLazy('extensions');\n\nextensionRegistry.registerExtension({\n id: \"system.monaco\",\n name: t('EXT_MONACO_NAME'),\n description: t('EXT_MONACO_DESC'),\n loader: () => import(\"./monaco-editor-extension\"),\n icon: \"file-pen\",\n \n dependencies: [\"system.pythonruntime\"],\n});\n"],"names":[],"mappings":";;;;;;;;;AAGA,qBAAqB,qBAAqB,yBAAyB,MAAa;AAEhF,MAAM,IAAI,SAAS,YAAY;AAE/B,kBAAkB,kBAAkB;AAAA,EAClC,IAAI;AAAA,EACJ,MAAM,EAAE,iBAAiB;AAAA,EACzB,aAAa,EAAE,iBAAiB;AAAA,EAChC,QAAQ,MAAM,OAAO,uCAA2B;AAAA,EAChD,MAAM;AAAA,EAEN,cAAc,CAAC,sBAAsB;AACvC,CAAC;"}
@@ -0,0 +1,309 @@
1
+ import * as monaco from "monaco-editor";
2
+ import styles from "monaco-editor/min/vs/editor/editor.main.css?raw";
3
+ import { property, state, customElement } from "lit/decorators.js";
4
+ import { KPart, logger, workspaceService } from "@kispace-io/core";
5
+ import { css, html } from "lit";
6
+ import { createRef, ref } from "lit/directives/ref.js";
7
+ import { styleMap } from "lit/directives/style-map.js";
8
+ import { PyEnv, pythonPackageManagerService } from "@kispace-io/extension-python-runtime/api";
9
+ var __defProp = Object.defineProperty;
10
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
+ var __decorateClass = (decorators, target, key, kind) => {
12
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
13
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
14
+ if (decorator = decorators[i])
15
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
16
+ if (kind && result) __defProp(target, key, result);
17
+ return result;
18
+ };
19
+ const workerMap = {
20
+ "json": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgSlNPTldvcmtlciB9IGZyb20gJy4vanNvbldvcmtlci5qcyc7CgpzZWxmLm9ubWVzc2FnZSA9ICgpID0+IHsKICBpbml0aWFsaXplKChjdHgsIGNyZWF0ZURhdGEpID0+IHsKICAgIHJldHVybiBuZXcgSlNPTldvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
21
+ "css": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgQ1NTV29ya2VyIH0gZnJvbSAnLi9jc3NXb3JrZXIuanMnOwoKc2VsZi5vbm1lc3NhZ2UgPSAoKSA9PiB7CiAgaW5pdGlhbGl6ZSgoY3R4LCBjcmVhdGVEYXRhKSA9PiB7CiAgICByZXR1cm4gbmV3IENTU1dvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
22
+ "scss": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgQ1NTV29ya2VyIH0gZnJvbSAnLi9jc3NXb3JrZXIuanMnOwoKc2VsZi5vbm1lc3NhZ2UgPSAoKSA9PiB7CiAgaW5pdGlhbGl6ZSgoY3R4LCBjcmVhdGVEYXRhKSA9PiB7CiAgICByZXR1cm4gbmV3IENTU1dvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
23
+ "less": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgQ1NTV29ya2VyIH0gZnJvbSAnLi9jc3NXb3JrZXIuanMnOwoKc2VsZi5vbm1lc3NhZ2UgPSAoKSA9PiB7CiAgaW5pdGlhbGl6ZSgoY3R4LCBjcmVhdGVEYXRhKSA9PiB7CiAgICByZXR1cm4gbmV3IENTU1dvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
24
+ "html": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgSFRNTFdvcmtlciB9IGZyb20gJy4vaHRtbFdvcmtlci5qcyc7CgpzZWxmLm9ubWVzc2FnZSA9ICgpID0+IHsKICBpbml0aWFsaXplKChjdHgsIGNyZWF0ZURhdGEpID0+IHsKICAgIHJldHVybiBuZXcgSFRNTFdvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
25
+ "handlebars": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgSFRNTFdvcmtlciB9IGZyb20gJy4vaHRtbFdvcmtlci5qcyc7CgpzZWxmLm9ubWVzc2FnZSA9ICgpID0+IHsKICBpbml0aWFsaXplKChjdHgsIGNyZWF0ZURhdGEpID0+IHsKICAgIHJldHVybiBuZXcgSFRNTFdvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
26
+ "razor": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgSFRNTFdvcmtlciB9IGZyb20gJy4vaHRtbFdvcmtlci5qcyc7CgpzZWxmLm9ubWVzc2FnZSA9ICgpID0+IHsKICBpbml0aWFsaXplKChjdHgsIGNyZWF0ZURhdGEpID0+IHsKICAgIHJldHVybiBuZXcgSFRNTFdvcmtlcihjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9Owo=", import.meta.url).href,
27
+ "typescript": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0ICogYXMgdHlwZXNjcmlwdFNlcnZpY2VzIGZyb20gJy4vbGliL3R5cGVzY3JpcHRTZXJ2aWNlcy5qcyc7CmV4cG9ydCB7IHR5cGVzY3JpcHRTZXJ2aWNlcyBhcyB0cyB9OwppbXBvcnQgeyBjcmVhdGUgfSBmcm9tICcuL3RzV29ya2VyLmpzJzsKZXhwb3J0IHsgVHlwZVNjcmlwdFdvcmtlciB9IGZyb20gJy4vdHNXb3JrZXIuanMnOwpleHBvcnQgeyBsaWJGaWxlTWFwIH0gZnJvbSAnLi9saWIvbGliLmpzJzsKCnNlbGYub25tZXNzYWdlID0gKCkgPT4gewogIGluaXRpYWxpemUoKGN0eCwgY3JlYXRlRGF0YSkgPT4gewogICAgcmV0dXJuIGNyZWF0ZShjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9OwoKZXhwb3J0IHsgY3JlYXRlLCBpbml0aWFsaXplIH07Cg==", import.meta.url).href,
28
+ "javascript": new URL("data:text/javascript;base64,aW1wb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uLy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0ICogYXMgdHlwZXNjcmlwdFNlcnZpY2VzIGZyb20gJy4vbGliL3R5cGVzY3JpcHRTZXJ2aWNlcy5qcyc7CmV4cG9ydCB7IHR5cGVzY3JpcHRTZXJ2aWNlcyBhcyB0cyB9OwppbXBvcnQgeyBjcmVhdGUgfSBmcm9tICcuL3RzV29ya2VyLmpzJzsKZXhwb3J0IHsgVHlwZVNjcmlwdFdvcmtlciB9IGZyb20gJy4vdHNXb3JrZXIuanMnOwpleHBvcnQgeyBsaWJGaWxlTWFwIH0gZnJvbSAnLi9saWIvbGliLmpzJzsKCnNlbGYub25tZXNzYWdlID0gKCkgPT4gewogIGluaXRpYWxpemUoKGN0eCwgY3JlYXRlRGF0YSkgPT4gewogICAgcmV0dXJuIGNyZWF0ZShjdHgsIGNyZWF0ZURhdGEpOwogIH0pOwp9OwoKZXhwb3J0IHsgY3JlYXRlLCBpbml0aWFsaXplIH07Cg==", import.meta.url).href
29
+ };
30
+ self.MonacoEnvironment = {
31
+ getWorkerUrl(_, label) {
32
+ return workerMap[label] || new URL("data:text/javascript;base64,aW1wb3J0IHsgaXNXb3JrZXJJbml0aWFsaXplZCB9IGZyb20gJy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKZXhwb3J0IHsgaW5pdGlhbGl6ZSB9IGZyb20gJy4uL2NvbW1vbi9pbml0aWFsaXplLmpzJzsKaW1wb3J0IHsgc3RhcnQgfSBmcm9tICcuL2VkaXRvci53b3JrZXIuc3RhcnQuanMnOwoKc2VsZi5vbm1lc3NhZ2UgPSAoKSA9PiB7CiAgaWYgKCFpc1dvcmtlckluaXRpYWxpemVkKCkpIHsKICAgIHN0YXJ0KCgpID0+IHsKICAgICAgcmV0dXJuIHt9OwogICAgfSk7CiAgfQp9Owo=", import.meta.url).href;
33
+ }
34
+ };
35
+ let KMonacoEditor = class extends KPart {
36
+ constructor() {
37
+ super(...arguments);
38
+ this.readOnly = false;
39
+ this.editorRef = createRef();
40
+ this.canExecute = false;
41
+ this.requiredPackages = [];
42
+ }
43
+ doBeforeUI() {
44
+ const file = this.input.data;
45
+ this.canExecute = file.getName().endsWith(".py");
46
+ }
47
+ updated(changedProperties) {
48
+ super.updated(changedProperties);
49
+ if (changedProperties.has("canExecute") || changedProperties.has("pyenv")) {
50
+ this.updateToolbar();
51
+ }
52
+ }
53
+ async doInitUI() {
54
+ const file = this.input.data;
55
+ const textContents = await file.getContents();
56
+ const container = this.editorRef.value;
57
+ const uri = monaco.Uri.file(file.getName());
58
+ this.model = monaco.editor.createModel(textContents, void 0, uri);
59
+ this.editor = monaco.editor.create(container, {
60
+ theme: "vs-dark",
61
+ automaticLayout: false
62
+ });
63
+ this.model.onDidChangeContent((_event) => {
64
+ if (this.readOnly) {
65
+ return;
66
+ }
67
+ this.markDirty(true);
68
+ });
69
+ this.editor.setModel(this.model);
70
+ if (this.canExecute) {
71
+ this.requiredPackages = this.parsePackagesFromContent(textContents);
72
+ }
73
+ }
74
+ getEditor() {
75
+ return this.editor;
76
+ }
77
+ save() {
78
+ const value = this.model.getValue();
79
+ this.input?.data.saveContents(value);
80
+ this.markDirty(false);
81
+ }
82
+ doClose() {
83
+ this.model?.dispose();
84
+ this.editor?.dispose();
85
+ this.model = void 0;
86
+ this.editor = void 0;
87
+ this.pyenv?.close();
88
+ this.pyenv = void 0;
89
+ }
90
+ async onRunCode() {
91
+ if (!this.canExecute) {
92
+ return;
93
+ }
94
+ if (!this.pyenv) {
95
+ await this.toggleConnection();
96
+ }
97
+ this.pyenv?.execCode(this.model.getValue());
98
+ }
99
+ getLanguage() {
100
+ return this.model?.getLanguageId()?.toLowerCase() || null;
101
+ }
102
+ getContent() {
103
+ if (!this.model) {
104
+ return null;
105
+ }
106
+ return this.model.getValue();
107
+ }
108
+ getSelection() {
109
+ if (!this.editor || !this.model) {
110
+ return null;
111
+ }
112
+ try {
113
+ const selection = this.editor.getSelection();
114
+ if (!selection || selection.isEmpty()) {
115
+ return null;
116
+ }
117
+ return this.model.getValueInRange(selection) || null;
118
+ } catch (err) {
119
+ return null;
120
+ }
121
+ }
122
+ getSnippet(lines = 5) {
123
+ if (!this.editor || !this.model) {
124
+ return null;
125
+ }
126
+ try {
127
+ const position = this.editor.getPosition();
128
+ if (!position) {
129
+ return null;
130
+ }
131
+ if (isNaN(lines) || lines < 0) {
132
+ lines = 5;
133
+ }
134
+ const cursorLineNumber = position.lineNumber;
135
+ const totalLines = this.model.getLineCount();
136
+ const startLine = Math.max(1, cursorLineNumber - lines);
137
+ const endLine = Math.min(totalLines, cursorLineNumber + lines);
138
+ const snippet = this.model.getValueInRange({
139
+ startLineNumber: startLine,
140
+ startColumn: 1,
141
+ endLineNumber: endLine,
142
+ endColumn: this.model.getLineMaxColumn(endLine)
143
+ });
144
+ return {
145
+ snippet,
146
+ cursorLine: cursorLineNumber
147
+ };
148
+ } catch (err) {
149
+ return null;
150
+ }
151
+ }
152
+ getFilePath() {
153
+ return this.input?.data?.getWorkspacePath() || null;
154
+ }
155
+ renderToolbar() {
156
+ if (!this.canExecute) {
157
+ return html``;
158
+ }
159
+ return html`
160
+ <wa-button @click=${() => this.onRunCode()} title="Run code"
161
+ ?disabled="${!this.canExecute}" appearance="plain" size="small">
162
+ <wa-icon name="play" label="Run code"></wa-icon>
163
+ </wa-button>
164
+ <wa-button @click=${() => this.toggleConnection()}
165
+ style="${styleMap({ color: this.pyenv ? "var(--wa-color-success-fill-loud)" : "var(--wa-color-danger-fill-loud)" })}"
166
+ title="(Re)Connect to execution environment"
167
+ ?disabled="${!this.canExecute}"
168
+ appearance="plain" size="small">
169
+ <wa-icon name="circle" label="Connection status"></wa-icon>
170
+ </wa-button>
171
+ <wa-button
172
+ size="small"
173
+ appearance="plain"
174
+ @click=${() => this.openPackageManager()}
175
+ title="Manage required Python packages">
176
+ <wa-icon name="box" label="Packages"></wa-icon>
177
+ Packages
178
+ </wa-button>
179
+ `;
180
+ }
181
+ async toggleConnection() {
182
+ if (this.pyenv) {
183
+ this.pyenv.close();
184
+ this.pyenv = void 0;
185
+ }
186
+ if (this.model.getLanguageId() !== "python") {
187
+ logger.error("Language not supported: " + this.model.getLanguageId());
188
+ return;
189
+ }
190
+ this.pyenv = new PyEnv();
191
+ const workspace = await workspaceService.getWorkspace();
192
+ await this.pyenv.init(workspace);
193
+ if (this.requiredPackages.length > 0) {
194
+ try {
195
+ await this.pyenv.loadPackages(this.requiredPackages);
196
+ } catch (error) {
197
+ logger.error("Failed to load required packages: " + String(error));
198
+ }
199
+ }
200
+ }
201
+ parsePackagesFromContent(content) {
202
+ const lines = content.split("\n");
203
+ const magicCommentRegex = /^#\s*@gs-packages:\s*(.+)$/i;
204
+ for (const line of lines) {
205
+ const match = line.match(magicCommentRegex);
206
+ if (match) {
207
+ return match[1].split(",").map((pkg) => pkg.trim()).filter((pkg) => pkg.length > 0);
208
+ }
209
+ }
210
+ return [];
211
+ }
212
+ updatePackagesInContent() {
213
+ if (!this.model) return;
214
+ const content = this.model.getValue();
215
+ const lines = content.split("\n");
216
+ const magicCommentRegex = /^#\s*@gs-packages:/i;
217
+ let magicCommentLineIndex = -1;
218
+ for (let i = 0; i < lines.length; i++) {
219
+ if (magicCommentRegex.test(lines[i])) {
220
+ magicCommentLineIndex = i;
221
+ break;
222
+ }
223
+ }
224
+ const newMagicComment = this.requiredPackages.length > 0 ? `# @gs-packages: ${this.requiredPackages.join(", ")}` : null;
225
+ if (newMagicComment) {
226
+ if (magicCommentLineIndex >= 0) {
227
+ lines[magicCommentLineIndex] = newMagicComment;
228
+ } else {
229
+ const insertIndex = lines[0]?.startsWith("#!") ? 1 : 0;
230
+ lines.splice(insertIndex, 0, newMagicComment);
231
+ }
232
+ } else if (magicCommentLineIndex >= 0) {
233
+ lines.splice(magicCommentLineIndex, 1);
234
+ }
235
+ const newContent = lines.join("\n");
236
+ if (newContent !== content) {
237
+ this.model.setValue(newContent);
238
+ }
239
+ }
240
+ openPackageManager() {
241
+ pythonPackageManagerService.showPackageManager({
242
+ packages: this.requiredPackages,
243
+ pyenv: this.pyenv,
244
+ onPackageAdded: (packageName) => {
245
+ if (!this.requiredPackages.includes(packageName)) {
246
+ this.requiredPackages = [...this.requiredPackages, packageName];
247
+ this.updatePackagesInContent();
248
+ }
249
+ },
250
+ onPackageRemoved: (packageName) => {
251
+ this.requiredPackages = this.requiredPackages.filter((pkg) => pkg !== packageName);
252
+ this.updatePackagesInContent();
253
+ }
254
+ });
255
+ }
256
+ render() {
257
+ return html`
258
+ <style>
259
+ ${styles}
260
+ </style>
261
+ <div class="monaco-editor-container" ${ref(this.editorRef)}>
262
+ </div>
263
+ `;
264
+ }
265
+ };
266
+ KMonacoEditor.styles = css`
267
+ :host {
268
+ display: flex;
269
+ flex-direction: column;
270
+ position: relative;
271
+ width: 100%;
272
+ height: 100%;
273
+ }
274
+
275
+ input.prompt {
276
+ flex: 1;
277
+ font-size: large;
278
+ }
279
+
280
+ div.monaco-editor-container {
281
+ position: absolute;
282
+ top: 0;
283
+ left: 0;
284
+ right: 0;
285
+ bottom: 0;
286
+ }
287
+ `;
288
+ __decorateClass([
289
+ property({ attribute: false })
290
+ ], KMonacoEditor.prototype, "input", 2);
291
+ __decorateClass([
292
+ property()
293
+ ], KMonacoEditor.prototype, "readOnly", 2);
294
+ __decorateClass([
295
+ state()
296
+ ], KMonacoEditor.prototype, "canExecute", 2);
297
+ __decorateClass([
298
+ state()
299
+ ], KMonacoEditor.prototype, "pyenv", 2);
300
+ __decorateClass([
301
+ state()
302
+ ], KMonacoEditor.prototype, "requiredPackages", 2);
303
+ KMonacoEditor = __decorateClass([
304
+ customElement("k-monaco-editor")
305
+ ], KMonacoEditor);
306
+ export {
307
+ KMonacoEditor
308
+ };
309
+ //# sourceMappingURL=k-monaco-editor-D9TjtA98.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k-monaco-editor-D9TjtA98.js","sources":["../src/k-monaco-editor.ts"],"sourcesContent":["import * as monaco from 'monaco-editor';\nimport styles from \"monaco-editor/min/vs/editor/editor.main.css?raw\";\nimport {customElement, property, state} from \"lit/decorators.js\";\nimport {KPart} from \"@kispace-io/core\";\nimport {css, html} from \"lit\";\nimport {createRef, ref} from \"lit/directives/ref.js\";\nimport {EditorInput, EditorContentProvider} from \"@kispace-io/core\";\nimport {styleMap} from \"lit/directives/style-map.js\";\nimport { PyEnv, pythonPackageManagerService } from \"@kispace-io/extension-python-runtime/api\";\nimport { workspaceService } from \"@kispace-io/core\";\nimport { logger } from '@kispace-io/core';\n\nconst workerMap: Record<string, string> = {\n 'json': new URL('monaco-editor/esm/vs/language/json/json.worker.js', import.meta.url).href,\n 'css': new URL('monaco-editor/esm/vs/language/css/css.worker.js', import.meta.url).href,\n 'scss': new URL('monaco-editor/esm/vs/language/css/css.worker.js', import.meta.url).href,\n 'less': new URL('monaco-editor/esm/vs/language/css/css.worker.js', import.meta.url).href,\n 'html': new URL('monaco-editor/esm/vs/language/html/html.worker.js', import.meta.url).href,\n 'handlebars': new URL('monaco-editor/esm/vs/language/html/html.worker.js', import.meta.url).href,\n 'razor': new URL('monaco-editor/esm/vs/language/html/html.worker.js', import.meta.url).href,\n 'typescript': new URL('monaco-editor/esm/vs/language/typescript/ts.worker.js', import.meta.url).href,\n 'javascript': new URL('monaco-editor/esm/vs/language/typescript/ts.worker.js', import.meta.url).href,\n};\n\nself.MonacoEnvironment = {\n getWorkerUrl(_: any, label: string) {\n return workerMap[label] || new URL('monaco-editor/esm/vs/editor/editor.worker.js', import.meta.url).href;\n }\n};\n\n@customElement('k-monaco-editor')\nexport class KMonacoEditor extends KPart implements EditorContentProvider {\n @property({attribute: false})\n public input?: EditorInput;\n @property()\n public readOnly: boolean = false;\n\n private editorRef = createRef();\n private editor?: any;\n private model?: any;\n\n @state()\n private canExecute: boolean = false;\n\n @state()\n private pyenv?: PyEnv;\n\n @state()\n private requiredPackages: string[] = [];\n\n\n protected doBeforeUI() {\n const file = this.input!.data\n this.canExecute = file.getName().endsWith(\".py\")\n }\n\n protected updated(changedProperties: Map<string, any>) {\n super.updated(changedProperties);\n \n if (changedProperties.has('canExecute') || changedProperties.has('pyenv')) {\n this.updateToolbar();\n }\n }\n\n protected async doInitUI() {\n const file = this.input!.data\n const textContents = await file.getContents()\n const container = this.editorRef.value as HTMLElement\n const uri = monaco.Uri.file(file.getName())\n this.model = monaco.editor.createModel(textContents, undefined, uri)\n this.editor = monaco.editor.create(container, {\n theme: 'vs-dark',\n automaticLayout: false,\n })\n this.model.onDidChangeContent((_event: Event) => {\n if (this.readOnly) {\n return\n }\n this.markDirty(true)\n })\n this.editor.setModel(this.model)\n\n if (this.canExecute) {\n this.requiredPackages = this.parsePackagesFromContent(textContents as string)\n }\n }\n\n public getEditor() {\n return this.editor\n }\n\n save(): void {\n const value = this.model.getValue()\n this.input?.data.saveContents(value)\n this.markDirty(false)\n }\n\n protected doClose() {\n this.model?.dispose();\n this.editor?.dispose()\n this.model = undefined\n this.editor = undefined\n this.pyenv?.close()\n this.pyenv = undefined\n }\n\n private async onRunCode() {\n if (!this.canExecute) {\n return\n }\n if (!this.pyenv) {\n await this.toggleConnection();\n }\n this.pyenv?.execCode(this.model.getValue())\n }\n\n public getLanguage() {\n return this.model?.getLanguageId()?.toLowerCase() || null\n }\n\n public getContent(): string | null {\n if (!this.model) {\n return null\n }\n return this.model.getValue()\n }\n\n public getSelection(): string | null {\n if (!this.editor || !this.model) {\n return null\n }\n try {\n const selection = this.editor.getSelection()\n if (!selection || selection.isEmpty()) {\n return null\n }\n return this.model.getValueInRange(selection) || null\n } catch (err) {\n return null\n }\n }\n\n public getSnippet(lines: number = 5): { snippet: string; cursorLine: number } | null {\n if (!this.editor || !this.model) {\n return null\n }\n try {\n const position = this.editor.getPosition()\n if (!position) {\n return null\n }\n\n if (isNaN(lines) || lines < 0) {\n lines = 5\n }\n\n const cursorLineNumber = position.lineNumber\n const totalLines = this.model.getLineCount()\n \n const startLine = Math.max(1, cursorLineNumber - lines)\n const endLine = Math.min(totalLines, cursorLineNumber + lines)\n \n const snippet = this.model.getValueInRange({\n startLineNumber: startLine,\n startColumn: 1,\n endLineNumber: endLine,\n endColumn: this.model.getLineMaxColumn(endLine)\n })\n\n return {\n snippet,\n cursorLine: cursorLineNumber\n }\n } catch (err) {\n return null\n }\n }\n\n public getFilePath(): string | null {\n return this.input?.data?.getWorkspacePath() || null\n }\n\n protected renderToolbar() {\n if (!this.canExecute) {\n return html``;\n }\n\n return html`\n <wa-button @click=${() => this.onRunCode()} title=\"Run code\"\n ?disabled=\"${!this.canExecute}\" appearance=\"plain\" size=\"small\">\n <wa-icon name=\"play\" label=\"Run code\"></wa-icon>\n </wa-button>\n <wa-button @click=${() => this.toggleConnection()}\n style=\"${styleMap({color: this.pyenv ? \"var(--wa-color-success-fill-loud)\" : \"var(--wa-color-danger-fill-loud)\"})}\"\n title=\"(Re)Connect to execution environment\"\n ?disabled=\"${!this.canExecute}\"\n appearance=\"plain\" size=\"small\">\n <wa-icon name=\"circle\" label=\"Connection status\"></wa-icon>\n </wa-button>\n <wa-button \n size=\"small\" \n appearance=\"plain\"\n @click=${() => this.openPackageManager()}\n title=\"Manage required Python packages\">\n <wa-icon name=\"box\" label=\"Packages\"></wa-icon>\n Packages\n </wa-button>\n `;\n }\n\n private async toggleConnection() {\n if (this.pyenv) {\n this.pyenv.close()\n this.pyenv = undefined\n }\n if (this.model.getLanguageId() !== \"python\") {\n logger.error(\"Language not supported: \" + this.model.getLanguageId());\n return\n }\n this.pyenv = new PyEnv()\n const workspace = await workspaceService.getWorkspace()\n await this.pyenv.init(workspace!)\n\n if (this.requiredPackages.length > 0) {\n try {\n await this.pyenv.loadPackages(this.requiredPackages)\n } catch (error) {\n logger.error(\"Failed to load required packages: \" + String(error))\n }\n }\n }\n\n private parsePackagesFromContent(content: string): string[] {\n const lines = content.split('\\n')\n const magicCommentRegex = /^#\\s*@gs-packages:\\s*(.+)$/i\n \n for (const line of lines) {\n const match = line.match(magicCommentRegex)\n if (match) {\n return match[1]\n .split(',')\n .map(pkg => pkg.trim())\n .filter(pkg => pkg.length > 0)\n }\n }\n \n return []\n }\n\n private updatePackagesInContent(): void {\n if (!this.model) return\n\n const content = this.model.getValue()\n const lines = content.split('\\n')\n const magicCommentRegex = /^#\\s*@gs-packages:/i\n \n let magicCommentLineIndex = -1\n for (let i = 0; i < lines.length; i++) {\n if (magicCommentRegex.test(lines[i])) {\n magicCommentLineIndex = i\n break\n }\n }\n\n const newMagicComment = this.requiredPackages.length > 0\n ? `# @gs-packages: ${this.requiredPackages.join(', ')}`\n : null\n\n if (newMagicComment) {\n if (magicCommentLineIndex >= 0) {\n lines[magicCommentLineIndex] = newMagicComment\n } else {\n const insertIndex = lines[0]?.startsWith('#!') ? 1 : 0\n lines.splice(insertIndex, 0, newMagicComment)\n }\n } else if (magicCommentLineIndex >= 0) {\n lines.splice(magicCommentLineIndex, 1)\n }\n\n const newContent = lines.join('\\n')\n if (newContent !== content) {\n this.model.setValue(newContent)\n }\n }\n\n private openPackageManager() {\n pythonPackageManagerService.showPackageManager({\n packages: this.requiredPackages,\n pyenv: this.pyenv,\n onPackageAdded: (packageName: string) => {\n if (!this.requiredPackages.includes(packageName)) {\n this.requiredPackages = [...this.requiredPackages, packageName]\n this.updatePackagesInContent()\n }\n },\n onPackageRemoved: (packageName: string) => {\n this.requiredPackages = this.requiredPackages.filter(pkg => pkg !== packageName)\n this.updatePackagesInContent()\n }\n })\n }\n\n render() {\n return html`\n <style>\n ${styles}\n </style>\n <div class=\"monaco-editor-container\" ${ref(this.editorRef)}>\n </div>\n `\n }\n\n static styles = css`\n :host {\n display: flex;\n flex-direction: column;\n position: relative;\n width: 100%;\n height: 100%;\n }\n\n input.prompt {\n flex: 1;\n font-size: large;\n }\n\n div.monaco-editor-container {\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'k-monaco-editor': KMonacoEditor\n }\n}\n\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,39 @@
1
+ import { KPart, EditorInput, EditorContentProvider } from '@kispace-io/core';
2
+ export declare class KMonacoEditor extends KPart implements EditorContentProvider {
3
+ input?: EditorInput;
4
+ readOnly: boolean;
5
+ private editorRef;
6
+ private editor?;
7
+ private model?;
8
+ private canExecute;
9
+ private pyenv?;
10
+ private requiredPackages;
11
+ protected doBeforeUI(): void;
12
+ protected updated(changedProperties: Map<string, any>): void;
13
+ protected doInitUI(): Promise<void>;
14
+ getEditor(): any;
15
+ save(): void;
16
+ protected doClose(): void;
17
+ private onRunCode;
18
+ getLanguage(): any;
19
+ getContent(): string | null;
20
+ getSelection(): string | null;
21
+ getSnippet(lines?: number): {
22
+ snippet: string;
23
+ cursorLine: number;
24
+ } | null;
25
+ getFilePath(): string | null;
26
+ protected renderToolbar(): import('lit-html').TemplateResult<1>;
27
+ private toggleConnection;
28
+ private parsePackagesFromContent;
29
+ private updatePackagesInContent;
30
+ private openPackageManager;
31
+ render(): import('lit-html').TemplateResult<1>;
32
+ static styles: import('lit').CSSResult;
33
+ }
34
+ declare global {
35
+ interface HTMLElementTagNameMap {
36
+ 'k-monaco-editor': KMonacoEditor;
37
+ }
38
+ }
39
+ //# sourceMappingURL=k-monaco-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"k-monaco-editor.d.ts","sourceRoot":"","sources":["../src/k-monaco-editor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAC,KAAK,EAAC,MAAM,kBAAkB,CAAC;AAGvC,OAAO,EAAC,WAAW,EAAE,qBAAqB,EAAC,MAAM,kBAAkB,CAAC;AAwBpE,qBACa,aAAc,SAAQ,KAAM,YAAW,qBAAqB;IAE9D,KAAK,CAAC,EAAE,WAAW,CAAC;IAEpB,QAAQ,EAAE,OAAO,CAAS;IAEjC,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,MAAM,CAAC,CAAM;IACrB,OAAO,CAAC,KAAK,CAAC,CAAM;IAGpB,OAAO,CAAC,UAAU,CAAkB;IAGpC,OAAO,CAAC,KAAK,CAAC,CAAQ;IAGtB,OAAO,CAAC,gBAAgB,CAAgB;IAGxC,SAAS,CAAC,UAAU;IAKpB,SAAS,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC;cAQrC,QAAQ;IAuBjB,SAAS;IAIhB,IAAI,IAAI,IAAI;IAMZ,SAAS,CAAC,OAAO;YASH,SAAS;IAUhB,WAAW;IAIX,UAAU,IAAI,MAAM,GAAG,IAAI;IAO3B,YAAY,IAAI,MAAM,GAAG,IAAI;IAe7B,UAAU,CAAC,KAAK,GAAE,MAAU,GAAG;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAoC7E,WAAW,IAAI,MAAM,GAAG,IAAI;IAInC,SAAS,CAAC,aAAa;YA4BT,gBAAgB;IAsB9B,OAAO,CAAC,wBAAwB;IAiBhC,OAAO,CAAC,uBAAuB;IAoC/B,OAAO,CAAC,kBAAkB;IAiB1B,MAAM;IAUN,MAAM,CAAC,MAAM,0BAqBX;CACL;AAED,OAAO,CAAC,MAAM,CAAC;IACX,UAAU,qBAAqB;QAC3B,iBAAiB,EAAE,aAAa,CAAA;KACnC;CACJ"}
@@ -0,0 +1,60 @@
1
+ import { html } from "lit";
2
+ import { editorRegistry, File, contributionRegistry } from "@kispace-io/core";
3
+ import { CID_PROMPT_ENHANCERS } from "@kispace-io/extension-ai-system/api";
4
+ const PYTHON_PROMPT = "**Python Programming Assistant:**\n\nYou are helping with Python code. Python code is executed in the browser using Pyodide.\n\n**Python-Specific Responsibilities:**\n- Explain Python code and help debug Python errors\n- Help with `js` module interaction: calling JavaScript functions from Python and passing data between Python and JavaScript\n- Provide Python code examples\n- Remember code runs in a browser environment (Pyodide) - be mindful of browser limitations\n\n**Python Environment:**\n- Working directory is `/workspace` (linked to user's local file system)\n- Install packages by adding them to `requirements.txt` in the workspace\n- Packages in `requirements.txt` are automatically installed before code execution\n\n";
5
+ const JAVASCRIPT_PROMPT = "**JavaScript Programming Assistant:**\n\nYou are helping with JavaScript code. JavaScript code is executed in a worker.\n\n**JavaScript-Specific Focus:**\n- Help with JavaScript, OpenLayers usage, and module patterns\n- When a user requests a starter module, provide this template:\n\n```javascript\nexport default function ({ map, env, render, html, style, when, ref, createRef, events, settings }) {\n const state = {};\n return () => html`\n <div>\n <h3>Hello!</h3>\n <button @click=${() => {}}>Click me</button>\n </div>\n `;\n}\n```\n\n";
6
+ editorRegistry.registerEditorInputHandler({
7
+ lazyInit: async () => {
8
+ await import("./k-monaco-editor-D9TjtA98.js");
9
+ },
10
+ canHandle: (input) => input instanceof File,
11
+ handle: async (input) => {
12
+ const editorInput = {
13
+ title: input.getName(),
14
+ data: input,
15
+ key: input.getName(),
16
+ editorId: "monaco-editor",
17
+ icon: "file-pen",
18
+ noOverflow: false,
19
+ state: {}
20
+ };
21
+ editorInput.widgetFactory = () => html`
22
+ <k-monaco-editor .input=${editorInput}></k-monaco-editor>`;
23
+ return editorInput;
24
+ }
25
+ });
26
+ function isMonacoEditorWithLanguage(context, language) {
27
+ const activeEditor = context.activeEditor;
28
+ return activeEditor && typeof activeEditor.getEditor === "function" && typeof activeEditor.getLanguage === "function" && activeEditor.getLanguage() === language;
29
+ }
30
+ const pythonPromptEnhancer = {
31
+ priority: 50,
32
+ enhance: async (prompt, context) => {
33
+ if (!isMonacoEditorWithLanguage(context, "python")) {
34
+ return prompt;
35
+ }
36
+ return `${prompt}
37
+
38
+ ${PYTHON_PROMPT}`;
39
+ }
40
+ };
41
+ const javascriptPromptEnhancer = {
42
+ priority: 50,
43
+ enhance: async (prompt, context) => {
44
+ if (!isMonacoEditorWithLanguage(context, "javascript")) {
45
+ return prompt;
46
+ }
47
+ return `${prompt}
48
+
49
+ ${JAVASCRIPT_PROMPT}`;
50
+ }
51
+ };
52
+ contributionRegistry.registerContribution(CID_PROMPT_ENHANCERS, {
53
+ label: "Python Programming Enhancer",
54
+ enhancer: pythonPromptEnhancer
55
+ });
56
+ contributionRegistry.registerContribution(CID_PROMPT_ENHANCERS, {
57
+ label: "JavaScript Programming Enhancer",
58
+ enhancer: javascriptPromptEnhancer
59
+ });
60
+ //# sourceMappingURL=monaco-editor-extension-B5XEGKAr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monaco-editor-extension-B5XEGKAr.js","sources":["../src/py-programming-prompt.txt?raw","../src/js-programming-prompt.txt?raw","../src/monaco-editor-extension.ts"],"sourcesContent":["export default \"**Python Programming Assistant:**\\n\\nYou are helping with Python code. Python code is executed in the browser using Pyodide.\\n\\n**Python-Specific Responsibilities:**\\n- Explain Python code and help debug Python errors\\n- Help with `js` module interaction: calling JavaScript functions from Python and passing data between Python and JavaScript\\n- Provide Python code examples\\n- Remember code runs in a browser environment (Pyodide) - be mindful of browser limitations\\n\\n**Python Environment:**\\n- Working directory is `/workspace` (linked to user's local file system)\\n- Install packages by adding them to `requirements.txt` in the workspace\\n- Packages in `requirements.txt` are automatically installed before code execution\\n\\n\"","export default \"**JavaScript Programming Assistant:**\\n\\nYou are helping with JavaScript code. JavaScript code is executed in a worker.\\n\\n**JavaScript-Specific Focus:**\\n- Help with JavaScript, OpenLayers usage, and module patterns\\n- When a user requests a starter module, provide this template:\\n\\n```javascript\\nexport default function ({ map, env, render, html, style, when, ref, createRef, events, settings }) {\\n const state = {};\\n return () => html`\\n <div>\\n <h3>Hello!</h3>\\n <button @click=${() => {}}>Click me</button>\\n </div>\\n `;\\n}\\n```\\n\\n\"","import {html} from \"lit\";\nimport {EditorInput, editorRegistry} from \"@kispace-io/core\";\nimport {File} from \"@kispace-io/core\";\nimport {contributionRegistry} from \"@kispace-io/core\";\nimport {CID_PROMPT_ENHANCERS, type PromptEnhancer, type PromptEnhancerContribution} from \"@kispace-io/extension-ai-system/api\";\nimport type {ExecutionContext} from \"@kispace-io/core\";\nimport PYTHON_PROMPT from \"./py-programming-prompt.txt?raw\";\nimport JAVASCRIPT_PROMPT from \"./js-programming-prompt.txt?raw\";\n\neditorRegistry.registerEditorInputHandler({\n lazyInit: async () => {\n await import('./k-monaco-editor');\n },\n canHandle: input => input instanceof File,\n handle: async (input: File) => {\n const editorInput = {\n title: input.getName(),\n data: input,\n key: input.getName(),\n editorId: \"monaco-editor\",\n icon: \"file-pen\",\n noOverflow: false,\n state: {},\n } as EditorInput\n editorInput.widgetFactory = () => html`\n <k-monaco-editor .input=${editorInput}></k-monaco-editor>`\n return editorInput;\n }\n})\n\n// Helper to check if active editor is a Monaco editor with specific language\nfunction isMonacoEditorWithLanguage(context: ExecutionContext, language: string): boolean {\n const activeEditor = context.activeEditor as any;\n return activeEditor &&\n typeof activeEditor.getEditor === 'function' &&\n typeof activeEditor.getLanguage === 'function' &&\n activeEditor.getLanguage() === language;\n}\n\n// Python programming prompt enhancer\nconst pythonPromptEnhancer: PromptEnhancer = {\n priority: 50,\n enhance: async (prompt: string, context: ExecutionContext) => {\n if (!isMonacoEditorWithLanguage(context, 'python')) {\n return prompt;\n }\n return `${prompt}\\n\\n${PYTHON_PROMPT}`;\n }\n};\n\n// JavaScript programming prompt enhancer\nconst javascriptPromptEnhancer: PromptEnhancer = {\n priority: 50,\n enhance: async (prompt: string, context: ExecutionContext) => {\n if (!isMonacoEditorWithLanguage(context, 'javascript')) {\n return prompt;\n }\n return `${prompt}\\n\\n${JAVASCRIPT_PROMPT}`;\n }\n};\n\n// Register prompt enhancers for programming languages\ncontributionRegistry.registerContribution(CID_PROMPT_ENHANCERS, {\n label: \"Python Programming Enhancer\",\n enhancer: pythonPromptEnhancer\n} as PromptEnhancerContribution);\n\ncontributionRegistry.registerContribution(CID_PROMPT_ENHANCERS, {\n label: \"JavaScript Programming Enhancer\",\n enhancer: javascriptPromptEnhancer\n} as PromptEnhancerContribution);\n\n"],"names":[],"mappings":";;;AAAA,MAAA,gBAAe;ACAf,MAAA,oBAAe;ACSf,eAAe,2BAA2B;AAAA,EACtC,UAAU,YAAY;AAClB,UAAM,OAAO,+BAAmB;AAAA,EACpC;AAAA,EACA,WAAW,WAAS,iBAAiB;AAAA,EACrC,QAAQ,OAAO,UAAgB;AAC3B,UAAM,cAAc;AAAA,MAChB,OAAO,MAAM,QAAA;AAAA,MACb,MAAM;AAAA,MACN,KAAK,MAAM,QAAA;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,OAAO,CAAA;AAAA,IAAC;AAEZ,gBAAY,gBAAgB,MAAM;AAAA,sCACJ,WAAW;AACzC,WAAO;AAAA,EACX;AACJ,CAAC;AAGD,SAAS,2BAA2B,SAA2B,UAA2B;AACtF,QAAM,eAAe,QAAQ;AAC7B,SAAO,gBACH,OAAO,aAAa,cAAc,cAClC,OAAO,aAAa,gBAAgB,cACpC,aAAa,YAAA,MAAkB;AACvC;AAGA,MAAM,uBAAuC;AAAA,EACzC,UAAU;AAAA,EACV,SAAS,OAAO,QAAgB,YAA8B;AAC1D,QAAI,CAAC,2BAA2B,SAAS,QAAQ,GAAG;AAChD,aAAO;AAAA,IACX;AACA,WAAO,GAAG,MAAM;AAAA;AAAA,EAAO,aAAa;AAAA,EACxC;AACJ;AAGA,MAAM,2BAA2C;AAAA,EAC7C,UAAU;AAAA,EACV,SAAS,OAAO,QAAgB,YAA8B;AAC1D,QAAI,CAAC,2BAA2B,SAAS,YAAY,GAAG;AACpD,aAAO;AAAA,IACX;AACA,WAAO,GAAG,MAAM;AAAA;AAAA,EAAO,iBAAiB;AAAA,EAC5C;AACJ;AAGA,qBAAqB,qBAAqB,sBAAsB;AAAA,EAC5D,OAAO;AAAA,EACP,UAAU;AACd,CAA+B;AAE/B,qBAAqB,qBAAqB,sBAAsB;AAAA,EAC5D,OAAO;AAAA,EACP,UAAU;AACd,CAA+B;"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=monaco-editor-extension.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"monaco-editor-extension.d.ts","sourceRoot":"","sources":["../src/monaco-editor-extension.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@kispace-io/extension-monaco-editor",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "type": "module",
5
- "main": "./src/index.ts",
5
+ "main": "./dist/index.js",
6
6
  "exports": {
7
7
  ".": {
8
- "import": "./src/index.ts",
9
- "types": "./src/index.ts"
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js"
10
10
  }
11
11
  },
12
12
  "dependencies": {
@@ -16,6 +16,16 @@
16
16
  "monaco-editor": "0.55.1"
17
17
  },
18
18
  "devDependencies": {
19
- "typescript": "^5.9.3"
19
+ "typescript": "^5.9.3",
20
+ "vite": "^7.1.12",
21
+ "vite-plugin-dts": "^4.5.4"
22
+ },
23
+ "module": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "files": [
26
+ "dist"
27
+ ],
28
+ "scripts": {
29
+ "build": "vite build"
20
30
  }
21
31
  }
package/src/index.ts DELETED
@@ -1,16 +0,0 @@
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
- });
@@ -1,20 +0,0 @@
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
-
@@ -1,342 +0,0 @@
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
-
@@ -1,72 +0,0 @@
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
-
@@ -1,15 +0,0 @@
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
-
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "strict": true,
7
- "skipLibCheck": true
8
- },
9
- "include": [
10
- "src/**/*"
11
- ]
12
- }