You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/07/05 09:03:07 UTC

(texera) branch gh-readonly-queue/main/pr-4997-5acb73433a17ebfaba73d5da19b00b4fc2d3823f created (now 3d4301f448)

This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a change to branch gh-readonly-queue/main/pr-4997-5acb73433a17ebfaba73d5da19b00b4fc2d3823f
in repository https://gitbox.apache.org/repos/asf/texera.git


      at 3d4301f448 chore(frontend): upgrade frontend to monaco-languageclient v10 (#4997)

This branch includes the following new commits:

     new 3d4301f448 chore(frontend): upgrade frontend to monaco-languageclient v10 (#4997)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(texera) 01/01: chore(frontend): upgrade frontend to monaco-languageclient v10 (#4997)

Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

github-merge-queue[bot] pushed a commit to branch gh-readonly-queue/main/pr-4997-5acb73433a17ebfaba73d5da19b00b4fc2d3823f
in repository https://gitbox.apache.org/repos/asf/texera.git

commit 3d4301f4486699ac2a3484cf887e62fbcfc803a9
Author: Xinyuan Lin <xi...@uci.edu>
AuthorDate: Sun Jul 5 02:02:45 2026 -0700

    chore(frontend): upgrade frontend to monaco-languageclient v10 (#4997)
    
    ### What changes were proposed in this PR?
    
    Brings the frontend's Monaco / VS Code language-client stack up to
    `monaco-languageclient` v10 (from v8.8.3) and the matching
    `@codingame/monaco-vscode-*` v25.1.2 ecosystem. v10 split the old
    single-wrapper API into three composable pieces
    (`MonacoVscodeApiWrapper` + `EditorApp` + `LanguageClientWrapper`), so
    the editor component is rewritten and the build/test pipeline picks up
    the codingame v25 quirks the new packages introduce. Adjacent dep
    cleanups land here too — several codingame side-deps and the R UDF
    editor become superfluous once v10 is in place.
    
    #### API shape: v8 → v10
    
    ```
    v8 (before)                                      v10 (after)
    ─────────────────                                ──────────────────────────────────
    new MonacoEditorLanguageClientWrapper(           const api  = new MonacoVscodeApiWrapper(...)
      // single config with editor + LSP + workers   const app  = new EditorApp(...)
      // all in one bag                              const lc   = new LanguageClientWrapper(...)
    ).start(htmlContainer)                           await api.start();         // global vscode-api init
                                                     await app.start(container);// mount editor
                                                     await lc.start();          // open WebSocket to LS
    ```
    
    The editor component is rewritten against the new shape, plus a
    `whenReady()` handshake on the default language extensions and a
    post-mount `forceTokenization` loop to fix a TextMate first-paint race
    that otherwise renders every token as the default `mtk1` class.
    
    #### Worker bundling: why three trampolines
    
    `new Worker(new URL("./relative", import.meta.url))` is the only shape
    webpack 5 treats as a worker entry point AND that esbuild can resolve at
    spec pre-bundle time. Inlining `new URL("@codingame/...",
    import.meta.url)` makes webpack happy but esbuild treats the spec as a
    literal relative URL and the spec pre-bundle fails. A
    `fileReplacements`-swapped factory file works but adds an `angular.json`
    delta. Three thin re-export trampolines satisfy both bundlers with zero
    `angular.json` change.
    
    #### What gets dropped
    
    - `@codingame/monaco-vscode-textmate-service-override` — now a
    transitive of the v25 wrapper; not needed at top level
    - `@codingame/monaco-vscode-theme-defaults-default-extension` — same;
    pulled in transitively by the language extensions
    - `@codingame/monaco-vscode-r-default-extension` — upstream stopped
    publishing; R UDF editor retired
    - `vscode` (package alias + `resolutions`) — v10 no longer needs the
    alias for type-only `vscode.Uri` references
    - `webpack-bundle-analyzer` + `analyze` script — dead; script never ran
    in CI
    - `content-disposition` + `@types/content-disposition` — dead `require`,
    never read
    
    ### Any related issues, documentation, discussions?
    
    Closes #4996.
    
    ### How was this PR tested?
    
    - `yarn install` resolves cleanly
    - `yarn build` exits 0; worker chunks identical hashes/sizes (~1.3 MB
    textmate, ~518 KB ext-host, ~220 KB editor)
    - `yarn test` stays at 63 / 269 spec parity
    
    Manual smoke-test plan:
    - [ ] Open a workflow with a Python UDF — confirm syntax highlighting
    renders correctly on first open
    - [ ] Set / clear / step through a breakpoint with the debugger panel
    - [ ] Verify the AI-assistant "Add Type Annotation" / "Add All Type
    Annotations" actions still work
    - [ ] Check that two browser tabs editing the same workflow show each
    other's coeditor cursors
    - [ ] Run a Java UDF and confirm the editor shows Java syntax (no LSP,
    just grammar)
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 4.7)
    
    ---------
    
    Co-authored-by: Yicong Huang <17...@users.noreply.github.com>
    Co-authored-by: Claude Fable 5 <no...@anthropic.com>
---
 frontend/LICENSE-binary                            |  61 +-
 frontend/custom-webpack.config.js                  |  72 ++-
 frontend/package.json                              |  14 +-
 .../code-editor-dialog/code-debugger.component.ts  |   3 -
 .../code-editor.component.browser.spec.ts          | 109 +++-
 .../code-editor.component.spec.ts                  |  14 +-
 .../code-editor-dialog/code-editor.component.ts    | 334 ++++++----
 .../code-editor-dialog/workers/editor.worker.ts    |  24 +
 .../workers/extension-host.worker.ts               |  21 +
 .../code-editor-dialog/workers/textmate.worker.ts  |  21 +
 frontend/src/jsdom-svg-polyfill.ts                 | 337 +++++-----
 frontend/src/tsconfig.app.json                     |   7 +-
 frontend/vitest.config.ts                          |  11 -
 frontend/yarn.lock                                 | 676 ++++++++++++---------
 14 files changed, 1049 insertions(+), 655 deletions(-)

diff --git a/frontend/LICENSE-binary b/frontend/LICENSE-binary
index 27ec9a61df..aab1349ea8 100644
--- a/frontend/LICENSE-binary
+++ b/frontend/LICENSE-binary
@@ -211,6 +211,7 @@ Dependencies under the Apache License, Version 2.0
 --------------------------------------------------------------------------------
 
 Angular / npm packages:
+  - dompurify@3.3.1
   - fuse.js@6.5.3
   - jschardet@3.1.3
   - rxjs@7.8.1
@@ -247,30 +248,40 @@ Angular / npm packages:
   - @ant-design/icons-angular@21.0.0
   - @auth0/angular-jwt@5.1.0
   - @babel/runtime@7.29.2
-  - @codingame/monaco-vscode-api@8.0.4
-  - @codingame/monaco-vscode-base-service-override@8.0.4
-  - @codingame/monaco-vscode-configuration-service-override@8.0.4
-  - @codingame/monaco-vscode-editor-api@8.0.4
-  - @codingame/monaco-vscode-environment-service-override@8.0.4
-  - @codingame/monaco-vscode-extensions-service-override@8.0.4
-  - @codingame/monaco-vscode-files-service-override@8.0.4
-  - @codingame/monaco-vscode-host-service-override@8.0.4
-  - @codingame/monaco-vscode-java-default-extension@8.0.4
-  - @codingame/monaco-vscode-languages-service-override@8.0.4
-  - @codingame/monaco-vscode-layout-service-override@8.0.4
-  - @codingame/monaco-vscode-model-service-override@8.0.4
-  - @codingame/monaco-vscode-monarch-service-override@8.0.4
-  - @codingame/monaco-vscode-python-default-extension@8.0.4
-  - @codingame/monaco-vscode-quickaccess-service-override@8.0.4
-  - @codingame/monaco-vscode-r-default-extension@8.0.4
-  - @codingame/monaco-vscode-textmate-service-override@8.0.4
-  - @codingame/monaco-vscode-theme-defaults-default-extension@8.0.4
-  - @codingame/monaco-vscode-theme-service-override@8.0.4
+  - @codingame/monaco-vscode-api@25.1.2
+  - @codingame/monaco-vscode-base-service-override@25.1.2
+  - @codingame/monaco-vscode-bulk-edit-service-override@25.1.2
+  - @codingame/monaco-vscode-configuration-service-override@25.1.2
+  - @codingame/monaco-vscode-editor-api@25.1.2
+  - @codingame/monaco-vscode-editor-service-override@25.1.2
+  - @codingame/monaco-vscode-environment-service-override@25.1.2
+  - @codingame/monaco-vscode-extension-api@25.1.2
+  - @codingame/monaco-vscode-extensions-service-override@25.1.2
+  - @codingame/monaco-vscode-files-service-override@25.1.2
+  - @codingame/monaco-vscode-host-service-override@25.1.2
+  - @codingame/monaco-vscode-java-default-extension@25.1.2
+  - @codingame/monaco-vscode-keybindings-service-override@25.1.2
+  - @codingame/monaco-vscode-languages-service-override@25.1.2
+  - @codingame/monaco-vscode-layout-service-override@25.1.2
+  - @codingame/monaco-vscode-log-service-override@25.1.2
+  - @codingame/monaco-vscode-model-service-override@25.1.2
+  - @codingame/monaco-vscode-monarch-service-override@25.1.2
+  - @codingame/monaco-vscode-python-default-extension@25.1.2
+  - @codingame/monaco-vscode-quickaccess-service-override@25.1.2
+  - @codingame/monaco-vscode-textmate-service-override@25.1.2
+  - @codingame/monaco-vscode-theme-defaults-default-extension@25.1.2
+  - @codingame/monaco-vscode-theme-service-override@25.1.2
+  - @codingame/monaco-vscode-view-banner-service-override@25.1.2
+  - @codingame/monaco-vscode-view-common-service-override@25.1.2
+  - @codingame/monaco-vscode-view-status-bar-service-override@25.1.2
+  - @codingame/monaco-vscode-view-title-bar-service-override@25.1.2
+  - @codingame/monaco-vscode-views-service-override@25.1.2
+  - @codingame/monaco-vscode-workbench-service-override@25.1.2
   - @ctrl/tinycolor@3.6.1
   - @ngneat/until-destroy@8.1.4
   - @ngx-formly/core@6.3.12
   - @ngx-formly/ng-zorro-antd@6.3.12
-  - @vscode/iconv-lite-umd@0.7.0
+  - @vscode/iconv-lite-umd@0.7.1
   - ajv@8.10.0
   - backbone@1.4.1
   - balanced-match@1.0.2
@@ -290,11 +301,10 @@ Angular / npm packages:
   - lib0@0.2.117
   - lodash@4.18.1
   - lodash-es@4.18.1
-  - marked@17.0.1
+  - marked@14.0.0
   - mobx@4.14.1
   - monaco-breakpoints@0.2.0
-  - monaco-editor-wrapper@5.5.3
-  - monaco-languageclient@8.8.3
+  - monaco-languageclient@10.7.0
   - ng-zorro-antd@21.3.1
   - ngx-color-picker@12.0.1
   - ngx-file-drop@16.0.0
@@ -305,7 +315,6 @@ Angular / npm packages:
   - point-in-polygon@1.1.0
   - python@1.0.0
   - quill-cursors@3.1.2
-  - r@1.0.0
   - rbush@4.0.1
   - read-excel-file@5.7.1
   - ring-buffer-ts@1.0.3
@@ -317,9 +326,7 @@ Angular / npm packages:
   - vscode-languageclient@9.0.1
   - vscode-languageserver-protocol@3.17.5
   - vscode-languageserver-types@3.17.5
-  - vscode-oniguruma@1.7.0
-  - vscode-textmate@9.0.0
-  - vscode-ws-jsonrpc@3.3.2
+  - vscode-ws-jsonrpc@3.5.0
   - y-monaco@0.1.5
   - y-protocols@1.0.7
   - y-quill@0.1.5
diff --git a/frontend/custom-webpack.config.js b/frontend/custom-webpack.config.js
index 47a804cf43..e39a43e1f1 100644
--- a/frontend/custom-webpack.config.js
+++ b/frontend/custom-webpack.config.js
@@ -17,46 +17,92 @@
  * under the License.
  */
 
+const path = require("path");
 const { LicenseWebpackPlugin } = require("license-webpack-plugin");
 
+const nodeModule = (...segments) => path.resolve(__dirname, "node_modules", ...segments);
+const codingameCssRe = /node_modules[\\/](?:@codingame[\\/]monaco-vscode-[^\\/]+|monaco-editor|vscode)[\\/].*\.css$/;
+
 module.exports = {
   module: {
     rules: [
+      {
+        // codingame monaco-vscode-* ships raw assets (svg/ttf/png/woff*) that
+        // webpack must emit as static files rather than try to parse as JS.
+        test: /\.(svg|ttf|woff2?|png|jpg|jpeg|gif)$/,
+        include: [nodeModule("@codingame")],
+        type: "asset/resource",
+      },
       {
         test: /\.css$/,
-        use: ["style-loader", "css-loader"],
-        include: [
-          require("path").resolve(__dirname, "node_modules/monaco-editor"),
-          require("path").resolve(__dirname, "node_modules/monaco-breakpoints")
+        oneOf: [
+          {
+            // codingame monaco-vscode-* CSS ships as Constructable Stylesheet
+            // imports — must skip style-loader and use css-loader's
+            // `exportType: 'css-style-sheet'`.
+            // https://github.com/CodinGame/monaco-vscode-api/wiki/Troubleshooting
+            test: codingameCssRe,
+            use: [
+              {
+                loader: "css-loader",
+                options: { esModule: false, exportType: "css-style-sheet", url: true, import: true },
+              },
+            ],
+          },
+          {
+            // monaco-breakpoints ships a plain stylesheet that needs
+            // style-loader so it injects at runtime.
+            include: [nodeModule("monaco-breakpoints")],
+            use: ["style-loader", "css-loader"],
+          },
         ],
       },
     ],
-    // Enable URL handling in webpack's JavaScript parser, required for loading .wasm files.
+    // Angular's webpack config disables both `new URL(...)` asset modules
+    // (url: false) and `new Worker(new URL(...))` handling (worker: false
+    // unless webWorkerTsConfig is set). monaco-vscode-api needs both: the
+    // textmate service fetches onig.wasm via `new URL(..., import.meta.url)`,
+    // and the editor/textmate/extension-host workers are spawned the same way.
+    // Without this, webpack inlines `import.meta.url` as a build-machine
+    // file:// path and everything 404s at runtime (no syntax highlighting).
     // See https://github.com/angular/angular-cli/issues/24617
     parser: {
       javascript: {
         url: true,
+        worker: true,
       },
     },
   },
+  resolve: {
+    // css-loader emits relative imports (e.g. '../../../../../../../css-loader/
+    // dist/runtime/api.js') computed from the source CSS location. The codingame
+    // monaco-vscode-* packages live one namespace level deeper (under
+    // `node_modules/@codingame/...`) than css-loader assumes, so the emitted
+    // path lands at `node_modules/@codingame/css-loader/...` instead of
+    // `node_modules/css-loader/...`. Alias the missing leg back to the real
+    // install so webpack can resolve the runtime files.
+    alias: {
+      [nodeModule("@codingame/css-loader")]: nodeModule("css-loader"),
+      [nodeModule("@codingame/style-loader")]: nodeModule("style-loader"),
+    },
+  },
   plugins: [
     new LicenseWebpackPlugin({
       perChunkOutput: false,
       outputFilename: "3rdpartylicenses.json",
+      // Some codingame monaco-vscode-* sub-modules don't expose a license file
+      // license-webpack-plugin can find; treat that as soft instead of fatal.
+      handleMissingLicenseText: () => null,
       renderLicenses: (modules) =>
         JSON.stringify(
           modules
+            .filter((m) => m.packageJson?.name && m.packageJson?.version)
             .map((m) => ({
-              name: m.packageJson && m.packageJson.name,
-              version: m.packageJson && m.packageJson.version,
+              name: m.packageJson.name,
+              version: m.packageJson.version,
               license: m.licenseId,
             }))
-            .filter((e) => e.name && e.version)
-            .sort((a, b) =>
-              a.name === b.name
-                ? a.version.localeCompare(b.version)
-                : a.name.localeCompare(b.name),
-            ),
+            .sort((a, b) => a.name.localeCompare(b.name) || a.version.localeCompare(b.version)),
           null,
           2,
         ),
diff --git a/frontend/package.json b/frontend/package.json
index 418b166ee8..889e7e2c72 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -34,9 +34,8 @@
     "@angular/platform-browser-dynamic": "21.2.10",
     "@angular/router": "21.2.10",
     "@auth0/angular-jwt": "5.1.0",
-    "@codingame/monaco-vscode-java-default-extension": "8.0.4",
-    "@codingame/monaco-vscode-python-default-extension": "8.0.4",
-    "@codingame/monaco-vscode-r-default-extension": "8.0.4",
+    "@codingame/monaco-vscode-java-default-extension": "25.1.2",
+    "@codingame/monaco-vscode-python-default-extension": "25.1.2",
     "@lezer/python": "1.1.18",
     "@ngneat/until-destroy": "8.1.4",
     "@ngx-formly/core": "6.3.12",
@@ -54,9 +53,8 @@
     "lodash-es": "4.18.1",
     "marked": "17.0.1",
     "monaco-breakpoints": "0.2.0",
-    "monaco-editor": "npm:@codingame/monaco-vscode-editor-api@8.0.4",
-    "monaco-editor-wrapper": "5.5.3",
-    "monaco-languageclient": "8.8.3",
+    "monaco-editor": "npm:@codingame/monaco-vscode-editor-api@25.1.2",
+    "monaco-languageclient": "10.7.0",
     "ng-zorro-antd": "21.3.1",
     "ngx-color-picker": "12.0.1",
     "ngx-file-drop": "16.0.0",
@@ -73,7 +71,6 @@
     "tinyqueue": "2.0.3",
     "tslib": "2.3.1",
     "uuid": "14.0.0",
-    "vscode": "npm:@codingame/monaco-vscode-api@8.0.4",
     "y-monaco": "0.1.5",
     "y-protocols": "1.0.5",
     "y-quill": "0.1.5",
@@ -83,8 +80,7 @@
     "zone.js": "0.15.1"
   },
   "resolutions": {
-    "vscode": "npm:@codingame/monaco-vscode-api@8.0.4",
-    "monaco-editor": "npm:@codingame/monaco-vscode-editor-api@8.0.4",
+    "monaco-editor": "npm:@codingame/monaco-vscode-editor-api@25.1.2",
     "webpack": "5.104.1",
     "jschardet": "portal:./tools/jschardet-stub"
   },
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/code-debugger.component.ts b/frontend/src/app/workspace/component/code-editor-dialog/code-debugger.component.ts
index 14384524cf..d46b19f734 100644
--- a/frontend/src/app/workspace/component/code-editor-dialog/code-debugger.component.ts
+++ b/frontend/src/app/workspace/component/code-editor-dialog/code-debugger.component.ts
@@ -20,9 +20,6 @@
 import { AfterViewInit, Component, Input, ViewChild } from "@angular/core";
 import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
 import { SafeStyle } from "@angular/platform-browser";
-import "@codingame/monaco-vscode-python-default-extension";
-import "@codingame/monaco-vscode-r-default-extension";
-import "@codingame/monaco-vscode-java-default-extension";
 import { isDefined } from "../../../common/util/predicate";
 import * as monaco from "monaco-editor";
 import { MonacoBreakpoint } from "monaco-breakpoints";
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.browser.spec.ts b/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.browser.spec.ts
index d6a3266fd1..677dd54c1f 100644
--- a/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.browser.spec.ts
+++ b/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.browser.spec.ts
@@ -21,11 +21,13 @@
 // spec covers the constructor, language detection, getFileSuffixByLanguage,
 // onFocus, getCoeditorCursorStyles, and the accept/reject annotation paths,
 // but cannot reach anything gated on a real Monaco editor — the
-// `initAndStart` subscribe body, `initializeDiffEditor`, AI-action run
-// callbacks, `handleTypeAnnotation`'s position branch, and the resize
-// handler. This spec drives those by swapping the component's editorWrapper
-// for a fake-with-real-DOM and running in vitest's Playwright/Chromium
-// browser mode, where monaco-editor's codingame fork can be imported without
+// `initializeMonacoEditor` subscribe body, `initializeDiffEditor`, AI-action
+// run callbacks, `handleTypeAnnotation`'s position branch, and the resize
+// handler. This spec drives those by stubbing the v10 editor seams — the
+// global vscode-api init (`ensureVscodeApiStarted`) and the per-editor
+// `EditorApp` — so the subscribe body runs against a fake editor, then running
+// in vitest's Playwright/Chromium browser mode, where monaco-editor's codingame
+// fork can be imported without
 // jsdom's missing-canvas / Node-Buffer-allocation tripwires (the Buffer/process
 // shim is wired as the first setupFile in vitest.browser.config.ts — see
 // src/browser-buffer-polyfill.ts).
@@ -70,6 +72,38 @@ vi.mock("y-monaco", () => ({
   },
 }));
 
+// monaco-languageclient v10 split the old single wrapper into a process-wide
+// `MonacoVscodeApiWrapper` (started once) and a per-editor `EditorApp`. The
+// component `new`s the EditorApp inside its start path, so there is no instance
+// field to swap — intercept the class instead. This recording stand-in captures
+// the `EditorAppConfig` handed to the constructor (the non-diff vs diff branch
+// is the assertion target), records the host element passed to `start()`, and
+// hands back the test's fake editor from `getEditor()`. The global vscode-api
+// init is stubbed separately in `beforeEach`.
+const { editorAppMock } = vi.hoisted(() => ({
+  editorAppMock: {
+    configs: [] as unknown[],
+    start: vi.fn(),
+    getEditor: vi.fn(),
+  },
+}));
+vi.mock("monaco-languageclient/editorApp", () => ({
+  EditorApp: class {
+    constructor(config: unknown) {
+      editorAppMock.configs.push(config);
+    }
+    start(host: unknown) {
+      return editorAppMock.start(host);
+    }
+    getEditor() {
+      return editorAppMock.getEditor();
+    }
+    dispose() {
+      return Promise.resolve();
+    }
+  },
+}));
+
 // Re-use the augmented stub from the jsdom spec so the component constructor
 // can resolve its highlighted operator regardless of operatorType.
 const baseSchema = mockOperatorMetaData.operators.find(op => op.operatorType === "PythonUDF");
@@ -134,14 +168,6 @@ function makeFakeEditor(): FakeEditor {
   };
 }
 
-function makeFakeWrapper(editor: FakeEditor) {
-  return {
-    initAndStart: vi.fn().mockResolvedValue(undefined),
-    getEditor: vi.fn(() => editor),
-    dispose: vi.fn(),
-  };
-}
-
 describe("CodeEditorComponent (browser)", () => {
   let displayVersionStream$: BehaviorSubject<boolean>;
   let aiEnabled$: BehaviorSubject<string>;
@@ -151,6 +177,15 @@ describe("CodeEditorComponent (browser)", () => {
 
   beforeEach(async () => {
     monacoBindingCalls.length = 0;
+    editorAppMock.configs.length = 0;
+    editorAppMock.start.mockReset().mockResolvedValue(undefined);
+    editorAppMock.getEditor.mockReset();
+    // The global vscode-api wrapper's start() spins up codingame workers and
+    // pulls the default language extensions over dynamic import — neither is
+    // needed here. Stub the lazy initializer so the editor start path resolves
+    // straight through to the EditorApp seam above.
+    vi.spyOn(CodeEditorComponent as any, "ensureVscodeApiStarted").mockResolvedValue(undefined);
+
     displayVersionStream$ = new BehaviorSubject<boolean>(false);
     aiEnabled$ = new BehaviorSubject<string>("OpenAI");
     getTypeAnnotationsSpy = vi.fn().mockReturnValue(of({ choices: [{ message: { content: ": int" } }] }));
@@ -182,10 +217,16 @@ describe("CodeEditorComponent (browser)", () => {
     workflowActionService = TestBed.inject(WorkflowActionService);
   });
 
+  afterEach(() => {
+    // Restore the `ensureVscodeApiStarted` spy so the next test re-stubs from a
+    // clean slate (vitest is not configured to auto-restore mocks).
+    vi.restoreAllMocks();
+  });
+
   // Builds a fixture for the highlighted operator, but defers the
-  // detectChanges/ngAfterViewInit step so the caller can swap in the fake
-  // editor wrapper and stage `code` / `formControl` before the subscribe body
-  // fires. Returns the fixture, the fake wrapper, and the fake editor.
+  // detectChanges/ngAfterViewInit step so the caller can stage `code` /
+  // `formControl` (and the EditorApp's fake editor) before the subscribe body
+  // fires. Returns the fixture, the fake editor, and the component instance.
   function makeFixtureWithFakes() {
     const predicate = { ...mockJavaUDFPredicate };
     workflowActionService.addOperator(predicate, mockPoint);
@@ -193,18 +234,20 @@ describe("CodeEditorComponent (browser)", () => {
 
     const fixture = TestBed.createComponent(CodeEditorComponent);
     const editor = makeFakeEditor();
-    const wrapper = makeFakeWrapper(editor);
+    // The component pulls the editor back out of `EditorApp.getEditor()` inside
+    // its start path (and again from `adjustEditorSize`), so the mocked
+    // EditorApp must hand back this same fake.
+    editorAppMock.getEditor.mockReturnValue(editor);
     const c = fixture.componentInstance as any;
-    c.editorWrapper = wrapper;
     c.formControl = new FormControl({ value: "", disabled: false });
     // A YText must live inside a Y.Doc to be useful; the binding stub doesn't
     // care, but we stage it as if it came from the shared model so the
     // subscribe body crosses the `if (!this.code) return;` gate.
     c.code = new Y.Doc().getText("code");
-    return { fixture, wrapper, editor, c: c as CodeEditorComponent };
+    return { fixture, editor, c: c as CodeEditorComponent };
   }
 
-  // The component's subscribe path runs `from(initAndStart(...)).pipe(...)`,
+  // The component's subscribe path runs `from(startEditor()).pipe(...)`,
   // which is microtask-async. One macrotask flush after detectChanges is
   // enough for the RxJS chain to deliver the editor into the subscribe body.
   async function flush(): Promise<void> {
@@ -213,16 +256,19 @@ describe("CodeEditorComponent (browser)", () => {
   }
 
   it("initializeMonacoEditor: wires the editor + MonacoBinding + AI actions when code exists", async () => {
-    const { fixture, wrapper, editor } = makeFixtureWithFakes();
+    const { fixture, editor } = makeFixtureWithFakes();
 
     fixture.detectChanges();
     await flush();
 
-    // The non-diff config branch should fire with the editor host element.
-    expect(wrapper.initAndStart).toHaveBeenCalledOnce();
-    const [userConfig, host] = wrapper.initAndStart.mock.calls[0];
-    expect((userConfig as any).wrapperConfig.editorAppConfig.useDiffEditor).toBeUndefined();
-    expect((userConfig as any).wrapperConfig.editorAppConfig.codeResources.main.uri).toMatch(/^in-memory-.*\.\.java$/);
+    // The non-diff branch should construct exactly one EditorApp and start it
+    // against the editor host element.
+    expect(editorAppMock.start).toHaveBeenCalledOnce();
+    expect(editorAppMock.configs).toHaveLength(1);
+    const config = editorAppMock.configs[0] as any;
+    const host = editorAppMock.start.mock.calls[0][0];
+    expect(config.useDiffEditor).toBeUndefined();
+    expect(config.codeResources.modified.uri).toMatch(/^in-memory-.*\.java$/);
     expect(host).toBeInstanceOf(HTMLElement);
 
     // The subscribe body should: push readOnly via updateOptions, construct
@@ -243,7 +289,7 @@ describe("CodeEditorComponent (browser)", () => {
   });
 
   it("initializeDiffEditor: when displayParticularVersion is true, runs the diff config path", async () => {
-    const { fixture, wrapper } = makeFixtureWithFakes();
+    const { fixture } = makeFixtureWithFakes();
     // Seed the stream BEFORE detectChanges so the subscribe in ngAfterViewInit
     // picks `true` on first emission and takes the diff branch.
     displayVersionStream$.next(true);
@@ -251,11 +297,12 @@ describe("CodeEditorComponent (browser)", () => {
     fixture.detectChanges();
     await flush();
 
-    expect(wrapper.initAndStart).toHaveBeenCalledOnce();
-    const [userConfig] = wrapper.initAndStart.mock.calls[0];
-    expect((userConfig as any).wrapperConfig.editorAppConfig.useDiffEditor).toBe(true);
+    expect(editorAppMock.start).toHaveBeenCalledOnce();
+    expect(editorAppMock.configs).toHaveLength(1);
+    const config = editorAppMock.configs[0] as any;
+    expect(config.useDiffEditor).toBe(true);
     // `original` is the previous-version source, only set on the diff path.
-    expect((userConfig as any).wrapperConfig.editorAppConfig.codeResources.original).toBeDefined();
+    expect(config.codeResources.original).toBeDefined();
   });
 
   it("setupAIAssistantActions: registers only the 'all' action when the gate is not OpenAI", async () => {
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts b/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts
index 0f37f851aa..c262036e87 100644
--- a/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts
+++ b/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.spec.ts
@@ -271,16 +271,16 @@ describe("CodeEditorComponent", () => {
       const fixture = makeFixture(mockJavaUDFPredicate);
       const c = fixture.componentInstance;
 
-      // The accept path reaches into the underlying MonacoEditorLanguageClientWrapper
-      // for `.getEditor()` and into the YText `.code` for `.insert()`. Both are
-      // private so we stub them through bracket access to a minimum that lets
-      // insertTypeAnnotations no-op cleanly. `dispose` is needed because
-      // ngOnDestroy fires at teardown and calls it.
-      (c as any).editorWrapper = {
+      // The accept path reaches into the underlying EditorApp for `.getEditor()`
+      // and into the YText `.code` for `.insert()`. Both are private so we stub
+      // them through bracket access to a minimum that lets insertTypeAnnotations
+      // no-op cleanly. `dispose` is needed because ngOnDestroy fires at teardown
+      // and calls it.
+      (c as any).editorApp = {
         getEditor: () => ({
           getModel: () => ({ getOffsetAt: () => 0 }),
         }),
-        dispose: vi.fn(),
+        dispose: vi.fn().mockResolvedValue(undefined),
       };
       (c as any).code = { insert: vi.fn() };
 
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.ts b/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.ts
index 5f934fe6e0..5dd1a6791f 100644
--- a/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.ts
+++ b/frontend/src/app/workspace/component/code-editor-dialog/code-editor.component.ts
@@ -33,7 +33,7 @@ import { WorkflowVersionService } from "../../../dashboard/service/user/workflow
 import type { Text as YText } from "yjs";
 import { getWebsocketUrl } from "src/app/common/util/url";
 import { MonacoBinding } from "y-monaco";
-import { catchError, from, of, Subject, take, timeout } from "rxjs";
+import { from, Subject, take } from "rxjs";
 import { CoeditorPresenceService } from "../../service/workflow-graph/model/coeditor-presence.service";
 import { DomSanitizer, SafeStyle } from "@angular/platform-browser";
 import { Coeditor } from "../../../common/type/user";
@@ -41,13 +41,16 @@ import { YType } from "../../types/shared-editing.interface";
 import { FormControl } from "@angular/forms";
 import { AIAssistantService, TypeAnnotationResponse } from "../../service/ai-assistant/ai-assistant.service";
 import { AnnotationSuggestionComponent } from "./annotation-suggestion.component";
-import { MonacoEditorLanguageClientWrapper, UserConfig } from "monaco-editor-wrapper";
 import * as monaco from "monaco-editor";
-import "@codingame/monaco-vscode-python-default-extension";
-import "@codingame/monaco-vscode-r-default-extension";
-import "@codingame/monaco-vscode-java-default-extension";
+import {
+  MonacoVscodeApiWrapper,
+  type MonacoVscodeApiConfig,
+  getEnhancedMonacoEnvironment,
+} from "monaco-languageclient/vscodeApiWrapper";
+import { LanguageClientWrapper, type LanguageClientConfig } from "monaco-languageclient/lcwrapper";
+import { EditorApp, type EditorAppConfig } from "monaco-languageclient/editorApp";
 import { isDefined } from "../../../common/util/predicate";
-import { filter, switchMap } from "rxjs/operators";
+import { filter } from "rxjs/operators";
 import { BreakpointConditionInputComponent } from "./breakpoint-condition-input/breakpoint-condition-input.component";
 import { CodeDebuggerComponent } from "./code-debugger.component";
 import { GuiConfigService } from "src/app/common/service/gui-config.service";
@@ -103,7 +106,9 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
   public language: string = "";
   public languageTitle: string = "";
 
-  private editorWrapper: MonacoEditorLanguageClientWrapper = new MonacoEditorLanguageClientWrapper();
+  private static apiWrapperStartPromise?: Promise<void>;
+  private editorApp?: EditorApp;
+  private languageClientWrapper?: LanguageClientWrapper;
   private monacoBinding?: MonacoBinding;
 
   // Boolean to determine whether the suggestion UI should be shown
@@ -122,14 +127,16 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
   public codeDebuggerComponent!: Type<any> | null;
   public editorToPass!: MonacoEditor;
 
-  private generateLanguageTitle(language: string): string {
-    return `${language.charAt(0).toUpperCase()}${language.slice(1)} UDF`;
-  }
-
-  setLanguage(newLanguage: string) {
-    this.language = newLanguage;
-    this.languageTitle = this.generateLanguageTitle(newLanguage);
-  }
+  // Operator-type → editor language. The R types are kept on the frontend
+  // even though Texera's R UDF backend now ships as a separate plugin —
+  // when that plugin is installed, the workflow may still surface `RUDF` /
+  // `RUDFSource` operators and the editor needs to open them in R mode.
+  private static readonly PYTHON_OPERATOR_TYPES: ReadonlySet<string> = new Set([
+    "PythonUDFV2",
+    "PythonUDFSourceV2",
+    "DualInputPortsPythonUDFV2",
+  ]);
+  private static readonly R_OPERATOR_TYPES: ReadonlySet<string> = new Set(["RUDFSource", "RUDF"]);
 
   constructor(
     private sanitizer: DomSanitizer,
@@ -141,18 +148,14 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
   ) {
     this.currentOperatorId = this.workflowActionService.getJointGraphWrapper().getCurrentHighlightedOperatorIDs()[0];
     const operatorType = this.workflowActionService.getTexeraGraph().getOperator(this.currentOperatorId).operatorType;
-
-    if (operatorType === "RUDFSource" || operatorType === "RUDF") {
-      this.setLanguage("r");
-    } else if (
-      operatorType === "PythonUDFV2" ||
-      operatorType === "PythonUDFSourceV2" ||
-      operatorType === "DualInputPortsPythonUDFV2"
-    ) {
-      this.setLanguage("python");
+    if (CodeEditorComponent.PYTHON_OPERATOR_TYPES.has(operatorType)) {
+      this.language = "python";
+    } else if (CodeEditorComponent.R_OPERATOR_TYPES.has(operatorType)) {
+      this.language = "r";
     } else {
-      this.setLanguage("java");
+      this.language = "java";
     }
+    this.languageTitle = `${this.language[0].toUpperCase()}${this.language.slice(1)} UDF`;
     this.workflowActionService.getTexeraGraph().updateSharedModelAwareness("editingCode", true);
     this.title = this.workflowActionService.getTexeraGraph().getOperator(this.currentOperatorId).customDisplayName;
     this.code = (
@@ -185,30 +188,113 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
     this.workflowActionService.getTexeraGraph().updateSharedModelAwareness("editingCode", false);
     localStorage.setItem(this.currentOperatorId, this.containerElement.nativeElement.style.cssText);
 
-    if (isDefined(this.monacoBinding)) {
-      this.monacoBinding.destroy();
-    }
-
-    this.editorWrapper.dispose(true);
+    this.monacoBinding?.destroy();
+    this.languageClientWrapper?.dispose().catch(() => {});
+    this.languageClientWrapper = undefined;
+    this.editorApp?.dispose().catch(() => {});
+    this.editorApp = undefined;
 
-    if (isDefined(this.workflowVersionStreamSubject)) {
-      this.workflowVersionStreamSubject.next();
-      this.workflowVersionStreamSubject.complete();
-    }
+    this.workflowVersionStreamSubject.next();
+    this.workflowVersionStreamSubject.complete();
   }
 
   /**
    * Specify the co-editor's cursor style. This step is missing from MonacoBinding.
+   *
+   * `coeditor.clientId` and `coeditor.color` come from yjs awareness state,
+   * which any peer can write to. Both are interpolated into a `<style>` tag
+   * passed through `bypassSecurityTrustHtml`, so anything that escapes the
+   * tag would land in the page as raw HTML. Validate both to a tight
+   * allow-list (digits-only id, hex / `rgb(a)` / `hsl(a)` colour) and bail
+   * out otherwise; nothing else should reach the sanitiser.
    * @param coeditor
    */
   public getCoeditorCursorStyles(coeditor: Coeditor) {
-    const textCSS =
+    if (!CodeEditorComponent.SAFE_CLIENT_ID.test(coeditor.clientId)) {
+      return this.sanitizer.bypassSecurityTrustHtml("");
+    }
+    if (!coeditor.color || !CodeEditorComponent.SAFE_CSS_COLOR.test(coeditor.color)) {
+      return this.sanitizer.bypassSecurityTrustHtml("");
+    }
+    const id = coeditor.clientId;
+    const color = coeditor.color;
+    const selectionBg = color.replace("0.8", "0.5");
+    return this.sanitizer.bypassSecurityTrustHtml(
       "<style>" +
-      `.yRemoteSelection-${coeditor.clientId} { background-color: ${coeditor.color?.replace("0.8", "0.5")}}` +
-      `.yRemoteSelectionHead-${coeditor.clientId}::after { border-color: ${coeditor.color}}` +
-      `.yRemoteSelectionHead-${coeditor.clientId} { border-color: ${coeditor.color}}` +
-      "</style>";
-    return this.sanitizer.bypassSecurityTrustHtml(textCSS);
+        `.yRemoteSelection-${id} { background-color: ${selectionBg}}` +
+        `.yRemoteSelectionHead-${id}::after { border-color: ${color}}` +
+        `.yRemoteSelectionHead-${id} { border-color: ${color}}` +
+        "</style>"
+    );
+  }
+
+  // Allow-lists for the two awareness-derived values that flow into a `<style>`
+  // tag in `getCoeditorCursorStyles`. yjs serialises clientIDs as the decimal
+  // form of a 32-bit integer, and the colours we generate elsewhere only use
+  // these notations — anything outside these patterns is rejected.
+  private static readonly SAFE_CLIENT_ID = /^\d{1,10}$/;
+  private static readonly SAFE_CSS_COLOR = /^(?:#[0-9a-fA-F]{3,8}|rgba?\([\d.,\s]+\)|hsla?\([\d.,%\s]+\))$/;
+
+  /**
+   * Lazily start the global monaco-vscode-api wrapper. The vscode API services are
+   * a process-wide singleton in v10; calling start() twice would throw, so we share
+   * a single Promise across every CodeEditorComponent instance.
+   */
+  private static async ensureVscodeApiStarted(): Promise<void> {
+    CodeEditorComponent.apiWrapperStartPromise ??= (async () => {
+      try {
+        const apiConfig: MonacoVscodeApiConfig = {
+          $type: "extended",
+          viewsConfig: { $type: "EditorService" },
+          userConfiguration: {
+            json: JSON.stringify({ "workbench.colorTheme": "Default Dark Modern" }),
+          },
+          // Wire workers via thin trampolines in `./workers/`. Webpack 5 only
+          // treats `new Worker(new URL("./relative", import.meta.url))` as a
+          // worker entry point and bundles the dep tree into a chunk; bare
+          // package URLs `new URL("@codingame/...", import.meta.url)` become
+          // static assets whose relative imports 404 at runtime. Esbuild
+          // (used by @angular/build:unit-test) also requires a real on-disk
+          // file for the URL spec — trampolines satisfy both bundlers.
+          monacoWorkerFactory: () => {
+            const env = getEnhancedMonacoEnvironment();
+            env.getWorker = (_workerId: string, label: string): Worker => {
+              switch (label) {
+                case "editorWorkerService":
+                  return new Worker(new URL("./workers/editor.worker", import.meta.url), { type: "module" });
+                case "extensionHostWorkerMain":
+                  return new Worker(new URL("./workers/extension-host.worker", import.meta.url), { type: "module" });
+                case "TextMateWorker":
+                  return new Worker(new URL("./workers/textmate.worker", import.meta.url), { type: "module" });
+                default:
+                  throw new Error(`No worker configured for label: ${label}`);
+              }
+            };
+          },
+        };
+        await new MonacoVscodeApiWrapper(apiConfig).start();
+
+        // Load AND fully activate the default language extensions. Each
+        // module exports a `whenReady()` that resolves after its TextMate
+        // grammar / configuration files are registered with the host —
+        // without waiting, the editor opens with every token rendered as
+        // the default `mtk1` class (no syntax colours). Dynamic `import(...)`
+        // is used so the Angular build pipeline doesn't tree-shake the
+        // side-effect imports.
+        const extensions = await Promise.all([
+          import("@codingame/monaco-vscode-python-default-extension"),
+          import("@codingame/monaco-vscode-java-default-extension"),
+        ]);
+        await Promise.all(extensions.map(ext => ext.whenReady?.()));
+      } catch (err) {
+        // Clear the cached promise so a later editor open can retry; without
+        // this the rejected promise would be returned forever and every
+        // subsequent open would fail with the same error.
+        CodeEditorComponent.apiWrapperStartPromise = undefined;
+        throw err;
+      }
+    })();
+    return CodeEditorComponent.apiWrapperStartPromise;
   }
 
   private getFileSuffixByLanguage(language: string): string {
@@ -232,50 +318,59 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
    */
   private initializeMonacoEditor() {
     const fileSuffix = this.getFileSuffixByLanguage(this.language);
-    const userConfig: UserConfig = {
-      wrapperConfig: {
-        editorAppConfig: {
-          $type: "extended",
-          codeResources: {
-            main: {
-              text: this.code?.toString() ?? "",
-              uri: `in-memory-${this.currentOperatorId}.${fileSuffix}`,
-            },
-          },
-          userConfiguration: {
-            json: JSON.stringify({
-              "workbench.colorTheme": "Default Dark Modern",
-            }),
-          },
+    const editorAppConfig: EditorAppConfig = {
+      codeResources: {
+        modified: {
+          text: this.code?.toString() ?? "",
+          uri: `in-memory-${this.currentOperatorId}${fileSuffix}`,
         },
       },
     };
 
-    // optionally, configure python language client.
-    // it may fail if no valid connection is established, yet the failure would be ignored.
     const languageServerWebsocketUrl = getWebsocketUrl(
       "/python-language-server",
       this.config.env.pythonLanguageServerPort
     );
-    if (this.language === "python") {
-      userConfig.languageClientConfig = {
-        languageId: this.language,
-        options: {
-          $type: "WebSocketUrl",
-          url: languageServerWebsocketUrl,
-        },
-      };
-    }
 
-    // init monaco editor, optionally with attempt on language client.
-    from(this.editorWrapper.initAndStart(userConfig, this.editorElement.nativeElement))
-      .pipe(
-        timeout(LANGUAGE_SERVER_CONNECTION_TIMEOUT_MS),
-        switchMap(() => of(this.editorWrapper.getEditor())),
-        catchError(() => of(this.editorWrapper.getEditor())),
-        filter(isDefined),
-        untilDestroyed(this)
-      )
+    const startEditor = async (): Promise<MonacoEditor | undefined> => {
+      await CodeEditorComponent.ensureVscodeApiStarted();
+      this.editorApp = new EditorApp(editorAppConfig);
+      await this.editorApp.start(this.editorElement.nativeElement);
+
+      // Configure the python language client as a best-effort step — a
+      // missing or unreachable language server should not block the editor
+      // from being usable. The timeout / catch is scoped tightly around
+      // `languageClientWrapper.start()` so the editor mount above is always
+      // awaited to completion (codingame v25 first-load init can take
+      // multiple seconds and easily exceed the LSP timeout).
+      if (this.language === "python") {
+        const lcConfig: LanguageClientConfig = {
+          languageId: this.language,
+          connection: {
+            options: { $type: "WebSocketUrl", url: languageServerWebsocketUrl },
+          },
+          clientOptions: { documentSelector: [this.language] },
+        };
+        this.languageClientWrapper = new LanguageClientWrapper(lcConfig);
+        try {
+          await Promise.race([
+            this.languageClientWrapper.start(),
+            new Promise<never>((_, reject) =>
+              setTimeout(
+                () => reject(new Error("Language server connection timed out")),
+                LANGUAGE_SERVER_CONNECTION_TIMEOUT_MS
+              )
+            ),
+          ]);
+        } catch {
+          // Editor stays usable without the LSP.
+        }
+      }
+      return this.editorApp.getEditor();
+    };
+
+    from(startEditor())
+      .pipe(filter(isDefined), untilDestroyed(this))
       .subscribe((editor: MonacoEditor) => {
         editor.updateOptions({ readOnly: this.formControl.disabled });
         if (!this.code) {
@@ -290,6 +385,22 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
           new Set([editor]),
           this.workflowActionService.getTexeraGraph().getSharedModelAwareness()
         );
+        // The TextMate grammar registers asynchronously (the host fetches the
+        // .tmLanguage.json from the codingame extension and spins up a worker).
+        // Even after the editor mounts, the model may have already been painted
+        // with the no-grammar tokens (everything as the default `mtk1` class).
+        // Force a re-tokenize so the syntax colours show up on first paint.
+        const model = editor.getModel();
+        const tokenization = (
+          model as unknown as {
+            tokenization?: { forceTokenization?: (line: number) => void };
+          }
+        )?.tokenization;
+        if (model && tokenization?.forceTokenization) {
+          for (let line = 1; line <= model.getLineCount(); line++) {
+            tokenization.forceTokenization(line);
+          }
+        }
         this.setupAIAssistantActions(editor);
         this.initCodeDebuggerComponent(editor);
       });
@@ -302,34 +413,29 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
       ?.content.operators?.find(({ operatorID }) => operatorID === this.currentOperatorId);
     const latestVersionCode: string = latestVersionOperator?.operatorProperties?.code ?? "";
     const oldVersionCode: string = this.code?.toString() ?? "";
-    const userConfig: UserConfig = {
-      wrapperConfig: {
-        editorAppConfig: {
-          $type: "extended",
-          codeResources: {
-            main: {
-              text: latestVersionCode,
-              uri: `in-memory-${this.currentOperatorId}.${fileSuffix}`,
-            },
-            original: {
-              text: oldVersionCode,
-              uri: `in-memory-${this.currentOperatorId}-version.${fileSuffix}`,
-            },
-          },
-          useDiffEditor: true,
-          diffEditorOptions: {
-            readOnly: true,
-          },
-          userConfiguration: {
-            json: JSON.stringify({
-              "workbench.colorTheme": "Default Dark Modern",
-            }),
-          },
+    const editorAppConfig: EditorAppConfig = {
+      codeResources: {
+        modified: {
+          text: latestVersionCode,
+          uri: `in-memory-${this.currentOperatorId}${fileSuffix}`,
+        },
+        original: {
+          text: oldVersionCode,
+          uri: `in-memory-${this.currentOperatorId}-version${fileSuffix}`,
         },
       },
+      useDiffEditor: true,
+      diffEditorOptions: {
+        readOnly: true,
+      },
     };
 
-    this.editorWrapper.initAndStart(userConfig, this.editorElement.nativeElement);
+    const startDiffEditor = async () => {
+      await CodeEditorComponent.ensureVscodeApiStarted();
+      this.editorApp = new EditorApp(editorAppConfig);
+      await this.editorApp.start(this.editorElement.nativeElement);
+    };
+    from(startDiffEditor()).pipe(untilDestroyed(this)).subscribe();
   }
 
   private initCodeDebuggerComponent(editor: MonacoEditor) {
@@ -503,21 +609,10 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
     if (!this.showAnnotationSuggestion || !this.currentRange || !this.currentSuggestion) {
       return;
     }
-
-    if (this.currentRange && this.currentSuggestion) {
-      const selection = new monaco.Selection(
-        this.currentRange.startLineNumber,
-        this.currentRange.startColumn,
-        this.currentRange.endLineNumber,
-        this.currentRange.endColumn
-      );
-
-      this.insertTypeAnnotations(this.editorWrapper.getEditor()!, selection, this.currentSuggestion);
-
-      // Only for "Add All Type Annotation"
-      if (this.isMultipleVariables && this.userResponseSubject) {
-        this.userResponseSubject.next();
-      }
+    this.insertTypeAnnotations(this.editorApp!.getEditor()!, this.currentRange, this.currentSuggestion);
+    // Only for "Add All Type Annotation"
+    if (this.isMultipleVariables && this.userResponseSubject) {
+      this.userResponseSubject.next();
     }
     // close the UI after adding the annotation
     this.showAnnotationSuggestion = false;
@@ -536,12 +631,9 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
     }
   }
 
-  private insertTypeAnnotations(editor: MonacoEditor, selection: monaco.Selection, annotations: string) {
-    const endLineNumber = selection.endLineNumber;
-    const endColumn = selection.endColumn;
-    const insertPosition = new monaco.Position(endLineNumber, endColumn);
-    const insertOffset = editor.getModel()?.getOffsetAt(insertPosition) || 0;
-    this.code?.insert(insertOffset, annotations);
+  private insertTypeAnnotations(editor: MonacoEditor, range: monaco.Range, annotations: string) {
+    const offset = editor.getModel()?.getOffsetAt(new monaco.Position(range.endLineNumber, range.endColumn)) ?? 0;
+    this.code?.insert(offset, annotations);
   }
 
   @HostListener("window:resize")
@@ -560,7 +652,7 @@ export class CodeEditorComponent implements AfterViewInit, SafeStyle, OnDestroy
     if (rect.bottom > viewportHeight) {
       container.style.height = `${viewportHeight - rect.top}px`;
     }
-    this.editorWrapper.getEditor()?.layout();
+    this.editorApp?.getEditor()?.layout();
   }
   onFocus() {
     this.workflowActionService.getJointGraphWrapper().highlightOperators(this.currentOperatorId);
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/workers/editor.worker.ts b/frontend/src/app/workspace/component/code-editor-dialog/workers/editor.worker.ts
new file mode 100644
index 0000000000..ed2a08a486
--- /dev/null
+++ b/frontend/src/app/workspace/component/code-editor-dialog/workers/editor.worker.ts
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// Worker trampoline — re-exports the codingame-shipped editor worker so a
+// relative-path `new Worker(new URL(...))` in code-editor.component.ts pulls
+// the dep tree into a webpack worker chunk. See the `monacoWorkerFactory`
+// comment there for the full rationale.
+import "@codingame/monaco-vscode-editor-api/esm/vs/editor/editor.worker.js";
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/workers/extension-host.worker.ts b/frontend/src/app/workspace/component/code-editor-dialog/workers/extension-host.worker.ts
new file mode 100644
index 0000000000..6d66702557
--- /dev/null
+++ b/frontend/src/app/workspace/component/code-editor-dialog/workers/extension-host.worker.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// See ./editor.worker.ts for why this trampoline exists.
+import "@codingame/monaco-vscode-api/workers/extensionHost.worker";
diff --git a/frontend/src/app/workspace/component/code-editor-dialog/workers/textmate.worker.ts b/frontend/src/app/workspace/component/code-editor-dialog/workers/textmate.worker.ts
new file mode 100644
index 0000000000..796224f901
--- /dev/null
+++ b/frontend/src/app/workspace/component/code-editor-dialog/workers/textmate.worker.ts
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// See ./editor.worker.ts for why this trampoline exists.
+import "@codingame/monaco-vscode-textmate-service-override/worker";
diff --git a/frontend/src/jsdom-svg-polyfill.ts b/frontend/src/jsdom-svg-polyfill.ts
index 34bccf59ce..4e659d7b6a 100644
--- a/frontend/src/jsdom-svg-polyfill.ts
+++ b/frontend/src/jsdom-svg-polyfill.ts
@@ -17,128 +17,181 @@
  * under the License.
  */
 
-/**
- * jsdom doesn't implement the SVG geometry APIs (`SVGSVGElement#createSVGMatrix`,
- * `createSVGPoint`, `createSVGTransform`, `getScreenCTM`, `getCTM`,
- * `getBBox`). jointjs reaches into these during graph layout and crashes
- * the spec build with `TypeError: svgDocument.createSVGMatrix is not a
- * function` etc.
- *
- * The stubs below return identity-ish geometry: matrices/points behave like
- * the identity, bounding boxes report zero dimensions. That's enough for
- * jointjs construction code to not throw; specs that actually depend on
- * accurate geometry should run under Vitest browser mode rather than
- * jsdom (tracked in #4861), but the bulk of the texera specs only need
- * jointjs to instantiate cleanly.
- */
+// Test-env polyfills loaded via `setupFiles` in `angular.json`. Most of
+// the gaps below were introduced by the monaco-languageclient v10 upgrade,
+// which pulls in `@codingame/monaco-vscode-*` v25 — that stack calls into
+// browser APIs jsdom doesn't ship (Constructable Stylesheets, `CSS.escape`,
+// `matchMedia`, `requestIdleCallback`, …). jointjs's SVG geometry stubs
+// are the only block that predates the upgrade.
+
+// CSS-import shim: the unit-test builder pre-bundles specs with
+// `externalPackages: true`, so transitive `.css` imports from the codingame
+// stack reach Node's native ESM loader and crash with
+// `Unknown file extension ".css"`. Register a hook that resolves any `.css`
+// specifier to a `CSSStyleSheet`-shaped no-op module. Source is inlined as
+// a `data:` URL (no `.mjs` sidecar). Gated by a `globalThis` flag because
+// `setupFiles` re-runs per spec file and `module.register` chains.
+import { register as registerLoader } from "node:module";
+
+const CSS_HOOK_FLAG = Symbol.for("texera.cssLoaderHookRegistered");
+const PROCESS_HANDLERS_FLAG = Symbol.for("texera.processErrorHandlersInstalled");
+const flagHolder = globalThis as Record<symbol, boolean | undefined>;
+if (!flagHolder[CSS_HOOK_FLAG]) {
+  // The hook's default export is a CSSStyleSheet-shaped stub rather than a
+  // bare `{}` — a few transitive consumers (codingame v25's
+  // `css-style-sheet` export form) read `.replaceSync` / `.cssRules` off
+  // the imported value, and a plain empty object would crash them.
+  const stubModule =
+    "const s = { cssRules: [] };" +
+    "s.replaceSync = () => {};" +
+    "s.replace = () => Promise.resolve();" +
+    "s.insertRule = () => 0;" +
+    "s.deleteRule = () => {};" +
+    "export default s;";
+  const stubUrl = `data:text/javascript;charset=utf-8,${encodeURIComponent(stubModule)}`;
+  const cssLoaderHookSource = `
+const STUB_URL = ${JSON.stringify(stubUrl)};
+export function resolve(specifier, context, nextResolve) {
+  if (specifier.endsWith(".css") || /\\.css(\\?|$)/.test(specifier)) {
+    return { url: STUB_URL, shortCircuit: true, format: "module" };
+  }
+  return nextResolve(specifier, context);
+}
+`;
+  registerLoader(`data:text/javascript;charset=utf-8,${encodeURIComponent(cssLoaderHookSource)}`);
+  flagHolder[CSS_HOOK_FLAG] = true;
+}
 
 type AnyFn = (...args: unknown[]) => unknown;
+// Loose `globalThis` accessor — jsdom installs DOM globals here, but TS's
+// `lib.dom.d.ts` types many of them as never-undefined. Cast through `any`
+// so the `?.prototype` short-circuits below stay typed-light.
+const G = globalThis as Record<string, any>;
+const installIfMissing = (proto: Record<string, AnyFn> | undefined, fns: Record<string, AnyFn>) => {
+  if (!proto) return;
+  for (const [name, impl] of Object.entries(fns)) {
+    if (typeof proto[name] !== "function") proto[name] = impl;
+  }
+};
 
-function fakeMatrix() {
-  // Minimal SVGMatrix shape — just the methods jointjs touches.
+// SVG geometry APIs (`SVGSVGElement#createSVGMatrix`, `createSVGPoint`,
+// `createSVGTransform`, `getScreenCTM`, `getCTM`, `getBBox`). jsdom doesn't
+// implement these and jointjs reaches into them during graph layout, so the
+// spec build crashes with `TypeError: svgDocument.createSVGMatrix is not a
+// function`. Stubs return identity-ish geometry — enough for jointjs to
+// instantiate. Specs needing accurate geometry should run under Vitest
+// browser mode rather than jsdom (tracked in #4861).
+// Method names are space-separated to keep the prettier-formatted source on
+// one line each; both stubs only need their named methods to exist as
+// callables, so the contents don't matter beyond returning the right shape.
+const MATRIX_METHODS =
+  "multiply inverse translate scale scaleNonUniform rotate rotateFromVector flipX flipY skewX skewY";
+const TRANSFORM_METHODS = "setMatrix setTranslate setScale setRotate setSkewX setSkewY";
+function fakeMatrix(): Record<string, unknown> {
   const m: Record<string, unknown> = { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 };
-  m.multiply = () => fakeMatrix();
-  m.inverse = () => fakeMatrix();
-  m.translate = () => fakeMatrix();
-  m.scale = () => fakeMatrix();
-  m.scaleNonUniform = () => fakeMatrix();
-  m.rotate = () => fakeMatrix();
-  m.rotateFromVector = () => fakeMatrix();
-  m.flipX = () => fakeMatrix();
-  m.flipY = () => fakeMatrix();
-  m.skewX = () => fakeMatrix();
-  m.skewY = () => fakeMatrix();
+  for (const fn of MATRIX_METHODS.split(" ")) m[fn] = () => fakeMatrix();
   return m;
 }
-
-function fakePoint() {
-  const p: Record<string, unknown> = { x: 0, y: 0 };
-  p.matrixTransform = () => fakePoint();
-  return p;
+function fakeTransform(): Record<string, unknown> {
+  const t: Record<string, unknown> = { type: 0, matrix: fakeMatrix(), angle: 0 };
+  for (const fn of TRANSFORM_METHODS.split(" ")) t[fn] = () => undefined;
+  return t;
 }
+const fakePoint = (): Record<string, unknown> => ({ x: 0, y: 0, matrixTransform: () => fakePoint() });
+const fakeRect = () => ({ x: 0, y: 0, width: 0, height: 0 });
+installIfMissing(G.SVGSVGElement?.prototype, {
+  createSVGMatrix: fakeMatrix as AnyFn,
+  createSVGPoint: fakePoint as AnyFn,
+  createSVGTransform: fakeTransform as AnyFn,
+  createSVGTransformFromMatrix: fakeTransform as AnyFn,
+});
+installIfMissing(G.SVGGraphicsElement?.prototype, {
+  getScreenCTM: fakeMatrix as AnyFn,
+  getCTM: fakeMatrix as AnyFn,
+  getBBox: fakeRect as AnyFn,
+});
 
-function fakeTransform() {
-  return {
-    type: 0,
-    matrix: fakeMatrix(),
-    angle: 0,
-    setMatrix: () => undefined,
-    setTranslate: () => undefined,
-    setScale: () => undefined,
-    setRotate: () => undefined,
-    setSkewX: () => undefined,
-    setSkewY: () => undefined,
+// Constructable Stylesheets API (`new CSSStyleSheet().replaceSync(...)`) —
+// jsdom doesn't ship it, but @codingame/monaco-vscode-api v25 calls it at
+// module load. Stub with an inert constructor; specs don't visually render
+// anything, so swallowing CSS is safe.
+if (!G.CSSStyleSheet) {
+  G.CSSStyleSheet = class {
+    cssRules: unknown[] = [];
+    replaceSync = () => undefined;
+    replace = () => Promise.resolve();
+    insertRule = () => 0;
+    deleteRule = () => undefined;
   };
+} else {
+  installIfMissing(G.CSSStyleSheet.prototype, {
+    replaceSync: (() => undefined) as AnyFn,
+    replace: (() => Promise.resolve()) as AnyFn,
+  });
 }
 
-function fakeRect() {
-  return { x: 0, y: 0, width: 0, height: 0 };
+// `Document.prototype` shims — jsdom is missing `adoptedStyleSheets` (used by
+// the codingame runtime to push Constructable Stylesheets at it) and the
+// legacy `queryCommandSupported` (probed by monaco-editor on init).
+const docProto = G.Document?.prototype as Record<string, unknown> | undefined;
+if (docProto && !("adoptedStyleSheets" in docProto)) {
+  Object.defineProperty(docProto, "adoptedStyleSheets", {
+    configurable: true,
+    get() {
+      return (this as { __adoptedStyleSheets?: unknown[] }).__adoptedStyleSheets ?? [];
+    },
+    set(v: unknown[]) {
+      (this as { __adoptedStyleSheets?: unknown[] }).__adoptedStyleSheets = v;
+    },
+  });
 }
+installIfMissing(docProto as Record<string, AnyFn> | undefined, { queryCommandSupported: (() => false) as AnyFn });
 
-const SVG_GLOBAL = (globalThis as unknown as { SVGSVGElement?: { prototype: Record<string, AnyFn> } }).SVGSVGElement;
-const SVG_ELEMENT_GLOBAL = (globalThis as unknown as { SVGGraphicsElement?: { prototype: Record<string, AnyFn> } })
-  .SVGGraphicsElement;
+// `CSS` global namespace (`CSS.escape`, `CSS.supports`) — jsdom doesn't
+// ship it; the codingame v25 theme service calls `CSS.escape(...)` from an
+// idle-callback runner and crashes without the stub. The escape impl mirrors
+// the spec (https://drafts.csswg.org/cssom/#serialize-an-identifier) just
+// enough that `value === out` for the common case — otherwise a noisy
+// `console.warn` fires every paint.
+G.CSS ??= {};
+installIfMissing(G.CSS, {
+  escape: ((v: string) => String(v).replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&")) as AnyFn,
+  supports: (() => false) as AnyFn,
+});
 
-if (SVG_GLOBAL?.prototype) {
-  const proto = SVG_GLOBAL.prototype;
-  if (typeof proto.createSVGMatrix !== "function") proto.createSVGMatrix = fakeMatrix as AnyFn;
-  if (typeof proto.createSVGPoint !== "function") proto.createSVGPoint = fakePoint as AnyFn;
-  if (typeof proto.createSVGTransform !== "function") proto.createSVGTransform = fakeTransform as AnyFn;
-  if (typeof proto.createSVGTransformFromMatrix !== "function")
-    proto.createSVGTransformFromMatrix = fakeTransform as AnyFn;
-}
+// `window.matchMedia` — jsdom doesn't implement it; the codingame v25 theme
+// service calls it in a deferred idle callback to detect dark/light preference.
+// Stub returns an inert MediaQueryList that always reports no match.
+const matchMediaStub: AnyFn = ((query: string) => ({
+  matches: false,
+  media: query,
+  onchange: null,
+  addListener: () => undefined,
+  removeListener: () => undefined,
+  addEventListener: () => undefined,
+  removeEventListener: () => undefined,
+  dispatchEvent: () => false,
+})) as AnyFn;
+if (typeof G.matchMedia !== "function") G.matchMedia = matchMediaStub;
+if (G.window && typeof G.window.matchMedia !== "function") G.window.matchMedia = matchMediaStub;
 
-if (SVG_ELEMENT_GLOBAL?.prototype) {
-  const proto = SVG_ELEMENT_GLOBAL.prototype;
-  if (typeof proto.getScreenCTM !== "function") proto.getScreenCTM = fakeMatrix as AnyFn;
-  if (typeof proto.getCTM !== "function") proto.getCTM = fakeMatrix as AnyFn;
-  if (typeof proto.getBBox !== "function") proto.getBBox = fakeRect as AnyFn;
-}
+// `requestIdleCallback` / `cancelIdleCallback` — Chrome-only APIs jsdom
+// doesn't ship; monaco-related modules crash at construction without them.
+// Approximate with `setTimeout`; the deadline arg is a coarse stub for
+// callers that only read `didTimeout`.
+G.requestIdleCallback ??= (cb: (d: { didTimeout: boolean; timeRemaining: () => number }) => void) =>
+  setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 50 }), 0);
+G.cancelIdleCallback ??= (id: number) => clearTimeout(id);
 
-/**
- * jsdom doesn't implement the legacy `document.queryCommandSupported`,
- * which monaco-editor probes during initialization. Without it the
- * editor's setup throws even when no spec actually exercises monaco.
- */
-const docProto = (globalThis as unknown as { Document?: { prototype: Record<string, AnyFn> } }).Document?.prototype;
-if (docProto && typeof docProto.queryCommandSupported !== "function") {
-  docProto.queryCommandSupported = (() => false) as AnyFn;
-}
-
-/**
- * jsdom doesn't implement `requestIdleCallback` / `cancelIdleCallback`
- * (a Chrome-only API). Specs that pull in monaco-related modules
- * crash at construction with `ReferenceError: requestIdleCallback is
- * not defined`.
- *
- * Approximate with `setTimeout` so callbacks still fire. The deadline
- * argument is a coarse stub — enough for callers that only read
- * `didTimeout`.
- */
-const idleGlobal = globalThis as unknown as Record<string, AnyFn | undefined>;
-if (typeof idleGlobal.requestIdleCallback !== "function") {
-  idleGlobal.requestIdleCallback = ((cb: (d: { didTimeout: boolean; timeRemaining: () => number }) => void) =>
-    setTimeout(() => cb({ didTimeout: false, timeRemaining: () => 50 }), 0)) as AnyFn;
-}
-if (typeof idleGlobal.cancelIdleCallback !== "function") {
-  idleGlobal.cancelIdleCallback = ((id: number) => clearTimeout(id)) as AnyFn;
-}
-
-/**
- * y-websocket schedules a reconnect timer the moment a service that uses
- * collaborative editing is constructed. When that timer fires AFTER vitest
- * has begun tearing down the jsdom window, jsdom's WebSocket implementation
- * crashes during construction (`Cannot read properties of null (reading
- * '_cookieJar')` → `Invalid value used as weak map key`). Vitest catches
- * this as an unhandled error and fails the run even though every test
- * passed.
- *
- * Stub WebSocket with an inert no-op so the timer can fire without
- * touching jsdom. The collaborative-editing specs that actually exercise
- * WebSocket behaviour are excluded from the test suite (component specs +
- * the workflow-action suite is the only collaboration-touching active
- * spec). Real WebSocket testing belongs under Vitest browser mode.
- */
+// `WebSocket` — y-websocket schedules a reconnect timer the moment a
+// collaborative-editing service is constructed. When that timer fires AFTER
+// vitest has begun tearing down the jsdom window, jsdom's WebSocket
+// implementation crashes during construction (`Cannot read properties of null
+// (reading '_cookieJar')` → `Invalid value used as weak map key`) and vitest
+// fails the run even though every test passed. Stub with an inert no-op so
+// the timer can fire without touching jsdom; the only specs that genuinely
+// exercise WebSocket behaviour are already excluded from the suite. Real
+// WebSocket testing belongs under Vitest browser mode.
 class InertWebSocket {
   static readonly CONNECTING = 0;
   static readonly OPEN = 1;
@@ -158,45 +211,51 @@ class InertWebSocket {
   onerror: AnyFn | null = null;
   onmessage: AnyFn | null = null;
   onclose: AnyFn | null = null;
-  send(): void {}
-  close(): void {}
-  addEventListener(): void {}
-  removeEventListener(): void {}
-  dispatchEvent(): boolean {
-    return false;
-  }
+  send = () => undefined;
+  close = () => undefined;
+  addEventListener = () => undefined;
+  removeEventListener = () => undefined;
+  dispatchEvent = () => false;
   constructor(_url?: string, _protocols?: string | string[]) {}
 }
-(globalThis as unknown as { WebSocket: typeof InertWebSocket }).WebSocket = InertWebSocket;
+G.WebSocket = InertWebSocket;
 
-/**
- * NgZorro's NzIconService dynamically fetches icon SVGs over HTTP from
- * `/assets/...` when the icon isn't pre-registered. jsdom's XHR
- * implementation rejects those requests with an `AggregateError`, and
- * downstream the icon lookup re-throws as `IconNotFoundError`. Vitest
- * catches both as unhandled errors, which CI treats as a hard failure
- * (locally Vitest only reports them as non-fatal warnings).
- *
- * Stubbing every spec with `NzIconModule.forChild([...])` for every
- * icon its template uses is impractical — there are dozens. Instead,
- * suppress the two specific error patterns at the process level: they
- * originate inside ngZorro's icon plumbing and don't affect the
- * assertions specs actually make.
- */
+// Process-level error suppression for benign ngZorro icon / codingame
+// extension fetches. NzIconService fetches icon SVGs from `/assets/...` when
+// the icon isn't pre-registered; jsdom's XHR rejects with `AggregateError`
+// and the lookup re-throws as `IconNotFoundError`. Vitest catches both as
+// unhandled errors and CI treats that as a hard failure. Stubbing every spec
+// with `NzIconModule.forChild([...])` is impractical — dozens of icons.
+// Suppress just these patterns at the process level.
 function isBenignIconError(err: unknown): boolean {
   const msg = err instanceof Error ? err.message : String(err);
+  const stack = err instanceof Error ? err.stack ?? "" : "";
   return (
     msg.includes("[@ant-design/icons-angular]") ||
-    (err instanceof Error && err.name === "AggregateError" && /xhr-utils/.test(err.stack ?? ""))
+    (err instanceof Error && err.name === "AggregateError" && /xhr-utils/.test(stack)) ||
+    // codingame v25 default extensions try to fetch their bundled themes /
+    // language configs over `extension-file://` URIs at activation time.
+    // jsdom can't resolve the scheme so the fetch rejects, but it's cosmetic
+    // — the spec body never depends on the theme/grammar being applied.
+    msg.includes("extension-file://") ||
+    /workbenchThemeService|monaco-vscode-theme|monaco-vscode-.*-default-extension/.test(stack)
   );
 }
-process.on("uncaughtException", err => {
-  if (isBenignIconError(err)) return;
-  // Re-throwing inside `uncaughtException` aborts the Node process, which
-  // crashes the Vitest worker mid-run and leaves the runner hanging.
-  console.error(err);
-});
-process.on("unhandledRejection", reason => {
-  if (isBenignIconError(reason)) return;
-  console.error(reason);
-});
+// Same gating pattern as the CSS loader hook above — vitest re-evaluates
+// this setup file once per spec file, and attaching fresh `process.on(...)`
+// handlers each time grows the listener chain (`MaxListenersExceededWarning`
+// after ~11 specs) and reruns the benign-error filter on every captured
+// rejection.
+if (!flagHolder[PROCESS_HANDLERS_FLAG]) {
+  process.on("uncaughtException", err => {
+    if (isBenignIconError(err)) return;
+    // Re-throwing inside `uncaughtException` aborts the Node process, which
+    // crashes the Vitest worker mid-run and leaves the runner hanging.
+    console.error(err);
+  });
+  process.on("unhandledRejection", reason => {
+    if (isBenignIconError(reason)) return;
+    console.error(reason);
+  });
+  flagHolder[PROCESS_HANDLERS_FLAG] = true;
+}
diff --git a/frontend/src/tsconfig.app.json b/frontend/src/tsconfig.app.json
index a05a55217b..a45e321c52 100644
--- a/frontend/src/tsconfig.app.json
+++ b/frontend/src/tsconfig.app.json
@@ -18,6 +18,11 @@
       }
     }
   },
-  "files": ["main.ts"],
+  "files": [
+    "main.ts",
+    "app/workspace/component/code-editor-dialog/workers/editor.worker.ts",
+    "app/workspace/component/code-editor-dialog/workers/extension-host.worker.ts",
+    "app/workspace/component/code-editor-dialog/workers/textmate.worker.ts"
+  ],
   "include": ["**/*.d.ts"]
 }
diff --git a/frontend/vitest.config.ts b/frontend/vitest.config.ts
index 82a35b7afe..9cb2f82f88 100644
--- a/frontend/vitest.config.ts
+++ b/frontend/vitest.config.ts
@@ -34,17 +34,6 @@ export default defineConfig({
     // which Angular's `fakeAsync` requires. Karma+Jasmine installed this
     // implicitly; the @angular/build:unit-test path doesn't.
     setupFiles: ["src/test-zone-setup.ts"],
-    // monaco-breakpoints' entry does `import './style.css'`. By default
-    // Vitest leaves third-party deps externalized, so Node's ESM loader
-    // tries to import the .css and crashes with
-    // `TypeError: Unknown file extension ".css"`. Inlining the package
-    // routes its imports through Vite/esbuild, which rewrites the CSS
-    // import to a no-op.
-    server: {
-      deps: {
-        inline: [/monaco-breakpoints/],
-      },
-    },
     // Per-spec exclusions live in `angular.json` (the unit-test builder
     // applies them at the discovery stage, before Vitest's own filter,
     // which is what the Vitest team recommends — see the Vite warning
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index eda557ccf8..be83dc8cea 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -2066,307 +2066,428 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-base-service-override@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-base-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-api@npm:25.1.2, @codingame/monaco-vscode-api@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-api@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/d47b59e95fb287f8fb9abbfc3bcaeb0afca7cadd9293d4ee06302798840cccb7e78a4de955048a27bf6766675d0ed91c1f418d5c6dca576ada0e8130618a115d
+    "@codingame/monaco-vscode-base-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-environment-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-extensions-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-host-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-layout-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-quickaccess-service-override": "npm:25.1.2"
+    "@vscode/iconv-lite-umd": "npm:0.7.1"
+    dompurify: "npm:3.3.1"
+    jschardet: "npm:3.1.4"
+    marked: "npm:14.0.0"
+  checksum: 10c0/c2d2be484906bc81575a70b3e00b3a15098793955ff02ebc172061ce6d570a19b3d14dc236a7cd09ad5c030a348283be9d83e907a6248fbf68ac5ab9333eed01
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-configuration-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-configuration-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-base-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-base-service-override@npm:25.1.2"
   dependencies:
-    "@codingame/monaco-vscode-files-service-override": "npm:8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/04cc87a27bc2e93e6f8ade15e53e8635bf6db55eb341b043e1583abd18eaa396065144308651de67a1ccbd2edd3148f89dcf798af0a9926362370634bfa9e9b8
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/2194d5fcdf1b606e2c0e09b702c2bd3288958f5dde4403afb165737fcc837fc11d07cc6266b6cfa0aa6f1783da92add3024da3689fc7f7237dbbcd135da974a8
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-editor-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-editor-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-bulk-edit-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-bulk-edit-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/82362f7df94bcf72ca21810e18f0a2f251f299f0d8fa9544e5460da38243b07340cbd82f83045fa505d3609bb57402def5011814656522b76dde1e6bd55c1622
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/8b8fea1cd62ffeef47909d775b68966d0c9f495e49ff62e87fb04af5e7cd9307f8ab4764995d0801b87ce8651b6eb5754965cb2a8e6415b5d87c3685e11cb25b
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-environment-service-override@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-environment-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-configuration-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-configuration-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/5c438986315a9a22eef3d5d927350f362179e19d6293d651cf6ecb3b32446d2ba7333b53463473230329aaa3a1db77a39362274a3703ab7e3914b2bb538e8f28
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+  checksum: 10c0/1733039adbf653b0105cd176a9679621aa0d174dc488b3c943b0cb3cfb11c0a65bfbf0898d895027520b31ed0121f5d3d789ddf6b9631ae5bbf2e087f933fc7f
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-extensions-service-override@npm:8.0.4, @codingame/monaco-vscode-extensions-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-extensions-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-editor-api@npm:^25.1.2, monaco-editor@npm:@codingame/monaco-vscode-editor-api@25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-editor-api@npm:25.1.2"
   dependencies:
-    "@codingame/monaco-vscode-files-service-override": "npm:8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/624b819238c017e20f29fc908ede2cd8f641d659ec23ba04879ea2f87a829d9777a6ea9c1898cacdf9e7a07734ae8eb2d00cd2ccd136356bb3e8ca3cf0bb90bc
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/46678d8eabaa487a8f8ffce9717818dc08afed748582a89b7d306113a593e5243d4e7e023a046b3cdd65e2f4de06e2be779aa82b21a3c9cc9b72cbad24565d4d
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-files-service-override@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-files-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-editor-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-editor-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/956b7d5636cab22e3ab66deb7f71bf2f3c9d95c166d6068a0f8d4e742f58cc7e8400b64aa2eb420cab1896ee38c62c7132c4765f997b6b5ceacbd8e01e5175d2
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/e159bb2a1fb8ae8ee883bd02d95f2fb05e21b4caabb30bc21544b87cdf05f3932a4d2a6fe5b2a31f63e87c02455a36351322ed081ff4b6b55ea36e916d8cf1fd
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-host-service-override@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-host-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-environment-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-environment-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/a9cee88b06868ec84914bf891d42133b30ab309be41ce0eab3dd604fd4ef6756d419dd891e2ad0a271e69da3cce0c0f6c8cb289f057329bb1115f6161877c600
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/cfa7b5997a91d2b8d01acccf9fd63e998e130a2e6ded9938b4412787ae1265a0667ce47a3bd1d3f8fea2a833ff893e3efc978d1261a09af2bba1394fa0c90a35
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-java-default-extension@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-java-default-extension@npm:8.0.4"
+"@codingame/monaco-vscode-extension-api@npm:^25.1.2, vscode@npm:@codingame/monaco-vscode-extension-api@^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-extension-api@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/58f34897c29e006395a754c6cd87189ea5b30a10e879d2720777889b1f6842b5e5c931a30ffef98d369fc9420a23fcf7cf2f775077adffbf1fbd2f5702eaee3a
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-extensions-service-override": "npm:25.1.2"
+  checksum: 10c0/182f90e359bd3d57aaf9a58eaabe9eff226d6bc94e4f51c43f846308352982cbbe3b2dade60177c5ab90e49d8d437493715cd224c1a6063e5c52e1c5e75b9be3
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-cs@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-cs@npm:8.0.4"
+"@codingame/monaco-vscode-extensions-service-override@npm:25.1.2, @codingame/monaco-vscode-extensions-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-extensions-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/87700f4599d8404e746f03ce1073396b25c268fdae55ddd65d85404d1b71cbb08c43f281745494857cda6e9ef2c88624e647335f3597a7082991ac03622f906f
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+  checksum: 10c0/fbbbcfae26b61582dde6ebe3f2e40a040a6593e30948d557b4ebd2c2f80fa011235fe2f8be20ccc62fa91dadfa7274a245482e1fb04a94facaa56dc33efe706a
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-de@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-de@npm:8.0.4"
+"@codingame/monaco-vscode-files-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-files-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/dfb4b7a2e7abe6574fd15b40b7ee7089445917900ff2611d0fd7d309b0233e6e90c811392685e6be4b976b751dcb001b42bf422842d53b8dac80abd834e11761
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/d8d700507199c4cac564751d9c8f8bb3514cc39256d1e6381b492c80833f8428f3b6490082bbfee1b3e73b0b65dbefa6e5966280678b9ebd35f27c93b49f9c9c
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-es@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-es@npm:8.0.4"
+"@codingame/monaco-vscode-host-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-host-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/c3c60adab9fb60a5e376a37260f80b95998ac94d88424b5b824751240bcc3997cb5e83c4c4f01cf18a1ccb9bce48f8e8e50a31fd87a92949c7d0bb3c0bb5a6e3
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/12522ef3494b94b195d643ffd4f3ab0e66e3be949809c19daab329661d781a8a836273914d96de15046121b562510324e75b1802fd7d8f01a59f5f371f18fff1
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-fr@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-fr@npm:8.0.4"
+"@codingame/monaco-vscode-java-default-extension@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-java-default-extension@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/abe94f70eea98cddddcadb6a6c2f3b0964fa034489cf3d8d99b6953919fc2b34e74fbb2321a7623c8fb37afd80db8206d2c1c0f83a1f5bc01a2085ec28fb8b0c
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/ad00d914f1236102b1e387aff0cc61e004d0aa4bffba6dda38f3b310950372974e059383131955876ed3882dc339a06944af13529706e11f10ea27ca0d64e071
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-it@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-it@npm:8.0.4"
+"@codingame/monaco-vscode-keybindings-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-keybindings-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/9e47ce0458bc37787a3d5763720657d357acbee9792b0520524f0609be90b3adf015327a03db630a7b82f391cfbb8f8293fd28f7749f83b941c3f2e322d6115a
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+  checksum: 10c0/81399b35c85cdcef067059370979282a282bac560b0e3f033b8dcf2877c2f33618fc75c31e671fb7486e45f0f791d7575afa40509f13b017088ee242caff65ed
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-ja@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-ja@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-cs@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-cs@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/65bc3e1e6544cb690f1b99973da1b6845d26594daf0bf95dd692ed665e58de7de0d39e15ef72bd6dc6801636c414229f07b0a6359e7e8c001ea226944181c6e1
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/55a977b197f3bf35f3061587020598ec533068d0a50d3020378bd7ea07b48d4cfb720d6584136266cc29fd18454ad47b66a4a4e0411371d7729619ccab81b709
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-ko@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-ko@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-de@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-de@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/7bc457932db34fb26cd4e2c11494c5e3b4e6757de32ddd5045a46c7c5a47ab4fa3789418a51e722af706098eab35c022f56e7027966b6894136f93d664870ede
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/45440482e91bf70fa0ec5982dc6b39b7541902b10edf2c6eb50de3ab71a9b400edb3e3ce0bb86f53a6edc587baf8b9320fe3e7536a80121acab5dc33bd3f220e
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-pl@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-pl@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-es@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-es@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/80274df3bb40b0669d522fc88064a7926f61ae436ffe557e1cd2822017b6fe3b6e8571018f3e22dcf39a074af84021f3bc7a6e7634e4f4fda9f8e7a285d1dcc8
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/58011acd0e2a247d2e38a5f9ee14c142744e889ddfd4b7863fa3b9f876fd3ef6833e6e11fa8563eec9bf66100fa39dd9b47c5895729e1053cd772a35788d9e55
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-pt-br@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-pt-br@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-fr@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-fr@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/bb61c3a6dd102b8d636101ce547a00a82806f12c38f697d2603b8ef8dc585e673a8e5e6a177a7e39721535b0773508d791ae982f61d5aad3e1291b1d87a2bd25
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/0dcef4989cce25a0a7e8dbfe352be348f691163914912cffff8d2788d468de313c60b834f2f2f8ec7f153fc6dfb9cdcde6bee1bb8cbe980bef6c4a6de64d60c9
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-qps-ploc@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-qps-ploc@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-it@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-it@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/be864dcbfe746e34c8f981ba190e3db4352b2672cf52f2471042b33ddaa600a5783a2c28b28a70cc5d8783a3a3c7f310a91cdc71ab02d65301eee89cebd5b4ec
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/f05af4dc4629be34ba87188b7700195f4e5dce747d0937792463bdfb1b0fbf7ef4653600cef0b4febf16ba6b1dec76a94dd7f7417f47e1f94e05859aad0baea8
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-ru@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-ru@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-ja@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-ja@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/345d42252634261be208df7989148b7115624a778a491afb3249e1d750fa2e7469f906c9ab11c5a8df9201ec4cd7fefab82e46d88714c27d64b9a1b8ecdd83d6
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/d816fe97a4db813875a38f25766a22d9cd5724f8919d092b4b9ffbe622e3f161f314a702af7ae0c2b9b14c7bb564a261d014613ef3ad97bf1f1295980a759132
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-tr@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-tr@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-ko@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-ko@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/fdaeff22f5b52f565f391e14be6ec6b06ef337dd148e2542e8b9c6b578bf395274c1d540bf530b91b71ad54714871941e916e618c43d526203c3d5c7c8bc310a
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/96a97f07c0f35436ba56fac26b3a227243bc27faae40152ca34d58f58a2aebf667fc2d4b039c9f8c1e51c27a90c943b1cab6eb306327b1b1f9bd6158efebf0e3
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-zh-hans@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-zh-hans@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-pl@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-pl@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/9997fc23adae93cc6bd33916085b341bdd2cdcc15a83d492809f6328bc95c14ec9c579b5dae6d35224b4eb96ab35f006c19539a765afd4c1713e8ca5eb10645b
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/d81fecd1f5858a39b9e58340883cac0198a3f855ea926fd7147f149fd98e7e070dcf6f42c713634f32a5d3bd721ce011de13df51ff9052aabd99561a523ffbe4
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-language-pack-zh-hant@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-language-pack-zh-hant@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-pt-br@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-pt-br@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/23fe87f2938cf00e2906fed63f23965a910ea8f9d3e15a6d39d3d3ef2f9e7a41dd423a59ce3a816924995479743dad6d6a67116bc2e152f9624586344dd102ba
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/4c55969eed67b15066fc2d0482f8de06694b10df48f65a239b2f34182e53bd3ebc07c28c0bf38a6b2cb637a6f5fdab979a80a38d65ec51322b08062264a310b0
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-languages-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-languages-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-qps-ploc@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-qps-ploc@npm:25.1.2"
   dependencies:
-    "@codingame/monaco-vscode-files-service-override": "npm:8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/f376fb13b75c57d8f509f3465c01dc6509bcae3b4b8f40b9adbee4f7b1b9027def0a1489d1f84b7a72eeebe08570eb968dcc4bbb624279974c1b3c3c336a6d17
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/425119b73c53687a209cc05554f3b562e98b6b8ee4e531a3ddd4e10b77b1a26684597ac30da164a77b4fb0b88d61faa354507af04de3d448ad400b8dd8e388b4
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-layout-service-override@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-layout-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-ru@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-ru@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/114d5d47e25719e01a23337bbbe1d051f2e50589cc27ee171bb4c49363618029d25124b7ea7eb37cf255467f2535cef4129f3be433161c7014ff5652c19488aa
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/038be50b55f39381a4f075a549e1f07febf8019ea6cc8e094b413047e5339cd6004dc2ebcc79e9ea97180757851f1e4079b101448bedbdcae61719717ee54fb6
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-localization-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-localization-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-tr@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-tr@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/77ad94652bdc9ea82453bbe6c3d8b3d1741dbb8cd311b477639a795751de2e52c4938fca27458b8be5f71bf35252bb6d0e752d3d2012f15150b254cb26f601c3
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/4a338cbb20449a07d721e5ed80e9f99abe7102827772591df3e4b076d4c893e9c0408d4c2a96acee20b36dee32bba7a021c59d6cab2015ac63e07d50b4af606a
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-model-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-model-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-zh-hans@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-zh-hans@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/5c95c11dd93d7b4f6c912b5e8c87b107406e72a1409c8ccf0acf5ef87b0fd464566a5b13661fe80e44c4f1dd9a216ae25f560ce7c1614a950af8f1fb64bcf625
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/65ce7622860502addf813631cbb70170d534764d7de3ef2318a44e39b5a3808e3c2b39945f6b7612ecdf3dbba2653f223bb834a62c6d7ac3b0657f96b6fa06c1
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-monarch-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-monarch-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-language-pack-zh-hant@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-language-pack-zh-hant@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/0cd64ee6e5ae23fbadde35833c86a009428088c93052bef979c51db9e22dcd53fa04177b907d77e23c133769b277845ef79c5407dab214ed27b15c4ae2f5fb81
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/4bb8461d30c6b5ddba2bb23c1890fe3397642c9b1d97b926caf7e7af9a0347624b97a9d95a67f7de5efdbf8a026e99873b3020410b46beae3435bc70ccc0a222
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-python-default-extension@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-python-default-extension@npm:8.0.4"
+"@codingame/monaco-vscode-languages-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-languages-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/d1e638b8a716f5c81ebd90ea15f7380f6448d959343118989dc5022f43e2bd7615ac9c7805d6d961380ecef2dcce21f4f08edbd562f2186c15afa6c0b8ca5b68
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+  checksum: 10c0/f4590a9d33df071c7649094ec99b50f2289e70e7a147a1a2f9905650da84078fc9562d35dd5da38b193a7738501e87a71d49c0cc55a2f5ef6069950d6dfbfa49
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-quickaccess-service-override@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-quickaccess-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-layout-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-layout-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/9dbe054be90b4ae57f295df4071382b71c8ec5e46194af07dc03bc4aeac375e019f068c2ef883453f4234f2b53b8426f2f5475ff8d0e61ebb4892379c07bdb96
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/eca1f91e750129cc1f07be960d7c1a9f2490f5c0ea798875707ef6a0b9fec6c6cdd9c7dc54c4e2ce32c26d2d517d7f8ee65f37cb4e72739d6c25cd80195ceb0e
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-r-default-extension@npm:8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-r-default-extension@npm:8.0.4"
+"@codingame/monaco-vscode-localization-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-localization-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/b83948b58b0e37693f29663fb34a896a689a1abfef28babf848d854574df27ef8b9d8dce6d53df1ac65b015e21929d7abdedf0a662dd6f7ed060fe2b84188471
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/c50d04d622443fddec26d489da060a729a3ff683111162755cdb83ee159bc8b78e5ce7b8d5f521abf0e44357d7049c3d4d67a508d10142f39da64d3e984a1fff
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-textmate-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-textmate-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-log-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-log-service-override@npm:25.1.2"
   dependencies:
-    "@codingame/monaco-vscode-files-service-override": "npm:8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-    vscode-oniguruma: "npm:1.7.0"
-    vscode-textmate: "npm:9.0.0"
-  checksum: 10c0/5a7ffd954bb801e2cb512efa2ff725b37a3dfb6661f050c7ab71761cd73a7d575f857cfd518d65a9412e6e45cd0c9c379a7781275eb3de19188714ee95905540
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-environment-service-override": "npm:25.1.2"
+  checksum: 10c0/f5c98c3afc02bb327afb59562b8d4fc30aba3a6fbd63369de68db63bac28bfe6fbec34f3d9acf1f6e1ece9fccda3d3e70c3e3260c973352cbdd1c8bcfc8d1243
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-theme-defaults-default-extension@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-theme-defaults-default-extension@npm:8.0.4"
+"@codingame/monaco-vscode-model-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-model-service-override@npm:25.1.2"
   dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/500dc8a1ff507a455b405477ea9558e997f23f2777562bb9cb54df0ab0b6e9bf349f0a970bcc321f28ae336379b3444787626c9d70716ce14d4e7efce55c4ec1
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/4c7a15cd3088cd41df076bc9935c154c001c3d33ae353145bf632a31ea2b40c17b1660b92c7742dcc9d447f004f376fce2bdf3a10370d6781f5cc5635c451bb6
   languageName: node
   linkType: hard
 
-"@codingame/monaco-vscode-theme-service-override@npm:~8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-theme-service-override@npm:8.0.4"
+"@codingame/monaco-vscode-monarch-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-monarch-service-override@npm:25.1.2"
   dependencies:
-    "@codingame/monaco-vscode-files-service-override": "npm:8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/9ce94a254f54c95313b59e8db63fe56031584fdb7ea76cf045557ce0076a684d5f2ffdad18fd7d3580331391b529b55d552ea39eac05a0fc2e11ee19122ed2a0
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/ba43c4463f8e641f13408e9c271ee24e57d573b7c6fd54e56d6d8e9cf3b170d0e82a8950bc3ab90ed24de82482249fb532df319b6aba40e24234fdb8a9e66e7d
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-python-default-extension@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-python-default-extension@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/a43b5023805be6237070117065ecb350817596b0819a944a5a4bbce4db9ef71fb45dea06bcbbe871389b4a79489ac1d42b84be02b7a82515338ffbdd521160f7
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-quickaccess-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-quickaccess-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/03e86955a6f1dcbce91d5c13d50f28824452675e5560992118b0e7a1005d50fbebe9ef8b0869b61bcc587abea7d1d5bfa89c60a731c4ee62b9c821a840934b83
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-textmate-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-textmate-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+  checksum: 10c0/1986ced74e425b5d918e9a4b262c3f6a6fa4b7699f3eff5bbfbf397b457f6de5d6d7a6cc74da522aea203f356c0ecd9ac0400beb68a07d85e4fab9d700ed8842
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-theme-defaults-default-extension@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-theme-defaults-default-extension@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/2d5c9af28b18e116ec2962d7c0f4c8d38e729d385243150b2bcd8d513056700b93d17bd020cc038fc0a28ed23795eb100530b5ba1dfdec53a9d391920b4bdde8
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-theme-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-theme-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-files-service-override": "npm:25.1.2"
+  checksum: 10c0/041e562624bcfbf34afb76c4a06f5f1de34a1a654151763d02f25a92fe24ed3e60d35d9087d823cf52edde8d6abf8dfdfb3a6547ba1fd39bf045e5cb4589fbf9
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-view-banner-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-view-banner-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/47030d59c8b702c09954bea6cee5678927bda6b1a619f005a40f2733e07db1262d26af3faa66d88b7fdcf11e80c6a574581e55b6f86e6592384a9a1a9ce4cfa3
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-view-common-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-view-common-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-bulk-edit-service-override": "npm:25.1.2"
+  checksum: 10c0/b17311fbfd1157d0787762b89091841ec37572096f013fe0a37c105f258923360e851c50058f2129869a8f74758cbdbf5c7ce66eb7894565632a9ceb557d1721
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-view-status-bar-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-view-status-bar-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/136a130ff4bdf6ed87c2c7b60b63186751497b7e20e1bdc2af39c6ecdb6747418ecf274736d7377ed1df8dd1571d3b5ecd3a254d83ede2ac9a0285f3310d003e
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-view-title-bar-service-override@npm:25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-view-title-bar-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+  checksum: 10c0/636628e73854043c41a7bd9b3020a8b6830c26f1a96b24fbf24b993a90a98efd3d8df0073b1c8f76bbd9436e53cdb05853534ec70459f0eeaee54aa277189e38
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-views-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-views-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-keybindings-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-layout-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-quickaccess-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-view-common-service-override": "npm:25.1.2"
+  checksum: 10c0/2df81bc7504965b99d39a144f0ae04b2bbde442e28295edd19cd66be19ec71d7b9b63ae30d634f1c3e9bff0abd342d25cdceedf2885e69a7ad85040cffee88ea
+  languageName: node
+  linkType: hard
+
+"@codingame/monaco-vscode-workbench-service-override@npm:^25.1.2":
+  version: 25.1.2
+  resolution: "@codingame/monaco-vscode-workbench-service-override@npm:25.1.2"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:25.1.2"
+    "@codingame/monaco-vscode-keybindings-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-quickaccess-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-view-banner-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-view-common-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-view-status-bar-service-override": "npm:25.1.2"
+    "@codingame/monaco-vscode-view-title-bar-service-override": "npm:25.1.2"
+  checksum: 10c0/594d488fc896ad30cb88e1ac3d094580d771d45528491e4485662a1b0af3733008e6f11e9911dd874fdee45c94acdd5ade87876f1c7ad70438b7af198bbc74ce
   languageName: node
   linkType: hard
 
@@ -6177,6 +6298,13 @@ __metadata:
   languageName: node
   linkType: hard
 
+"@types/trusted-types@npm:^2.0.7":
+  version: 2.0.7
+  resolution: "@types/trusted-types@npm:2.0.7"
+  checksum: 10c0/4c4855f10de7c6c135e0d32ce462419d8abbbc33713b31d294596c0cc34ae1fa6112a2f9da729c8f7a20707782b0d69da3b1f8df6645b0366d08825ca1522e0c
+  languageName: node
+  linkType: hard
+
 "@types/underscore@npm:*":
   version: 1.13.0
   resolution: "@types/underscore@npm:1.13.0"
@@ -6745,10 +6873,10 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@vscode/iconv-lite-umd@npm:0.7.0":
-  version: 0.7.0
-  resolution: "@vscode/iconv-lite-umd@npm:0.7.0"
-  checksum: 10c0/3316664f65f2b2089f58d5f31d09ebc931da01d826c7f57d44740689bc862ba970224ebcf70da6b823b138c80c070f484c98a21ecfddf49c84c614a0b0bd3f6f
+"@vscode/iconv-lite-umd@npm:0.7.1":
+  version: 0.7.1
+  resolution: "@vscode/iconv-lite-umd@npm:0.7.1"
+  checksum: 10c0/ed6026004465fd2b034cae2b4f03df15b16b90d701ac380f2596972cc651dbd143a9fcf4e68472d7cceaf3d8f91fad5b45b72077127f0b275395f6358d841e5a
   languageName: node
   linkType: hard
 
@@ -7022,7 +7150,16 @@ __metadata:
   languageName: node
   linkType: hard
 
-"acorn@npm:^8.0.4, acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1, acorn@npm:^8.9.0":
+"acorn@npm:^8.0.4":
+  version: 8.17.0
+  resolution: "acorn@npm:8.17.0"
+  bin:
+    acorn: bin/acorn
+  checksum: 10c0/5dcefea5f8f023b6cc24cbe71fb5a8112b601d36c4fa07d14e4e6ffc2ee47383332c46b36c766d9437725aa6660156eae50efa0c838719823b50d7c327c4ed42
+  languageName: node
+  linkType: hard
+
+"acorn@npm:^8.11.0, acorn@npm:^8.15.0, acorn@npm:^8.4.1, acorn@npm:^8.9.0":
   version: 8.16.0
   resolution: "acorn@npm:8.16.0"
   bin:
@@ -9094,6 +9231,18 @@ __metadata:
   languageName: node
   linkType: hard
 
+"dompurify@npm:3.3.1":
+  version: 3.3.1
+  resolution: "dompurify@npm:3.3.1"
+  dependencies:
+    "@types/trusted-types": "npm:^2.0.7"
+  dependenciesMeta:
+    "@types/trusted-types":
+      optional: true
+  checksum: 10c0/fa0a8c55a436ba0d54389195e3d2337e311f56de709a2fc9efc98dbbc7746fa53bb4b74b6ac043b77a279a8f2ebd8685f0ebaa6e58c9e32e92051d529bc0baf8
+  languageName: node
+  linkType: hard
+
 "domutils@npm:^3.0.1, domutils@npm:^3.2.2":
   version: 3.2.2
   resolution: "domutils@npm:3.2.2"
@@ -10658,9 +10807,8 @@ __metadata:
     "@angular/platform-browser-dynamic": "npm:21.2.10"
     "@angular/router": "npm:21.2.10"
     "@auth0/angular-jwt": "npm:5.1.0"
-    "@codingame/monaco-vscode-java-default-extension": "npm:8.0.4"
-    "@codingame/monaco-vscode-python-default-extension": "npm:8.0.4"
-    "@codingame/monaco-vscode-r-default-extension": "npm:8.0.4"
+    "@codingame/monaco-vscode-java-default-extension": "npm:25.1.2"
+    "@codingame/monaco-vscode-python-default-extension": "npm:25.1.2"
     "@lezer/python": "npm:1.1.18"
     "@ngneat/until-destroy": "npm:8.1.4"
     "@ngx-formly/core": "npm:6.3.12"
@@ -10707,9 +10855,8 @@ __metadata:
     lodash-es: "npm:4.18.1"
     marked: "npm:17.0.1"
     monaco-breakpoints: "npm:0.2.0"
-    monaco-editor: "npm:@codingame/monaco-vscode-editor-api@8.0.4"
-    monaco-editor-wrapper: "npm:5.5.3"
-    monaco-languageclient: "npm:8.8.3"
+    monaco-editor: "npm:@codingame/monaco-vscode-editor-api@25.1.2"
+    monaco-languageclient: "npm:10.7.0"
     ng-zorro-antd: "npm:21.3.1"
     ngx-color-picker: "npm:12.0.1"
     ngx-file-drop: "npm:16.0.0"
@@ -10736,7 +10883,6 @@ __metadata:
     typescript: "npm:5.9.3"
     uuid: "npm:14.0.0"
     vitest: "npm:4.1.9"
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
     webpack-bundle-analyzer: "npm:4.5.0"
     y-monaco: "npm:0.1.5"
     y-protocols: "npm:1.0.5"
@@ -12577,6 +12723,15 @@ __metadata:
   languageName: node
   linkType: hard
 
+"marked@npm:14.0.0":
+  version: 14.0.0
+  resolution: "marked@npm:14.0.0"
+  bin:
+    marked: bin/marked.js
+  checksum: 10c0/57a47cb110f7b1a10f398b0a7236f9183aad2dcd5345ee73f2732b6387e585d04cef472bc655d2f84c542296be9728e179aebe3ed7f2f8666b8a0a9dae592876
+  languageName: node
+  linkType: hard
+
 "marked@npm:17.0.1":
   version: 17.0.1
   resolution: "marked@npm:17.0.1"
@@ -12939,79 +13094,45 @@ __metadata:
   languageName: node
   linkType: hard
 
-"monaco-editor-wrapper@npm:5.5.3":
-  version: 5.5.3
-  resolution: "monaco-editor-wrapper@npm:5.5.3"
-  dependencies:
-    "@codingame/monaco-vscode-configuration-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-editor-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-cs": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-de": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-es": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-fr": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-it": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-ja": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-ko": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-pl": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-pt-br": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-qps-ploc": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-ru": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-tr": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-zh-hans": "npm:~8.0.4"
-    "@codingame/monaco-vscode-language-pack-zh-hant": "npm:~8.0.4"
-    "@codingame/monaco-vscode-monarch-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-textmate-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-theme-defaults-default-extension": "npm:~8.0.4"
-    "@codingame/monaco-vscode-theme-service-override": "npm:~8.0.4"
-    monaco-editor: "npm:@codingame/monaco-vscode-editor-api@~8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@~8.0.4"
+"monaco-languageclient@npm:10.7.0":
+  version: 10.7.0
+  resolution: "monaco-languageclient@npm:10.7.0"
+  dependencies:
+    "@codingame/monaco-vscode-api": "npm:^25.1.2"
+    "@codingame/monaco-vscode-configuration-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-editor-api": "npm:^25.1.2"
+    "@codingame/monaco-vscode-editor-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-extension-api": "npm:^25.1.2"
+    "@codingame/monaco-vscode-extensions-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-cs": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-de": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-es": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-fr": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-it": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-ja": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-ko": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-pl": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-pt-br": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-qps-ploc": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-ru": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-tr": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-zh-hans": "npm:^25.1.2"
+    "@codingame/monaco-vscode-language-pack-zh-hant": "npm:^25.1.2"
+    "@codingame/monaco-vscode-languages-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-localization-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-log-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-model-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-monarch-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-textmate-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-theme-defaults-default-extension": "npm:^25.1.2"
+    "@codingame/monaco-vscode-theme-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-views-service-override": "npm:^25.1.2"
+    "@codingame/monaco-vscode-workbench-service-override": "npm:^25.1.2"
+    vscode: "npm:@codingame/monaco-vscode-extension-api@^25.1.2"
     vscode-languageclient: "npm:~9.0.1"
     vscode-languageserver-protocol: "npm:~3.17.5"
-    vscode-ws-jsonrpc: "npm:~3.3.2"
-  peerDependencies:
-    monaco-editor: "*"
-    monaco-languageclient: ~8.8.3
-    vscode: "*"
-  peerDependenciesMeta:
-    monaco-editor:
-      optional: false
-    monaco-languageclient:
-      optional: false
-    vscode:
-      optional: false
-  checksum: 10c0/d113ea5408cc178d7f5558e943c9fe59e060ead59d38bcc4944f19f9120814e68d7f39f97ebb1f9ab8df862cfe4810c23bd9744e6543525b607ed0676f60e268
-  languageName: node
-  linkType: hard
-
-"monaco-editor@npm:@codingame/monaco-vscode-editor-api@8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-editor-api@npm:8.0.4"
-  dependencies:
-    vscode: "npm:@codingame/monaco-vscode-api@8.0.4"
-  checksum: 10c0/8ab6eab164826cbca220868c07a6c071e1730ac8cd7e2057353af70d7ff58f054863bb04538ac609a09aea0b0a942eed1651e9d81434e097dfc1b3251fa5ebec
-  languageName: node
-  linkType: hard
-
-"monaco-languageclient@npm:8.8.3":
-  version: 8.8.3
-  resolution: "monaco-languageclient@npm:8.8.3"
-  dependencies:
-    "@codingame/monaco-vscode-extensions-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-languages-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-localization-service-override": "npm:~8.0.4"
-    "@codingame/monaco-vscode-model-service-override": "npm:~8.0.4"
-    monaco-editor: "npm:@codingame/monaco-vscode-editor-api@~8.0.4"
-    vscode: "npm:@codingame/monaco-vscode-api@~8.0.4"
-    vscode-languageclient: "npm:~9.0.1"
-  peerDependencies:
-    monaco-editor: "*"
-    vscode: "*"
-  peerDependenciesMeta:
-    monaco-editor:
-      optional: false
-    vscode:
-      optional: false
-  checksum: 10c0/ed32080a773de3537cae8042c83a79e90e6010f9f9fe8bb1cb57518b75330c676788b2975963ce5a97e12ebbbb32dc561570fa22c5fbeef0f88fa7d0068284b5
+    vscode-ws-jsonrpc: "npm:~3.5.0"
+  checksum: 10c0/b8fd931cc0a490d1a744ab54f8d596eb82808e471d2fbd1f2aec55d1b65fb24243a13a9ff0bd6998af75984289c631aa606c76e3198c6dec691ada151b71ec4a
   languageName: node
   linkType: hard
 
@@ -17698,43 +17819,12 @@ __metadata:
   languageName: node
   linkType: hard
 
-"vscode-oniguruma@npm:1.7.0":
-  version: 1.7.0
-  resolution: "vscode-oniguruma@npm:1.7.0"
-  checksum: 10c0/bef0073c665ddf8c86e51da94529c905856559e9aba97a9882f951acd572da560384775941ab6e7e8db94d9c578b25fefb951e4b73c37e8712e16b0231de2689
-  languageName: node
-  linkType: hard
-
-"vscode-textmate@npm:9.0.0":
-  version: 9.0.0
-  resolution: "vscode-textmate@npm:9.0.0"
-  checksum: 10c0/83d874e1776d93d926eb0eb562476d4fd3f9633074efef056a443aee0f809d6648600b73e451f74687706435a16578a2037629247fac82a8f108ea3ff434048d
-  languageName: node
-  linkType: hard
-
-"vscode-ws-jsonrpc@npm:~3.3.2":
-  version: 3.3.2
-  resolution: "vscode-ws-jsonrpc@npm:3.3.2"
+"vscode-ws-jsonrpc@npm:~3.5.0":
+  version: 3.5.0
+  resolution: "vscode-ws-jsonrpc@npm:3.5.0"
   dependencies:
     vscode-jsonrpc: "npm:~8.2.1"
-  checksum: 10c0/35b71071ccd3c9478d8b4f2c07ef80fa2d988f6e6d4e5d1bfc7109a8282cf091905a5c9f056bb5be8946461cb3be8e50f608825cb82b16e9b7998afc13da5783
-  languageName: node
-  linkType: hard
-
-"vscode@npm:@codingame/monaco-vscode-api@8.0.4":
-  version: 8.0.4
-  resolution: "@codingame/monaco-vscode-api@npm:8.0.4"
-  dependencies:
-    "@codingame/monaco-vscode-base-service-override": "npm:8.0.4"
-    "@codingame/monaco-vscode-environment-service-override": "npm:8.0.4"
-    "@codingame/monaco-vscode-extensions-service-override": "npm:8.0.4"
-    "@codingame/monaco-vscode-files-service-override": "npm:8.0.4"
-    "@codingame/monaco-vscode-host-service-override": "npm:8.0.4"
-    "@codingame/monaco-vscode-layout-service-override": "npm:8.0.4"
-    "@codingame/monaco-vscode-quickaccess-service-override": "npm:8.0.4"
-    "@vscode/iconv-lite-umd": "npm:0.7.0"
-    jschardet: "npm:3.1.3"
-  checksum: 10c0/268b6584f3e5473ecd1e4ee5492477cbf9a670204fe82d8d97490987415b63bf9b40bc539d639e7f0aaf19b982d9445b746465acf6a0b4b669050b5c2c380d21
+  checksum: 10c0/be2297cddeb3850218b1c4529345e2335ead38f8114036eb02f754911a833af6d18f3b7f19ee3596692386f8f00f7d94cb85f3e65ff44381525f0e174b249cfb
   languageName: node
   linkType: hard
 
@@ -18158,8 +18248,8 @@ __metadata:
   linkType: hard
 
 "ws@npm:^7.3.1":
-  version: 7.5.10
-  resolution: "ws@npm:7.5.10"
+  version: 7.5.11
+  resolution: "ws@npm:7.5.11"
   peerDependencies:
     bufferutil: ^4.0.1
     utf-8-validate: ^5.0.2
@@ -18168,7 +18258,7 @@ __metadata:
       optional: true
     utf-8-validate:
       optional: true
-  checksum: 10c0/bd7d5f4aaf04fae7960c23dcb6c6375d525e00f795dd20b9385902bd008c40a94d3db3ce97d878acc7573df852056ca546328b27b39f47609f80fb22a0a9b61d
+  checksum: 10c0/7972670b676fb1ccba73b0899ca3c2e04e8c2075629c2614cced7f556536f96a672bbf4619fc5a06c8b8720bb839a47ca88c69c95dc14c9c61a99fbecba1c866
   languageName: node
   linkType: hard