@theia/plugin-ext 1.63.0-next.24 → 1.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/lib/common/lm-protocol.d.ts +103 -0
  2. package/lib/common/lm-protocol.d.ts.map +1 -0
  3. package/lib/common/lm-protocol.js +21 -0
  4. package/lib/common/lm-protocol.js.map +1 -0
  5. package/lib/common/plugin-api-rpc.d.ts +22 -1
  6. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  7. package/lib/common/plugin-api-rpc.js +4 -2
  8. package/lib/common/plugin-api-rpc.js.map +1 -1
  9. package/lib/common/plugin-protocol.d.ts +6 -0
  10. package/lib/common/plugin-protocol.d.ts.map +1 -1
  11. package/lib/common/plugin-protocol.js.map +1 -1
  12. package/lib/hosted/browser/worker/worker-plugin-module.d.ts.map +1 -1
  13. package/lib/hosted/browser/worker/worker-plugin-module.js +2 -0
  14. package/lib/hosted/browser/worker/worker-plugin-module.js.map +1 -1
  15. package/lib/hosted/node/plugin-host-module.d.ts.map +1 -1
  16. package/lib/hosted/node/plugin-host-module.js +4 -0
  17. package/lib/hosted/node/plugin-host-module.js.map +1 -1
  18. package/lib/main/browser/comments/comment-thread-widget.d.ts +1 -2
  19. package/lib/main/browser/comments/comment-thread-widget.d.ts.map +1 -1
  20. package/lib/main/browser/comments/comment-thread-widget.js +8 -6
  21. package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
  22. package/lib/main/browser/documents-main.d.ts +3 -3
  23. package/lib/main/browser/documents-main.d.ts.map +1 -1
  24. package/lib/main/browser/documents-main.js +41 -28
  25. package/lib/main/browser/documents-main.js.map +1 -1
  26. package/lib/main/browser/editors-and-documents-main.d.ts +1 -0
  27. package/lib/main/browser/editors-and-documents-main.d.ts.map +1 -1
  28. package/lib/main/browser/editors-and-documents-main.js +4 -1
  29. package/lib/main/browser/editors-and-documents-main.js.map +1 -1
  30. package/lib/main/browser/lm-main.d.ts +17 -0
  31. package/lib/main/browser/lm-main.d.ts.map +1 -0
  32. package/lib/main/browser/lm-main.js +119 -0
  33. package/lib/main/browser/lm-main.js.map +1 -0
  34. package/lib/main/browser/main-context.d.ts.map +1 -1
  35. package/lib/main/browser/main-context.js +4 -3
  36. package/lib/main/browser/main-context.js.map +1 -1
  37. package/lib/main/browser/text-editor-model-service.d.ts +9 -2
  38. package/lib/main/browser/text-editor-model-service.d.ts.map +1 -1
  39. package/lib/main/browser/text-editor-model-service.js +10 -0
  40. package/lib/main/browser/text-editor-model-service.js.map +1 -1
  41. package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
  42. package/lib/main/browser/view/tree-view-widget.js +4 -3
  43. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  44. package/lib/main/browser/workspace-main.d.ts +20 -0
  45. package/lib/main/browser/workspace-main.d.ts.map +1 -1
  46. package/lib/main/browser/workspace-main.js +54 -15
  47. package/lib/main/browser/workspace-main.js.map +1 -1
  48. package/lib/plugin/document-data.d.ts +3 -1
  49. package/lib/plugin/document-data.d.ts.map +1 -1
  50. package/lib/plugin/document-data.js +7 -1
  51. package/lib/plugin/document-data.js.map +1 -1
  52. package/lib/plugin/documents.d.ts +7 -1
  53. package/lib/plugin/documents.d.ts.map +1 -1
  54. package/lib/plugin/documents.js +21 -3
  55. package/lib/plugin/documents.js.map +1 -1
  56. package/lib/plugin/editors-and-documents.d.ts.map +1 -1
  57. package/lib/plugin/editors-and-documents.js +1 -1
  58. package/lib/plugin/editors-and-documents.js.map +1 -1
  59. package/lib/plugin/lm-ext.d.ts +52 -0
  60. package/lib/plugin/lm-ext.d.ts.map +1 -0
  61. package/lib/plugin/lm-ext.js +131 -0
  62. package/lib/plugin/lm-ext.js.map +1 -0
  63. package/lib/plugin/notebook/notebook-document.d.ts.map +1 -1
  64. package/lib/plugin/notebook/notebook-document.js +2 -1
  65. package/lib/plugin/notebook/notebook-document.js.map +1 -1
  66. package/lib/plugin/plugin-context.d.ts.map +1 -1
  67. package/lib/plugin/plugin-context.js +34 -12
  68. package/lib/plugin/plugin-context.js.map +1 -1
  69. package/lib/plugin/types-impl.d.ts +79 -0
  70. package/lib/plugin/types-impl.d.ts.map +1 -1
  71. package/lib/plugin/types-impl.js +43 -1
  72. package/lib/plugin/types-impl.js.map +1 -1
  73. package/lib/plugin/workspace.d.ts +11 -0
  74. package/lib/plugin/workspace.d.ts.map +1 -1
  75. package/lib/plugin/workspace.js +33 -0
  76. package/lib/plugin/workspace.js.map +1 -1
  77. package/package.json +30 -29
  78. package/src/common/lm-protocol.ts +137 -0
  79. package/src/common/plugin-api-rpc.ts +12 -4
  80. package/src/common/plugin-protocol.ts +7 -0
  81. package/src/hosted/browser/worker/worker-plugin-module.ts +2 -0
  82. package/src/hosted/node/plugin-host-module.ts +4 -0
  83. package/src/main/browser/comments/comment-thread-widget.tsx +6 -7
  84. package/src/main/browser/documents-main.ts +49 -39
  85. package/src/main/browser/editors-and-documents-main.ts +5 -1
  86. package/src/main/browser/lm-main.ts +136 -0
  87. package/src/main/browser/main-context.ts +5 -3
  88. package/src/main/browser/text-editor-model-service.ts +14 -2
  89. package/src/main/browser/view/tree-view-widget.tsx +4 -3
  90. package/src/main/browser/workspace-main.ts +66 -1
  91. package/src/plugin/document-data.ts +8 -1
  92. package/src/plugin/documents.ts +22 -5
  93. package/src/plugin/editors-and-documents.ts +2 -1
  94. package/src/plugin/lm-ext.ts +158 -0
  95. package/src/plugin/notebook/notebook-document.ts +2 -1
  96. package/src/plugin/plugin-context.ts +41 -16
  97. package/src/plugin/types-impl.ts +104 -0
  98. package/src/plugin/workspace.ts +39 -1
package/package.json CHANGED
@@ -1,37 +1,38 @@
1
1
  {
2
2
  "name": "@theia/plugin-ext",
3
- "version": "1.63.0-next.24+83b50cc66",
3
+ "version": "1.63.0",
4
4
  "description": "Theia - Plugin Extension",
5
5
  "main": "lib/common/index.js",
6
6
  "typings": "lib/common/index.d.ts",
7
7
  "dependencies": {
8
- "@theia/bulk-edit": "1.63.0-next.24+83b50cc66",
9
- "@theia/callhierarchy": "1.63.0-next.24+83b50cc66",
10
- "@theia/console": "1.63.0-next.24+83b50cc66",
11
- "@theia/core": "1.63.0-next.24+83b50cc66",
12
- "@theia/debug": "1.63.0-next.24+83b50cc66",
13
- "@theia/editor": "1.63.0-next.24+83b50cc66",
14
- "@theia/editor-preview": "1.63.0-next.24+83b50cc66",
15
- "@theia/file-search": "1.63.0-next.24+83b50cc66",
16
- "@theia/filesystem": "1.63.0-next.24+83b50cc66",
17
- "@theia/markers": "1.63.0-next.24+83b50cc66",
18
- "@theia/messages": "1.63.0-next.24+83b50cc66",
19
- "@theia/monaco": "1.63.0-next.24+83b50cc66",
8
+ "@theia/ai-mcp": "1.63.0",
9
+ "@theia/bulk-edit": "1.63.0",
10
+ "@theia/callhierarchy": "1.63.0",
11
+ "@theia/console": "1.63.0",
12
+ "@theia/core": "1.63.0",
13
+ "@theia/debug": "1.63.0",
14
+ "@theia/editor": "1.63.0",
15
+ "@theia/editor-preview": "1.63.0",
16
+ "@theia/file-search": "1.63.0",
17
+ "@theia/filesystem": "1.63.0",
18
+ "@theia/markers": "1.63.0",
19
+ "@theia/messages": "1.63.0",
20
+ "@theia/monaco": "1.63.0",
20
21
  "@theia/monaco-editor-core": "1.96.302",
21
- "@theia/navigator": "1.63.0-next.24+83b50cc66",
22
- "@theia/notebook": "1.63.0-next.24+83b50cc66",
23
- "@theia/output": "1.63.0-next.24+83b50cc66",
24
- "@theia/plugin": "1.63.0-next.24+83b50cc66",
25
- "@theia/preferences": "1.63.0-next.24+83b50cc66",
26
- "@theia/scm": "1.63.0-next.24+83b50cc66",
27
- "@theia/search-in-workspace": "1.63.0-next.24+83b50cc66",
28
- "@theia/task": "1.63.0-next.24+83b50cc66",
29
- "@theia/terminal": "1.63.0-next.24+83b50cc66",
30
- "@theia/test": "1.63.0-next.24+83b50cc66",
31
- "@theia/timeline": "1.63.0-next.24+83b50cc66",
32
- "@theia/typehierarchy": "1.63.0-next.24+83b50cc66",
33
- "@theia/variable-resolver": "1.63.0-next.24+83b50cc66",
34
- "@theia/workspace": "1.63.0-next.24+83b50cc66",
22
+ "@theia/navigator": "1.63.0",
23
+ "@theia/notebook": "1.63.0",
24
+ "@theia/output": "1.63.0",
25
+ "@theia/plugin": "1.63.0",
26
+ "@theia/preferences": "1.63.0",
27
+ "@theia/scm": "1.63.0",
28
+ "@theia/search-in-workspace": "1.63.0",
29
+ "@theia/task": "1.63.0",
30
+ "@theia/terminal": "1.63.0",
31
+ "@theia/test": "1.63.0",
32
+ "@theia/timeline": "1.63.0",
33
+ "@theia/typehierarchy": "1.63.0",
34
+ "@theia/variable-resolver": "1.63.0",
35
+ "@theia/workspace": "1.63.0",
35
36
  "@types/mime": "^2.0.1",
36
37
  "@vscode/debugprotocol": "^1.51.0",
37
38
  "@vscode/proxy-agent": "^0.13.2",
@@ -89,7 +90,7 @@
89
90
  "watch": "theiaext watch"
90
91
  },
91
92
  "devDependencies": {
92
- "@theia/ext-scripts": "1.62.0",
93
+ "@theia/ext-scripts": "1.63.0",
93
94
  "@types/decompress": "^4.2.2",
94
95
  "@types/escape-html": "^0.0.20",
95
96
  "@types/lodash.clonedeep": "^4.5.3",
@@ -98,5 +99,5 @@
98
99
  "nyc": {
99
100
  "extends": "../../configs/nyc.json"
100
101
  },
101
- "gitHead": "83b50cc66b001a5b9100ccd944dcace04cd4ae2e"
102
+ "gitHead": "facf442522991134333495a0b90cf56a56990280"
102
103
  }
@@ -0,0 +1,137 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2025 EclipseSource.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { UriComponents } from './uri-components';
18
+
19
+ /**
20
+ * Protocol interfaces for MCP server definition providers.
21
+ */
22
+
23
+ export interface McpStdioServerDefinitionDto {
24
+ /**
25
+ * The human-readable name of the server.
26
+ */
27
+ readonly label: string;
28
+
29
+ /**
30
+ * The working directory used to start the server.
31
+ */
32
+ cwd?: UriComponents;
33
+
34
+ /**
35
+ * The command used to start the server. Node.js-based servers may use
36
+ * `process.execPath` to use the editor's version of Node.js to run the script.
37
+ */
38
+ command: string;
39
+
40
+ /**
41
+ * Additional command-line arguments passed to the server.
42
+ */
43
+ args?: string[];
44
+
45
+ /**
46
+ * Optional additional environment information for the server. Variables
47
+ * in this environment will overwrite or remove (if null) the default
48
+ * environment variables of the editor's extension host.
49
+ */
50
+ env?: Record<string, string | number | null>;
51
+
52
+ /**
53
+ * Optional version identification for the server. If this changes, the
54
+ * editor will indicate that tools have changed and prompt to refresh them.
55
+ */
56
+ version?: string;
57
+
58
+ }
59
+
60
+ /**
61
+ * McpHttpServerDefinition represents an MCP server available using the
62
+ * Streamable HTTP transport.
63
+ */
64
+ export interface McpHttpServerDefinitionDto {
65
+ /**
66
+ * The human-readable name of the server.
67
+ */
68
+ readonly label: string;
69
+
70
+ /**
71
+ * The URI of the server. The editor will make a POST request to this URI
72
+ * to begin each session.
73
+ */
74
+ uri: UriComponents;
75
+
76
+ /**
77
+ * Optional additional heads included with each request to the server.
78
+ */
79
+ headers?: Record<string, string>;
80
+
81
+ /**
82
+ * Optional version identification for the server. If this changes, the
83
+ * editor will indicate that tools have changed and prompt to refresh them.
84
+ */
85
+ version?: string;
86
+ }
87
+
88
+ /**
89
+ * Definitions that describe different types of Model Context Protocol servers,
90
+ * which can be returned from the {@link McpServerDefinitionProvider}.
91
+ */
92
+ export type McpServerDefinitionDto = McpStdioServerDefinitionDto | McpHttpServerDefinitionDto;
93
+ export const isMcpHttpServerDefinitionDto = (definition: McpServerDefinitionDto): definition is McpHttpServerDefinitionDto => 'uri' in definition;
94
+ /**
95
+ * Main side of the MCP server definition registry.
96
+ */
97
+ export interface McpServerDefinitionRegistryMain {
98
+ /**
99
+ * Register an MCP server definition provider.
100
+ */
101
+ $registerMcpServerDefinitionProvider(handle: number, name: string): void;
102
+
103
+ /**
104
+ * Unregister an MCP server definition provider.
105
+ */
106
+ $unregisterMcpServerDefinitionProvider(handle: number): void;
107
+
108
+ /**
109
+ * Notify that server definitions have changed.
110
+ */
111
+ $onDidChangeMcpServerDefinitions(handle: number): void;
112
+
113
+ /**
114
+ * Get server definitions from a provider.
115
+ */
116
+ $getServerDefinitions(handle: number): Promise<McpServerDefinitionDto[]>;
117
+
118
+ /**
119
+ * Resolve a server definition.
120
+ */
121
+ $resolveServerDefinition(handle: number, server: McpServerDefinitionDto): Promise<McpServerDefinitionDto | undefined>;
122
+ }
123
+
124
+ /**
125
+ * Extension side of the MCP server definition registry.
126
+ */
127
+ export interface McpServerDefinitionRegistryExt {
128
+ /**
129
+ * Request server definitions from a provider.
130
+ */
131
+ $provideServerDefinitions(handle: number): Promise<McpServerDefinitionDto[]>;
132
+
133
+ /**
134
+ * Resolve a server definition from a provider.
135
+ */
136
+ $resolveServerDefinition(handle: number, server: McpServerDefinitionDto): Promise<McpServerDefinitionDto | undefined>;
137
+ }
@@ -127,6 +127,7 @@ import { AccessibilityInformation } from '@theia/core/lib/common/accessibility';
127
127
  import { TreeDelta } from '@theia/test/lib/common/tree-delta';
128
128
  import { TestItemDTO, TestOutputDTO, TestRunDTO, TestRunProfileDTO, TestRunRequestDTO, TestStateChangeDTO } from './test-types';
129
129
  import { ArgumentProcessor } from './commands';
130
+ import { McpServerDefinitionRegistryMain, McpServerDefinitionRegistryExt } from './lm-protocol';
130
131
 
131
132
  export interface PreferenceData {
132
133
  [scope: number]: any;
@@ -768,6 +769,9 @@ export interface WorkspaceMain {
768
769
  $registerCanonicalUriProvider(scheme: string): Promise<void | undefined>;
769
770
  $unregisterCanonicalUriProvider(scheme: string): void;
770
771
  $getCanonicalUri(uri: string, targetScheme: string, token: theia.CancellationToken): Promise<string | undefined>;
772
+ $resolveDecoding(resource: UriComponents | undefined, options?: { encoding?: string }): Promise<{ preferredEncoding: string; guessEncoding: boolean; }>;
773
+ $resolveEncoding(resource: UriComponents | undefined, options?: { encoding?: string }): Promise<{ encoding: string; hasBOM: boolean }>;
774
+ $getValidEncoding(uri: UriComponents | undefined, detectedEncoding: string | undefined, opts: { encoding: string; } | undefined): Promise<string>;
771
775
  }
772
776
 
773
777
  export interface WorkspaceExt {
@@ -1366,6 +1370,7 @@ export interface ModelAddedData {
1366
1370
  EOL: string;
1367
1371
  modeId: string;
1368
1372
  isDirty: boolean;
1373
+ encoding: string;
1369
1374
  }
1370
1375
 
1371
1376
  export interface TextEditorAddData {
@@ -1415,13 +1420,14 @@ export interface DocumentsExt {
1415
1420
  $acceptModelSaved(strUrl: UriComponents): void;
1416
1421
  $acceptModelWillSave(strUrl: UriComponents, reason: theia.TextDocumentSaveReason, saveTimeout: number): Promise<SingleEditOperation[]>;
1417
1422
  $acceptDirtyStateChanged(strUrl: UriComponents, isDirty: boolean): void;
1423
+ $acceptEncodingChanged(strUrl: UriComponents, encoding: string): void;
1418
1424
  $acceptModelChanged(strUrl: UriComponents, e: ModelChangedEvent, isDirty: boolean): void;
1419
1425
  }
1420
1426
 
1421
1427
  export interface DocumentsMain {
1422
- $tryCreateDocument(options?: { language?: string; content?: string; }): Promise<UriComponents>;
1428
+ $tryCreateDocument(options?: { language?: string; content?: string; encoding?: string }): Promise<UriComponents>;
1423
1429
  $tryShowDocument(uri: UriComponents, options?: TextDocumentShowOptions): Promise<void>;
1424
- $tryOpenDocument(uri: UriComponents): Promise<boolean>;
1430
+ $tryOpenDocument(uri: UriComponents, encoding?: string): Promise<boolean>;
1425
1431
  $trySaveDocument(uri: UriComponents): Promise<boolean>;
1426
1432
  }
1427
1433
 
@@ -2346,7 +2352,8 @@ export const PLUGIN_RPC_CONTEXT = {
2346
2352
  TELEMETRY_MAIN: createProxyIdentifier<TelemetryMain>('TelemetryMain'),
2347
2353
  LOCALIZATION_MAIN: createProxyIdentifier<LocalizationMain>('LocalizationMain'),
2348
2354
  TESTING_MAIN: createProxyIdentifier<TestingMain>('TestingMain'),
2349
- URI_MAIN: createProxyIdentifier<UriMain>('UriMain')
2355
+ URI_MAIN: createProxyIdentifier<UriMain>('UriMain'),
2356
+ MCP_SERVER_DEFINITION_REGISTRY_MAIN: createProxyIdentifier<McpServerDefinitionRegistryMain>('McpServerDefinitionRegistryMain')
2350
2357
  };
2351
2358
 
2352
2359
  export const MAIN_RPC_CONTEXT = {
@@ -2389,7 +2396,8 @@ export const MAIN_RPC_CONTEXT = {
2389
2396
  TABS_EXT: createProxyIdentifier<TabsExt>('TabsExt'),
2390
2397
  TELEMETRY_EXT: createProxyIdentifier<TelemetryExt>('TelemetryExt)'),
2391
2398
  TESTING_EXT: createProxyIdentifier<TestingExt>('TestingExt'),
2392
- URI_EXT: createProxyIdentifier<UriExt>('UriExt')
2399
+ URI_EXT: createProxyIdentifier<UriExt>('UriExt'),
2400
+ MCP_SERVER_DEFINITION_REGISTRY_EXT: createProxyIdentifier<McpServerDefinitionRegistryExt>('McpServerDefinitionRegistryExt')
2393
2401
  };
2394
2402
 
2395
2403
  export interface TasksExt {
@@ -104,6 +104,7 @@ export interface PluginPackageContribution {
104
104
  notebooks?: PluginPackageNotebook[];
105
105
  notebookRenderer?: PluginNotebookRendererContribution[];
106
106
  notebookPreload?: PluginPackageNotebookPreload[];
107
+ mcpServerDefinitionProviders?: PluginPackageMcpServerDefinitionProviderContribution[];
107
108
  }
108
109
 
109
110
  export interface PluginPackageNotebook {
@@ -126,6 +127,12 @@ export interface PluginPackageNotebookPreload {
126
127
  entrypoint: string;
127
128
  }
128
129
 
130
+ export interface PluginPackageMcpServerDefinitionProviderContribution {
131
+ id: string;
132
+ label: string;
133
+ description?: string;
134
+ }
135
+
129
136
  export interface PluginPackageAuthenticationProvider {
130
137
  id: string;
131
138
  label: string;
@@ -35,6 +35,7 @@ import { EnvExtImpl } from '../../../plugin/env';
35
35
  import { WorkerEnvExtImpl } from './worker-env-ext';
36
36
  import { DebugExtImpl } from '../../../plugin/debug/debug-ext';
37
37
  import { LocalizationExtImpl } from '../../../plugin/localization-ext';
38
+ import { EncodingService } from '@theia/core/lib/common/encoding-service';
38
39
 
39
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
41
  const ctx = self as any;
@@ -70,6 +71,7 @@ export default new ContainerModule(bind => {
70
71
  child.bind(DebugExtImpl).toSelf();
71
72
  return createDebugExtStub(child);
72
73
  }).inSingletonScope();
74
+ bind(EncodingService).toSelf().inSingletonScope();
73
75
  bind(EditorsAndDocumentsExtImpl).toSelf().inSingletonScope();
74
76
  bind(WorkspaceExtImpl).toSelf().inSingletonScope();
75
77
  bind(MessageRegistryExt).toSelf().inSingletonScope();
@@ -36,6 +36,8 @@ import { WebviewsExtImpl } from '../../plugin/webviews';
36
36
  import { TerminalServiceExtImpl } from '../../plugin/terminal-ext';
37
37
  import { InternalSecretsExt, SecretsExtImpl } from '../../plugin/secrets-ext';
38
38
  import { setupPluginHostLogger } from './plugin-host-logger';
39
+ import { LmExtImpl } from '../../plugin/lm-ext';
40
+ import { EncodingService } from '@theia/core/lib/common/encoding-service';
39
41
 
40
42
  export default new ContainerModule(bind => {
41
43
  const channel = new IPCChannel();
@@ -63,6 +65,8 @@ export default new ContainerModule(bind => {
63
65
  bind(SecretsExtImpl).toSelf().inSingletonScope();
64
66
  bind(PreferenceRegistryExtImpl).toSelf().inSingletonScope();
65
67
  bind(DebugExtImpl).toSelf().inSingletonScope();
68
+ bind(LmExtImpl).toSelf().inSingletonScope();
69
+ bind(EncodingService).toSelf().inSingletonScope();
66
70
  bind(EditorsAndDocumentsExtImpl).toSelf().inSingletonScope();
67
71
  bind(WorkspaceExtImpl).toSelf().inSingletonScope();
68
72
  bind(MessageRegistryExt).toSelf().inSingletonScope();
@@ -57,7 +57,6 @@ export class CommentThreadWidget extends BaseWidget {
57
57
  protected readonly zoneWidget: MonacoEditorZoneWidget;
58
58
  protected readonly containerNodeRoot: Root;
59
59
  protected readonly commentGlyphWidget: CommentGlyphWidget;
60
- protected readonly contextMenu: CompoundMenuNode;
61
60
  protected readonly commentFormRef: RefObject<CommentForm> = React.createRef<CommentForm>();
62
61
 
63
62
  protected isExpanded?: boolean;
@@ -101,8 +100,8 @@ export class CommentThreadWidget extends BaseWidget {
101
100
  this.toDispose.push(this._commentThread.onDidChangeState(_state => {
102
101
  this.update();
103
102
  }));
104
- this.contextMenu = this.menus.getMenu(COMMENT_THREAD_CONTEXT);
105
- this.contextMenu.children.forEach(node => {
103
+ const contextMenu = this.menus.getMenu(COMMENT_THREAD_CONTEXT);
104
+ contextMenu?.children.forEach(node => {
106
105
  if (node.onDidChange) {
107
106
  this.toDispose.push(node.onDidChange(() => {
108
107
  const commentForm = this.commentFormRef.current;
@@ -560,7 +559,7 @@ export class ReviewComment<P extends ReviewComment.Props = ReviewComment.Props>
560
559
  <span className={'isPending'}>{comment.label}</span>
561
560
  <div className={'theia-comments-inline-actions-container'}>
562
561
  <div className={'theia-comments-inline-actions'} role={'toolbar'}>
563
- {hover && menus.getMenuNode(COMMENT_TITLE) && menus.getMenu(COMMENT_TITLE).children.map((node, index): React.ReactNode => CommandMenu.is(node) &&
562
+ {hover && menus.getMenuNode(COMMENT_TITLE) && menus.getMenu(COMMENT_TITLE)?.children.map((node, index): React.ReactNode => CommandMenu.is(node) &&
564
563
  <CommentsInlineAction key={index} {...{
565
564
  node, nodePath: [...COMMENT_TITLE, node.id], commands, commentThread, commentUniqueId,
566
565
  contextKeyService, commentsContext
@@ -662,7 +661,7 @@ export class CommentEditContainer extends React.Component<CommentEditContainer.P
662
661
  </div>
663
662
  </div>
664
663
  <div className={'form-actions'}>
665
- {menus.getMenu(COMMENT_CONTEXT).children.map((node, index): React.ReactNode => {
664
+ {menus.getMenu(COMMENT_CONTEXT)?.children.map((node, index): React.ReactNode => {
666
665
  const onClick = () => {
667
666
  commands.executeCommand(node.id, {
668
667
  commentControlHandle: commentThread.controllerHandle,
@@ -722,7 +721,7 @@ namespace CommentActions {
722
721
  contextKeyService: ContextKeyService;
723
722
  commentsContext: CommentsContext;
724
723
  menuPath: MenuPath,
725
- menu: CompoundMenuNode;
724
+ menu: CompoundMenuNode | undefined;
726
725
  commentThread: CommentThread;
727
726
  getInput: () => string;
728
727
  clearInput: () => void;
@@ -733,7 +732,7 @@ export class CommentActions extends React.Component<CommentActions.Props> {
733
732
  override render(): React.ReactNode {
734
733
  const { contextKeyService, commentsContext, menuPath, menu, commentThread, getInput, clearInput } = this.props;
735
734
  return <div className={'form-actions'}>
736
- {menu.children.map((node, index) => CommandMenu.is(node) &&
735
+ {menu?.children.map((node, index) => CommandMenu.is(node) &&
737
736
  <CommentAction key={index}
738
737
  nodePath={menuPath}
739
738
  node={node}
@@ -16,14 +16,14 @@
16
16
  import { DocumentsMain, MAIN_RPC_CONTEXT, DocumentsExt } from '../../common/plugin-api-rpc';
17
17
  import { UriComponents } from '../../common/uri-components';
18
18
  import { EditorsAndDocumentsMain } from './editors-and-documents-main';
19
- import { DisposableCollection, Disposable, UntitledResourceResolver, CancellationToken } from '@theia/core';
19
+ import { DisposableCollection, Disposable, UntitledResourceResolver } from '@theia/core';
20
20
  import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
21
21
  import { RPCProtocol } from '../../common/rpc-protocol';
22
22
  import { EditorModelService } from './text-editor-model-service';
23
- import { EditorOpenerOptions } from '@theia/editor/lib/browser';
23
+ import { EditorOpenerOptions, EncodingMode } from '@theia/editor/lib/browser';
24
24
  import URI from '@theia/core/lib/common/uri';
25
25
  import { URI as CodeURI } from '@theia/core/shared/vscode-uri';
26
- import { ApplicationShell, SaveOptions, SaveReason } from '@theia/core/lib/browser';
26
+ import { ApplicationShell, SaveReason } from '@theia/core/lib/browser';
27
27
  import { TextDocumentShowOptions } from '../../common/plugin-api-rpc-model';
28
28
  import { Range } from '@theia/core/shared/vscode-languageserver-protocol';
29
29
  import { OpenerService } from '@theia/core/lib/browser/opener-service';
@@ -33,8 +33,6 @@ import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
33
33
  import * as monaco from '@theia/monaco-editor-core';
34
34
  import { TextDocumentChangeReason } from '../../plugin/types-impl';
35
35
  import { NotebookDocumentsMainImpl } from './notebooks/notebook-documents-main';
36
- import { MonacoEditorProvider, SAVE_PARTICIPANT_DEFAULT_ORDER } from '@theia/monaco/lib/browser/monaco-editor-provider';
37
- import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
38
36
 
39
37
  /*---------------------------------------------------------------------------------------------
40
38
  * Copyright (c) Microsoft Corporation. All rights reserved.
@@ -99,8 +97,7 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
99
97
  private openerService: OpenerService,
100
98
  private shell: ApplicationShell,
101
99
  private untitledResourceResolver: UntitledResourceResolver,
102
- private languageService: MonacoLanguages,
103
- monacoEditorProvider: MonacoEditorProvider
100
+ private languageService: MonacoLanguages
104
101
  ) {
105
102
  this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.DOCUMENTS_EXT);
106
103
 
@@ -114,39 +111,36 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
114
111
  this.toDispose.push(modelService.onModelSaved(m => {
115
112
  this.proxy.$acceptModelSaved(m.textEditorModel.uri);
116
113
  }));
117
- this.toDispose.push(monacoEditorProvider.registerSaveParticipant(({
118
- order: SAVE_PARTICIPANT_DEFAULT_ORDER,
119
- applyChangesOnSave: async (
120
- editor: MonacoEditor,
121
- cancellationToken: CancellationToken,
122
- options: SaveOptions): Promise<void> => {
123
-
124
- const saveReason = options.saveReason ?? SaveReason.Manual;
125
-
126
- const edits = await this.proxy.$acceptModelWillSave(editor.uri.toComponents(), saveReason.valueOf(), this.saveTimeout);
127
- const editOperations: monaco.editor.IIdentifiedSingleEditOperation[] = [];
128
- for (const edit of edits) {
129
- const { range, text } = edit;
130
- if (!range && !text) {
131
- continue;
132
- }
133
- if (range && range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn && !edit.text) {
134
- continue;
135
- }
136
-
137
- editOperations.push({
138
- range: range ? monaco.Range.lift(range) : editor.document.textEditorModel.getFullModelRange(),
139
- /* eslint-disable-next-line no-null/no-null */
140
- text: text || null,
141
- forceMoveMarkers: edit.forceMoveMarkers
142
- });
114
+ this.toDispose.push(modelService.onModelWillSave(async e => {
115
+
116
+ const saveReason = e.options?.saveReason ?? SaveReason.Manual;
117
+
118
+ const edits = await this.proxy.$acceptModelWillSave(new URI(e.model.uri).toComponents(), saveReason.valueOf(), this.saveTimeout);
119
+ const editOperations: monaco.editor.IIdentifiedSingleEditOperation[] = [];
120
+ for (const edit of edits) {
121
+ const { range, text } = edit;
122
+ if (!range && !text) {
123
+ continue;
124
+ }
125
+ if (range && range.startLineNumber === range.endLineNumber && range.startColumn === range.endColumn && !edit.text) {
126
+ continue;
143
127
  }
144
- editor.document.textEditorModel.applyEdits(editOperations);
128
+
129
+ editOperations.push({
130
+ range: range ? monaco.Range.lift(range) : e.model.textEditorModel.getFullModelRange(),
131
+ /* eslint-disable-next-line no-null/no-null */
132
+ text: text || null,
133
+ forceMoveMarkers: edit.forceMoveMarkers
134
+ });
145
135
  }
146
- })));
136
+ e.model.textEditorModel.applyEdits(editOperations);
137
+ }));
147
138
  this.toDispose.push(modelService.onModelDirtyChanged(m => {
148
139
  this.proxy.$acceptDirtyStateChanged(m.textEditorModel.uri, m.dirty);
149
140
  }));
141
+ this.toDispose.push(modelService.onModelEncodingChanged(e => {
142
+ this.proxy.$acceptEncodingChanged(e.model.textEditorModel.uri, e.encoding);
143
+ }));
150
144
  }
151
145
 
152
146
  dispose(): void {
@@ -192,10 +186,11 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
192
186
  }
193
187
  }
194
188
 
195
- async $tryCreateDocument(options?: { language?: string; content?: string; }): Promise<UriComponents> {
189
+ async $tryCreateDocument(options?: { language?: string; content?: string; encoding?: string }): Promise<UriComponents> {
196
190
  const language = options?.language && this.languageService.getExtension(options.language);
197
191
  const content = options?.content;
198
- const resource = await this.untitledResourceResolver.createUntitledResource(content, language);
192
+ const encoding = options?.encoding;
193
+ const resource = await this.untitledResourceResolver.createUntitledResource(content, language, undefined, encoding);
199
194
  return monaco.Uri.parse(resource.uri.toString());
200
195
  }
201
196
 
@@ -217,9 +212,24 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
217
212
  return this.modelService.save(new URI(CodeURI.revive(uri)));
218
213
  }
219
214
 
220
- async $tryOpenDocument(uri: UriComponents): Promise<boolean> {
221
- const ref = await this.modelService.createModelReference(new URI(CodeURI.revive(uri)));
215
+ async $tryOpenDocument(uri: UriComponents, encoding?: string): Promise<boolean> {
216
+ // Convert URI to Theia URI
217
+ const theiaUri = new URI(CodeURI.revive(uri));
218
+
219
+ // Create model reference
220
+ const ref = await this.modelService.createModelReference(theiaUri);
221
+
222
222
  if (ref.object) {
223
+ // If we have encoding option, make sure to apply it
224
+ if (encoding && ref.object.setEncoding) {
225
+ try {
226
+ await ref.object.setEncoding(encoding, EncodingMode.Decode);
227
+ } catch (e) {
228
+ // If encoding fails, log error but continue
229
+ console.error(`Failed to set encoding ${encoding} for ${theiaUri.toString()}`, e);
230
+ }
231
+ }
232
+
223
233
  this.modelReferenceCache.add(ref);
224
234
  return true;
225
235
  } else {
@@ -37,6 +37,7 @@ import { SaveableService } from '@theia/core/lib/browser/saveable-service';
37
37
  import { TabsMainImpl } from './tabs/tabs-main';
38
38
  import { NotebookCellEditorService, NotebookEditorWidgetService } from '@theia/notebook/lib/browser';
39
39
  import { SimpleMonacoEditor } from '@theia/monaco/lib/browser/simple-monaco-editor';
40
+ import { EncodingRegistry } from '@theia/core/lib/browser/encoding-registry';
40
41
 
41
42
  export class EditorsAndDocumentsMain implements Disposable {
42
43
 
@@ -48,6 +49,7 @@ export class EditorsAndDocumentsMain implements Disposable {
48
49
  private readonly modelService: EditorModelService;
49
50
  private readonly editorManager: EditorManager;
50
51
  private readonly saveResourceService: SaveableService;
52
+ private readonly encodingRegistry: EncodingRegistry;
51
53
 
52
54
  private readonly onTextEditorAddEmitter = new Emitter<TextEditorMain[]>();
53
55
  private readonly onTextEditorRemoveEmitter = new Emitter<string[]>();
@@ -69,6 +71,7 @@ export class EditorsAndDocumentsMain implements Disposable {
69
71
  this.editorManager = container.get(EditorManager);
70
72
  this.modelService = container.get(EditorModelService);
71
73
  this.saveResourceService = container.get(SaveableService);
74
+ this.encodingRegistry = container.get(EncodingRegistry);
72
75
 
73
76
  this.stateComputer = new EditorAndDocumentStateComputer(d => this.onDelta(d),
74
77
  this.editorManager,
@@ -153,7 +156,8 @@ export class EditorsAndDocumentsMain implements Disposable {
153
156
  languageId: model.getLanguageId(),
154
157
  EOL: model.textEditorModel.getEOL(),
155
158
  modeId: model.languageId,
156
- isDirty: model.dirty
159
+ isDirty: model.dirty,
160
+ encoding: this.encodingRegistry.getEncodingForResource(URI.fromComponents(model.textEditorModel.uri), model.getEncoding())
157
161
  };
158
162
  }
159
163