diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d8ff1b8e4171..8aed2f4a66368 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,47 @@ - [Previous Changelogs](https://github.com/eclipse-theia/theia/tree/master/doc/changelogs/) - -- [core] Updated AuthenticationService to handle multiple accounts per provider [#14149](https://github.com/eclipse-theia/theia/pull/14149) - Contributed on behalf of STMicroelectronics -- [ai] Add toolbar actions on chat nodes [#14181](https://github.com/eclipse-theia/theia/pull/14181) - Contributed on behalf of STMicroelectronics +## 1.54.0 - 09/26/2024 + +- [ai] add Theia AI LLM Support [Experimental] [#14048](https://github.com/eclipse-theia/theia/pull/14048) +- [ai] adapted default LLM for Theia AI to gpt-4o [#14165](https://github.com/eclipse-theia/theia/pull/14165) +- [ai] add enable state of agent to preferences [#14206](https://github.com/eclipse-theia/theia/pull/14206) +- [ai] chore: polished AI code completion [#14192](https://github.com/eclipse-theia/theia/pull/14192) +- [ai] consistently named agents and added tags [#14182](https://github.com/eclipse-theia/theia/pull/14182) +- [ai] feat: added toolbar actions for chat nodes [#14181](https://github.com/eclipse-theia/theia/pull/14181) - Contributed on behalf of STMicroelectronics +- [ai] feat: show variables and functions on AI agent configuration [#14177](https://github.com/eclipse-theia/theia/pull/14177) +- [ai] feat: supported models served via OpenAI API [#14172](https://github.com/eclipse-theia/theia/pull/14172) +- [ai] fixed ai-settings retrieval [#14221](https://github.com/eclipse-theia/theia/pull/14221) +- [ai] fixed enablement of AI support [#14166](https://github.com/eclipse-theia/theia/pull/14166) +- [ai] improved prompt of workspace agent [#14159](https://github.com/eclipse-theia/theia/pull/14159) +- [ai] refined AI settings [#14202](https://github.com/eclipse-theia/theia/pull/14202) +- [ai] refined experimental message for AI features [#14187](https://github.com/eclipse-theia/theia/pull/14187) +- [ai] removed type duplication for kind property [#14207](https://github.com/eclipse-theia/theia/pull/14207) +- [ai] consistent prompt ids [#14162](https://github.com/eclipse-theia/theia/pull/14162) +- [ai] fix: disabled an agent also disabled its UIContribution [#14184](https://github.com/eclipse-theia/theia/pull/14184) +- [application-package] bumped API version to 1.93.1 [#14224](https://github.com/eclipse-theia/theia/pull/14224) - Contributed on behalf of STMicroelectronics +- [core] fixed selection of contributed menu action argument adapters [#14132](https://github.com/eclipse-theia/theia/pull/14132) - Contributed on behalf of STMicroelectronics +- [core] supported proxy env variable for schema catalog download [#14130](https://github.com/eclipse-theia/theia/pull/14130) +- [core] supported workbench.editorAssociations preference [#14139](https://github.com/eclipse-theia/theia/pull/14139) +- [editor] aligned active text and notebook editor more towards vscode [#14190](https://github.com/eclipse-theia/theia/pull/14190) +- [filesystem] fixed FileResource sometimes sending contents change event during writing [#14043](https://github.com/eclipse-theia/theia/pull/14043) - Contributed on behalf of Toro Cloud +- [notebook] focused notebook cell container correctly [#14175](https://github.com/eclipse-theia/theia/pull/14175) +- [notebook] fixed notebook context selection [#14179](https://github.com/eclipse-theia/theia/pull/14179) +- [notebook] made the cell editor border grey when not focused [#14195](https://github.com/eclipse-theia/theia/pull/14195) +- [plugin] removed stub tag from TerminalOptions#color [#14171](https://github.com/eclipse-theia/theia/pull/14171) +- [plugin] moved stubbed API TerminalShellIntegration into main API [#14168](https://github.com/eclipse-theia/theia/pull/14168) - Contributed on behalf of STMicroelectronics +- [plugin] supported evolution on proposed API extensionAny [#14199](https://github.com/eclipse-theia/theia/pull/14199) - Contributed on behalf of STMicroelectronics +- [plugin] updated TreeView reveal options to be readonly [#14198](https://github.com/eclipse-theia/theia/pull/14198) - Contributed on behalf of STMicroelectronics +- [plugin-ext] properly supported executeDocumentSymbolProvider command [#14173](https://github.com/eclipse-theia/theia/pull/14173) +- [plugin-ext] fixed leak in tabs-main.ts [#14186](https://github.com/eclipse-theia/theia/pull/14186) +- [preferences] expanded plugin preferences on scroll correctly [#14170](https://github.com/eclipse-theia/theia/pull/14170) +- [test] supported TestMessage stack traces [#14154](https://github.com/eclipse-theia/theia/pull/14154) - Contributed on behalf of STMicroelectronics +- [workspace] handled only the user workspace security settings [#14147](https://github.com/eclipse-theia/theia/pull/14147) + +[Breaking Changes:](#breaking_changes_1.54.0) + +- [ai] added toolbar actions on chat nodes [#14181](https://github.com/eclipse-theia/theia/pull/14181) - Contributed on behalf of STMicroelectronics +- [core] updated AuthenticationService to handle multiple accounts per provider [#14149](https://github.com/eclipse-theia/theia/pull/14149) - Contributed on behalf of STMicroelectronics ## 1.53.0 - 08/29/2024 diff --git a/dev-packages/application-manager/package.json b/dev-packages/application-manager/package.json index 253333063f3d8..3ab87e9160235 100644 --- a/dev-packages/application-manager/package.json +++ b/dev-packages/application-manager/package.json @@ -1,6 +1,6 @@ { "name": "@theia/application-manager", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia application manager API.", "publishConfig": { "access": "public" @@ -33,9 +33,9 @@ "@babel/plugin-transform-classes": "^7.10.0", "@babel/plugin-transform-runtime": "^7.10.0", "@babel/preset-env": "^7.10.0", - "@theia/application-package": "1.53.0", - "@theia/ffmpeg": "1.53.0", - "@theia/native-webpack-plugin": "1.53.0", + "@theia/application-package": "1.54.0", + "@theia/ffmpeg": "1.54.0", + "@theia/native-webpack-plugin": "1.54.0", "@types/fs-extra": "^4.0.2", "@types/semver": "^7.5.0", "babel-loader": "^8.2.2", @@ -74,7 +74,7 @@ } }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/node-abi": "*" }, "nyc": { diff --git a/dev-packages/application-package/package.json b/dev-packages/application-package/package.json index 5b9d6fdb4b895..642f2d38ae863 100644 --- a/dev-packages/application-package/package.json +++ b/dev-packages/application-package/package.json @@ -1,6 +1,6 @@ { "name": "@theia/application-package", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia application package API.", "publishConfig": { "access": "public" @@ -29,7 +29,7 @@ "watch": "theiaext watch" }, "dependencies": { - "@theia/request": "1.53.0", + "@theia/request": "1.54.0", "@types/fs-extra": "^4.0.2", "@types/semver": "^7.5.0", "@types/write-json-file": "^2.2.1", @@ -43,7 +43,7 @@ "write-json-file": "^2.2.0" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/dev-packages/application-package/src/api.ts b/dev-packages/application-package/src/api.ts index 2b0276ac5d6f2..b824ab9a72c55 100644 --- a/dev-packages/application-package/src/api.ts +++ b/dev-packages/application-package/src/api.ts @@ -18,4 +18,4 @@ * The default supported API version the framework supports. * The version should be in the format `x.y.z`. */ -export const DEFAULT_SUPPORTED_API_VERSION = '1.92.2'; +export const DEFAULT_SUPPORTED_API_VERSION = '1.93.1'; diff --git a/dev-packages/cli/package.json b/dev-packages/cli/package.json index 585de9466de36..5dde36d20d869 100644 --- a/dev-packages/cli/package.json +++ b/dev-packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@theia/cli", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia CLI.", "publishConfig": { "access": "public" @@ -32,12 +32,12 @@ "clean": "theiaext clean" }, "dependencies": { - "@theia/application-manager": "1.53.0", - "@theia/application-package": "1.53.0", - "@theia/ffmpeg": "1.53.0", - "@theia/localization-manager": "1.53.0", - "@theia/ovsx-client": "1.53.0", - "@theia/request": "1.53.0", + "@theia/application-manager": "1.54.0", + "@theia/application-package": "1.54.0", + "@theia/ffmpeg": "1.54.0", + "@theia/localization-manager": "1.54.0", + "@theia/ovsx-client": "1.54.0", + "@theia/request": "1.54.0", "@types/chai": "^4.2.7", "@types/mocha": "^10.0.0", "@types/node-fetch": "^2.5.7", diff --git a/dev-packages/ffmpeg/package.json b/dev-packages/ffmpeg/package.json index 04b6c254c6995..8e516fe0f99a2 100644 --- a/dev-packages/ffmpeg/package.json +++ b/dev-packages/ffmpeg/package.json @@ -1,6 +1,6 @@ { "name": "@theia/ffmpeg", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia FFMPEG reader utility.", "publishConfig": { "access": "public" diff --git a/dev-packages/localization-manager/package.json b/dev-packages/localization-manager/package.json index 0b17fa8efce24..d902aff6c108c 100644 --- a/dev-packages/localization-manager/package.json +++ b/dev-packages/localization-manager/package.json @@ -1,6 +1,6 @@ { "name": "@theia/localization-manager", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia localization manager API.", "publishConfig": { "access": "public" @@ -40,7 +40,7 @@ "typescript": "~5.4.5" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/dev-packages/native-webpack-plugin/package.json b/dev-packages/native-webpack-plugin/package.json index 47de634969c89..cf2394dc898af 100644 --- a/dev-packages/native-webpack-plugin/package.json +++ b/dev-packages/native-webpack-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@theia/native-webpack-plugin", - "version": "1.53.0", + "version": "1.54.0", "description": "Webpack Plugin for native dependencies of Theia.", "publishConfig": { "access": "public" diff --git a/dev-packages/ovsx-client/package.json b/dev-packages/ovsx-client/package.json index 160fe418dc6b3..3a16cb7fd5918 100644 --- a/dev-packages/ovsx-client/package.json +++ b/dev-packages/ovsx-client/package.json @@ -1,6 +1,6 @@ { "name": "@theia/ovsx-client", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia Open-VSX Client", "publishConfig": { "access": "public" @@ -29,7 +29,7 @@ "watch": "theiaext watch" }, "dependencies": { - "@theia/request": "1.53.0", + "@theia/request": "1.54.0", "limiter": "^2.1.0", "semver": "^7.5.4", "tslib": "^2.6.2" diff --git a/dev-packages/private-eslint-plugin/package.json b/dev-packages/private-eslint-plugin/package.json index ef8aa9cb183a1..df56642978462 100644 --- a/dev-packages/private-eslint-plugin/package.json +++ b/dev-packages/private-eslint-plugin/package.json @@ -1,16 +1,16 @@ { "private": true, "name": "@theia/eslint-plugin", - "version": "1.53.0", + "version": "1.54.0", "description": "Custom ESLint rules for developing Theia extensions and applications", "main": "index.js", "scripts": { "prepare": "tsc -b" }, "dependencies": { - "@theia/core": "1.53.0", - "@theia/ext-scripts": "1.53.0", - "@theia/re-exports": "1.53.0", + "@theia/core": "1.54.0", + "@theia/ext-scripts": "1.54.0", + "@theia/re-exports": "1.54.0", "js-levenshtein": "^1.1.6" } } diff --git a/dev-packages/private-ext-scripts/package.json b/dev-packages/private-ext-scripts/package.json index 1ab8efa73e4b6..7cbc0f55acee9 100644 --- a/dev-packages/private-ext-scripts/package.json +++ b/dev-packages/private-ext-scripts/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@theia/ext-scripts", - "version": "1.53.0", + "version": "1.54.0", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "description": "NPM scripts for Theia packages.", "bin": { diff --git a/dev-packages/private-re-exports/package.json b/dev-packages/private-re-exports/package.json index e91f290766f93..d5076c0f8e950 100644 --- a/dev-packages/private-re-exports/package.json +++ b/dev-packages/private-re-exports/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@theia/re-exports", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia re-export helper functions and scripts.", "main": "lib/index.js", "engines": { diff --git a/dev-packages/request/package.json b/dev-packages/request/package.json index 58f272d50880c..f55e01682458e 100644 --- a/dev-packages/request/package.json +++ b/dev-packages/request/package.json @@ -1,6 +1,6 @@ { "name": "@theia/request", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia Proxy-Aware Request Service", "publishConfig": { "access": "public" diff --git a/doc/Plugin-API.md b/doc/Plugin-API.md index ae614f70a101b..54c0f91e27a64 100644 --- a/doc/Plugin-API.md +++ b/doc/Plugin-API.md @@ -77,9 +77,9 @@ For headless plugins, "Main-Ext" pattern is very similar, except that there is o ![Communication between Theia and Plugin API for Headless Plugins](./images/headless-plugin-diagram.svg) -As the lifecycle of a plugin starts inside its process on the `Ext` side, anything that the plugin needs from Theia (e.g. state, command execution, access to services) has to be invoked over RCP via an implementation on the `Main` side. +As the lifecycle of a plugin starts inside its process on the `Ext` side, anything that the plugin needs from Theia (e.g. state, command execution, access to services) has to be invoked over RPC via an implementation on the `Main` side. In the inverse direction, the same is true for code that runs on the `Main` side and that needs something from the plugin side (e.g. changing plugin state after a user input). -It needs to be invoked over RCP via an implementation on the `Ext` side. +It needs to be invoked over RPC via an implementation on the `Ext` side. Therefore, `Main` and `Ext` interfaces usually come in pairs (e.g. [LanguagesExt](https://github.com/eclipse-theia/theia/blob/541b300adc029ab1dd729da1ca49179ace1447b2/packages/plugin-ext/src/common/plugin-api-rpc.ts#L1401) and [LanguagesMain](https://github.com/eclipse-theia/theia/blob/541b300adc029ab1dd729da1ca49179ace1447b2/packages/plugin-ext/src/common/plugin-api-rpc.ts#L1474)). To communicate with each other, the implementation of each side of the API - `Main` and `Ext` - has an RPC proxy of its corresponding counterpart. @@ -160,9 +160,9 @@ export function createAPIFactory( ### Adding new Ext and Main interfaces with implementations -`Ext` and `Main` interfaces only contain the functions called over RCP. +`Ext` and `Main` interfaces only contain the functions called over RPC. Further functions are just part of the implementations. -Functions to be called over RCP must start with `$`, e.g. `$executeStuff`. +Functions to be called over RPC must start with `$`, e.g. `$executeStuff`. - Define `Ext` and `Main` interfaces in [plugin-ext/src/common/plugin-api-rpc.ts](https://github.com/eclipse-theia/theia/blob/master/packages/plugin-ext/src/common/plugin-api-rpc.ts). The interfaces should be suffixed with `Ext` and `Main` correspondingly (e.g. `LanguagesMain` and `LanguagesExt`). diff --git a/examples/api-provider-sample/package.json b/examples/api-provider-sample/package.json index 33d76b3bf09ce..410a1d085df1e 100644 --- a/examples/api-provider-sample/package.json +++ b/examples/api-provider-sample/package.json @@ -1,12 +1,12 @@ { "private": true, "name": "@theia/api-provider-sample", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Example code to demonstrate Theia API Provider Extensions", "dependencies": { - "@theia/core": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/plugin-ext-headless": "1.53.0" + "@theia/core": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/plugin-ext-headless": "1.54.0" }, "theiaExtensions": [ { @@ -37,6 +37,6 @@ "clean": "theiaext clean" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" } } diff --git a/examples/api-samples/package.json b/examples/api-samples/package.json index ae2ecda230173..410372c39b76e 100644 --- a/examples/api-samples/package.json +++ b/examples/api-samples/package.json @@ -1,22 +1,22 @@ { "private": true, "name": "@theia/api-samples", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Example code to demonstrate Theia API", "dependencies": { - "@theia/ai-chat-ui": "1.53.0", - "@theia/core": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/ai-chat-ui": "1.54.0", + "@theia/core": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/output": "1.53.0", - "@theia/ovsx-client": "1.53.0", - "@theia/search-in-workspace": "1.53.0", - "@theia/test": "1.53.0", - "@theia/toolbar": "1.53.0", - "@theia/vsx-registry": "1.53.0", - "@theia/workspace": "1.53.0" + "@theia/output": "1.54.0", + "@theia/ovsx-client": "1.54.0", + "@theia/search-in-workspace": "1.54.0", + "@theia/test": "1.54.0", + "@theia/toolbar": "1.54.0", + "@theia/vsx-registry": "1.54.0", + "@theia/workspace": "1.54.0" }, "theiaExtensions": [ { @@ -58,6 +58,6 @@ "clean": "theiaext clean" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" } } diff --git a/examples/api-tests/package.json b/examples/api-tests/package.json index 32a8954956517..ffad1dc080294 100644 --- a/examples/api-tests/package.json +++ b/examples/api-tests/package.json @@ -1,9 +1,9 @@ { "name": "@theia/api-tests", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia API tests", "dependencies": { - "@theia/core": "1.53.0" + "@theia/core": "1.54.0" }, "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "repository": { diff --git a/examples/browser-only/package.json b/examples/browser-only/package.json index bec4142e20b8c..dc2bbce1b8f8c 100644 --- a/examples/browser-only/package.json +++ b/examples/browser-only/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@theia/example-browser-only", - "version": "1.53.0", + "version": "1.54.0", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "theia": { "target": "browser-only", @@ -15,57 +15,57 @@ } }, "dependencies": { - "@theia/ai-chat": "1.53.0", - "@theia/ai-chat-ui": "1.53.0", - "@theia/ai-code-completion": "1.53.0", - "@theia/ai-core": "1.53.0", - "@theia/ai-history": "1.53.0", - "@theia/ai-openai": "1.53.0", - "@theia/ai-ollama": "1.53.0", - "@theia/api-samples": "1.53.0", - "@theia/bulk-edit": "1.53.0", - "@theia/callhierarchy": "1.53.0", - "@theia/collaboration": "1.53.0", - "@theia/console": "1.53.0", - "@theia/core": "1.53.0", - "@theia/debug": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/editor-preview": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/getting-started": "1.53.0", - "@theia/git": "1.53.0", - "@theia/keymaps": "1.53.0", - "@theia/markers": "1.53.0", - "@theia/memory-inspector": "1.53.0", - "@theia/messages": "1.53.0", - "@theia/metrics": "1.53.0", - "@theia/mini-browser": "1.53.0", - "@theia/monaco": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/outline-view": "1.53.0", - "@theia/output": "1.53.0", - "@theia/plugin-dev": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/plugin-ext-vscode": "1.53.0", - "@theia/plugin-metrics": "1.53.0", - "@theia/preferences": "1.53.0", - "@theia/preview": "1.53.0", - "@theia/process": "1.53.0", - "@theia/property-view": "1.53.0", - "@theia/scm": "1.53.0", - "@theia/scm-extra": "1.53.0", - "@theia/search-in-workspace": "1.53.0", - "@theia/secondary-window": "1.53.0", - "@theia/task": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/timeline": "1.53.0", - "@theia/toolbar": "1.53.0", - "@theia/typehierarchy": "1.53.0", - "@theia/userstorage": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/vsx-registry": "1.53.0", - "@theia/workspace": "1.53.0" + "@theia/ai-chat": "1.54.0", + "@theia/ai-chat-ui": "1.54.0", + "@theia/ai-code-completion": "1.54.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-history": "1.54.0", + "@theia/ai-ollama": "1.54.0", + "@theia/ai-openai": "1.54.0", + "@theia/api-samples": "1.54.0", + "@theia/bulk-edit": "1.54.0", + "@theia/callhierarchy": "1.54.0", + "@theia/collaboration": "1.54.0", + "@theia/console": "1.54.0", + "@theia/core": "1.54.0", + "@theia/debug": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/editor-preview": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/getting-started": "1.54.0", + "@theia/git": "1.54.0", + "@theia/keymaps": "1.54.0", + "@theia/markers": "1.54.0", + "@theia/memory-inspector": "1.54.0", + "@theia/messages": "1.54.0", + "@theia/metrics": "1.54.0", + "@theia/mini-browser": "1.54.0", + "@theia/monaco": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/outline-view": "1.54.0", + "@theia/output": "1.54.0", + "@theia/plugin-dev": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/plugin-ext-vscode": "1.54.0", + "@theia/plugin-metrics": "1.54.0", + "@theia/preferences": "1.54.0", + "@theia/preview": "1.54.0", + "@theia/process": "1.54.0", + "@theia/property-view": "1.54.0", + "@theia/scm": "1.54.0", + "@theia/scm-extra": "1.54.0", + "@theia/search-in-workspace": "1.54.0", + "@theia/secondary-window": "1.54.0", + "@theia/task": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/timeline": "1.54.0", + "@theia/toolbar": "1.54.0", + "@theia/typehierarchy": "1.54.0", + "@theia/userstorage": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/vsx-registry": "1.54.0", + "@theia/workspace": "1.54.0" }, "scripts": { "prepare:no-native": "lerna run prepare --scope=\"@theia/re-exports\" && lerna run generate-theia-re-exports --scope=\"@theia/core\"", @@ -81,6 +81,6 @@ "watch:compile": "tsc -b -w" }, "devDependencies": { - "@theia/cli": "1.53.0" + "@theia/cli": "1.54.0" } } diff --git a/examples/browser/package.json b/examples/browser/package.json index 21ce9dccb8410..f121e2b09e290 100644 --- a/examples/browser/package.json +++ b/examples/browser/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "@theia/example-browser", - "version": "1.53.0", + "version": "1.54.0", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "theia": { "frontend": { @@ -20,64 +20,64 @@ } }, "dependencies": { - "@theia/ai-chat": "1.53.0", - "@theia/ai-chat-ui": "1.53.0", - "@theia/ai-code-completion": "1.53.0", - "@theia/ai-core": "1.53.0", - "@theia/ai-history": "1.53.0", - "@theia/ai-openai": "1.53.0", - "@theia/ai-ollama": "1.53.0", - "@theia/ai-terminal": "1.53.0", - "@theia/ai-workspace-agent": "1.53.0", - "@theia/api-provider-sample": "1.53.0", - "@theia/api-samples": "1.53.0", - "@theia/bulk-edit": "1.53.0", - "@theia/callhierarchy": "1.53.0", - "@theia/collaboration": "1.53.0", - "@theia/console": "1.53.0", - "@theia/core": "1.53.0", - "@theia/debug": "1.53.0", - "@theia/dev-container": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/editor-preview": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/getting-started": "1.53.0", - "@theia/keymaps": "1.53.0", - "@theia/markers": "1.53.0", - "@theia/memory-inspector": "1.53.0", - "@theia/messages": "1.53.0", - "@theia/metrics": "1.53.0", - "@theia/mini-browser": "1.53.0", - "@theia/monaco": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/notebook": "1.53.0", - "@theia/outline-view": "1.53.0", - "@theia/output": "1.53.0", - "@theia/plugin-dev": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/plugin-ext-headless": "1.53.0", - "@theia/plugin-ext-vscode": "1.53.0", - "@theia/plugin-metrics": "1.53.0", - "@theia/preferences": "1.53.0", - "@theia/preview": "1.53.0", - "@theia/process": "1.53.0", - "@theia/property-view": "1.53.0", - "@theia/remote": "1.53.0", - "@theia/scm": "1.53.0", - "@theia/scm-extra": "1.53.0", - "@theia/search-in-workspace": "1.53.0", - "@theia/secondary-window": "1.53.0", - "@theia/task": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/test": "1.53.0", - "@theia/timeline": "1.53.0", - "@theia/toolbar": "1.53.0", - "@theia/typehierarchy": "1.53.0", - "@theia/userstorage": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/vsx-registry": "1.53.0", - "@theia/workspace": "1.53.0" + "@theia/ai-chat": "1.54.0", + "@theia/ai-chat-ui": "1.54.0", + "@theia/ai-code-completion": "1.54.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-history": "1.54.0", + "@theia/ai-ollama": "1.54.0", + "@theia/ai-openai": "1.54.0", + "@theia/ai-terminal": "1.54.0", + "@theia/ai-workspace-agent": "1.54.0", + "@theia/api-provider-sample": "1.54.0", + "@theia/api-samples": "1.54.0", + "@theia/bulk-edit": "1.54.0", + "@theia/callhierarchy": "1.54.0", + "@theia/collaboration": "1.54.0", + "@theia/console": "1.54.0", + "@theia/core": "1.54.0", + "@theia/debug": "1.54.0", + "@theia/dev-container": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/editor-preview": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/getting-started": "1.54.0", + "@theia/keymaps": "1.54.0", + "@theia/markers": "1.54.0", + "@theia/memory-inspector": "1.54.0", + "@theia/messages": "1.54.0", + "@theia/metrics": "1.54.0", + "@theia/mini-browser": "1.54.0", + "@theia/monaco": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/notebook": "1.54.0", + "@theia/outline-view": "1.54.0", + "@theia/output": "1.54.0", + "@theia/plugin-dev": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/plugin-ext-headless": "1.54.0", + "@theia/plugin-ext-vscode": "1.54.0", + "@theia/plugin-metrics": "1.54.0", + "@theia/preferences": "1.54.0", + "@theia/preview": "1.54.0", + "@theia/process": "1.54.0", + "@theia/property-view": "1.54.0", + "@theia/remote": "1.54.0", + "@theia/scm": "1.54.0", + "@theia/scm-extra": "1.54.0", + "@theia/search-in-workspace": "1.54.0", + "@theia/secondary-window": "1.54.0", + "@theia/task": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/test": "1.54.0", + "@theia/timeline": "1.54.0", + "@theia/toolbar": "1.54.0", + "@theia/typehierarchy": "1.54.0", + "@theia/userstorage": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/vsx-registry": "1.54.0", + "@theia/workspace": "1.54.0" }, "scripts": { "clean": "theia clean", @@ -100,6 +100,6 @@ "watch:compile": "tsc -b -w" }, "devDependencies": { - "@theia/cli": "1.53.0" + "@theia/cli": "1.54.0" } } diff --git a/examples/electron/package.json b/examples/electron/package.json index 6080cd438088e..04482481be284 100644 --- a/examples/electron/package.json +++ b/examples/electron/package.json @@ -2,7 +2,7 @@ "private": true, "name": "@theia/example-electron", "productName": "Theia Electron Example", - "version": "1.53.0", + "version": "1.54.0", "main": "lib/backend/electron-main.js", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "theia": { @@ -26,63 +26,63 @@ } }, "dependencies": { - "@theia/ai-chat": "1.53.0", - "@theia/ai-chat-ui": "1.53.0", - "@theia/ai-code-completion": "1.53.0", - "@theia/ai-core": "1.53.0", - "@theia/ai-history": "1.53.0", - "@theia/ai-openai": "1.53.0", - "@theia/ai-ollama": "1.53.0", - "@theia/ai-terminal": "1.53.0", - "@theia/ai-workspace-agent": "1.53.0", - "@theia/api-provider-sample": "1.53.0", - "@theia/api-samples": "1.53.0", - "@theia/bulk-edit": "1.53.0", - "@theia/callhierarchy": "1.53.0", - "@theia/collaboration": "1.53.0", - "@theia/console": "1.53.0", - "@theia/core": "1.53.0", - "@theia/debug": "1.53.0", - "@theia/dev-container": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/editor-preview": "1.53.0", - "@theia/electron": "1.53.0", - "@theia/external-terminal": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/getting-started": "1.53.0", - "@theia/keymaps": "1.53.0", - "@theia/markers": "1.53.0", - "@theia/memory-inspector": "1.53.0", - "@theia/messages": "1.53.0", - "@theia/metrics": "1.53.0", - "@theia/mini-browser": "1.53.0", - "@theia/monaco": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/outline-view": "1.53.0", - "@theia/output": "1.53.0", - "@theia/plugin-dev": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/plugin-ext-headless": "1.53.0", - "@theia/plugin-ext-vscode": "1.53.0", - "@theia/preferences": "1.53.0", - "@theia/preview": "1.53.0", - "@theia/process": "1.53.0", - "@theia/property-view": "1.53.0", - "@theia/remote": "1.53.0", - "@theia/scm": "1.53.0", - "@theia/scm-extra": "1.53.0", - "@theia/search-in-workspace": "1.53.0", - "@theia/secondary-window": "1.53.0", - "@theia/task": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/timeline": "1.53.0", - "@theia/toolbar": "1.53.0", - "@theia/typehierarchy": "1.53.0", - "@theia/userstorage": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/vsx-registry": "1.53.0", - "@theia/workspace": "1.53.0" + "@theia/ai-chat": "1.54.0", + "@theia/ai-chat-ui": "1.54.0", + "@theia/ai-code-completion": "1.54.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-history": "1.54.0", + "@theia/ai-ollama": "1.54.0", + "@theia/ai-openai": "1.54.0", + "@theia/ai-terminal": "1.54.0", + "@theia/ai-workspace-agent": "1.54.0", + "@theia/api-provider-sample": "1.54.0", + "@theia/api-samples": "1.54.0", + "@theia/bulk-edit": "1.54.0", + "@theia/callhierarchy": "1.54.0", + "@theia/collaboration": "1.54.0", + "@theia/console": "1.54.0", + "@theia/core": "1.54.0", + "@theia/debug": "1.54.0", + "@theia/dev-container": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/editor-preview": "1.54.0", + "@theia/electron": "1.54.0", + "@theia/external-terminal": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/getting-started": "1.54.0", + "@theia/keymaps": "1.54.0", + "@theia/markers": "1.54.0", + "@theia/memory-inspector": "1.54.0", + "@theia/messages": "1.54.0", + "@theia/metrics": "1.54.0", + "@theia/mini-browser": "1.54.0", + "@theia/monaco": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/outline-view": "1.54.0", + "@theia/output": "1.54.0", + "@theia/plugin-dev": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/plugin-ext-headless": "1.54.0", + "@theia/plugin-ext-vscode": "1.54.0", + "@theia/preferences": "1.54.0", + "@theia/preview": "1.54.0", + "@theia/process": "1.54.0", + "@theia/property-view": "1.54.0", + "@theia/remote": "1.54.0", + "@theia/scm": "1.54.0", + "@theia/scm-extra": "1.54.0", + "@theia/search-in-workspace": "1.54.0", + "@theia/secondary-window": "1.54.0", + "@theia/task": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/timeline": "1.54.0", + "@theia/toolbar": "1.54.0", + "@theia/typehierarchy": "1.54.0", + "@theia/userstorage": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/vsx-registry": "1.54.0", + "@theia/workspace": "1.54.0" }, "scripts": { "build": "yarn -s compile && yarn -s bundle", @@ -100,7 +100,7 @@ "watch:compile": "tsc -b -w" }, "devDependencies": { - "@theia/cli": "1.53.0", + "@theia/cli": "1.54.0", "electron": "^30.1.2" } } diff --git a/examples/playwright/package.json b/examples/playwright/package.json index 0d0b175d74bf6..3d42b8481bf3a 100644 --- a/examples/playwright/package.json +++ b/examples/playwright/package.json @@ -1,6 +1,6 @@ { "name": "@theia/playwright", - "version": "1.53.0", + "version": "1.54.0", "description": "System tests for Theia", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "repository": { diff --git a/lerna.json b/lerna.json index 2221326102421..63463ee9ae474 100644 --- a/lerna.json +++ b/lerna.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/lerna.json", "npmClient": "yarn", - "version": "1.53.0", + "version": "1.54.0", "command": { "run": { "stream": true diff --git a/packages/ai-chat-ui/package.json b/packages/ai-chat-ui/package.json index 895049bd2d70e..0edf7837f7294 100644 --- a/packages/ai-chat-ui/package.json +++ b/packages/ai-chat-ui/package.json @@ -1,17 +1,17 @@ { "name": "@theia/ai-chat-ui", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - AI Chat UI Extension", "dependencies": { - "@theia/ai-core": "1.53.0", - "@theia/ai-chat": "1.53.0", - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-chat": "1.54.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/editor-preview": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/editor-preview": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2", "uuid": "^9.0.1" @@ -50,7 +50,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-chat-ui/src/browser/ai-chat-ui-frontend-module.ts b/packages/ai-chat-ui/src/browser/ai-chat-ui-frontend-module.ts index 293d58c26c5c7..285f2cadd42fc 100644 --- a/packages/ai-chat-ui/src/browser/ai-chat-ui-frontend-module.ts +++ b/packages/ai-chat-ui/src/browser/ai-chat-ui-frontend-module.ts @@ -35,6 +35,7 @@ import { ChatViewMenuContribution } from './chat-view-contribution'; import { ChatViewLanguageContribution } from './chat-view-language-contribution'; import { ChatViewWidget } from './chat-view-widget'; import { ChatViewWidgetToolbarContribution } from './chat-view-widget-toolbar-contribution'; +import { EditorPreviewManager } from '@theia/editor-preview/lib/browser/editor-preview-manager'; export default new ContainerModule((bind, _unbind, _isBound, rebind) => { bindViewContribution(bind, AIChatContribution); @@ -71,6 +72,7 @@ export default new ContainerModule((bind, _unbind, _isBound, rebind) => { bind(AIEditorManager).toSelf().inSingletonScope(); rebind(EditorManager).toService(AIEditorManager); + rebind(EditorPreviewManager).toService(AIEditorManager); bindContributionProvider(bind, AIEditorSelectionResolver); bind(AIEditorSelectionResolver).to(GitHubSelectionResolver).inSingletonScope(); diff --git a/packages/ai-chat-ui/src/browser/chat-response-renderer/markdown-part-renderer.tsx b/packages/ai-chat-ui/src/browser/chat-response-renderer/markdown-part-renderer.tsx index a2fcc7329d53b..8fba51ad2fcbd 100644 --- a/packages/ai-chat-ui/src/browser/chat-response-renderer/markdown-part-renderer.tsx +++ b/packages/ai-chat-ui/src/browser/chat-response-renderer/markdown-part-renderer.tsx @@ -15,7 +15,7 @@ // ***************************************************************************** import { ChatResponsePartRenderer } from '../chat-response-part-renderer'; -import { inject, injectable } from '@theia/core/shared/inversify'; +import { injectable } from '@theia/core/shared/inversify'; import { ChatResponseContent, InformationalChatResponseContent, @@ -23,12 +23,13 @@ import { } from '@theia/ai-chat/lib/common'; import { ReactNode, useEffect, useRef } from '@theia/core/shared/react'; import * as React from '@theia/core/shared/react'; +import * as markdownit from '@theia/core/shared/markdown-it'; +import * as DOMPurify from '@theia/core/shared/dompurify'; import { MarkdownString } from '@theia/core/lib/common/markdown-rendering'; -import { MarkdownRenderer } from '@theia/core/lib/browser/markdown-rendering/markdown-renderer'; @injectable() export class MarkdownPartRenderer implements ChatResponsePartRenderer { - @inject(MarkdownRenderer) private renderer: MarkdownRenderer; + protected readonly markdownIt = markdownit(); canHandle(response: ChatResponseContent): number { if (MarkdownChatResponseContent.is(response)) { return 10; @@ -38,9 +39,6 @@ export class MarkdownPartRenderer implements ChatResponsePartRenderer; + + return ; } } -export const MarkdownWrapper = (props: { data: MarkdownString, renderCallback: (md: MarkdownString) => HTMLElement }) => { - // eslint-disable-next-line no-null/no-null - const ref: React.MutableRefObject = useRef(null); +const MarkdownRender = ({ response }: { response: MarkdownChatResponseContent | InformationalChatResponseContent }) => { + const ref = useMarkdownRendering(response.content); - useEffect(() => { - const myDomElement = props.renderCallback(props.data); + return
; +}; +/** + * This hook uses markdown-it directly to render markdown. + * The reason to use markdown-it directly is that the MarkdownRenderer is + * overriden by theia with a monaco version. This monaco version strips all html + * tags from the markdown with empty content. + * This leads to unexpected behavior when rendering markdown with html tags. + * + * @param markdown the string to render as markdown + * @returns the ref to use in an element to render the markdown + */ +export const useMarkdownRendering = (markdown: string | MarkdownString) => { + // eslint-disable-next-line no-null/no-null + const ref = useRef(null); + const markdownString = typeof markdown === 'string' ? markdown : markdown.value; + useEffect(() => { + const markdownIt = markdownit(); + const host = document.createElement('div'); + const html = markdownIt.render(markdownString); + host.innerHTML = DOMPurify.sanitize(html, { + ALLOW_UNKNOWN_PROTOCOLS: true // DOMPurify usually strips non http(s) links from hrefs + }); while (ref?.current?.firstChild) { ref.current.removeChild(ref.current.firstChild); } - ref?.current?.appendChild(myDomElement); - }, [props.data.value]); + ref?.current?.appendChild(host); + }, [markdownString]); - return
; + return ref; }; diff --git a/packages/ai-chat-ui/src/browser/chat-tree-view/chat-view-tree-widget.tsx b/packages/ai-chat-ui/src/browser/chat-tree-view/chat-view-tree-widget.tsx index 04fa4d4253c5c..19d7daacdd9b8 100644 --- a/packages/ai-chat-ui/src/browser/chat-tree-view/chat-view-tree-widget.tsx +++ b/packages/ai-chat-ui/src/browser/chat-tree-view/chat-view-tree-widget.tsx @@ -35,7 +35,6 @@ import { TreeProps, TreeWidget, } from '@theia/core/lib/browser'; -import { MarkdownStringImpl } from '@theia/core/lib/common/markdown-rendering/markdown-string'; import { inject, injectable, @@ -44,10 +43,9 @@ import { } from '@theia/core/shared/inversify'; import * as React from '@theia/core/shared/react'; -import { MarkdownRenderer } from '@theia/core/lib/browser/markdown-rendering/markdown-renderer'; import { ChatNodeToolbarActionContribution } from '../chat-node-toolbar-action-contribution'; import { ChatResponsePartRenderer } from '../chat-response-part-renderer'; -import { MarkdownWrapper } from '../chat-response-renderer/markdown-part-renderer'; +import { useMarkdownRendering } from '../chat-response-renderer/markdown-part-renderer'; // TODO Instead of directly operating on the ChatRequestModel we could use an intermediate view model export interface RequestNode extends TreeNode { @@ -76,9 +74,6 @@ export class ChatViewTreeWidget extends TreeWidget { @inject(ContributionProvider) @named(ChatNodeToolbarActionContribution) protected readonly chatNodeToolbarActionContributions: ContributionProvider; - @inject(MarkdownRenderer) - private renderer: MarkdownRenderer; - @inject(ChatAgentService) protected chatAgentService: ChatAgentService; @@ -336,16 +331,7 @@ export class ChatViewTreeWidget extends TreeWidget { } private renderChatRequest(node: RequestNode): React.ReactNode { - const text = node.request.request.displayText ?? node.request.request.text; - const markdownString = new MarkdownStringImpl(text, { supportHtml: true, isTrusted: true }); - return ( -
- { this.renderer.render(markdownString).element} - >} -
- ); + return ; } private renderChatResponse(node: ResponseNode): React.ReactNode { @@ -389,6 +375,13 @@ export class ChatViewTreeWidget extends TreeWidget { } } +const ChatRequestRender = ({ node }: { node: RequestNode }) => { + const text = node.request.request.displayText ?? node.request.request.text; + const ref = useMarkdownRendering(text); + + return
; +}; + const ProgressMessage = (c: ChatProgressMessage) => (
{c.content} diff --git a/packages/ai-chat/package.json b/packages/ai-chat/package.json index 907a6b05712c6..bc6843dc6fe42 100644 --- a/packages/ai-chat/package.json +++ b/packages/ai-chat/package.json @@ -1,13 +1,13 @@ { "name": "@theia/ai-chat", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - AI Chat Extension", "dependencies": { - "@theia/ai-core": "1.53.0", - "@theia/ai-history": "1.53.0", - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-history": "1.54.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2" }, @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-chat/src/browser/ai-chat-frontend-module.ts b/packages/ai-chat/src/browser/ai-chat-frontend-module.ts index d4ed71579b514..c2231c64734aa 100644 --- a/packages/ai-chat/src/browser/ai-chat-frontend-module.ts +++ b/packages/ai-chat/src/browser/ai-chat-frontend-module.ts @@ -33,6 +33,7 @@ import { UniversalChatAgent } from '../common/universal-chat-agent'; import { aiChatPreferences } from './ai-chat-preferences'; import { ChatAgentsVariableContribution } from '../common/chat-agents-variable-contribution'; import { FrontendChatServiceImpl } from './frontend-chat-service'; +import { DefaultResponseContentMatcherProvider, DefaultResponseContentFactory, ResponseContentMatcherProvider } from '../common/response-content-matcher'; export default new ContainerModule(bind => { bindContributionProvider(bind, Agent); @@ -42,6 +43,11 @@ export default new ContainerModule(bind => { bind(ChatAgentService).toService(ChatAgentServiceImpl); bind(DefaultChatAgentId).toConstantValue({ id: OrchestratorChatAgentId }); + bindContributionProvider(bind, ResponseContentMatcherProvider); + bind(DefaultResponseContentMatcherProvider).toSelf().inSingletonScope(); + bind(ResponseContentMatcherProvider).toService(DefaultResponseContentMatcherProvider); + bind(DefaultResponseContentFactory).toSelf().inSingletonScope(); + bind(AIVariableContribution).to(ChatAgentsVariableContribution).inSingletonScope(); bind(ChatRequestParserImpl).toSelf().inSingletonScope(); diff --git a/packages/ai-chat/src/common/chat-agents.ts b/packages/ai-chat/src/common/chat-agents.ts index ee279125855be..ce6bbd741a17c 100644 --- a/packages/ai-chat/src/common/chat-agents.ts +++ b/packages/ai-chat/src/common/chat-agents.ts @@ -25,6 +25,7 @@ import { LanguageModel, LanguageModelRequirement, LanguageModelResponse, + LanguageModelStreamResponse, PromptService, ResolvedPromptTemplate, ToolRequest, @@ -37,19 +38,20 @@ import { LanguageModelStreamResponsePart, MessageActor, } from '@theia/ai-core/lib/common'; -import { CancellationToken, CancellationTokenSource, ILogger, isArray } from '@theia/core'; -import { inject, injectable } from '@theia/core/shared/inversify'; +import { CancellationToken, CancellationTokenSource, ContributionProvider, ILogger, isArray } from '@theia/core'; +import { inject, injectable, named, postConstruct } from '@theia/core/shared/inversify'; import { ChatAgentService } from './chat-agent-service'; import { ChatModel, ChatRequestModel, ChatRequestModelImpl, ChatResponseContent, - CodeChatResponseContentImpl, ErrorChatResponseContentImpl, MarkdownChatResponseContentImpl, ToolCallChatResponseContentImpl } from './chat-model'; +import { findFirstMatch, parseContents } from './parse-contents'; +import { DefaultResponseContentFactory, ResponseContentMatcher, ResponseContentMatcherProvider } from './response-content-matcher'; /** * A conversation consists of a sequence of ChatMessages. @@ -121,6 +123,14 @@ export abstract class AbstractChatAgent { @inject(ILogger) protected logger: ILogger; @inject(CommunicationRecordingService) protected recordingService: CommunicationRecordingService; @inject(PromptService) protected promptService: PromptService; + + @inject(ContributionProvider) @named(ResponseContentMatcherProvider) + protected contentMatcherProviders: ContributionProvider; + protected contentMatchers: ResponseContentMatcher[] = []; + + @inject(DefaultResponseContentFactory) + protected defaultContentFactory: DefaultResponseContentFactory; + constructor( public id: string, public languageModelRequirements: LanguageModelRequirement[], @@ -130,6 +140,11 @@ export abstract class AbstractChatAgent { public tags: String[] = ['Chat']) { } + @postConstruct() + init(): void { + this.contentMatchers = this.contentMatcherProviders.getContributions().flatMap(provider => provider.matchers); + } + async invoke(request: ChatRequestModelImpl): Promise { try { const languageModel = await this.getLanguageModel(this.defaultLanguageModelPurpose); @@ -189,6 +204,14 @@ export abstract class AbstractChatAgent { } } + protected parseContents(text: string): ChatResponseContent[] { + return parseContents( + text, + this.contentMatchers, + this.defaultContentFactory?.create.bind(this.defaultContentFactory) + ); + }; + protected handleError(request: ChatRequestModelImpl, error: Error): void { request.response.response.addContent(new ErrorChatResponseContentImpl(error)); request.response.error(error); @@ -281,9 +304,8 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent { protected override async addContentsToResponse(languageModelResponse: LanguageModelResponse, request: ChatRequestModelImpl): Promise { if (isLanguageModelTextResponse(languageModelResponse)) { - request.response.response.addContent( - new MarkdownChatResponseContentImpl(languageModelResponse.text) - ); + const contents = this.parseContents(languageModelResponse.text); + request.response.response.addContents(contents); request.response.complete(); this.recordingService.recordResponse({ agentId: this.id, @@ -295,57 +317,7 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent { return; } if (isLanguageModelStreamResponse(languageModelResponse)) { - for await (const token of languageModelResponse.stream) { - const newContents = this.parse(token, request.response.response.content); - if (isArray(newContents)) { - newContents.forEach(newContent => request.response.response.addContent(newContent)); - } else { - request.response.response.addContent(newContents); - } - - const lastContent = request.response.response.content.pop(); - if (lastContent === undefined) { - return; - } - const text = lastContent.asString?.(); - if (text === undefined) { - return; - } - let curSearchIndex = 0; - const result: ChatResponseContent[] = []; - while (curSearchIndex < text.length) { - // find start of code block: ```[language]\n[\n]``` - const codeStartIndex = text.indexOf('```', curSearchIndex); - if (codeStartIndex === -1) { - break; - } - - // find language specifier if present - const newLineIndex = text.indexOf('\n', codeStartIndex + 3); - const language = codeStartIndex + 3 < newLineIndex ? text.substring(codeStartIndex + 3, newLineIndex) : undefined; - - // find end of code block - const codeEndIndex = text.indexOf('```', codeStartIndex + 3); - if (codeEndIndex === -1) { - break; - } - - // add text before code block as markdown content - result.push(new MarkdownChatResponseContentImpl(text.substring(curSearchIndex, codeStartIndex))); - // add code block as code content - const codeText = text.substring(newLineIndex + 1, codeEndIndex).trimEnd(); - result.push(new CodeChatResponseContentImpl(codeText, language)); - curSearchIndex = codeEndIndex + 3; - } - - if (result.length > 0) { - result.forEach(r => { - request.response.response.addContent(r); - }); - } else { - request.response.response.addContent(lastContent); - } - } + await this.addStreamResponse(languageModelResponse, request); request.response.complete(); this.recordingService.recordResponse({ agentId: this.id, @@ -366,11 +338,38 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent { ); } - private parse(token: LanguageModelStreamResponsePart, previousContent: ChatResponseContent[]): ChatResponseContent | ChatResponseContent[] { + protected async addStreamResponse(languageModelResponse: LanguageModelStreamResponse, request: ChatRequestModelImpl): Promise { + for await (const token of languageModelResponse.stream) { + const newContents = this.parse(token, request.response.response.content); + if (isArray(newContents)) { + request.response.response.addContents(newContents); + } else { + request.response.response.addContent(newContents); + } + + const lastContent = request.response.response.content.pop(); + if (lastContent === undefined) { + return; + } + const text = lastContent.asString?.(); + if (text === undefined) { + return; + } + + const result: ChatResponseContent[] = findFirstMatch(this.contentMatchers, text) ? this.parseContents(text) : []; + if (result.length > 0) { + request.response.response.addContents(result); + } else { + request.response.response.addContent(lastContent); + } + } + } + + protected parse(token: LanguageModelStreamResponsePart, previousContent: ChatResponseContent[]): ChatResponseContent | ChatResponseContent[] { const content = token.content; // eslint-disable-next-line no-null/no-null if (content !== undefined && content !== null) { - return new MarkdownChatResponseContentImpl(content); + return this.defaultContentFactory.create(content); } const toolCalls = token.tool_calls; if (toolCalls !== undefined) { @@ -378,7 +377,7 @@ export abstract class AbstractStreamParsingChatAgent extends AbstractChatAgent { new ToolCallChatResponseContentImpl(toolCall.id, toolCall.function?.name, toolCall.function?.arguments, toolCall.finished, toolCall.result)); return toolCallContents; } - return new MarkdownChatResponseContentImpl(''); + return this.defaultContentFactory.create(''); } } diff --git a/packages/ai-chat/src/common/chat-model.ts b/packages/ai-chat/src/common/chat-model.ts index a71c273f04110..c485c69c7c4c8 100644 --- a/packages/ai-chat/src/common/chat-model.ts +++ b/packages/ai-chat/src/common/chat-model.ts @@ -374,7 +374,7 @@ export class ChatRequestModelImpl implements ChatRequestModel { } export class ErrorChatResponseContentImpl implements ErrorChatResponseContent { - kind: 'error' = 'error'; + readonly kind = 'error'; protected _error: Error; constructor(error: Error) { this._error = error; @@ -388,7 +388,7 @@ export class ErrorChatResponseContentImpl implements ErrorChatResponseContent { } export class TextChatResponseContentImpl implements TextChatResponseContent { - kind: 'text' = 'text'; + readonly kind = 'text'; protected _content: string; constructor(content: string) { @@ -410,7 +410,7 @@ export class TextChatResponseContentImpl implements TextChatResponseContent { } export class MarkdownChatResponseContentImpl implements MarkdownChatResponseContent { - kind: 'markdownContent' = 'markdownContent'; + readonly kind = 'markdownContent'; protected _content: MarkdownStringImpl = new MarkdownStringImpl(); constructor(content: string) { @@ -432,7 +432,7 @@ export class MarkdownChatResponseContentImpl implements MarkdownChatResponseCont } export class InformationalChatResponseContentImpl implements InformationalChatResponseContent { - kind: 'informational' = 'informational'; + readonly kind = 'informational'; protected _content: MarkdownStringImpl; constructor(content: string) { @@ -454,7 +454,7 @@ export class InformationalChatResponseContentImpl implements InformationalChatRe } export class CodeChatResponseContentImpl implements CodeChatResponseContent { - kind: 'code' = 'code'; + readonly kind = 'code'; protected _code: string; protected _language?: string; protected _location?: Location; @@ -488,7 +488,7 @@ export class CodeChatResponseContentImpl implements CodeChatResponseContent { } export class ToolCallChatResponseContentImpl implements ToolCallChatResponseContent { - kind: 'toolCall' = 'toolCall'; + readonly kind = 'toolCall'; protected _id?: string; protected _name?: string; protected _arguments?: string; @@ -546,7 +546,7 @@ export const COMMAND_CHAT_RESPONSE_COMMAND: Command = { id: 'ai-chat.command-chat-response.generic' }; export class CommandChatResponseContentImpl implements CommandChatResponseContent { - kind: 'command' = 'command'; + readonly kind = 'command'; constructor(public command?: Command, public customCallback?: CustomCallback, protected args?: unknown[]) { } @@ -561,7 +561,7 @@ export class CommandChatResponseContentImpl implements CommandChatResponseConten } export class HorizontalLayoutChatResponseContentImpl implements HorizontalLayoutChatResponseContent { - kind: 'horizontal' = 'horizontal'; + readonly kind = 'horizontal'; protected _content: ChatResponseContent[]; constructor(content: ChatResponseContent[] = []) { @@ -601,10 +601,20 @@ class ChatResponseImpl implements ChatResponse { return this._content; } + addContents(contents: ChatResponseContent[]): void { + contents.forEach(c => this.doAddContent(c)); + this._onDidChangeEmitter.fire(); + } + addContent(nextContent: ChatResponseContent): void { // TODO: Support more complex merges affecting different content than the last, e.g. via some kind of ProcessorRegistry // TODO: Support more of the built-in VS Code behavior, see // https://github.com/microsoft/vscode/blob/a2cab7255c0df424027be05d58e1b7b941f4ea60/src/vs/workbench/contrib/chat/common/chatModel.ts#L188-L244 + this.doAddContent(nextContent); + this._onDidChangeEmitter.fire(); + } + + protected doAddContent(nextContent: ChatResponseContent): void { if (ToolCallChatResponseContent.is(nextContent) && nextContent.id !== undefined) { const fittingTool = this._content.find(c => ToolCallChatResponseContent.is(c) && c.id === nextContent.id); if (fittingTool !== undefined) { @@ -613,10 +623,9 @@ class ChatResponseImpl implements ChatResponse { this._content.push(nextContent); } } else { - const lastElement = - this._content.length > 0 - ? this._content[this._content.length - 1] - : undefined; + const lastElement = this._content.length > 0 + ? this._content[this._content.length - 1] + : undefined; if (lastElement?.kind === nextContent.kind && ChatResponseContent.hasMerge(lastElement)) { const mergeSuccess = lastElement.merge(nextContent); if (!mergeSuccess) { @@ -627,7 +636,6 @@ class ChatResponseImpl implements ChatResponse { } } this._updateResponseRepresentation(); - this._onDidChangeEmitter.fire(); } protected _updateResponseRepresentation(): void { diff --git a/packages/ai-chat/src/common/parse-contents.spec.ts b/packages/ai-chat/src/common/parse-contents.spec.ts new file mode 100644 index 0000000000000..c0a009f8cb814 --- /dev/null +++ b/packages/ai-chat/src/common/parse-contents.spec.ts @@ -0,0 +1,142 @@ +// ***************************************************************************** +// Copyright (C) 2024 EclipseSource GmbH. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { expect } from 'chai'; +import { ChatResponseContent, CodeChatResponseContentImpl, MarkdownChatResponseContentImpl } from './chat-model'; +import { parseContents } from './parse-contents'; +import { CodeContentMatcher, ResponseContentMatcher } from './response-content-matcher'; + +export class CommandChatResponseContentImpl implements ChatResponseContent { + constructor(public readonly command: string) { } + kind = 'command'; +} + +export const CommandContentMatcher: ResponseContentMatcher = { + start: /^$/m, + end: /^<\/command>$/m, + contentFactory: (content: string) => { + const code = content.replace(/^\n|<\/command>$/g, ''); + return new CommandChatResponseContentImpl(code.trim()); + } +}; + +describe('parseContents', () => { + it('should parse code content', () => { + const text = '```typescript\nconsole.log("Hello World");\n```'; + const result = parseContents(text); + expect(result).to.deep.equal([new CodeChatResponseContentImpl('console.log("Hello World");', 'typescript')]); + }); + + it('should parse markdown content', () => { + const text = 'Hello **World**'; + const result = parseContents(text); + expect(result).to.deep.equal([new MarkdownChatResponseContentImpl('Hello **World**')]); + }); + + it('should parse multiple content blocks', () => { + const text = '```typescript\nconsole.log("Hello World");\n```\nHello **World**'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'), + new MarkdownChatResponseContentImpl('\nHello **World**') + ]); + }); + + it('should parse multiple content blocks with different languages', () => { + const text = '```typescript\nconsole.log("Hello World");\n```\n```python\nprint("Hello World")\n```'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'), + new CodeChatResponseContentImpl('print("Hello World")', 'python') + ]); + }); + + it('should parse multiple content blocks with different languages and markdown', () => { + const text = '```typescript\nconsole.log("Hello World");\n```\nHello **World**\n```python\nprint("Hello World")\n```'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'), + new MarkdownChatResponseContentImpl('\nHello **World**\n'), + new CodeChatResponseContentImpl('print("Hello World")', 'python') + ]); + }); + + it('should parse content blocks with empty content', () => { + const text = '```typescript\n```\nHello **World**\n```python\nprint("Hello World")\n```'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new CodeChatResponseContentImpl('', 'typescript'), + new MarkdownChatResponseContentImpl('\nHello **World**\n'), + new CodeChatResponseContentImpl('print("Hello World")', 'python') + ]); + }); + + it('should parse content with markdown, code, and markdown', () => { + const text = 'Hello **World**\n```typescript\nconsole.log("Hello World");\n```\nGoodbye **World**'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new MarkdownChatResponseContentImpl('Hello **World**\n'), + new CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'), + new MarkdownChatResponseContentImpl('\nGoodbye **World**') + ]); + }); + + it('should handle text with no special content', () => { + const text = 'Just some plain text.'; + const result = parseContents(text); + expect(result).to.deep.equal([new MarkdownChatResponseContentImpl('Just some plain text.')]); + }); + + it('should handle text with only start code block', () => { + const text = '```typescript\nconsole.log("Hello World");'; + const result = parseContents(text); + expect(result).to.deep.equal([new MarkdownChatResponseContentImpl('```typescript\nconsole.log("Hello World");')]); + }); + + it('should handle text with only end code block', () => { + const text = 'console.log("Hello World");\n```'; + const result = parseContents(text); + expect(result).to.deep.equal([new MarkdownChatResponseContentImpl('console.log("Hello World");\n```')]); + }); + + it('should handle text with unmatched code block', () => { + const text = '```typescript\nconsole.log("Hello World");\n```\n```python\nprint("Hello World")'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new CodeChatResponseContentImpl('console.log("Hello World");', 'typescript'), + new MarkdownChatResponseContentImpl('\n```python\nprint("Hello World")') + ]); + }); + + it('should parse code block without newline after language', () => { + const text = '```typescript console.log("Hello World");```'; + const result = parseContents(text); + expect(result).to.deep.equal([ + new MarkdownChatResponseContentImpl('```typescript console.log("Hello World");```') + ]); + }); + + it('should parse with matches of multiple different matchers and default', () => { + const text = '\nMY_SPECIAL_COMMAND\n\nHello **World**\n```python\nprint("Hello World")\n```\n\nMY_SPECIAL_COMMAND2\n'; + const result = parseContents(text, [CodeContentMatcher, CommandContentMatcher]); + expect(result).to.deep.equal([ + new CommandChatResponseContentImpl('MY_SPECIAL_COMMAND'), + new MarkdownChatResponseContentImpl('\nHello **World**\n'), + new CodeChatResponseContentImpl('print("Hello World")', 'python'), + new CommandChatResponseContentImpl('MY_SPECIAL_COMMAND2'), + ]); + }); +}); diff --git a/packages/ai-chat/src/common/parse-contents.ts b/packages/ai-chat/src/common/parse-contents.ts new file mode 100644 index 0000000000000..16f405495ce20 --- /dev/null +++ b/packages/ai-chat/src/common/parse-contents.ts @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2024 EclipseSource GmbH. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 + */ +import { ChatResponseContent } from './chat-model'; +import { CodeContentMatcher, MarkdownContentFactory, ResponseContentFactory, ResponseContentMatcher } from './response-content-matcher'; + +interface Match { + matcher: ResponseContentMatcher; + index: number; + content: string; +} + +export function parseContents( + text: string, + contentMatchers: ResponseContentMatcher[] = [CodeContentMatcher], + defaultContentFactory: ResponseContentFactory = MarkdownContentFactory +): ChatResponseContent[] { + const result: ChatResponseContent[] = []; + + let currentIndex = 0; + while (currentIndex < text.length) { + const remainingText = text.substring(currentIndex); + const match = findFirstMatch(contentMatchers, remainingText); + if (!match) { + // Add the remaining text as default content + if (remainingText.length > 0) { + result.push(defaultContentFactory(remainingText)); + } + break; + } + // We have a match + // 1. Add preceding text as default content + if (match.index > 0) { + const precedingContent = remainingText.substring(0, match.index); + if (precedingContent.trim().length > 0) { + result.push(defaultContentFactory(precedingContent)); + } + } + // 2. Add the matched content object + result.push(match.matcher.contentFactory(match.content)); + // Update currentIndex to the end of the end of the match + // And continue with the search after the end of the match + currentIndex += match.index + match.content.length; + } + + return result; +} + +export function findFirstMatch(contentMatchers: ResponseContentMatcher[], text: string): Match | undefined { + let firstMatch: { matcher: ResponseContentMatcher, index: number, content: string } | undefined; + for (const matcher of contentMatchers) { + const startMatch = matcher.start.exec(text); + if (!startMatch) { + // No start match found, try next matcher. + continue; + } + const endOfStartMatch = startMatch.index + startMatch[0].length; + if (endOfStartMatch >= text.length) { + // There is no text after the start match. + // No need to search for the end match yet, try next matcher. + continue; + } + const remainingTextAfterStartMatch = text.substring(endOfStartMatch); + const endMatch = matcher.end.exec(remainingTextAfterStartMatch); + if (!endMatch) { + // No end match found, try next matcher. + continue; + } + // Found start and end match. + // Record the full match, if it is the earliest found so far. + const index = startMatch.index; + const contentEnd = index + startMatch[0].length + endMatch.index + endMatch[0].length; + const content = text.substring(index, contentEnd); + if (!firstMatch || index < firstMatch.index) { + firstMatch = { matcher, index, content }; + } + } + return firstMatch; +} + diff --git a/packages/ai-chat/src/common/response-content-matcher.ts b/packages/ai-chat/src/common/response-content-matcher.ts new file mode 100644 index 0000000000000..3fb785e603c5f --- /dev/null +++ b/packages/ai-chat/src/common/response-content-matcher.ts @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2024 EclipseSource GmbH. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 + */ +import { + ChatResponseContent, + CodeChatResponseContentImpl, + MarkdownChatResponseContentImpl +} from './chat-model'; +import { injectable } from '@theia/core/shared/inversify'; + +export type ResponseContentFactory = (content: string) => ChatResponseContent; + +export const MarkdownContentFactory: ResponseContentFactory = (content: string) => + new MarkdownChatResponseContentImpl(content); + +/** + * Default response content factory used if no other `ResponseContentMatcher` applies. + * By default, this factory creates a markdown content object. + * + * @see MarkdownChatResponseContentImpl + */ +@injectable() +export class DefaultResponseContentFactory { + create(content: string): ChatResponseContent { + return MarkdownContentFactory(content); + } +} + +/** + * Clients can contribute response content matchers to parse a chat response into specific + * `ChatResponseContent` instances. + */ +export interface ResponseContentMatcher { + /** Regular expression for finding the start delimiter. */ + start: RegExp; + /** Regular expression for finding the start delimiter. */ + end: RegExp; + /** + * The factory creating a response content from the matching content, + * from start index to end index of the match (including delimiters). + */ + contentFactory: ResponseContentFactory; +} + +export const CodeContentMatcher: ResponseContentMatcher = { + start: /^```.*?$/m, + end: /^```$/m, + contentFactory: (content: string) => { + const language = content.match(/^```(\w+)/)?.[1] || ''; + const code = content.replace(/^```(\w+)\n|```$/g, ''); + return new CodeChatResponseContentImpl(code.trim(), language); + } +}; + +/** + * Clients can contribute response content matchers to parse the response content. + * + * The default chat user interface will collect all contributed matchers and use them + * to parse the response into structured content parts (e.g. code blocks, markdown blocks), + * which are then rendered with a `ChatResponsePartRenderer` registered for the respective + * content part type. + * + * ### Example + * ```ts + * bind(ResponseContentMatcherProvider).to(MyResponseContentMatcherProvider); + * ... + * @injectable() + * export class MyResponseContentMatcherProvider implements ResponseContentMatcherProvider { + * readonly matchers: ResponseContentMatcher[] = [{ + * start: /^$/m, + * end: /^$/m, + * contentFactory: (content: string) => { + * const command = content.replace(/^\n|<\/command>$/g, ''); + * return new MyChatResponseContentImpl(command.trim()); + * } + * }]; + * } + * ``` + * + * @see ResponseContentMatcher + */ +export const ResponseContentMatcherProvider = Symbol('ResponseContentMatcherProvider'); +export interface ResponseContentMatcherProvider { + readonly matchers: ResponseContentMatcher[]; +} + +@injectable() +export class DefaultResponseContentMatcherProvider implements ResponseContentMatcherProvider { + readonly matchers: ResponseContentMatcher[] = [CodeContentMatcher]; +} diff --git a/packages/ai-code-completion/package.json b/packages/ai-code-completion/package.json index 8ab9c57a3de79..8cf5e1a630163 100644 --- a/packages/ai-code-completion/package.json +++ b/packages/ai-code-completion/package.json @@ -1,14 +1,14 @@ { "name": "@theia/ai-code-completion", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - AI Core", "dependencies": { - "@theia/ai-core": "1.53.0", - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", + "@theia/ai-core": "1.54.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/output": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/output": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2" }, @@ -46,7 +46,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-core/package.json b/packages/ai-core/package.json index 294fbcb871fc2..e40cc0906d1a3 100644 --- a/packages/ai-core/package.json +++ b/packages/ai-core/package.json @@ -1,16 +1,16 @@ { "name": "@theia/ai-core", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - AI Core", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/output": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/output": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2" }, @@ -50,7 +50,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-core/src/browser/ai-configuration/language-model-renderer.tsx b/packages/ai-core/src/browser/ai-configuration/language-model-renderer.tsx index f41a8acfd84bd..1305168f65f59 100644 --- a/packages/ai-core/src/browser/ai-configuration/language-model-renderer.tsx +++ b/packages/ai-core/src/browser/ai-configuration/language-model-renderer.tsx @@ -31,7 +31,7 @@ export const LanguageModelRenderer: React.FC = ( const findLanguageModelRequirement = async (purpose: string): Promise => { const requirementSetting = await aiSettingsService.getAgentSettings(agent.id); - return requirementSetting?.languageModelRequirements.find(e => e.purpose === purpose); + return requirementSetting?.languageModelRequirements?.find(e => e.purpose === purpose); }; const [lmRequirementMap, setLmRequirementMap] = React.useState>({}); diff --git a/packages/ai-core/src/browser/frontend-language-model-registry.ts b/packages/ai-core/src/browser/frontend-language-model-registry.ts index 045d066b60970..90b80a0688451 100644 --- a/packages/ai-core/src/browser/frontend-language-model-registry.ts +++ b/packages/ai-core/src/browser/frontend-language-model-registry.ts @@ -288,7 +288,7 @@ export class FrontendLanguageModelRegistryImpl override async selectLanguageModels(request: LanguageModelSelector): Promise { await this.initialized; - const userSettings = (await this.settingsService.getAgentSettings(request.agent))?.languageModelRequirements.find(req => req.purpose === request.purpose); + const userSettings = (await this.settingsService.getAgentSettings(request.agent))?.languageModelRequirements?.find(req => req.purpose === request.purpose); if (userSettings?.identifier) { const model = await this.getLanguageModel(userSettings.identifier); if (model) { diff --git a/packages/ai-core/src/common/settings-service.ts b/packages/ai-core/src/common/settings-service.ts index 2c8f204b96643..007daec366250 100644 --- a/packages/ai-core/src/common/settings-service.ts +++ b/packages/ai-core/src/common/settings-service.ts @@ -28,6 +28,6 @@ export interface AISettingsService { } export type AISettings = Record; export interface AgentSettings { - languageModelRequirements: LanguageModelRequirement[]; - enable: boolean; + languageModelRequirements?: LanguageModelRequirement[]; + enable?: boolean; } diff --git a/packages/ai-history/package.json b/packages/ai-history/package.json index 0eb2b6f471cc2..f4c4cd224670d 100644 --- a/packages/ai-history/package.json +++ b/packages/ai-history/package.json @@ -1,13 +1,13 @@ { "name": "@theia/ai-history", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - AI communication history", "dependencies": { - "@theia/ai-core": "1.53.0", - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/output": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/ai-core": "1.54.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/output": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2" }, @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-ollama/package.json b/packages/ai-ollama/package.json index 779515df07d0b..b2a5d74346abb 100644 --- a/packages/ai-ollama/package.json +++ b/packages/ai-ollama/package.json @@ -1,15 +1,15 @@ { "name": "@theia/ai-ollama", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Ollama Integration", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2", "ollama": "^0.5.8", - "@theia/ai-core": "1.53.0" + "@theia/ai-core": "1.54.0" }, "publishConfig": { "access": "public" @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-openai/package.json b/packages/ai-openai/package.json index 1a0d2f69e8859..3ac4dd9ab057e 100644 --- a/packages/ai-openai/package.json +++ b/packages/ai-openai/package.json @@ -1,15 +1,15 @@ { "name": "@theia/ai-openai", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - OpenAI Integration", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2", "openai": "^4.55.7", - "@theia/ai-core": "1.53.0" + "@theia/ai-core": "1.54.0" }, "publishConfig": { "access": "public" @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-openai/src/node/openai-language-model.ts b/packages/ai-openai/src/node/openai-language-model.ts index e7edc59b0fb23..7692a21f8a9e4 100644 --- a/packages/ai-openai/src/node/openai-language-model.ts +++ b/packages/ai-openai/src/node/openai-language-model.ts @@ -134,9 +134,12 @@ export class OpenAiModel implements LanguageModel { } protected supportsStructuredOutput(): boolean { - // currently only the lastest 4o and 4o-mini models support structured output - // see https://platform.openai.com/docs/guides/structured-outputs - return this.model === 'gpt-4o-2024-08-06' || this.model === 'gpt-4o-mini'; + // see https://platform.openai.com/docs/models/gpt-4o + return [ + 'gpt-4o', + 'gpt-4o-2024-08-06', + 'gpt-4o-mini' + ].includes(this.model); } protected async handleStructuredOutputRequest(openai: OpenAI, request: LanguageModelRequest): Promise { diff --git a/packages/ai-terminal/package.json b/packages/ai-terminal/package.json index f32d1794bf62b..acf37e6632656 100644 --- a/packages/ai-terminal/package.json +++ b/packages/ai-terminal/package.json @@ -1,12 +1,12 @@ { "name": "@theia/ai-terminal", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - AI Terminal Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/ai-core": "1.53.0", - "@theia/ai-chat": "1.53.0", - "@theia/terminal": "1.53.0", + "@theia/core": "1.54.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-chat": "1.54.0", + "@theia/terminal": "1.54.0", "zod": "^3.23.8", "zod-to-json-schema": "^3.23.2" }, @@ -43,7 +43,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/ai-terminal/src/browser/ai-terminal-agent.ts b/packages/ai-terminal/src/browser/ai-terminal-agent.ts index f68f73eeb3424..98d083d7bee76 100644 --- a/packages/ai-terminal/src/browser/ai-terminal-agent.ts +++ b/packages/ai-terminal/src/browser/ai-terminal-agent.ts @@ -16,12 +16,13 @@ import { Agent, + CommunicationRecordingService, getJsonOfResponse, isLanguageModelParsedResponse, LanguageModelRegistry, LanguageModelRequirement, PromptService } from '@theia/ai-core/lib/common'; -import { ILogger } from '@theia/core'; +import { generateUuid, ILogger } from '@theia/core'; import { inject, injectable } from '@theia/core/shared/inversify'; import { z } from 'zod'; import zodToJsonSchema from 'zod-to-json-schema'; @@ -33,6 +34,8 @@ type Commands = z.infer; @injectable() export class AiTerminalAgent implements Agent { + @inject(CommunicationRecordingService) + protected recordingService: CommunicationRecordingService; id = 'Terminal Assistant'; name = 'Terminal Assistant'; @@ -153,6 +156,18 @@ recent-terminal-contents: return []; } + // since we do not actually hold complete conversions, the request/response pair is considered a session + const sessionId = generateUuid(); + const requestId = generateUuid(); + this.recordingService.recordRequest({ + agentId: this.id, + sessionId, + timestamp: Date.now(), + requestId, + request: systemPrompt, + messages: [userPrompt], + }); + try { const result = await lm.request({ messages: [ @@ -181,12 +196,28 @@ recent-terminal-contents: // model returned structured output const parsedResult = Commands.safeParse(result.parsed); if (parsedResult.success) { + const responseTextfromParsed = JSON.stringify(parsedResult.data.commands); + this.recordingService.recordResponse({ + agentId: this.id, + sessionId, + timestamp: Date.now(), + requestId, + response: responseTextfromParsed, + }); return parsedResult.data.commands; } } // fall back to agent-based parsing of result const jsonResult = await getJsonOfResponse(result); + const responseTextFromJSON = JSON.stringify(jsonResult); + this.recordingService.recordResponse({ + agentId: this.id, + sessionId, + timestamp: Date.now(), + requestId, + response: responseTextFromJSON + }); const parsedJsonResult = Commands.safeParse(jsonResult); if (parsedJsonResult.success) { return parsedJsonResult.data.commands; diff --git a/packages/ai-workspace-agent/package.json b/packages/ai-workspace-agent/package.json index 65a50a7f12990..d992fb740a4cc 100644 --- a/packages/ai-workspace-agent/package.json +++ b/packages/ai-workspace-agent/package.json @@ -1,6 +1,6 @@ { "name": "@theia/ai-workspace-agent", - "version": "1.53.0", + "version": "1.54.0", "description": "AI Workspace Agent Extension", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "repository": { @@ -15,20 +15,20 @@ "theia-extension" ], "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/workspace": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/ai-core": "1.53.0", - "@theia/ai-chat": "1.53.0" + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/workspace": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/ai-core": "1.54.0", + "@theia/ai-chat": "1.54.0" }, "publishConfig": { "access": "public" }, "devDependencies": { - "@theia/cli": "1.53.0", - "@theia/test": "1.53.0" + "@theia/cli": "1.54.0", + "@theia/test": "1.54.0" }, "theiaExtensions": [ { diff --git a/packages/bulk-edit/package.json b/packages/bulk-edit/package.json index 312ef80cc23a8..c0352dc098be6 100644 --- a/packages/bulk-edit/package.json +++ b/packages/bulk-edit/package.json @@ -1,14 +1,14 @@ { "name": "@theia/bulk-edit", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Bulk Edit Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/workspace": "1.53.0", + "@theia/workspace": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -44,7 +44,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/callhierarchy/package.json b/packages/callhierarchy/package.json index cde8b9af18d1d..ebad7bf16c619 100644 --- a/packages/callhierarchy/package.json +++ b/packages/callhierarchy/package.json @@ -1,10 +1,10 @@ { "name": "@theia/callhierarchy", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Call Hierarchy Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", "ts-md5": "^1.2.2", "tslib": "^2.6.2" }, @@ -41,7 +41,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/collaboration/package.json b/packages/collaboration/package.json index ef39af5fad751..76a4a88e72794 100644 --- a/packages/collaboration/package.json +++ b/packages/collaboration/package.json @@ -1,14 +1,14 @@ { "name": "@theia/collaboration", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Collaboration Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/workspace": "1.53.0", + "@theia/workspace": "1.54.0", "open-collaboration-protocol": "0.2.0", "open-collaboration-yjs": "0.2.0", "socket.io-client": "^4.5.3", @@ -49,7 +49,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/console/package.json b/packages/console/package.json index 6b0055c2b2fb5..a0a68be4de510 100644 --- a/packages/console/package.json +++ b/packages/console/package.json @@ -1,10 +1,10 @@ { "name": "@theia/console", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Console Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", "anser": "^2.0.1", "tslib": "^2.6.2" @@ -42,7 +42,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/core/README.md b/packages/core/README.md index 2483bb3abbaa4..438d5b4d9ead9 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -84,12 +84,12 @@ export class SomeClass { - `@phosphor/signaling` (from [`@phosphor/signaling@1`](https://www.npmjs.com/package/@phosphor/signaling)) - `@phosphor/virtualdom` (from [`@phosphor/virtualdom@1`](https://www.npmjs.com/package/@phosphor/virtualdom)) - `@phosphor/widgets` (from [`@phosphor/widgets@1`](https://www.npmjs.com/package/@phosphor/widgets)) - - `@theia/application-package` (from [`@theia/application-package@1.53.0`](https://www.npmjs.com/package/@theia/application-package/v/1.53.0)) - - `@theia/application-package/lib/api` (from [`@theia/application-package@1.53.0`](https://www.npmjs.com/package/@theia/application-package/v/1.53.0)) - - `@theia/application-package/lib/environment` (from [`@theia/application-package@1.53.0`](https://www.npmjs.com/package/@theia/application-package/v/1.53.0)) - - `@theia/request` (from [`@theia/request@1.53.0`](https://www.npmjs.com/package/@theia/request/v/1.53.0)) - - `@theia/request/lib/proxy` (from [`@theia/request@1.53.0`](https://www.npmjs.com/package/@theia/request/v/1.53.0)) - - `@theia/request/lib/node-request-service` (from [`@theia/request@1.53.0`](https://www.npmjs.com/package/@theia/request/v/1.53.0)) + - `@theia/application-package` (from [`@theia/application-package@1.54.0`](https://www.npmjs.com/package/@theia/application-package/v/1.54.0)) + - `@theia/application-package/lib/api` (from [`@theia/application-package@1.54.0`](https://www.npmjs.com/package/@theia/application-package/v/1.54.0)) + - `@theia/application-package/lib/environment` (from [`@theia/application-package@1.54.0`](https://www.npmjs.com/package/@theia/application-package/v/1.54.0)) + - `@theia/request` (from [`@theia/request@1.54.0`](https://www.npmjs.com/package/@theia/request/v/1.54.0)) + - `@theia/request/lib/proxy` (from [`@theia/request@1.54.0`](https://www.npmjs.com/package/@theia/request/v/1.54.0)) + - `@theia/request/lib/node-request-service` (from [`@theia/request@1.54.0`](https://www.npmjs.com/package/@theia/request/v/1.54.0)) - `fs-extra` (from [`fs-extra@^4.0.2`](https://www.npmjs.com/package/fs-extra)) - `fuzzy` (from [`fuzzy@^0.1.3`](https://www.npmjs.com/package/fuzzy)) - `inversify` (from [`inversify@^6.0.1`](https://www.npmjs.com/package/inversify)) diff --git a/packages/core/i18n/nls.cs.json b/packages/core/i18n/nls.cs.json index 5168d1dd92a9a..4d8ba688a5bc8 100644 --- a/packages/core/i18n/nls.cs.json +++ b/packages/core/i18n/nls.cs.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Otevřete zobrazení konfigurace AI", + "aiHistory:open": "Otevřít zobrazení Historie AI", "debug.breakpoint.editCondition": "Upravit stav...", "notebook.cell.changeToCode": "Změna buňky na kód", "notebook.cell.changeToMarkdown": "Změna buňky na Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Zrušení všech testovacích běhů", + "stackFrameAt": "na adrese", "testRunDefaultName": "{0} spustit {1}", "testRuns": "Testovací běhy" }, diff --git a/packages/core/i18n/nls.de.json b/packages/core/i18n/nls.de.json index c032b6c735f39..99e7919a92af1 100644 --- a/packages/core/i18n/nls.de.json +++ b/packages/core/i18n/nls.de.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "AI-Konfigurationsansicht öffnen", + "aiHistory:open": "AI-Historienansicht öffnen", "debug.breakpoint.editCondition": "Edit Bedingung...", "notebook.cell.changeToCode": "Zelle in Code ändern", "notebook.cell.changeToMarkdown": "Zelle in Mardown ändern", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Alle Testläufe abbrechen", + "stackFrameAt": "unter", "testRunDefaultName": "{0} laufen. {1}", "testRuns": "Testläufe" }, diff --git a/packages/core/i18n/nls.es.json b/packages/core/i18n/nls.es.json index 8931ed3df2226..bdc2b7c783ed9 100644 --- a/packages/core/i18n/nls.es.json +++ b/packages/core/i18n/nls.es.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Abrir la vista Configuración AI", + "aiHistory:open": "Abrir la vista Historial de IA", "debug.breakpoint.editCondition": "Editar condición...", "notebook.cell.changeToCode": "Cambiar celda por código", "notebook.cell.changeToMarkdown": "Cambiar Celda a Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Cancelar todas las pruebas", + "stackFrameAt": "en", "testRunDefaultName": "{0} ejecute {1}", "testRuns": "Pruebas" }, diff --git a/packages/core/i18n/nls.fr.json b/packages/core/i18n/nls.fr.json index 45accd898c9b0..b6685cda6431e 100644 --- a/packages/core/i18n/nls.fr.json +++ b/packages/core/i18n/nls.fr.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Ouvrir la vue Configuration AI", + "aiHistory:open": "Ouvrir la vue de l'historique de l'IA", "debug.breakpoint.editCondition": "Edit Condition...", "notebook.cell.changeToCode": "Changer la cellule en code", "notebook.cell.changeToMarkdown": "Changer la cellule en Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Annuler tous les essais", + "stackFrameAt": "à", "testRunDefaultName": "{0} courir {1}", "testRuns": "Essais" }, diff --git a/packages/core/i18n/nls.hu.json b/packages/core/i18n/nls.hu.json index c059404ecd184..c91fe4d959b39 100644 --- a/packages/core/i18n/nls.hu.json +++ b/packages/core/i18n/nls.hu.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "AI konfigurációs nézet megnyitása", + "aiHistory:open": "AI előzmények nézet megnyitása", "debug.breakpoint.editCondition": "Szerkesztési feltétel...", "notebook.cell.changeToCode": "Cellát kódra váltani", "notebook.cell.changeToMarkdown": "Cellát átváltoztatni Mardown-ra", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Minden tesztfuttatás törlése", + "stackFrameAt": "a címen.", "testRunDefaultName": "{0} fuss {1}", "testRuns": "Tesztfutások" }, diff --git a/packages/core/i18n/nls.it.json b/packages/core/i18n/nls.it.json index 46ff1f2ae77fb..41589e74f0a4c 100644 --- a/packages/core/i18n/nls.it.json +++ b/packages/core/i18n/nls.it.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Aprire la vista Configurazione AI", + "aiHistory:open": "Aprire la vista Cronologia AI", "debug.breakpoint.editCondition": "Modifica della condizione...", "notebook.cell.changeToCode": "Cambia cella in codice", "notebook.cell.changeToMarkdown": "Cambiare la cella in Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Annullamento di tutte le esecuzioni di test", + "stackFrameAt": "a", "testRunDefaultName": "{0} corsa {1}", "testRuns": "Esecuzioni di prova" }, diff --git a/packages/core/i18n/nls.ja.json b/packages/core/i18n/nls.ja.json index 1d823f74c0c86..ddcbf18d4c7a2 100644 --- a/packages/core/i18n/nls.ja.json +++ b/packages/core/i18n/nls.ja.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "AI設定ビューを開く", + "aiHistory:open": "AI履歴ビューを開く", "debug.breakpoint.editCondition": "編集条件...", "notebook.cell.changeToCode": "セルをコードに変更", "notebook.cell.changeToMarkdown": "セルをマーダウンに変更", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "すべてのテスト実行をキャンセルする", + "stackFrameAt": "で", "testRunDefaultName": "{0} 走る{1}", "testRuns": "テスト走行" }, diff --git a/packages/core/i18n/nls.json b/packages/core/i18n/nls.json index e797ed9a60e8a..e20a2fba22fcc 100644 --- a/packages/core/i18n/nls.json +++ b/packages/core/i18n/nls.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Open AI Configuration view", + "aiHistory:open": "Open AI History view", "debug.breakpoint.editCondition": "Edit Condition...", "notebook.cell.changeToCode": "Change Cell to Code", "notebook.cell.changeToMarkdown": "Change Cell to Markdown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Cancel All Test Runs", + "stackFrameAt": "at", "testRunDefaultName": "{0} run {1}", "testRuns": "Test Runs" }, diff --git a/packages/core/i18n/nls.ko.json b/packages/core/i18n/nls.ko.json index c35b5f4e7a0d9..38710bd357012 100644 --- a/packages/core/i18n/nls.ko.json +++ b/packages/core/i18n/nls.ko.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "AI 구성 보기 열기", + "aiHistory:open": "AI 기록 보기 열기", "debug.breakpoint.editCondition": "조건 편집...", "notebook.cell.changeToCode": "셀을 코드로 변경", "notebook.cell.changeToMarkdown": "셀을 마크다운으로 변경", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "모든 테스트 실행 취소", + "stackFrameAt": "에서", "testRunDefaultName": "{0} 실행 {1}", "testRuns": "테스트 실행" }, diff --git a/packages/core/i18n/nls.pl.json b/packages/core/i18n/nls.pl.json index 8955829d6df56..189aa3f86f263 100644 --- a/packages/core/i18n/nls.pl.json +++ b/packages/core/i18n/nls.pl.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Otwórz widok konfiguracji AI", + "aiHistory:open": "Otwórz widok historii AI", "debug.breakpoint.editCondition": "Warunek edycji...", "notebook.cell.changeToCode": "Zmień komórkę na kod", "notebook.cell.changeToMarkdown": "Zmień komórkę na Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Anulowanie wszystkich testów", + "stackFrameAt": "na", "testRunDefaultName": "{0} bieg {1}", "testRuns": "Przebiegi testowe" }, diff --git a/packages/core/i18n/nls.pt-br.json b/packages/core/i18n/nls.pt-br.json index 10793ca773fd0..2fba038a91fe7 100644 --- a/packages/core/i18n/nls.pt-br.json +++ b/packages/core/i18n/nls.pt-br.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Abrir a visualização de Configuração de IA", + "aiHistory:open": "Abrir a visualização do histórico de IA", "debug.breakpoint.editCondition": "Editar condição...", "notebook.cell.changeToCode": "Alterar célula para código", "notebook.cell.changeToMarkdown": "Mudança de célula para Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Cancelar todas as execuções de teste", + "stackFrameAt": "em", "testRunDefaultName": "{0} executar {1}", "testRuns": "Execuções de teste" }, diff --git a/packages/core/i18n/nls.ru.json b/packages/core/i18n/nls.ru.json index 18e1d8d01d3fa..26efaa004ac7e 100644 --- a/packages/core/i18n/nls.ru.json +++ b/packages/core/i18n/nls.ru.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "Откройте представление конфигурации AI", + "aiHistory:open": "Откройте представление истории ИИ", "debug.breakpoint.editCondition": "Изменить состояние...", "notebook.cell.changeToCode": "Измените ячейку на код", "notebook.cell.changeToMarkdown": "Измените ячейку на Мардаун", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Отмена всех тестовых запусков", + "stackFrameAt": "на", "testRunDefaultName": "{0} запустить {1}", "testRuns": "Тестовые испытания" }, diff --git a/packages/core/i18n/nls.tr.json b/packages/core/i18n/nls.tr.json index 87ebc516eaeed..d855292211eb6 100644 --- a/packages/core/i18n/nls.tr.json +++ b/packages/core/i18n/nls.tr.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "AI Yapılandırma görünümünü açın", + "aiHistory:open": "Yapay Zeka Geçmişi görünümünü açın", "debug.breakpoint.editCondition": "Düzenleme Durumu...", "notebook.cell.changeToCode": "Hücreyi Kod Olarak Değiştir", "notebook.cell.changeToMarkdown": "Hücreyi Markdown Olarak Değiştirme", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "Tüm Test Çalışmalarını İptal Et", + "stackFrameAt": "at", "testRunDefaultName": "{0} koşmak {1}", "testRuns": "Test Çalışmaları" }, diff --git a/packages/core/i18n/nls.zh-cn.json b/packages/core/i18n/nls.zh-cn.json index 3c356b419855d..43694260cfc3f 100644 --- a/packages/core/i18n/nls.zh-cn.json +++ b/packages/core/i18n/nls.zh-cn.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "打开 AI 配置视图", + "aiHistory:open": "打开人工智能历史视图", "debug.breakpoint.editCondition": "编辑条件...", "notebook.cell.changeToCode": "将单元格更改为代码", "notebook.cell.changeToMarkdown": "将 Cell 改为 Mardown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "取消所有测试运行", + "stackFrameAt": "于", "testRunDefaultName": "{0} 运行{1}", "testRuns": "测试运行" }, diff --git a/packages/core/i18n/nls.zh-tw.json b/packages/core/i18n/nls.zh-tw.json index b3f4b4f67c936..ede1123f822d0 100644 --- a/packages/core/i18n/nls.zh-tw.json +++ b/packages/core/i18n/nls.zh-tw.json @@ -1,4 +1,6 @@ { + "aiConfiguration:open": "開啟 AI 設定檢視", + "aiHistory:open": "開啟 AI 歷史檢視", "debug.breakpoint.editCondition": "編輯條件...", "notebook.cell.changeToCode": "變更儲存格為代碼", "notebook.cell.changeToMarkdown": "變更儲存格為 Markdown", @@ -499,6 +501,7 @@ }, "test": { "cancelAllTestRuns": "取消所有測試執行", + "stackFrameAt": "於", "testRunDefaultName": "{0} 跑{1}", "testRuns": "測試運行" }, diff --git a/packages/core/package.json b/packages/core/package.json index b941db18927e3..d86b2ab085578 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@theia/core", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia is a cloud & desktop IDE framework implemented in TypeScript.", "main": "lib/common/index.js", "typings": "lib/common/index.d.ts", @@ -16,8 +16,8 @@ "@phosphor/signaling": "1", "@phosphor/virtualdom": "1", "@phosphor/widgets": "1", - "@theia/application-package": "1.53.0", - "@theia/request": "1.53.0", + "@theia/application-package": "1.54.0", + "@theia/request": "1.54.0", "@types/body-parser": "^1.16.4", "@types/cookie": "^0.3.3", "@types/dompurify": "^2.2.2", @@ -210,8 +210,8 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", - "@theia/re-exports": "1.53.0", + "@theia/ext-scripts": "1.54.0", + "@theia/re-exports": "1.54.0", "minimist": "^1.2.0", "nodejs-file-downloader": "4.13.0" }, diff --git a/packages/core/src/browser/frontend-application-module.ts b/packages/core/src/browser/frontend-application-module.ts index 51131f9b1ce93..ea29eff0ebf87 100644 --- a/packages/core/src/browser/frontend-application-module.ts +++ b/packages/core/src/browser/frontend-application-module.ts @@ -144,6 +144,7 @@ import { bindTreePreferences } from './tree'; import { OpenWithService } from './open-with-service'; import { ViewColumnService } from './shell/view-column-service'; import { DomInputUndoRedoHandler, UndoRedoHandler, UndoRedoHandlerService } from './undo-redo-handler'; +import { WidgetStatusBarContribution, WidgetStatusBarService } from './widget-status-bar-service'; export { bindResourceProvider, bindMessageService, bindPreferenceService }; @@ -471,4 +472,8 @@ export const frontendApplicationModule = new ContainerModule((bind, _unbind, _is bindContributionProvider(bind, UndoRedoHandler); bind(DomInputUndoRedoHandler).toSelf().inSingletonScope(); bind(UndoRedoHandler).toService(DomInputUndoRedoHandler); + + bind(WidgetStatusBarService).toSelf().inSingletonScope(); + bind(FrontendApplicationContribution).toService(WidgetStatusBarService); + bindContributionProvider(bind, WidgetStatusBarContribution); }); diff --git a/packages/core/src/browser/index.ts b/packages/core/src/browser/index.ts index ecc1ccc4da2f8..02cae0fbdf1f4 100644 --- a/packages/core/src/browser/index.ts +++ b/packages/core/src/browser/index.ts @@ -48,3 +48,4 @@ export * from './styling-service'; export * from './hover-service'; export * from './saveable-service'; export * from './undo-redo-handler'; +export * from './widget-status-bar-service'; diff --git a/packages/core/src/browser/open-with-service.ts b/packages/core/src/browser/open-with-service.ts index 1e347ca88301b..56eb7c4d54a93 100644 --- a/packages/core/src/browser/open-with-service.ts +++ b/packages/core/src/browser/open-with-service.ts @@ -77,6 +77,10 @@ export class OpenWithService { protected readonly handlers: OpenWithHandler[] = []; registerHandler(handler: OpenWithHandler): Disposable { + if (this.handlers.some(h => h.id === handler.id)) { + console.warn('Duplicate OpenWithHandler registration: ' + handler.id); + return Disposable.NULL; + } this.handlers.push(handler); return Disposable.create(() => { const index = this.handlers.indexOf(handler); diff --git a/packages/core/src/browser/style/tabs.css b/packages/core/src/browser/style/tabs.css index d81927dca9e90..661030977fa90 100644 --- a/packages/core/src/browser/style/tabs.css +++ b/packages/core/src/browser/style/tabs.css @@ -9,10 +9,7 @@ --theia-private-horizontal-tab-scrollbar-height: 5px; --theia-tabbar-toolbar-z-index: 1001; --theia-toolbar-active-transform-scale: 1.272019649; - --theia-horizontal-toolbar-height: calc( - var(--theia-private-horizontal-tab-height) + - var(--theia-private-horizontal-tab-scrollbar-rail-height) / 2 - ); + --theia-horizontal-toolbar-height: calc(var(--theia-private-horizontal-tab-height) + var(--theia-private-horizontal-tab-scrollbar-rail-height) / 2); --theia-dragover-tab-border-width: 2px; } @@ -75,9 +72,7 @@ border-left: var(--theia-border-width) solid var(--theia-editorGroup-border); } -#theia-main-content-panel - .p-DockPanel-handle[data-orientation="vertical"] - + .p-TabBar { +#theia-main-content-panel .p-DockPanel-handle[data-orientation="vertical"]+.p-TabBar { border-top: var(--theia-border-width) solid var(--theia-editorGroup-border); } @@ -142,11 +137,9 @@ -webkit-appearance: none; -moz-appearance: none; - background-image: linear-gradient( - 45deg, + background-image: linear-gradient(45deg, transparent 50%, - var(--theia-icon-foreground) 50% - ), + var(--theia-icon-foreground) 50%), linear-gradient(135deg, var(--theia-icon-foreground) 50%, transparent 50%); background-position: calc(100% - 6px) 8px, calc(100% - 2px) 8px, 100% 0; background-size: 4px 5px; @@ -225,12 +218,8 @@ visibility: hidden; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-closable - > .p-TabBar-tabCloseIcon, -.p-TabBar.theia-app-centers - .p-TabBar-tab.theia-mod-pinned - > .p-TabBar-tabCloseIcon { +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable>.p-TabBar-tabCloseIcon, +.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned>.p-TabBar-tabCloseIcon { padding: 2px; margin-top: 2px; margin-left: 4px; @@ -248,31 +237,19 @@ -ms-user-select: none; } -.p-TabBar.theia-app-centers.dynamic-tabs - .p-TabBar-tab.p-mod-closable - > .p-TabBar-tabCloseIcon, -.p-TabBar.theia-app-centers.dynamic-tabs - .p-TabBar-tab.theia-mod-pinned - > .p-TabBar-tabCloseIcon { +.p-TabBar.theia-app-centers.dynamic-tabs .p-TabBar-tab.p-mod-closable>.p-TabBar-tabCloseIcon, +.p-TabBar.theia-app-centers.dynamic-tabs .p-TabBar-tab.theia-mod-pinned>.p-TabBar-tabCloseIcon { /* hide close icon for dynamic tabs strategy*/ display: none; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-current - > .p-TabBar-tabCloseIcon, -.p-TabBar.theia-app-centers - .p-TabBar-tab:hover.p-mod-closable - > .p-TabBar-tabCloseIcon, -.p-TabBar.theia-app-centers - .p-TabBar-tab:hover.theia-mod-pinned - > .p-TabBar-tabCloseIcon { +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-current>.p-TabBar-tabCloseIcon, +.p-TabBar.theia-app-centers .p-TabBar-tab:hover.p-mod-closable>.p-TabBar-tabCloseIcon, +.p-TabBar.theia-app-centers .p-TabBar-tab:hover.theia-mod-pinned>.p-TabBar-tabCloseIcon { display: inline-block; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-closable - > .p-TabBar-tabCloseIcon:hover { +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable>.p-TabBar-tabCloseIcon:hover { border-radius: 5px; background-color: rgba(50%, 50%, 50%, 0.2); } @@ -282,33 +259,21 @@ padding-right: 4px; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-closable:not(.theia-mod-dirty):hover - > .p-TabBar-tabCloseIcon:before, -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-closable:not(.theia-mod-dirty).p-TabBar-tab.p-mod-current - > .p-TabBar-tabCloseIcon:before, -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-closable.theia-mod-dirty - > .p-TabBar-tabCloseIcon:hover:before { +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable:not(.theia-mod-dirty):hover>.p-TabBar-tabCloseIcon:before, +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable:not(.theia-mod-dirty).p-TabBar-tab.p-mod-current>.p-TabBar-tabCloseIcon:before, +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable.theia-mod-dirty>.p-TabBar-tabCloseIcon:hover:before { content: "\ea76"; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.p-mod-closable.theia-mod-dirty - > .p-TabBar-tabCloseIcon:before { +.p-TabBar.theia-app-centers .p-TabBar-tab.p-mod-closable.theia-mod-dirty>.p-TabBar-tabCloseIcon:before { content: "\ea71"; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.theia-mod-pinned - > .p-TabBar-tabCloseIcon:before { +.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned>.p-TabBar-tabCloseIcon:before { content: "\eba0"; } -.p-TabBar.theia-app-centers - .p-TabBar-tab.theia-mod-pinned.theia-mod-dirty - > .p-TabBar-tabCloseIcon:before { +.p-TabBar.theia-app-centers .p-TabBar-tab.theia-mod-pinned.theia-mod-dirty>.p-TabBar-tabCloseIcon:before { content: "\ebb2"; } @@ -351,72 +316,35 @@ | Perfect scrollbar |----------------------------------------------------------------------------*/ -.p-TabBar[data-orientation="horizontal"] - .p-TabBar-content-container - > .ps__rail-x { +.p-TabBar[data-orientation="horizontal"] .p-TabBar-content-container>.ps__rail-x { height: var(--theia-private-horizontal-tab-scrollbar-rail-height); z-index: 1000; } -.p-TabBar[data-orientation="horizontal"] - .p-TabBar-content-container - > .ps__rail-x - > .ps__thumb-x { +.p-TabBar[data-orientation="horizontal"] .p-TabBar-content-container>.ps__rail-x>.ps__thumb-x { height: var(--theia-private-horizontal-tab-scrollbar-height) !important; - bottom: calc( - ( - var(--theia-private-horizontal-tab-scrollbar-rail-height) - - var(--theia-private-horizontal-tab-scrollbar-height) - ) / 2 - ); -} - -.p-TabBar[data-orientation="horizontal"] - .p-TabBar-content-container - > .ps__rail-x:hover, -.p-TabBar[data-orientation="horizontal"] - .p-TabBar-content-container - > .ps__rail-x:focus { + bottom: calc((var(--theia-private-horizontal-tab-scrollbar-rail-height) - var(--theia-private-horizontal-tab-scrollbar-height)) / 2); +} + +.p-TabBar[data-orientation="horizontal"] .p-TabBar-content-container>.ps__rail-x:hover, +.p-TabBar[data-orientation="horizontal"] .p-TabBar-content-container>.ps__rail-x:focus { height: var(--theia-private-horizontal-tab-scrollbar-rail-height) !important; } -.p-TabBar[data-orientation="horizontal"] - .p-TabBar-content-container - > .ps__rail-x:hover - > .ps__thumb-x, -.p-TabBar[data-orientation="horizontal"] - .p-TabBar-content-container - > .ps__rail-x:focus - > .ps__thumb-x { - height: calc( - var(--theia-private-horizontal-tab-scrollbar-height) / 2 - ) !important; - bottom: calc( - ( - var(--theia-private-horizontal-tab-scrollbar-rail-height) - - var(--theia-private-horizontal-tab-scrollbar-height) - ) / 2 - ); -} - -.p-TabBar[data-orientation="vertical"] - .p-TabBar-content-container - > .ps__rail-y { +.p-TabBar[data-orientation="horizontal"] .p-TabBar-content-container>.ps__rail-x:hover>.ps__thumb-x, +.p-TabBar[data-orientation="horizontal"] .p-TabBar-content-container>.ps__rail-x:focus>.ps__thumb-x { + height: calc(var(--theia-private-horizontal-tab-scrollbar-height) / 2) !important; + bottom: calc((var(--theia-private-horizontal-tab-scrollbar-rail-height) - var(--theia-private-horizontal-tab-scrollbar-height)) / 2); +} + +.p-TabBar[data-orientation="vertical"] .p-TabBar-content-container>.ps__rail-y { width: var(--theia-private-horizontal-tab-scrollbar-rail-height); z-index: 1000; } -.p-TabBar[data-orientation="vertical"] - .p-TabBar-content-container - > .ps__rail-y - > .ps__thumb-y { +.p-TabBar[data-orientation="vertical"] .p-TabBar-content-container>.ps__rail-y>.ps__thumb-y { width: var(--theia-private-horizontal-tab-scrollbar-height) !important; - right: calc( - ( - var(--theia-private-horizontal-tab-scrollbar-rail-height) - - var(--theia-private-horizontal-tab-scrollbar-height) - ) / 2 - ); + right: calc((var(--theia-private-horizontal-tab-scrollbar-rail-height) - var(--theia-private-horizontal-tab-scrollbar-height)) / 2); } .p-TabBar[data-orientation="vertical"] .p-TabBar-content-container { @@ -447,9 +375,8 @@ |----------------------------------------------------------------------------*/ .p-TabBar-toolbar { - z-index: var( - --theia-tabbar-toolbar-z-index - ); /* Due to the scrollbar (`z-index: 1000;`) it has a greater `z-index`. */ + z-index: var(--theia-tabbar-toolbar-z-index); + /* Due to the scrollbar (`z-index: 1000;`) it has a greater `z-index`. */ display: flex; flex-direction: row-reverse; padding: 4px; @@ -460,7 +387,8 @@ .p-TabBar-content-container { display: flex; flex: 1; - position: relative; /* This is necessary for perfect-scrollbar */ + position: relative; + /* This is necessary for perfect-scrollbar */ } .p-TabBar-toolbar .item { @@ -473,7 +401,7 @@ } .p-TabBar-toolbar .item>div { - height: 100%; + height: 100%; } .p-TabBar-toolbar .item.enabled { @@ -491,14 +419,14 @@ background-color: var(--theia-inputOption-activeBackground); } -.p-TabBar-toolbar .item > div { - line-height: calc(var(--theia-icon-size)+2px); - height: calc(var(--theia-icon-size)+2px); +.p-TabBar-toolbar .item>div { + line-height: calc(var(--theia-icon-size) + 2px); + height: calc(var(--theia-icon-size) + 2px); background-repeat: no-repeat; line-height: 18px; } -.p-TabBar-toolbar .item > div.no-icon { +.p-TabBar-toolbar .item>div.no-icon { /* Make room for a text label instead of an icon. */ width: 100%; } @@ -532,9 +460,7 @@ vertical-align: bottom; } -#theia-main-content-panel - .p-TabBar:not(.theia-tabBar-active) - .p-TabBar-toolbar { +#theia-main-content-panel .p-TabBar:not(.theia-tabBar-active) .p-TabBar-toolbar { display: none; } @@ -543,9 +469,7 @@ } .p-TabBar.theia-tabBar-multirow[data-orientation="horizontal"] { - min-height: calc( - var(--theia-breadcrumbs-height) + var(--theia-horizontal-toolbar-height) - ); + min-height: calc(var(--theia-breadcrumbs-height) + var(--theia-horizontal-toolbar-height)); flex-direction: column; } @@ -569,19 +493,14 @@ flex-direction: column; } -.p-TabBar.theia-app-centers[data-orientation="horizontal"].dynamic-tabs - .p-TabBar-tabLabel { +.p-TabBar.theia-app-centers[data-orientation="horizontal"].dynamic-tabs .p-TabBar-tabLabel { /* fade out text with dynamic tabs strategy */ - mask-image: linear-gradient( - to left, - rgba(0, 0, 0, 0.3), - rgba(0, 0, 0, 1) 15px - ); - -webkit-mask-image: linear-gradient( - to left, - rgba(0, 0, 0, 0.3), - rgba(0, 0, 0, 1) 15px - ); + mask-image: linear-gradient(to left, + rgba(0, 0, 0, 0.3), + rgba(0, 0, 0, 1) 15px); + -webkit-mask-image: linear-gradient(to left, + rgba(0, 0, 0, 0.3), + rgba(0, 0, 0, 1) 15px); flex: 1; } @@ -625,13 +544,11 @@ /*----------------------------------------------------------------------------- | Open tabs dropdown |----------------------------------------------------------------------------*/ -.theia-tabBar-open-tabs - > .theia-select-component - .theia-select-component-label { +.theia-tabBar-open-tabs>.theia-select-component .theia-select-component-label { display: none; } -.theia-tabBar-open-tabs > .theia-select-component { +.theia-tabBar-open-tabs>.theia-select-component { min-width: auto; height: 100%; } @@ -644,4 +561,4 @@ .theia-tabBar-open-tabs.p-mod-hidden { display: none; -} +} \ No newline at end of file diff --git a/packages/core/src/browser/widget-status-bar-service.ts b/packages/core/src/browser/widget-status-bar-service.ts new file mode 100644 index 0000000000000..d705880d90546 --- /dev/null +++ b/packages/core/src/browser/widget-status-bar-service.ts @@ -0,0 +1,84 @@ +// ***************************************************************************** +// Copyright (C) 2024 TypeFox and others. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0. +// +// This Source Code may also be made available under the following Secondary +// Licenses when the conditions for such availability set forth in the Eclipse +// Public License v. 2.0 are satisfied: GNU General Public License, version 2 +// with the GNU Classpath Exception which is available at +// https://www.gnu.org/software/classpath/license.html. +// +// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 +// ***************************************************************************** + +import { inject, injectable, named } from 'inversify'; +import { Widget } from './widgets'; +import { StatusBar } from './status-bar'; +import { FrontendApplicationContribution } from './frontend-application-contribution'; +import { ContributionProvider } from '../common'; +import { FrontendApplication } from './frontend-application'; + +export const WidgetStatusBarContribution = Symbol('WidgetStatusBarContribution'); + +export interface WidgetStatusBarContribution { + canHandle(widget: Widget): widget is T; + activate(statusBar: StatusBar, widget: T): void; + deactivate(statusBar: StatusBar): void; +} + +/** + * Creates an empty {@link WidgetStatusBarContribution} that does nothing. + * Useful for widgets that are not handled by any other contribution, for example: + * * Settings widget + * * Welcome widget + * * Webview widget + * + * @param prototype Prototype to identify the kind of the widget. + * @returns An empty {@link WidgetStatusBarContribution}. + */ +export function noopWidgetStatusBarContribution(prototype: Function): WidgetStatusBarContribution { + return { + canHandle(widget: Widget): widget is Widget { + return widget instanceof prototype; + }, + activate: () => { }, + deactivate: () => { } + }; +} + +@injectable() +export class WidgetStatusBarService implements FrontendApplicationContribution { + + @inject(ContributionProvider) @named(WidgetStatusBarContribution) + protected readonly contributionProvider: ContributionProvider>; + + @inject(StatusBar) + protected readonly statusBar: StatusBar; + + onStart(app: FrontendApplication): void { + app.shell.onDidChangeCurrentWidget(event => { + if (event.newValue) { + this.show(event.newValue); + } + }); + } + + protected show(widget: Widget): void { + const contributions = this.contributionProvider.getContributions(); + // If any contribution can handle the widget, activate it + // If none can, keep everything as is + if (contributions.some(contribution => contribution.canHandle(widget))) { + for (const contribution of contributions) { + // Deactivate all contributions + contribution.deactivate(this.statusBar); + if (contribution.canHandle(widget)) { + // Selectively re-activate them + contribution.activate(this.statusBar, widget); + } + } + } + } +} diff --git a/packages/core/src/browser/widgets/split-widget.ts b/packages/core/src/browser/widgets/split-widget.ts index 0c1e5dd3d4269..ff54f218a7483 100644 --- a/packages/core/src/browser/widgets/split-widget.ts +++ b/packages/core/src/browser/widgets/split-widget.ts @@ -14,12 +14,11 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { Emitter } from 'vscode-languageserver-protocol'; import { ApplicationShell, StatefulWidget } from '../shell'; import { BaseWidget, Message, PanelLayout, SplitPanel, Widget } from './widget'; import { CompositeSaveable, Saveable, SaveableSource } from '../saveable'; import { Navigatable } from '../navigatable-types'; -import { URI } from '../../common'; +import { Emitter, URI } from '../../common'; /** * A widget containing a number of panes in a split layout. diff --git a/packages/debug/package.json b/packages/debug/package.json index 20c5f05cf0f2a..bb7dcb3e6d939 100644 --- a/packages/debug/package.json +++ b/packages/debug/package.json @@ -1,22 +1,22 @@ { "name": "@theia/debug", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Debug Extension", "dependencies": { - "@theia/console": "1.53.0", - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/markers": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/console": "1.54.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/markers": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/output": "1.53.0", - "@theia/process": "1.53.0", - "@theia/task": "1.53.0", - "@theia/test": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/output": "1.54.0", + "@theia/process": "1.54.0", + "@theia/task": "1.54.0", + "@theia/test": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/workspace": "1.54.0", "@vscode/debugprotocol": "^1.51.0", "fast-deep-equal": "^3.1.3", "jsonc-parser": "^2.2.0", @@ -59,7 +59,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/dev-container/package.json b/packages/dev-container/package.json index 32f233826ae62..8c50696c150f6 100644 --- a/packages/dev-container/package.json +++ b/packages/dev-container/package.json @@ -1,12 +1,12 @@ { "name": "@theia/dev-container", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Editor Preview Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/output": "1.53.0", - "@theia/remote": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/output": "1.54.0", + "@theia/remote": "1.54.0", + "@theia/workspace": "1.54.0", "dockerode": "^4.0.2", "jsonc-parser": "^2.2.0", "uuid": "^8.0.0" @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/dockerode": "^3.3.23" }, "nyc": { diff --git a/packages/editor-preview/package.json b/packages/editor-preview/package.json index 7f55c86cd94fc..9c572f902b63e 100644 --- a/packages/editor-preview/package.json +++ b/packages/editor-preview/package.json @@ -1,11 +1,11 @@ { "name": "@theia/editor-preview", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Editor Preview Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/navigator": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/navigator": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -41,7 +41,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/editor-preview/src/browser/editor-preview-tree-decorator.ts b/packages/editor-preview/src/browser/editor-preview-tree-decorator.ts index 21c6671cee3ca..c5908ef105624 100644 --- a/packages/editor-preview/src/browser/editor-preview-tree-decorator.ts +++ b/packages/editor-preview/src/browser/editor-preview-tree-decorator.ts @@ -30,11 +30,10 @@ import { import { Disposable } from '@theia/core/lib/common'; import { OpenEditorNode } from '@theia/navigator/lib/browser/open-editors-widget/navigator-open-editors-tree-model'; import { EditorPreviewWidget } from './editor-preview-widget'; -import { EditorPreviewManager } from './editor-preview-manager'; @injectable() export class EditorPreviewTreeDecorator implements TreeDecorator, FrontendApplicationContribution { - @inject(EditorPreviewManager) protected readonly editorPreviewManager: EditorPreviewManager; + @inject(ApplicationShell) protected readonly shell: ApplicationShell; readonly id = 'theia-open-editors-file-decorator'; diff --git a/packages/editor/package.json b/packages/editor/package.json index c0a330246a020..32d1e2d9d1f7b 100644 --- a/packages/editor/package.json +++ b/packages/editor/package.json @@ -1,10 +1,10 @@ { "name": "@theia/editor", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Editor Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/variable-resolver": "1.53.0", + "@theia/core": "1.54.0", + "@theia/variable-resolver": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -41,7 +41,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/editor/src/browser/editor-contribution.ts b/packages/editor/src/browser/editor-contribution.ts index a51191531fdf4..00dca84019da8 100644 --- a/packages/editor/src/browser/editor-contribution.ts +++ b/packages/editor/src/browser/editor-contribution.ts @@ -20,7 +20,9 @@ import { injectable, inject, optional } from '@theia/core/shared/inversify'; import { StatusBarAlignment, StatusBar } from '@theia/core/lib/browser/status-bar/status-bar'; import { FrontendApplicationContribution, DiffUris, DockLayout, - QuickInputService, KeybindingRegistry, KeybindingContribution, SHELL_TABBAR_CONTEXT_SPLIT, ApplicationShell + QuickInputService, KeybindingRegistry, KeybindingContribution, SHELL_TABBAR_CONTEXT_SPLIT, ApplicationShell, + WidgetStatusBarContribution, + Widget } from '@theia/core/lib/browser'; import { ContextKeyService } from '@theia/core/lib/browser/context-key-service'; import { CommandHandler, DisposableCollection, MenuContribution, MenuModelRegistry } from '@theia/core'; @@ -33,9 +35,9 @@ import { EditorWidget } from './editor-widget'; import { EditorLanguageStatusService } from './language-status/editor-language-status-service'; @injectable() -export class EditorContribution implements FrontendApplicationContribution, CommandContribution, KeybindingContribution, MenuContribution { +export class EditorContribution implements FrontendApplicationContribution, + CommandContribution, KeybindingContribution, MenuContribution, WidgetStatusBarContribution { - @inject(StatusBar) protected readonly statusBar: StatusBar; @inject(EditorManager) protected readonly editorManager: EditorManager; @inject(EditorLanguageStatusService) protected readonly languageStatusService: EditorLanguageStatusService; @inject(ApplicationShell) protected readonly shell: ApplicationShell; @@ -48,9 +50,6 @@ export class EditorContribution implements FrontendApplicationContribution, Comm onStart(): void { this.initEditorContextKeys(); - - this.updateStatusBar(); - this.editorManager.onCurrentEditorChanged(() => this.updateStatusBar()); } protected initEditorContextKeys(): void { @@ -72,33 +71,41 @@ export class EditorContribution implements FrontendApplicationContribution, Comm } protected readonly toDisposeOnCurrentEditorChanged = new DisposableCollection(); - protected updateStatusBar(): void { + + canHandle(widget: Widget): widget is EditorWidget { + return widget instanceof EditorWidget; + } + + activate(statusBar: StatusBar, widget: EditorWidget): void { this.toDisposeOnCurrentEditorChanged.dispose(); + const editor = widget.editor; + this.updateLanguageStatus(statusBar, editor); + this.updateEncodingStatus(statusBar, editor); + this.setCursorPositionStatus(statusBar, editor); + this.toDisposeOnCurrentEditorChanged.pushAll([ + editor.onLanguageChanged(() => this.updateLanguageStatus(statusBar, editor)), + editor.onEncodingChanged(() => this.updateEncodingStatus(statusBar, editor)), + editor.onCursorPositionChanged(() => this.setCursorPositionStatus(statusBar, editor)) + ]); + } - const widget = this.editorManager.currentEditor; - const editor = widget && widget.editor; - this.updateLanguageStatus(editor); - this.updateEncodingStatus(editor); - this.setCursorPositionStatus(editor); - if (editor) { - this.toDisposeOnCurrentEditorChanged.pushAll([ - editor.onLanguageChanged(() => this.updateLanguageStatus(editor)), - editor.onEncodingChanged(() => this.updateEncodingStatus(editor)), - editor.onCursorPositionChanged(() => this.setCursorPositionStatus(editor)) - ]); - } + deactivate(statusBar: StatusBar): void { + this.toDisposeOnCurrentEditorChanged.dispose(); + this.updateLanguageStatus(statusBar, undefined); + this.updateEncodingStatus(statusBar, undefined); + this.setCursorPositionStatus(statusBar, undefined); } - protected updateLanguageStatus(editor: TextEditor | undefined): void { + protected updateLanguageStatus(statusBar: StatusBar, editor: TextEditor | undefined): void { this.languageStatusService.updateLanguageStatus(editor); } - protected updateEncodingStatus(editor: TextEditor | undefined): void { + protected updateEncodingStatus(statusBar: StatusBar, editor: TextEditor | undefined): void { if (!editor) { - this.statusBar.removeElement('editor-status-encoding'); + statusBar.removeElement('editor-status-encoding'); return; } - this.statusBar.setElement('editor-status-encoding', { + statusBar.setElement('editor-status-encoding', { text: SUPPORTED_ENCODINGS[editor.getEncoding()].labelShort, alignment: StatusBarAlignment.RIGHT, priority: 10, @@ -107,13 +114,13 @@ export class EditorContribution implements FrontendApplicationContribution, Comm }); } - protected setCursorPositionStatus(editor: TextEditor | undefined): void { + protected setCursorPositionStatus(statusBar: StatusBar, editor: TextEditor | undefined): void { if (!editor) { - this.statusBar.removeElement('editor-status-cursor-position'); + statusBar.removeElement('editor-status-cursor-position'); return; } const { cursor } = editor; - this.statusBar.setElement('editor-status-cursor-position', { + statusBar.setElement('editor-status-cursor-position', { text: nls.localizeByDefault('Ln {0}, Col {1}', cursor.line + 1, editor.getVisibleColumn(cursor)), alignment: StatusBarAlignment.RIGHT, priority: 100, diff --git a/packages/editor/src/browser/editor-frontend-module.ts b/packages/editor/src/browser/editor-frontend-module.ts index e4a089ae90b2a..d5142fa29fa9e 100644 --- a/packages/editor/src/browser/editor-frontend-module.ts +++ b/packages/editor/src/browser/editor-frontend-module.ts @@ -19,7 +19,7 @@ import '../../src/browser/language-status/editor-language-status.css'; import { ContainerModule } from '@theia/core/shared/inversify'; import { CommandContribution, MenuContribution } from '@theia/core/lib/common'; -import { OpenHandler, WidgetFactory, FrontendApplicationContribution, KeybindingContribution } from '@theia/core/lib/browser'; +import { OpenHandler, WidgetFactory, FrontendApplicationContribution, KeybindingContribution, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { VariableContribution } from '@theia/variable-resolver/lib/browser'; import { EditorManager, EditorAccess, ActiveEditorAccess, CurrentEditorAccess } from './editor-manager'; import { EditorContribution } from './editor-contribution'; @@ -59,7 +59,6 @@ export default new ContainerModule(bind => { bind(KeybindingContribution).toService(EditorKeybindingContribution); bind(EditorContribution).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(EditorContribution); bind(EditorLanguageStatusService).toSelf().inSingletonScope(); bind(EditorLineNumberContribution).toSelf().inSingletonScope(); @@ -73,7 +72,13 @@ export default new ContainerModule(bind => { bind(VariableContribution).to(EditorVariableContribution).inSingletonScope(); - [CommandContribution, KeybindingContribution, MenuContribution].forEach(serviceIdentifier => { + [ + FrontendApplicationContribution, + WidgetStatusBarContribution, + CommandContribution, + KeybindingContribution, + MenuContribution + ].forEach(serviceIdentifier => { bind(serviceIdentifier).toService(EditorContribution); }); bind(QuickEditorService).toSelf().inSingletonScope(); diff --git a/packages/electron/package.json b/packages/electron/package.json index e6ec7699f5883..23e63797d9c8e 100644 --- a/packages/electron/package.json +++ b/packages/electron/package.json @@ -1,6 +1,6 @@ { "name": "@theia/electron", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Electron utility package", "dependencies": { "electron-store": "^8.0.0", @@ -8,8 +8,8 @@ "native-keymap": "^2.2.1" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", - "@theia/re-exports": "1.53.0" + "@theia/ext-scripts": "1.54.0", + "@theia/re-exports": "1.54.0" }, "peerDependencies": { "electron": "^30.1.2" diff --git a/packages/external-terminal/package.json b/packages/external-terminal/package.json index e0348b0654fed..e15aedbc83909 100644 --- a/packages/external-terminal/package.json +++ b/packages/external-terminal/package.json @@ -1,11 +1,11 @@ { "name": "@theia/external-terminal", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - External Terminal Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/workspace": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -42,7 +42,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/file-search/package.json b/packages/file-search/package.json index 4c5ba9e5d522e..79861c8efdc55 100644 --- a/packages/file-search/package.json +++ b/packages/file-search/package.json @@ -1,13 +1,13 @@ { "name": "@theia/file-search", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - File Search Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/process": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/process": "1.54.0", + "@theia/workspace": "1.54.0", "@vscode/ripgrep": "^1.14.2", "tslib": "^2.6.2" }, @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/filesystem/package.json b/packages/filesystem/package.json index 7c1a60322c673..bcdd37c09bc2f 100644 --- a/packages/filesystem/package.json +++ b/packages/filesystem/package.json @@ -1,9 +1,9 @@ { "name": "@theia/filesystem", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - FileSystem Extension", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "@types/body-parser": "^1.17.0", "@types/multer": "^1.4.7", "@types/rimraf": "^2.0.2", @@ -73,7 +73,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/getting-started/package.json b/packages/getting-started/package.json index 644cfca695224..cb666bfd2dc5f 100644 --- a/packages/getting-started/package.json +++ b/packages/getting-started/package.json @@ -1,14 +1,14 @@ { "name": "@theia/getting-started", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - GettingStarted Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/keymaps": "1.53.0", - "@theia/preview": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/keymaps": "1.54.0", + "@theia/preview": "1.54.0", + "@theia/workspace": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/getting-started/src/browser/getting-started-frontend-module.ts b/packages/getting-started/src/browser/getting-started-frontend-module.ts index fbcc828646f02..d029dd7a2236c 100644 --- a/packages/getting-started/src/browser/getting-started-frontend-module.ts +++ b/packages/getting-started/src/browser/getting-started-frontend-module.ts @@ -17,13 +17,14 @@ import { GettingStartedContribution } from './getting-started-contribution'; import { ContainerModule, interfaces } from '@theia/core/shared/inversify'; import { GettingStartedWidget } from './getting-started-widget'; -import { WidgetFactory, FrontendApplicationContribution, bindViewContribution } from '@theia/core/lib/browser'; +import { WidgetFactory, FrontendApplicationContribution, bindViewContribution, noopWidgetStatusBarContribution, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { bindGettingStartedPreferences } from './getting-started-preferences'; import '../../src/browser/style/index.css'; export default new ContainerModule((bind: interfaces.Bind) => { bindViewContribution(bind, GettingStartedContribution); bind(FrontendApplicationContribution).toService(GettingStartedContribution); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(GettingStartedWidget)); bind(GettingStartedWidget).toSelf(); bind(WidgetFactory).toDynamicValue(context => ({ id: GettingStartedWidget.ID, diff --git a/packages/git/package.json b/packages/git/package.json index eb69eba9b6383..a5e1b776c1ec3 100644 --- a/packages/git/package.json +++ b/packages/git/package.json @@ -1,16 +1,16 @@ { "name": "@theia/git", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Git Integration", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/navigator": "1.53.0", - "@theia/scm": "1.53.0", - "@theia/scm-extra": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/navigator": "1.54.0", + "@theia/scm": "1.54.0", + "@theia/scm-extra": "1.54.0", + "@theia/workspace": "1.54.0", "@types/diff": "^5.2.1", "@types/p-queue": "^2.3.1", "diff": "^5.2.0", @@ -67,7 +67,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/luxon": "^2.3.2", "upath": "^1.0.2" }, diff --git a/packages/keymaps/package.json b/packages/keymaps/package.json index 425fe663b24fd..5a0bbff683274 100644 --- a/packages/keymaps/package.json +++ b/packages/keymaps/package.json @@ -1,18 +1,18 @@ { "name": "@theia/keymaps", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Custom Keymaps Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/preferences": "1.53.0", - "@theia/userstorage": "1.53.0", + "@theia/preferences": "1.54.0", + "@theia/userstorage": "1.54.0", "jsonc-parser": "^2.2.0", "tslib": "^2.6.2" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "publishConfig": { "access": "public" diff --git a/packages/keymaps/src/browser/keymaps-frontend-module.ts b/packages/keymaps/src/browser/keymaps-frontend-module.ts index 2056444246231..5a2c1476bc357 100644 --- a/packages/keymaps/src/browser/keymaps-frontend-module.ts +++ b/packages/keymaps/src/browser/keymaps-frontend-module.ts @@ -22,7 +22,7 @@ import { KeymapsFrontendContribution } from './keymaps-frontend-contribution'; import { CommandContribution, MenuContribution } from '@theia/core/lib/common'; import { KeybindingContribution } from '@theia/core/lib/browser/keybinding'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; -import { WidgetFactory } from '@theia/core/lib/browser'; +import { noopWidgetStatusBarContribution, WidgetFactory, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { KeybindingWidget } from './keybindings-widget'; import { KeybindingSchemaUpdater } from './keybinding-schema-updater'; import { JsonSchemaContribution } from '@theia/core/lib/browser/json-schema-store'; @@ -41,4 +41,5 @@ export default new ContainerModule(bind => { })).inSingletonScope(); bind(KeybindingSchemaUpdater).toSelf().inSingletonScope(); bind(JsonSchemaContribution).toService(KeybindingSchemaUpdater); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(KeybindingWidget)); }); diff --git a/packages/markers/package.json b/packages/markers/package.json index 97d1a36c62c8a..47aba430ee260 100644 --- a/packages/markers/package.json +++ b/packages/markers/package.json @@ -1,11 +1,11 @@ { "name": "@theia/markers", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Markers Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/workspace": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -41,7 +41,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/memory-inspector/package.json b/packages/memory-inspector/package.json index ff3b247c27495..a505a90f24873 100644 --- a/packages/memory-inspector/package.json +++ b/packages/memory-inspector/package.json @@ -1,6 +1,6 @@ { "name": "@theia/memory-inspector", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Memory Inspector", "keywords": [ "theia-extension" @@ -27,8 +27,8 @@ "watch": "theiaext watch" }, "dependencies": { - "@theia/core": "1.53.0", - "@theia/debug": "1.53.0", + "@theia/core": "1.54.0", + "@theia/debug": "1.54.0", "@vscode/debugprotocol": "^1.51.0", "long": "^4.0.0", "tslib": "^2.6.2" diff --git a/packages/messages/package.json b/packages/messages/package.json index 56cfe7f700f30..d0526320a5100 100644 --- a/packages/messages/package.json +++ b/packages/messages/package.json @@ -1,9 +1,9 @@ { "name": "@theia/messages", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Messages Extension", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "react-perfect-scrollbar": "^1.5.3", "ts-md5": "^1.2.2", "tslib": "^2.6.2" @@ -41,7 +41,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/metrics/package.json b/packages/metrics/package.json index 422ede4ef0702..ffa673db971e4 100644 --- a/packages/metrics/package.json +++ b/packages/metrics/package.json @@ -1,9 +1,9 @@ { "name": "@theia/metrics", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Metrics Extension", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "prom-client": "^10.2.0", "tslib": "^2.6.2" }, @@ -44,7 +44,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/mini-browser/package.json b/packages/mini-browser/package.json index 405aab53fc71c..2dbc4baf27487 100644 --- a/packages/mini-browser/package.json +++ b/packages/mini-browser/package.json @@ -1,10 +1,10 @@ { "name": "@theia/mini-browser", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Mini-Browser Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", "@types/mime-types": "^2.1.0", "mime-types": "^2.1.18", "pdfobject": "^2.0.201604172", @@ -49,7 +49,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/monaco/package.json b/packages/monaco/package.json index 626ab8cb50145..7e65c3cd66811 100644 --- a/packages/monaco/package.json +++ b/packages/monaco/package.json @@ -1,15 +1,15 @@ { "name": "@theia/monaco", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Monaco Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/markers": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/markers": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/outline-view": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/outline-view": "1.54.0", + "@theia/workspace": "1.54.0", "fast-plist": "^0.1.2", "idb": "^4.0.5", "jsonc-parser": "^2.2.0", @@ -52,7 +52,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/monaco/src/browser/monaco-frontend-module.ts b/packages/monaco/src/browser/monaco-frontend-module.ts index 0bd3a74f2500c..e7d727453bb07 100644 --- a/packages/monaco/src/browser/monaco-frontend-module.ts +++ b/packages/monaco/src/browser/monaco-frontend-module.ts @@ -21,7 +21,8 @@ import { FrontendApplicationContribution, KeybindingContribution, PreferenceService, PreferenceSchemaProvider, createPreferenceProxy, PreferenceScope, PreferenceChange, OVERRIDE_PROPERTY_PATTERN, QuickInputService, StylingParticipant, WebSocketConnectionProvider, - UndoRedoHandler + UndoRedoHandler, + WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { TextEditorProvider, DiffNavigatorProvider, TextEditor } from '@theia/editor/lib/browser'; import { MonacoEditorProvider, MonacoEditorFactory } from './monaco-editor-provider'; @@ -135,7 +136,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(FrontendApplicationContribution).toService(MonacoFormattingConflictsContribution); bind(MonacoStatusBarContribution).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(MonacoStatusBarContribution); + bind(WidgetStatusBarContribution).toService(MonacoStatusBarContribution); bind(MonacoCommandRegistry).toSelf().inSingletonScope(); bind(MonacoEditorCommandHandlers).toSelf().inSingletonScope(); diff --git a/packages/monaco/src/browser/monaco-status-bar-contribution.ts b/packages/monaco/src/browser/monaco-status-bar-contribution.ts index fae85805e9f1a..c7ac733d29987 100644 --- a/packages/monaco/src/browser/monaco-status-bar-contribution.ts +++ b/packages/monaco/src/browser/monaco-status-bar-contribution.ts @@ -14,93 +14,90 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { injectable, inject } from '@theia/core/shared/inversify'; +import { injectable } from '@theia/core/shared/inversify'; import { DisposableCollection, nls } from '@theia/core'; -import { FrontendApplicationContribution, FrontendApplication, StatusBar, StatusBarAlignment } from '@theia/core/lib/browser'; -import { EditorCommands, EditorManager, EditorWidget } from '@theia/editor/lib/browser'; +import { StatusBar, StatusBarAlignment, Widget, WidgetStatusBarContribution } from '@theia/core/lib/browser'; +import { EditorCommands, EditorWidget } from '@theia/editor/lib/browser'; import { MonacoEditor } from './monaco-editor'; import * as monaco from '@theia/monaco-editor-core'; +export const EDITOR_STATUS_TABBING_CONFIG = 'editor-status-tabbing-config'; +export const EDITOR_STATUS_EOL = 'editor-status-eol'; + @injectable() -export class MonacoStatusBarContribution implements FrontendApplicationContribution { +export class MonacoStatusBarContribution implements WidgetStatusBarContribution { protected readonly toDispose = new DisposableCollection(); - constructor( - @inject(EditorManager) protected readonly editorManager: EditorManager, - @inject(StatusBar) protected readonly statusBar: StatusBar - ) { } - - onStart(app: FrontendApplication): void { - this.updateStatusBar(); - this.editorManager.onCurrentEditorChanged(() => this.updateStatusBar()); + canHandle(widget: Widget): widget is EditorWidget { + if (widget instanceof EditorWidget) { + return Boolean(this.getModel(widget)); + } + return false; } - protected updateStatusBar(): void { - const editor = this.editorManager.currentEditor; + activate(statusBar: StatusBar, editor: EditorWidget): void { + this.toDispose.dispose(); const editorModel = this.getModel(editor); - if (editor && editorModel) { - this.setConfigTabSizeWidget(); - this.setLineEndingWidget(); - - this.toDispose.dispose(); + if (editorModel) { + this.setConfigTabSizeWidget(statusBar, editorModel); + this.setLineEndingWidget(statusBar, editorModel); this.toDispose.push(editorModel.onDidChangeOptions(() => { - this.setConfigTabSizeWidget(); - this.setLineEndingWidget(); + this.setConfigTabSizeWidget(statusBar, editorModel); + this.setLineEndingWidget(statusBar, editorModel); })); let previous = editorModel.getEOL(); this.toDispose.push(editorModel.onDidChangeContent(e => { if (previous !== e.eol) { previous = e.eol; - this.setLineEndingWidget(); + this.setLineEndingWidget(statusBar, editorModel); } })); } else { - this.removeConfigTabSizeWidget(); - this.removeLineEndingWidget(); + this.deactivate(statusBar); } } - protected setConfigTabSizeWidget(): void { - const editor = this.editorManager.currentEditor; - const editorModel = this.getModel(editor); - if (editor && editorModel) { - const modelOptions = editorModel.getOptions(); - const tabSize = modelOptions.tabSize; - const indentSize = modelOptions.indentSize; - const spaceOrTabSizeMessage = modelOptions.insertSpaces - ? nls.localizeByDefault('Spaces: {0}', indentSize) - : nls.localizeByDefault('Tab Size: {0}', tabSize); - this.statusBar.setElement('editor-status-tabbing-config', { - text: spaceOrTabSizeMessage, - alignment: StatusBarAlignment.RIGHT, - priority: 10, - command: EditorCommands.CONFIG_INDENTATION.id, - tooltip: nls.localizeByDefault('Select Indentation') - }); - } + deactivate(statusBar: StatusBar): void { + this.toDispose.dispose(); + this.removeConfigTabSizeWidget(statusBar); + this.removeLineEndingWidget(statusBar); } - protected removeConfigTabSizeWidget(): void { - this.statusBar.removeElement('editor-status-tabbing-config'); + + protected setConfigTabSizeWidget(statusBar: StatusBar, model: monaco.editor.ITextModel): void { + const modelOptions = model.getOptions(); + const tabSize = modelOptions.tabSize; + const indentSize = modelOptions.indentSize; + const spaceOrTabSizeMessage = modelOptions.insertSpaces + ? nls.localizeByDefault('Spaces: {0}', indentSize) + : nls.localizeByDefault('Tab Size: {0}', tabSize); + statusBar.setElement(EDITOR_STATUS_TABBING_CONFIG, { + text: spaceOrTabSizeMessage, + alignment: StatusBarAlignment.RIGHT, + priority: 10, + command: EditorCommands.CONFIG_INDENTATION.id, + tooltip: nls.localizeByDefault('Select Indentation') + }); } - protected setLineEndingWidget(): void { - const editor = this.editorManager.currentEditor; - const editorModel = this.getModel(editor); - if (editor && editorModel) { - const eol = editorModel.getEOL(); - const text = eol === '\n' ? 'LF' : 'CRLF'; - this.statusBar.setElement('editor-status-eol', { - text: `${text}`, - alignment: StatusBarAlignment.RIGHT, - priority: 11, - command: EditorCommands.CONFIG_EOL.id, - tooltip: nls.localizeByDefault('Select End of Line Sequence') - }); - } + protected removeConfigTabSizeWidget(statusBar: StatusBar): void { + statusBar.removeElement(EDITOR_STATUS_TABBING_CONFIG); } - protected removeLineEndingWidget(): void { - this.statusBar.removeElement('editor-status-eol'); + + protected setLineEndingWidget(statusBar: StatusBar, model: monaco.editor.ITextModel): void { + const eol = model.getEOL(); + const text = eol === '\n' ? 'LF' : 'CRLF'; + statusBar.setElement(EDITOR_STATUS_EOL, { + text: `${text}`, + alignment: StatusBarAlignment.RIGHT, + priority: 11, + command: EditorCommands.CONFIG_EOL.id, + tooltip: nls.localizeByDefault('Select End of Line Sequence') + }); + } + + protected removeLineEndingWidget(statusBar: StatusBar): void { + statusBar.removeElement(EDITOR_STATUS_EOL); } protected getModel(editor: EditorWidget | undefined): monaco.editor.ITextModel | undefined { diff --git a/packages/navigator/package.json b/packages/navigator/package.json index e20b6b9692b2a..9abadafa4f317 100644 --- a/packages/navigator/package.json +++ b/packages/navigator/package.json @@ -1,11 +1,11 @@ { "name": "@theia/navigator", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Navigator Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/workspace": "1.54.0", "minimatch": "^5.1.0", "tslib": "^2.6.2" }, @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/notebook/package.json b/packages/notebook/package.json index c62ef82bb0701..cc15cf13ac99f 100644 --- a/packages/notebook/package.json +++ b/packages/notebook/package.json @@ -1,14 +1,14 @@ { "name": "@theia/notebook", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Notebook Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/outline-view": "1.53.0", + "@theia/outline-view": "1.54.0", "advanced-mark.js": "^2.6.0", "react-perfect-scrollbar": "^1.5.8", "tslib": "^2.6.2" @@ -46,7 +46,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/markdown-it": "^12.2.3", "@types/vscode-notebook-renderer": "^1.72.0" }, diff --git a/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts b/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts index 05ded847b5bb3..740970baf76ca 100644 --- a/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts +++ b/packages/notebook/src/browser/contributions/notebook-status-bar-contribution.ts @@ -14,10 +14,9 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { inject, injectable } from '@theia/core/shared/inversify'; -import { FrontendApplicationContribution, StatusBar, StatusBarAlignment } from '@theia/core/lib/browser'; +import { injectable } from '@theia/core/shared/inversify'; +import { StatusBar, StatusBarAlignment, Widget, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { Disposable } from '@theia/core/lib/common'; -import { NotebookEditorWidgetService } from '../service/notebook-editor-widget-service'; import { NotebookEditorWidget } from '../notebook-editor-widget'; import { nls } from '@theia/core'; import { NotebookCommands } from './notebook-actions-contribution'; @@ -25,53 +24,43 @@ import { NotebookCommands } from './notebook-actions-contribution'; export const NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID = 'notebook-cell-selection-position'; @injectable() -export class NotebookStatusBarContribution implements FrontendApplicationContribution { +export class NotebookStatusBarContribution implements WidgetStatusBarContribution { - @inject(StatusBar) protected readonly statusBar: StatusBar; - @inject(NotebookEditorWidgetService) protected readonly editorWidgetService: NotebookEditorWidgetService; + protected onDeactivate: Disposable | undefined; - protected currentCellSelectionListener: Disposable | undefined; - protected lastFocusedEditor: NotebookEditorWidget | undefined; + canHandle(widget: Widget): widget is NotebookEditorWidget { + return widget instanceof NotebookEditorWidget; + } - onStart(): void { - this.editorWidgetService.onDidChangeFocusedEditor(editor => { - this.currentCellSelectionListener?.dispose(); - this.currentCellSelectionListener = editor?.model?.onDidChangeSelectedCell(() => - this.updateStatusbar(editor) - ); - editor?.onDidDispose(() => { - this.lastFocusedEditor = undefined; - this.updateStatusbar(); + activate(statusBar: StatusBar, widget: NotebookEditorWidget): void { + widget.ready.then(model => { + this.onDeactivate = model.onDidChangeSelectedCell(() => { + this.updateStatusbar(statusBar, widget); }); - this.updateStatusbar(editor); - this.lastFocusedEditor = editor; }); - if (this.editorWidgetService.focusedEditor) { - this.updateStatusbar(); - } + this.updateStatusbar(statusBar, widget); } - protected async updateStatusbar(editor?: NotebookEditorWidget): Promise { - if ((!editor && !this.lastFocusedEditor?.isVisible) || editor?.model?.cells.length === 0) { - this.statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID); - return; - } + deactivate(statusBar: StatusBar): void { + this.onDeactivate?.dispose(); + this.updateStatusbar(statusBar); + } - await editor?.ready; - if (!editor?.model) { + protected async updateStatusbar(statusBar: StatusBar, editor?: NotebookEditorWidget): Promise { + const model = await editor?.ready; + if (!model || model.cells.length === 0 || !model.selectedCell) { + statusBar.removeElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID); return; } - const selectedCellIndex = editor.model.selectedCell ? editor.model.cells.indexOf(editor.model.selectedCell) + 1 : ''; + const selectedCellIndex = model.cells.indexOf(model.selectedCell) + 1; - this.statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, { - text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, editor.model.cells.length), + statusBar.setElement(NOTEBOOK_CELL_SELECTION_STATUS_BAR_ID, { + text: nls.localizeByDefault('Cell {0} of {1}', selectedCellIndex, model.cells.length), alignment: StatusBarAlignment.RIGHT, priority: 100, command: NotebookCommands.CENTER_ACTIVE_CELL.id, arguments: [editor] }); - } - } diff --git a/packages/notebook/src/browser/notebook-editor-widget.tsx b/packages/notebook/src/browser/notebook-editor-widget.tsx index a936a270825a4..3451d76615e8d 100644 --- a/packages/notebook/src/browser/notebook-editor-widget.tsx +++ b/packages/notebook/src/browser/notebook-editor-widget.tsx @@ -212,7 +212,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa protected override onActivateRequest(msg: Message): void { super.onActivateRequest(msg); - this.node.focus(); + (this.node.getElementsByClassName('theia-notebook-main-container')[0] as HTMLDivElement)?.focus(); } getResourceUri(): URI | undefined { @@ -271,7 +271,7 @@ export class NotebookEditorWidget extends ReactWidget implements Navigatable, Sa
; } else { - return
+ return
; } diff --git a/packages/notebook/src/browser/notebook-frontend-module.ts b/packages/notebook/src/browser/notebook-frontend-module.ts index 839d16908a17d..b5158315668b2 100644 --- a/packages/notebook/src/browser/notebook-frontend-module.ts +++ b/packages/notebook/src/browser/notebook-frontend-module.ts @@ -16,7 +16,9 @@ import '../../src/browser/style/index.css'; import { ContainerModule } from '@theia/core/shared/inversify'; -import { FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory } from '@theia/core/lib/browser'; +import { + FrontendApplicationContribution, KeybindingContribution, LabelProviderContribution, OpenHandler, UndoRedoHandler, WidgetFactory, WidgetStatusBarContribution +} from '@theia/core/lib/browser'; import { ColorContribution } from '@theia/core/lib/browser/color-application-contribution'; import { NotebookOpenHandler } from './notebook-open-handler'; import { CommandContribution, MenuContribution, ResourceResolver, } from '@theia/core'; @@ -117,5 +119,5 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(UndoRedoHandler).toService(NotebookUndoRedoHandler); bind(NotebookStatusBarContribution).toSelf().inSingletonScope(); - bind(FrontendApplicationContribution).toService(NotebookStatusBarContribution); + bind(WidgetStatusBarContribution).toService(NotebookStatusBarContribution); }); diff --git a/packages/outline-view/package.json b/packages/outline-view/package.json index b843df4db85ab..d7ce97cab677c 100644 --- a/packages/outline-view/package.json +++ b/packages/outline-view/package.json @@ -1,9 +1,9 @@ { "name": "@theia/outline-view", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Outline View Extension", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -39,7 +39,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/output/package.json b/packages/output/package.json index 3844098b6f9fc..ef2c8059bcf49 100644 --- a/packages/output/package.json +++ b/packages/output/package.json @@ -1,11 +1,11 @@ { "name": "@theia/output", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Output Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", "@types/p-queue": "^2.3.1", "p-queue": "^2.4.2", @@ -44,7 +44,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/plugin-dev/package.json b/packages/plugin-dev/package.json index 64e3d429d2b0c..eff7071bcf6d1 100644 --- a/packages/plugin-dev/package.json +++ b/packages/plugin-dev/package.json @@ -1,16 +1,16 @@ { "name": "@theia/plugin-dev", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Plugin Development Extension", "main": "lib/common/index.js", "typings": "lib/common/index.d.ts", "dependencies": { - "@theia/core": "1.53.0", - "@theia/debug": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/output": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/debug": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/output": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/workspace": "1.54.0", "ps-tree": "^1.2.0", "tslib": "^2.6.2" }, @@ -49,7 +49,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/plugin-ext-headless/package.json b/packages/plugin-ext-headless/package.json index 0a37cd93a205d..52ac90e82f9d8 100644 --- a/packages/plugin-ext-headless/package.json +++ b/packages/plugin-ext-headless/package.json @@ -1,13 +1,13 @@ { "name": "@theia/plugin-ext-headless", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Headless (Backend-only) Plugin Extension", "main": "lib/common/index.js", "typings": "lib/common/index.d.ts", "dependencies": { - "@theia/core": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/terminal": "1.53.0", + "@theia/core": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/terminal": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -44,7 +44,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/decompress": "^4.2.2", "@types/escape-html": "^0.0.20", "@types/lodash.clonedeep": "^4.5.3", diff --git a/packages/plugin-ext-vscode/package.json b/packages/plugin-ext-vscode/package.json index 2e8ce00a71ea7..b58d98b27c46e 100644 --- a/packages/plugin-ext-vscode/package.json +++ b/packages/plugin-ext-vscode/package.json @@ -1,22 +1,22 @@ { "name": "@theia/plugin-ext-vscode", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Plugin Extension for VsCode", "dependencies": { - "@theia/callhierarchy": "1.53.0", - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/callhierarchy": "1.54.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/navigator": "1.53.0", - "@theia/outline-view": "1.53.0", - "@theia/plugin": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/typehierarchy": "1.53.0", - "@theia/userstorage": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/navigator": "1.54.0", + "@theia/outline-view": "1.54.0", + "@theia/plugin": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/typehierarchy": "1.54.0", + "@theia/userstorage": "1.54.0", + "@theia/workspace": "1.54.0", "decompress": "^4.2.1", "filenamify": "^4.1.0", "tslib": "^2.6.2" @@ -55,7 +55,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/plugin-ext/package.json b/packages/plugin-ext/package.json index 129124f12c7d1..3143dc53e15be 100644 --- a/packages/plugin-ext/package.json +++ b/packages/plugin-ext/package.json @@ -1,37 +1,37 @@ { "name": "@theia/plugin-ext", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Plugin Extension", "main": "lib/common/index.js", "typings": "lib/common/index.d.ts", "dependencies": { - "@theia/bulk-edit": "1.53.0", - "@theia/callhierarchy": "1.53.0", - "@theia/console": "1.53.0", - "@theia/core": "1.53.0", - "@theia/debug": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/editor-preview": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/markers": "1.53.0", - "@theia/messages": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/bulk-edit": "1.54.0", + "@theia/callhierarchy": "1.54.0", + "@theia/console": "1.54.0", + "@theia/core": "1.54.0", + "@theia/debug": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/editor-preview": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/markers": "1.54.0", + "@theia/messages": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/navigator": "1.53.0", - "@theia/notebook": "1.53.0", - "@theia/output": "1.53.0", - "@theia/plugin": "1.53.0", - "@theia/preferences": "1.53.0", - "@theia/scm": "1.53.0", - "@theia/search-in-workspace": "1.53.0", - "@theia/task": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/test": "1.53.0", - "@theia/timeline": "1.53.0", - "@theia/typehierarchy": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/navigator": "1.54.0", + "@theia/notebook": "1.54.0", + "@theia/output": "1.54.0", + "@theia/plugin": "1.54.0", + "@theia/preferences": "1.54.0", + "@theia/scm": "1.54.0", + "@theia/search-in-workspace": "1.54.0", + "@theia/task": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/test": "1.54.0", + "@theia/timeline": "1.54.0", + "@theia/typehierarchy": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/workspace": "1.54.0", "@types/mime": "^2.0.1", "@vscode/debugprotocol": "^1.51.0", "@vscode/proxy-agent": "^0.13.2", @@ -88,7 +88,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/decompress": "^4.2.2", "@types/escape-html": "^0.0.20", "@types/lodash.clonedeep": "^4.5.3", diff --git a/packages/plugin-ext/src/common/plugin-api-rpc-model.ts b/packages/plugin-ext/src/common/plugin-api-rpc-model.ts index 7a4ecdae2f2b4..de2450bff21bb 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc-model.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc-model.ts @@ -72,6 +72,17 @@ export interface Range { readonly endColumn: number; } +export interface Position { + /** + * line number (starts at 1) + */ + readonly lineNumber: number, + /** + * column (starts at 1) + */ + readonly column: number +} + export { MarkdownStringDTO as MarkdownString }; export interface SerializedDocumentFilter { diff --git a/packages/plugin-ext/src/common/plugin-api-rpc.ts b/packages/plugin-ext/src/common/plugin-api-rpc.ts index 4c06174642f4f..7c21c72086927 100644 --- a/packages/plugin-ext/src/common/plugin-api-rpc.ts +++ b/packages/plugin-ext/src/common/plugin-api-rpc.ts @@ -805,9 +805,9 @@ export interface RegisterTreeDataProviderOptions { } export interface TreeViewRevealOptions { - select: boolean - focus: boolean - expand: boolean | number + readonly select: boolean + readonly focus: boolean + readonly expand: boolean | number } export interface TreeViewsMain { diff --git a/packages/plugin-ext/src/common/test-types.ts b/packages/plugin-ext/src/common/test-types.ts index af87290c87672..56c2ec4015262 100644 --- a/packages/plugin-ext/src/common/test-types.ts +++ b/packages/plugin-ext/src/common/test-types.ts @@ -27,6 +27,7 @@ import { MarkdownString } from '@theia/core/lib/common/markdown-rendering'; import { UriComponents } from './uri-components'; import { Location, Range } from './plugin-api-rpc-model'; import { isObject } from '@theia/core'; +import * as languageProtocol from '@theia/core/shared/vscode-languageserver-protocol'; export enum TestRunProfileKind { Run = 1, @@ -74,17 +75,30 @@ export interface TestFailureDTO extends TestStateChangeDTO { readonly duration?: number; } +export namespace TestFailureDTO { + export function is(ref: unknown): ref is TestFailureDTO { + return isObject(ref) + && (ref.state === TestExecutionState.Failed || ref.state === TestExecutionState.Errored); + } +} export interface TestSuccessDTO extends TestStateChangeDTO { readonly state: TestExecutionState.Passed; readonly duration?: number; } +export interface TestMessageStackFrameDTO { + uri?: languageProtocol.DocumentUri; + position?: languageProtocol.Position; + label: string; +} + export interface TestMessageDTO { readonly expected?: string; readonly actual?: string; - readonly location?: Location; + readonly location?: languageProtocol.Location; readonly message: string | MarkdownString; readonly contextValue?: string; + readonly stackTrace?: TestMessageStackFrameDTO[]; } export interface TestItemDTO { diff --git a/packages/plugin-ext/src/main/browser/menus/plugin-menu-command-adapter.ts b/packages/plugin-ext/src/main/browser/menus/plugin-menu-command-adapter.ts index 9e79ae892cd96..2f1dc3c7e49ab 100644 --- a/packages/plugin-ext/src/main/browser/menus/plugin-menu-command-adapter.ts +++ b/packages/plugin-ext/src/main/browser/menus/plugin-menu-command-adapter.ts @@ -32,7 +32,6 @@ import { TreeViewWidget } from '../view/tree-view-widget'; import { CodeEditorWidgetUtil, codeToTheiaMappings, ContributionPoint } from './vscode-theia-menu-mappings'; import { TAB_BAR_TOOLBAR_CONTEXT_MENU } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { TestItem, TestMessage } from '@theia/test/lib/browser/test-service'; -import { fromLocation } from '../hierarchy/hierarchy-types-converters'; export type ArgumentAdapter = (...args: unknown[]) => unknown[]; @@ -315,7 +314,8 @@ export class PluginMenuCommandAdapter implements MenuCommandAdapter { actual: testMessage.actual, expected: testMessage.expected, contextValue: testMessage.contextValue, - location: testMessage.location ? fromLocation(testMessage.location) : undefined + location: testMessage.location, + stackTrace: testMessage.stackTrace }; return [TestMessageArg.create(testItemReference, testMessageDTO)]; } diff --git a/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts b/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts index a8510268870f3..5e592c30c397b 100644 --- a/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts +++ b/packages/plugin-ext/src/main/browser/plugin-ext-frontend-module.ts @@ -22,7 +22,9 @@ import { ContainerModule } from '@theia/core/shared/inversify'; import { FrontendApplicationContribution, WidgetFactory, bindViewContribution, ViewContainerIdentifier, ViewContainer, createTreeContainer, TreeWidget, LabelProviderContribution, LabelProvider, - UndoRedoHandler, DiffUris, Navigatable, SplitWidget + UndoRedoHandler, DiffUris, Navigatable, SplitWidget, + noopWidgetStatusBarContribution, + WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { MaybePromise, CommandContribution, ResourceResolver, bindContributionProvider, URI, generateUuid } from '@theia/core/lib/common'; import { WebSocketConnectionProvider } from '@theia/core/lib/browser/messaging'; @@ -191,6 +193,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { bind(WebviewSecondaryWindowSupport).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(WebviewSecondaryWindowSupport); bind(FrontendApplicationContribution).toService(WebviewContextKeys); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(WebviewWidget)); bind(PluginCustomEditorRegistry).toSelf().inSingletonScope(); bind(CustomEditorService).toSelf().inSingletonScope(); diff --git a/packages/plugin-ext/src/main/browser/test-main.ts b/packages/plugin-ext/src/main/browser/test-main.ts index cd50fd4813ddf..3662373142758 100644 --- a/packages/plugin-ext/src/main/browser/test-main.ts +++ b/packages/plugin-ext/src/main/browser/test-main.ts @@ -27,7 +27,10 @@ import { CancellationToken, Disposable, Event, URI } from '@theia/core'; import { MAIN_RPC_CONTEXT, TestControllerUpdate, TestingExt, TestingMain } from '../../common'; import { RPCProtocol } from '../../common/rpc-protocol'; import { interfaces } from '@theia/core/shared/inversify'; -import { TestExecutionState, TestItemDTO, TestItemReference, TestOutputDTO, TestRunDTO, TestRunProfileDTO, TestStateChangeDTO } from '../../common/test-types'; +import { + TestExecutionState, TestItemDTO, TestItemReference, TestOutputDTO, + TestRunDTO, TestRunProfileDTO, TestStateChangeDTO +} from '../../common/test-types'; import { TestRunProfileKind } from '../../plugin/types-impl'; import { CommandRegistryMainImpl } from './command-registry-main'; diff --git a/packages/plugin-ext/src/plugin/file-system-ext-impl.ts b/packages/plugin-ext/src/plugin/file-system-ext-impl.ts index 9eb59c06cc12c..b54be1a8dc093 100644 --- a/packages/plugin-ext/src/plugin/file-system-ext-impl.ts +++ b/packages/plugin-ext/src/plugin/file-system-ext-impl.ts @@ -40,8 +40,9 @@ import { State, StateMachine, LinkComputer, Edge } from '../common/link-computer import { commonPrefixLength } from '@theia/core/lib/common/strings'; import { CharCode } from '@theia/core/lib/common/char-code'; import { BinaryBuffer } from '@theia/core/lib/common/buffer'; -import { Emitter } from '@theia/core/shared/vscode-languageserver-protocol'; import { MarkdownString } from '../common/plugin-api-rpc-model'; +import { Emitter } from '@theia/core/lib/common'; +import { createAPIObject } from './plugin-context'; type IDisposable = vscode.Disposable; @@ -137,8 +138,11 @@ export class FsLinkProvider { } class ConsumerFileSystem implements vscode.FileSystem { + apiObject: vscode.FileSystem; - constructor(private _proxy: FileSystemMain, private _capabilities: Map) { } + constructor(private _proxy: FileSystemMain, private _capabilities: Map) { + this.apiObject = createAPIObject(this); + } stat(uri: vscode.Uri): Promise { return this._proxy.$stat(uri).catch(ConsumerFileSystem._handleError); @@ -210,7 +214,7 @@ export class FileSystemExtImpl implements FileSystemExt { private _handlePool: number = 0; - readonly fileSystem: vscode.FileSystem; + readonly fileSystem: ConsumerFileSystem; constructor(rpc: RPCProtocol) { this._proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.FILE_SYSTEM_MAIN); diff --git a/packages/plugin-ext/src/plugin/plugin-context.ts b/packages/plugin-ext/src/plugin/plugin-context.ts index bb19d777fb058..61688deddeecf 100644 --- a/packages/plugin-ext/src/plugin/plugin-context.ts +++ b/packages/plugin-ext/src/plugin/plugin-context.ts @@ -187,6 +187,7 @@ import { TestTag, TestRunRequest, TestMessage, + TestMessageStackFrame, ExtensionKind, InlineCompletionItem, InlineCompletionList, @@ -278,6 +279,21 @@ import { NotebookEditorsExtImpl } from './notebook/notebook-editors'; import { TestingExtImpl } from './tests'; import { UriExtImpl } from './uri-ext'; +export function createAPIObject(rawObject: T): T { + return new Proxy(rawObject, { + get(target, p, receiver) { + const isOwnProperty = !!Object.getOwnPropertyDescriptor(target, p); + const val = Reflect.get(target, p); + if (!isOwnProperty && typeof val === 'function') { + // bind functions that are inherited from the prototype to the object itself. + // This should handle the case of events. + return val.bind(target); + } + return val; + }, + }) as T; +} + export function createAPIFactory( rpc: RPCProtocol, pluginManager: PluginManager, @@ -495,7 +511,8 @@ export function createAPIFactory( return quickOpenExt.showQuickPick(plugin, items, options, token); }, createQuickPick(): theia.QuickPick { - return quickOpenExt.createQuickPick(plugin); + + return createAPIObject(quickOpenExt.createQuickPick(plugin)); }, showWorkspaceFolderPick(options?: theia.WorkspaceFolderPickOptions): PromiseLike { return workspaceExt.pickWorkspaceFolder(options); @@ -534,9 +551,12 @@ export function createAPIFactory( priority = priorityOrAlignment; } + // TODO: here return statusBarMessageRegistryExt.createStatusBarItem(alignment, priority, id); }, createOutputChannel(name: string, options?: { log: true }): any { + + // TODO: here return !options ? outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin)) : outputChannelRegistryExt.createOutputChannel(name, pluginToPluginInfo(plugin), options); @@ -545,7 +565,7 @@ export function createAPIFactory( title: string, showOptions: theia.ViewColumn | theia.WebviewPanelShowOptions, options: theia.WebviewPanelOptions & theia.WebviewOptions = {}): theia.WebviewPanel { - return webviewExt.createWebview(viewType, title, showOptions, options, plugin); + return createAPIObject(webviewExt.createWebview(viewType, title, showOptions, options, plugin)); }, registerWebviewPanelSerializer(viewType: string, serializer: theia.WebviewPanelSerializer): theia.Disposable { return webviewExt.registerWebviewPanelSerializer(viewType, serializer, plugin); @@ -573,19 +593,19 @@ export function createAPIFactory( createTerminal(nameOrOptions: theia.TerminalOptions | theia.ExtensionTerminalOptions | theia.ExtensionTerminalOptions | (string | undefined), shellPath?: string, shellArgs?: string[] | string): theia.Terminal { - return terminalExt.createTerminal(plugin, nameOrOptions, shellPath, shellArgs); + return createAPIObject(terminalExt.createTerminal(plugin, nameOrOptions, shellPath, shellArgs)); }, onDidChangeTerminalState, onDidCloseTerminal, onDidOpenTerminal, createTextEditorDecorationType(options: theia.DecorationRenderOptions): theia.TextEditorDecorationType { - return editors.createTextEditorDecorationType(options); + return createAPIObject(editors.createTextEditorDecorationType(options)); }, registerTreeDataProvider(viewId: string, treeDataProvider: theia.TreeDataProvider): Disposable { return treeViewsExt.registerTreeDataProvider(plugin, viewId, treeDataProvider); }, createTreeView(viewId: string, options: theia.TreeViewOptions): theia.TreeView { - return treeViewsExt.createTreeView(plugin, viewId, options); + return createAPIObject(treeViewsExt.createTreeView(plugin, viewId, options)); }, withScmProgress(task: (progress: theia.Progress) => Thenable) { const options: ProgressOptions = { location: ProgressLocation.SourceControl }; @@ -604,7 +624,7 @@ export function createAPIFactory( return uriExt.registerUriHandler(handler, pluginToPluginInfo(plugin)); }, createInputBox(): theia.InputBox { - return quickOpenExt.createInputBox(plugin); + return createAPIObject(quickOpenExt.createInputBox(plugin)); }, registerTerminalLinkProvider(provider: theia.TerminalLinkProvider): theia.Disposable { return terminalExt.registerTerminalLinkProvider(provider); @@ -652,7 +672,7 @@ export function createAPIFactory( const workspace: typeof theia.workspace = { get fs(): theia.FileSystem { - return fileSystemExt.fileSystem; + return fileSystemExt.fileSystem.apiObject; }, get rootPath(): string | undefined { @@ -755,7 +775,7 @@ export function createAPIFactory( return notebooksExt.getNotebookDocument(uri).apiNotebook; }, createFileSystemWatcher: (pattern, ignoreCreate, ignoreChange, ignoreDelete): theia.FileSystemWatcher => - extHostFileSystemEvent.createFileSystemWatcher(fromGlobPattern(pattern), ignoreCreate, ignoreChange, ignoreDelete), + createAPIObject(extHostFileSystemEvent.createFileSystemWatcher(fromGlobPattern(pattern), ignoreCreate, ignoreChange, ignoreDelete)), findFiles(include: theia.GlobPattern, exclude?: theia.GlobPattern | null, maxResults?: number, token?: CancellationToken): PromiseLike { return workspaceExt.findFiles(include, exclude, maxResults, token); }, @@ -848,7 +868,7 @@ export function createAPIFactory( return telemetryExt.onDidChangeTelemetryEnabled; }, createTelemetryLogger(sender: theia.TelemetrySender, options?: theia.TelemetryLoggerOptions): theia.TelemetryLogger { - return telemetryExt.createTelemetryLogger(sender, options); + return createAPIObject(telemetryExt.createTelemetryLogger(sender, options)); }, get remoteName(): string | undefined { return envExt.remoteName; }, get machineId(): string { return envExt.machineId; }, @@ -923,7 +943,7 @@ export function createAPIFactory( return languagesExt.getDiagnostics(resource); }, createDiagnosticCollection(name?: string): theia.DiagnosticCollection { - return languagesExt.createDiagnosticCollection(name); + return createAPIObject(languagesExt.createDiagnosticCollection(name)); }, setLanguageConfiguration(language: string, configuration: theia.LanguageConfiguration): theia.Disposable { return languagesExt.setLanguageConfiguration(language, configuration); @@ -1060,7 +1080,7 @@ export function createAPIFactory( const tests: typeof theia.tests = { createTestController(id, label: string) { - return testingExt.createTestController(id, label); + return createAPIObject(testingExt.createTestController(id, label)); } }; /* End of Tests API */ @@ -1172,6 +1192,7 @@ export function createAPIFactory( }, get taskExecutions(): ReadonlyArray { + // TODO: here return tasksExt.taskExecutions; }, onDidStartTask(listener, thisArg?, disposables?) { @@ -1192,19 +1213,19 @@ export function createAPIFactory( get inputBox(): theia.SourceControlInputBox { const inputBox = scmExt.getLastInputBox(plugin); if (inputBox) { - return inputBox; + return inputBox.apiObject; } else { throw new Error('Input box not found!'); } }, createSourceControl(id: string, label: string, rootUri?: URI): theia.SourceControl { - return scmExt.createSourceControl(plugin, id, label, rootUri); + return createAPIObject(scmExt.createSourceControl(plugin, id, label, rootUri)); } }; const comments: typeof theia.comments = { createCommentController(id: string, label: string): theia.CommentController { - return commentsExt.createCommentController(plugin, id, label); + return createAPIObject(commentsExt.createCommentController(plugin, id, label)); } }; @@ -1463,6 +1484,7 @@ export function createAPIFactory( TestTag, TestRunRequest, TestMessage, + TestMessageStackFrame, ExtensionKind, InlineCompletionItem, InlineCompletionList, diff --git a/packages/plugin-ext/src/plugin/scm.ts b/packages/plugin-ext/src/plugin/scm.ts index 4703ab3626f14..f34556cee2ae8 100644 --- a/packages/plugin-ext/src/plugin/scm.ts +++ b/packages/plugin-ext/src/plugin/scm.ts @@ -39,6 +39,7 @@ import { URI, ThemeIcon } from './types-impl'; import { ScmCommandArg } from '../common/plugin-api-rpc'; import { sep } from '@theia/core/lib/common/paths'; import { PluginIconPath } from './plugin-icon-path'; +import { createAPIObject } from './plugin-context'; type ProviderHandle = number; type GroupHandle = number; type ResourceStateHandle = number; @@ -290,6 +291,7 @@ interface ValidateInput { export class ScmInputBoxImpl implements theia.SourceControlInputBox { private _value: string = ''; + apiObject: theia.SourceControlInputBox; get value(): string { return this._value; @@ -354,7 +356,7 @@ export class ScmInputBoxImpl implements theia.SourceControlInputBox { } constructor(private plugin: Plugin, private proxy: ScmMain, private sourceControlHandle: number) { - // noop + this.apiObject = createAPIObject(this); } onInputBoxValueChange(value: string): void { @@ -543,8 +545,7 @@ class SourceControlImpl implements theia.SourceControl { return this._rootUri; } - private _inputBox: ScmInputBoxImpl; - get inputBox(): ScmInputBoxImpl { return this._inputBox; } + readonly inputBox: ScmInputBoxImpl; private _count: number | undefined = undefined; @@ -642,7 +643,7 @@ class SourceControlImpl implements theia.SourceControl { private _label: string, private _rootUri?: theia.Uri ) { - this._inputBox = new ScmInputBoxImpl(plugin, this.proxy, this.handle); + this.inputBox = new ScmInputBoxImpl(plugin, this.proxy, this.handle); this.proxy.$registerSourceControl(this.handle, _id, _label, _rootUri); } diff --git a/packages/plugin-ext/src/plugin/tests.ts b/packages/plugin-ext/src/plugin/tests.ts index 101532e86b2ed..514bcbbe4fabc 100644 --- a/packages/plugin-ext/src/plugin/tests.ts +++ b/packages/plugin-ext/src/plugin/tests.ts @@ -40,10 +40,12 @@ import { TestItemImpl, TestItemCollection } from './test-item'; import { AccumulatingTreeDeltaEmitter, TreeDelta } from '@theia/test/lib/common/tree-delta'; import { TestItemDTO, TestOutputDTO, TestExecutionState, TestRunProfileDTO, - TestRunProfileKind, TestRunRequestDTO, TestStateChangeDTO, TestItemReference, TestMessageArg, TestMessageDTO + TestRunProfileKind, TestRunRequestDTO, TestStateChangeDTO, TestItemReference, TestMessageArg, TestMessageDTO, + TestMessageStackFrameDTO } from '../common/test-types'; +import * as protocol from '@theia/core/shared/vscode-languageserver-protocol'; import { ChangeBatcher, observableProperty } from '@theia/test/lib/common/collections'; -import { TestRunRequest } from './types-impl'; +import { Location, Position, Range, TestRunRequest, URI } from './types-impl'; import { MarkdownString } from '../common/plugin-api-rpc-model'; type RefreshHandler = (token: theia.CancellationToken) => void | theia.Thenable; @@ -374,7 +376,36 @@ export class TestingExtImpl implements TestingExt { actualOutput: testMessage.actual, expectedOutput: testMessage.expected, contextValue: testMessage.contextValue, - location: testMessage.location ? Convert.toLocation(testMessage.location) : undefined + location: this.toLocation(testMessage.location), + stackTrace: testMessage.stackTrace ? testMessage.stackTrace.map(frame => this.toStackFrame(frame)) : undefined + }; + } + + toLocation(location: protocol.Location | undefined): Location | undefined { + if (!location) { + return undefined; + } + return new Location(URI.parse(location.uri), this.toRange(location.range)); + } + + toRange(range: protocol.Range): Range { + return new Range(this.toPosition(range.start), this.toPosition(range.end)); + } + + toPosition(position: protocol.Position): Position; + toPosition(position: protocol.Position | undefined): Position | undefined; + toPosition(position: protocol.Position | undefined): Position | undefined { + if (!position) { + return undefined; + } + return new Position(position.line, position.character); + } + + toStackFrame(stackFrame: TestMessageStackFrameDTO): theia.TestMessageStackFrame { + return { + label: stackFrame.label, + position: this.toPosition(stackFrame.position), + uri: stackFrame.uri ? URI.parse(stackFrame.uri) : undefined }; } diff --git a/packages/plugin-ext/src/plugin/type-converters.ts b/packages/plugin-ext/src/plugin/type-converters.ts index 7419d07e9da07..c25ac586a7b78 100644 --- a/packages/plugin-ext/src/plugin/type-converters.ts +++ b/packages/plugin-ext/src/plugin/type-converters.ts @@ -34,7 +34,7 @@ import { BinaryBuffer } from '@theia/core/lib/common/buffer'; import { CellRange, isTextStreamMime } from '@theia/notebook/lib/common'; import { MarkdownString as MarkdownStringDTO } from '@theia/core/lib/common/markdown-rendering'; -import { TestItemDTO, TestMessageDTO } from '../common/test-types'; +import { TestItemDTO, TestMessageDTO, TestMessageStackFrameDTO } from '../common/test-types'; import { PluginIconPath } from './plugin-icon-path'; const SIDE_GROUP = -2; @@ -134,12 +134,21 @@ export function fromRange(range: theia.Range | undefined): model.Range | undefin endColumn: end.character + 1 }; } - -export function fromPosition(position: types.Position | theia.Position): Position { +export function fromPosition(position: types.Position | theia.Position): Position; +export function fromPosition(position: types.Position | theia.Position | undefined): Position | undefined; +export function fromPosition(position: types.Position | theia.Position | undefined): Position | undefined { + if (!position) { + return undefined; + } return { lineNumber: position.line + 1, column: position.character + 1 }; } -export function toPosition(position: Position): types.Position { +export function toPosition(position: Position): types.Position; +export function toPosition(position: Position | undefined): types.Position | undefined; +export function toPosition(position: Position | undefined): types.Position | undefined { + if (!position) { + return undefined; + } return new types.Position(position.lineNumber - 1, position.column - 1); } @@ -474,6 +483,18 @@ export function fromLocation(location: theia.Location | undefined): model.Locati }; } +export function fromLocationToLanguageServerLocation(location: theia.Location): lstypes.Location; +export function fromLocationToLanguageServerLocation(location: theia.Location | undefined): lstypes.Location | undefined; +export function fromLocationToLanguageServerLocation(location: theia.Location | undefined): lstypes.Location | undefined { + if (!location) { + return undefined; + } + return { + uri: location.uri.toString(), + range: location.range + }; +} + export function fromTextDocumentShowOptions(options: theia.TextDocumentShowOptions): model.TextDocumentShowOptions { if (options.selection) { return { @@ -1697,15 +1718,26 @@ export namespace TestMessage { return message.map(msg => TestMessage.from(msg)[0]); } return [{ - location: fromLocation(message.location), + location: fromLocationToLanguageServerLocation(message.location), message: fromMarkdown(message.message)!, expected: message.expectedOutput, actual: message.actualOutput, - contextValue: message.contextValue + contextValue: message.contextValue, + stackTrace: message.stackTrace && message.stackTrace.map(frame => TestMessageStackFrame.from(frame)) }]; } } +export namespace TestMessageStackFrame { + export function from(stackTrace: theia.TestMessageStackFrame): TestMessageStackFrameDTO { + return { + label: stackTrace.label, + position: stackTrace.position, + uri: stackTrace?.uri?.toString() + }; + } +} + export namespace TestItem { export function from(test: theia.TestItem): TestItemDTO { return TestItem.fromPartial(test); diff --git a/packages/plugin-ext/src/plugin/types-impl.ts b/packages/plugin-ext/src/plugin/types-impl.ts index 1aee501f2e810..d7a0734259657 100644 --- a/packages/plugin-ext/src/plugin/types-impl.ts +++ b/packages/plugin-ext/src/plugin/types-impl.ts @@ -3036,7 +3036,7 @@ export class DebugThread implements theia.DebugThread { } export class DebugStackFrame implements theia.DebugStackFrame { - constructor(readonly session: theia.DebugSession, readonly threadId: number, readonly frameId: number) { } + constructor(readonly session: theia.DebugSession, readonly threadId: number, readonly frameId: number) { } } @es5ClassCompat @@ -3350,6 +3350,7 @@ export class TestMessage implements theia.TestMessage { public actualOutput?: string; public location?: theia.Location; public contextValue?: string; + public stackTrace?: theia.TestMessageStackFrame[] | undefined; public static diff(message: string | theia.MarkdownString, expected: string, actual: string): theia.TestMessage { const msg = new TestMessage(message); @@ -3366,6 +3367,14 @@ export class TestCoverageCount { constructor(public covered: number, public total: number) { } } +export class TestMessageStackFrame implements theia.TestMessageStackFrame { + constructor( + public label: string, + public uri?: theia.Uri, + public position?: Position + ) { } +} + @es5ClassCompat export class FileCoverage { diff --git a/packages/plugin-metrics/package.json b/packages/plugin-metrics/package.json index e94657de4a0d5..4852c50738780 100644 --- a/packages/plugin-metrics/package.json +++ b/packages/plugin-metrics/package.json @@ -1,13 +1,13 @@ { "name": "@theia/plugin-metrics", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Plugin Metrics", "dependencies": { - "@theia/core": "1.53.0", - "@theia/metrics": "1.53.0", + "@theia/core": "1.54.0", + "@theia/metrics": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/plugin": "1.53.0", - "@theia/plugin-ext": "1.53.0", + "@theia/plugin": "1.54.0", + "@theia/plugin-ext": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -44,7 +44,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/plugin/package.json b/packages/plugin/package.json index 7acbf0e09fd9e..b9c572034c9e6 100644 --- a/packages/plugin/package.json +++ b/packages/plugin/package.json @@ -1,6 +1,6 @@ { "name": "@theia/plugin", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Plugin API", "types": "./src/theia.d.ts", "publishConfig": { @@ -27,7 +27,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/plugin/src/theia.d.ts b/packages/plugin/src/theia.d.ts index 6caa690fdacf1..fe8d5f6200d28 100644 --- a/packages/plugin/src/theia.d.ts +++ b/packages/plugin/src/theia.d.ts @@ -6728,13 +6728,31 @@ export module '@theia/plugin' { badge: ViewBadge | undefined; /** - * Reveal an element. By default revealed element is selected. + * Reveals the given element in the tree view. + * If the tree view is not visible then the tree view is shown and element is revealed. * + * By default revealed element is selected. * In order to not to select, set the option `select` to `false`. + * In order to focus, set the option `focus` to `true`. + * In order to expand the revealed element, set the option `expand` to `true`. To expand recursively set `expand` to the number of levels to expand. * - * **NOTE:** {@link TreeDataProvider TreeDataProvider} is required to implement {@link TreeDataProvider.getParent getParent} method to access this API. + * * *NOTE:* In VS Code, you can expand only to 3 levels maximum. This is not the case in Theia, there are no limits to expansion level. + * * *NOTE:* The {@link TreeDataProvider} that the `TreeView` {@link window.createTreeView is registered with} with must implement {@link TreeDataProvider.getParent getParent} method to access this API. */ - reveal(element: T, options?: { select?: boolean; focus?: boolean; expand?: boolean | number }): Thenable; + reveal(element: T, options?: { + /** + * If true, then the element will be selected. + */ + readonly select?: boolean; + /** + * If true, then the element will be focused. + */ + readonly focus?: boolean; + /** + * If true, then the element will be expanded. If a number is passed, then up to that number of levels of children will be expanded + */ + readonly expand?: boolean | number; + }): Thenable; } /** @@ -16966,6 +16984,34 @@ export module '@theia/plugin' { error: string | MarkdownString | undefined; } + /** + * A stack frame found in the {@link TestMessage.stackTrace}. + */ + export class TestMessageStackFrame { + /** + * The location of this stack frame. This should be provided as a URI if the + * location of the call frame can be accessed by the editor. + */ + uri?: Uri; + + /** + * Position of the stack frame within the file. + */ + position?: Position; + + /** + * The name of the stack frame, typically a method or function name. + */ + label: string; + + /** + * @param label The name of the stack frame + * @param file The file URI of the stack frame + * @param position The position of the stack frame within the file + */ + constructor(label: string, uri?: Uri, position?: Position); + } + /** * Message associated with the test state. Can be linked to a specific * source range -- useful for assertion failures, for example. @@ -17022,6 +17068,11 @@ export module '@theia/plugin' { */ contextValue?: string; + /** + * The stack trace associated with the message or failure. + */ + stackTrace?: TestMessageStackFrame[]; + /** * Creates a new TestMessage that will present as a diff in the editor. * @param message Message to display to the user. diff --git a/packages/preferences/package.json b/packages/preferences/package.json index 7963265e81868..83f970627b727 100644 --- a/packages/preferences/package.json +++ b/packages/preferences/package.json @@ -1,15 +1,15 @@ { "name": "@theia/preferences", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Preferences Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/userstorage": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/userstorage": "1.54.0", + "@theia/workspace": "1.54.0", "async-mutex": "^0.3.1", "fast-deep-equal": "^3.1.3", "jsonc-parser": "^2.2.0", @@ -50,7 +50,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/preferences/src/browser/preference-frontend-module.ts b/packages/preferences/src/browser/preference-frontend-module.ts index ef7d553bcee84..d55f47e63d60b 100644 --- a/packages/preferences/src/browser/preference-frontend-module.ts +++ b/packages/preferences/src/browser/preference-frontend-module.ts @@ -17,7 +17,7 @@ import '../../src/browser/style/index.css'; import './preferences-monaco-contribution'; import { ContainerModule, interfaces } from '@theia/core/shared/inversify'; -import { bindViewContribution, FrontendApplicationContribution, OpenHandler } from '@theia/core/lib/browser'; +import { bindViewContribution, FrontendApplicationContribution, noopWidgetStatusBarContribution, OpenHandler, WidgetStatusBarContribution } from '@theia/core/lib/browser'; import { TabBarToolbarContribution } from '@theia/core/lib/browser/shell/tab-bar-toolbar'; import { PreferenceTreeGenerator } from './util/preference-tree-generator'; import { bindPreferenceProviders } from './preference-bindings'; @@ -33,6 +33,7 @@ import { CliPreferences, CliPreferencesPath } from '../common/cli-preferences'; import { ServiceConnectionProvider } from '@theia/core/lib/browser/messaging/service-connection-provider'; import { PreferenceFrontendContribution } from './preference-frontend-contribution'; import { PreferenceLayoutProvider } from './util/preference-layout'; +import { PreferencesWidget } from './views/preference-widget'; export function bindPreferences(bind: interfaces.Bind, unbind: interfaces.Unbind): void { bindPreferenceProviders(bind, unbind); @@ -59,6 +60,8 @@ export function bindPreferences(bind: interfaces.Bind, unbind: interfaces.Unbind bind(CliPreferences).toDynamicValue(ctx => ServiceConnectionProvider.createProxy(ctx.container, CliPreferencesPath)).inSingletonScope(); bind(PreferenceFrontendContribution).toSelf().inSingletonScope(); bind(FrontendApplicationContribution).toService(PreferenceFrontendContribution); + + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(PreferencesWidget)); } export default new ContainerModule((bind, unbind, isBound, rebind) => { diff --git a/packages/preview/package.json b/packages/preview/package.json index 3b346f27ec6ce..0fae6f0b68c67 100644 --- a/packages/preview/package.json +++ b/packages/preview/package.json @@ -1,12 +1,12 @@ { "name": "@theia/preview", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Preview Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/mini-browser": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/mini-browser": "1.54.0", + "@theia/monaco": "1.54.0", "@types/highlight.js": "^10.1.0", "@types/markdown-it-anchor": "^4.0.1", "highlight.js": "10.4.1", @@ -46,7 +46,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/process/package.json b/packages/process/package.json index e1626aa212009..bef30552ed384 100644 --- a/packages/process/package.json +++ b/packages/process/package.json @@ -1,9 +1,9 @@ { "name": "@theia/process", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia process support.", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "node-pty": "0.11.0-beta24", "string-argv": "^0.1.1", "tslib": "^2.6.2" @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/property-view/package.json b/packages/property-view/package.json index 46cc02f53cd1a..515ea5bbd4ad9 100644 --- a/packages/property-view/package.json +++ b/packages/property-view/package.json @@ -1,10 +1,10 @@ { "name": "@theia/property-view", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Property View Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -40,7 +40,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/remote/package.json b/packages/remote/package.json index 4993914bbbd03..71377a15a35d4 100644 --- a/packages/remote/package.json +++ b/packages/remote/package.json @@ -1,10 +1,10 @@ { "name": "@theia/remote", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Remote", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", "archiver": "^5.3.1", "decompress": "^4.2.1", "decompress-tar": "^4.0.0", @@ -52,7 +52,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/archiver": "^5.3.2", "@types/decompress": "^4.2.4", "@types/express-http-proxy": "^1.6.3", diff --git a/packages/scm-extra/package.json b/packages/scm-extra/package.json index 0a83d3c53fa75..227b1f92580cd 100644 --- a/packages/scm-extra/package.json +++ b/packages/scm-extra/package.json @@ -1,13 +1,13 @@ { "name": "@theia/scm-extra", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Source control extras Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/scm": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/scm": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -43,7 +43,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/scm/package.json b/packages/scm/package.json index 4a5bfd979221a..87b52c2704627 100644 --- a/packages/scm/package.json +++ b/packages/scm/package.json @@ -1,12 +1,12 @@ { "name": "@theia/scm", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Source control Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", "@types/diff": "^5.2.1", "diff": "^5.2.0", @@ -49,7 +49,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/search-in-workspace/package.json b/packages/search-in-workspace/package.json index ba4cde4e6bfc6..2b8e007c68d19 100644 --- a/packages/search-in-workspace/package.json +++ b/packages/search-in-workspace/package.json @@ -1,14 +1,14 @@ { "name": "@theia/search-in-workspace", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Search in workspace", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/process": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/process": "1.54.0", + "@theia/workspace": "1.54.0", "@vscode/ripgrep": "^1.14.2", "minimatch": "^5.1.0", "react-autosize-textarea": "^7.0.0", @@ -48,6 +48,6 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" } } diff --git a/packages/secondary-window/package.json b/packages/secondary-window/package.json index 237203d85b302..1513249fc66f7 100644 --- a/packages/secondary-window/package.json +++ b/packages/secondary-window/package.json @@ -1,9 +1,9 @@ { "name": "@theia/secondary-window", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Secondary Window Extension", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -39,6 +39,6 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" } } diff --git a/packages/task/package.json b/packages/task/package.json index 507ff9d0724b3..5d2cc954395e8 100644 --- a/packages/task/package.json +++ b/packages/task/package.json @@ -1,19 +1,19 @@ { "name": "@theia/task", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Task extension. This extension adds support for executing raw or terminal processes in the backend.", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/markers": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/markers": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/process": "1.53.0", - "@theia/terminal": "1.53.0", - "@theia/userstorage": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/process": "1.54.0", + "@theia/terminal": "1.54.0", + "@theia/userstorage": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/workspace": "1.54.0", "async-mutex": "^0.3.1", "jsonc-parser": "^2.2.0", "p-debounce": "^2.1.0", @@ -53,7 +53,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/terminal/package.json b/packages/terminal/package.json index bf9c8a435a54d..7dd3431211d6e 100644 --- a/packages/terminal/package.json +++ b/packages/terminal/package.json @@ -1,15 +1,15 @@ { "name": "@theia/terminal", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Terminal Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/process": "1.53.0", - "@theia/variable-resolver": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/process": "1.54.0", + "@theia/variable-resolver": "1.54.0", + "@theia/workspace": "1.54.0", "tslib": "^2.6.2", "xterm": "^5.3.0", "xterm-addon-fit": "^0.8.0", @@ -50,7 +50,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/test/package.json b/packages/test/package.json index e30f799f7ac30..74637739d8f82 100644 --- a/packages/test/package.json +++ b/packages/test/package.json @@ -1,13 +1,13 @@ { "name": "@theia/test", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Test Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/terminal": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/terminal": "1.54.0", "xterm": "^4.16.0", "xterm-addon-fit": "^0.5.0" }, @@ -44,7 +44,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/test/src/browser/style/index.css b/packages/test/src/browser/style/index.css index f919706ee4318..c880f8c433ac4 100644 --- a/packages/test/src/browser/style/index.css +++ b/packages/test/src/browser/style/index.css @@ -18,25 +18,29 @@ } .theia-test-view .passed, -.theia-test-result-view .passed { +.theia-test-run-view .passed { color: var(--theia-successBackground); } .theia-test-view .failed, -.theia-test-result-view .failed { +.theia-test-run-view .failed { color: var(--theia-editorError-foreground); } .theia-test-view .errored, -.theia-test-result-view .errored { +.theia-test-run-view .errored { color: var(--theia-editorError-foreground); } .theia-test-view .queued, -.theia-test-result-view .queued { +.theia-test-run-view .queued { color: var(--theia-editorWarning-foreground); } +.theia-test-result-view .debug-frame { + white-space: pre; +} + .theia-test-view .theia-TreeNode:not(:hover):not(.theia-mod-selected) .theia-test-tree-inline-action { display: none; } \ No newline at end of file diff --git a/packages/test/src/browser/test-service.ts b/packages/test/src/browser/test-service.ts index 210ca558c58c7..c2fb29f2744d0 100644 --- a/packages/test/src/browser/test-service.ts +++ b/packages/test/src/browser/test-service.ts @@ -15,7 +15,7 @@ // ***************************************************************************** import { CancellationToken, ContributionProvider, Disposable, Emitter, Event, QuickPickService, isObject, nls } from '@theia/core/lib/common'; -import { CancellationTokenSource, Location, Range } from '@theia/core/shared/vscode-languageserver-protocol'; +import { CancellationTokenSource, Location, Range, Position, DocumentUri } from '@theia/core/shared/vscode-languageserver-protocol'; import { CollectionDelta, TreeDelta } from '../common/tree-delta'; import { MarkdownString } from '@theia/core/lib/common/markdown-rendering'; import URI from '@theia/core/lib/common/uri'; @@ -56,9 +56,16 @@ export enum TestExecutionState { export interface TestMessage { readonly expected?: string; readonly actual?: string; - readonly location: Location; + readonly location?: Location; readonly message: string | MarkdownString; readonly contextValue?: string; + readonly stackTrace?: TestMessageStackFrame[]; +} + +export interface TestMessageStackFrame { + readonly label: string, + readonly uri?: DocumentUri, + readonly position?: Position, } export namespace TestMessage { @@ -367,7 +374,7 @@ export class DefaultTestService implements TestService { selectDefaultProfile(): void { this.pickProfileKind().then(kind => { - const profiles = this.getControllers().flatMap(c => c.testRunProfiles).filter(profile => profile.kind === kind); + const profiles = this.getControllers().flatMap(c => c.testRunProfiles).filter(profile => profile.kind === kind); this.pickProfile(profiles, nls.localizeByDefault('Pick a test profile to use')).then(activeProfile => { if (activeProfile) { // only change the default for the controller containing selected profile for default and its profiles with same kind diff --git a/packages/test/src/browser/view/test-result-widget.ts b/packages/test/src/browser/view/test-result-widget.ts index 4df73d7914e97..a1f154acc9f50 100644 --- a/packages/test/src/browser/view/test-result-widget.ts +++ b/packages/test/src/browser/view/test-result-widget.ts @@ -14,14 +14,17 @@ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** -import { BaseWidget, Message, codicon } from '@theia/core/lib/browser'; +import { BaseWidget, LabelProvider, Message, OpenerService, codicon } from '@theia/core/lib/browser'; import { inject, injectable, postConstruct } from '@theia/core/shared/inversify'; import { TestOutputUIModel } from './test-output-ui-model'; import { DisposableCollection, nls } from '@theia/core'; -import { TestFailure, TestMessage } from '../test-service'; +import { TestFailure, TestMessage, TestMessageStackFrame } from '../test-service'; import { MarkdownRenderer } from '@theia/core/lib/browser/markdown-rendering/markdown-renderer'; import { MarkdownString } from '@theia/core/lib/common/markdown-rendering'; - +import { URI } from '@theia/core/lib/common/uri'; +import { FileService } from '@theia/filesystem/lib/browser/file-service'; +import { NavigationLocationService } from '@theia/editor/lib/browser/navigation/navigation-location-service'; +import { NavigationLocation, Position } from '@theia/editor/lib/browser/navigation/navigation-location'; @injectable() export class TestResultWidget extends BaseWidget { @@ -29,6 +32,10 @@ export class TestResultWidget extends BaseWidget { @inject(TestOutputUIModel) uiModel: TestOutputUIModel; @inject(MarkdownRenderer) markdownRenderer: MarkdownRenderer; + @inject(OpenerService) openerService: OpenerService; + @inject(FileService) fileService: FileService; + @inject(NavigationLocationService) navigationService: NavigationLocationService; + @inject(LabelProvider) protected readonly labelProvider: LabelProvider; protected toDisposeOnRender = new DisposableCollection(); protected input: TestMessage[] = []; @@ -36,6 +43,7 @@ export class TestResultWidget extends BaseWidget { constructor() { super(); + this.addClass('theia-test-result-view'); this.id = TestResultWidget.ID; this.title.label = nls.localizeByDefault('Test Results'); this.title.caption = nls.localizeByDefault('Test Results'); @@ -83,6 +91,48 @@ export class TestResultWidget extends BaseWidget { } else { this.content.append(this.node.ownerDocument.createTextNode(message.message)); } + if (message.stackTrace) { + const stackTraceElement = this.node.ownerDocument.createElement('div'); + message.stackTrace.map(frame => this.renderFrame(frame, stackTraceElement)); + this.content.append(stackTraceElement); + } + }); + } + + renderFrame(stackFrame: TestMessageStackFrame, stackTraceElement: HTMLElement): void { + const frameElement = stackTraceElement.ownerDocument.createElement('div'); + frameElement.classList.add('debug-frame'); + frameElement.append(` ${nls.localize('theia/test/stackFrameAt', 'at')} ${stackFrame.label}`); + + // Add URI information as clickable links + if (stackFrame.uri) { + frameElement.append(' ('); + const uri = new URI(stackFrame.uri); + + const link = this.node.ownerDocument.createElement('a'); + let content = `${this.labelProvider.getName(uri)}`; + if (stackFrame.position) { + // Display Position as a 1-based position, similar to Monaco ones. + const monacoPosition = { + lineNumber: stackFrame.position.line + 1, + column: stackFrame.position.character + 1 + }; + content += `:${monacoPosition.lineNumber}:${monacoPosition.column}`; + } + link.textContent = content; + link.href = `${uri}`; + link.onclick = () => this.openUriInWorkspace(uri, stackFrame.position); + frameElement.append(link); + frameElement.append(')'); + } + stackTraceElement.append(frameElement); + } + + async openUriInWorkspace(uri: URI, position?: Position): Promise { + this.fileService.resolve(uri).then(stat => { + if (stat.isFile) { + this.navigationService.reveal(NavigationLocation.create(uri, position ?? { line: 0, character: 0 })); + } }); } diff --git a/packages/test/src/browser/view/test-run-widget.tsx b/packages/test/src/browser/view/test-run-widget.tsx index c45a6454be7e8..02001bd4347cf 100644 --- a/packages/test/src/browser/view/test-run-widget.tsx +++ b/packages/test/src/browser/view/test-run-widget.tsx @@ -198,7 +198,7 @@ export class TestRunTreeWidget extends TreeWidget { @postConstruct() protected override init(): void { super.init(); - this.addClass('theia-test-result-view'); + this.addClass('theia-test-run-view'); this.model.onSelectionChanged(() => { const node = this.model.selectedNodes[0]; if (node instanceof TestRunNode) { diff --git a/packages/timeline/package.json b/packages/timeline/package.json index d508da7c10aaf..f778a8d5978f9 100644 --- a/packages/timeline/package.json +++ b/packages/timeline/package.json @@ -1,10 +1,10 @@ { "name": "@theia/timeline", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Timeline Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/navigator": "1.53.0", + "@theia/core": "1.54.0", + "@theia/navigator": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -40,7 +40,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/toolbar/package.json b/packages/toolbar/package.json index da728cf0315f3..7c0abda7c4399 100644 --- a/packages/toolbar/package.json +++ b/packages/toolbar/package.json @@ -1,6 +1,6 @@ { "name": "@theia/toolbar", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Toolbar", "keywords": [ "theia-extension" @@ -27,15 +27,15 @@ "watch": "theiaext watch" }, "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", - "@theia/file-search": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/monaco": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", + "@theia/file-search": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/monaco": "1.54.0", "@theia/monaco-editor-core": "1.83.101", - "@theia/search-in-workspace": "1.53.0", - "@theia/userstorage": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/search-in-workspace": "1.54.0", + "@theia/userstorage": "1.54.0", + "@theia/workspace": "1.54.0", "ajv": "^6.5.3", "jsonc-parser": "^2.2.0", "perfect-scrollbar": "^1.3.0", diff --git a/packages/typehierarchy/package.json b/packages/typehierarchy/package.json index d9965c61e42d0..0802b6ccd5530 100644 --- a/packages/typehierarchy/package.json +++ b/packages/typehierarchy/package.json @@ -1,10 +1,10 @@ { "name": "@theia/typehierarchy", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Type Hierarchy Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/editor": "1.53.0", + "@theia/core": "1.54.0", + "@theia/editor": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -40,7 +40,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/userstorage/package.json b/packages/userstorage/package.json index 0b7cee4c41d76..f43f417ae21e4 100644 --- a/packages/userstorage/package.json +++ b/packages/userstorage/package.json @@ -1,10 +1,10 @@ { "name": "@theia/userstorage", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - User Storage Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -40,7 +40,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/variable-resolver/package.json b/packages/variable-resolver/package.json index ba8fbdafbd7cb..5cdb301cebdf6 100644 --- a/packages/variable-resolver/package.json +++ b/packages/variable-resolver/package.json @@ -1,9 +1,9 @@ { "name": "@theia/variable-resolver", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Variable Resolver Extension", "dependencies": { - "@theia/core": "1.53.0", + "@theia/core": "1.54.0", "tslib": "^2.6.2" }, "publishConfig": { @@ -45,7 +45,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/packages/vsx-registry/package.json b/packages/vsx-registry/package.json index 86656ef7f8dac..3eabc882978ee 100644 --- a/packages/vsx-registry/package.json +++ b/packages/vsx-registry/package.json @@ -1,16 +1,16 @@ { "name": "@theia/vsx-registry", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - VSX Registry", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/navigator": "1.53.0", - "@theia/ovsx-client": "1.53.0", - "@theia/plugin-ext": "1.53.0", - "@theia/plugin-ext-vscode": "1.53.0", - "@theia/preferences": "1.53.0", - "@theia/workspace": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/navigator": "1.54.0", + "@theia/ovsx-client": "1.54.0", + "@theia/plugin-ext": "1.54.0", + "@theia/plugin-ext-vscode": "1.54.0", + "@theia/preferences": "1.54.0", + "@theia/workspace": "1.54.0", "limiter": "^2.1.0", "luxon": "^2.4.0", "p-debounce": "^2.1.0", @@ -55,7 +55,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0", + "@theia/ext-scripts": "1.54.0", "@types/luxon": "^2.3.2" }, "nyc": { diff --git a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts index 2bb0b34eec0c9..19736daf75b62 100644 --- a/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts +++ b/packages/vsx-registry/src/browser/vsx-registry-frontend-module.ts @@ -18,7 +18,9 @@ import '../../src/browser/style/index.css'; import { ContainerModule } from '@theia/core/shared/inversify'; import { - WidgetFactory, bindViewContribution, FrontendApplicationContribution, ViewContainerIdentifier, OpenHandler, WidgetManager, WebSocketConnectionProvider + WidgetFactory, bindViewContribution, FrontendApplicationContribution, ViewContainerIdentifier, OpenHandler, WidgetManager, WebSocketConnectionProvider, + WidgetStatusBarContribution, + noopWidgetStatusBarContribution } from '@theia/core/lib/browser'; import { VSXExtensionsViewContainer } from './vsx-extensions-view-container'; import { VSXExtensionsContribution } from './vsx-extensions-contribution'; @@ -64,6 +66,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => { })).inSingletonScope(); bind(VSXExtensionEditorManager).toSelf().inSingletonScope(); bind(OpenHandler).toService(VSXExtensionEditorManager); + bind(WidgetStatusBarContribution).toConstantValue(noopWidgetStatusBarContribution(VSXExtensionEditor)); bind(WidgetFactory).toDynamicValue(({ container }) => ({ id: VSXExtensionsWidget.ID, diff --git a/packages/workspace/package.json b/packages/workspace/package.json index 85340e1e18638..4480fb4d92c12 100644 --- a/packages/workspace/package.json +++ b/packages/workspace/package.json @@ -1,11 +1,11 @@ { "name": "@theia/workspace", - "version": "1.53.0", + "version": "1.54.0", "description": "Theia - Workspace Extension", "dependencies": { - "@theia/core": "1.53.0", - "@theia/filesystem": "1.53.0", - "@theia/variable-resolver": "1.53.0", + "@theia/core": "1.54.0", + "@theia/filesystem": "1.54.0", + "@theia/variable-resolver": "1.54.0", "jsonc-parser": "^2.2.0", "tslib": "^2.6.2", "valid-filename": "^2.0.1" @@ -47,7 +47,7 @@ "watch": "theiaext watch" }, "devDependencies": { - "@theia/ext-scripts": "1.53.0" + "@theia/ext-scripts": "1.54.0" }, "nyc": { "extends": "../../configs/nyc.json" diff --git a/sample-plugins/sample-namespace/plugin-a/package.json b/sample-plugins/sample-namespace/plugin-a/package.json index 6979f04fb5433..8b1af99d4c01f 100644 --- a/sample-plugins/sample-namespace/plugin-a/package.json +++ b/sample-plugins/sample-namespace/plugin-a/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "plugin-a", - "version": "1.53.0", + "version": "1.54.0", "main": "extension.js", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "repository": { diff --git a/sample-plugins/sample-namespace/plugin-b/package.json b/sample-plugins/sample-namespace/plugin-b/package.json index 4cb8ea0bd7577..6f195fb4b3569 100644 --- a/sample-plugins/sample-namespace/plugin-b/package.json +++ b/sample-plugins/sample-namespace/plugin-b/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "plugin-b", - "version": "1.53.0", + "version": "1.54.0", "main": "extension.js", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "repository": { diff --git a/sample-plugins/sample-namespace/plugin-gotd/package.json b/sample-plugins/sample-namespace/plugin-gotd/package.json index eee86aed9b23a..0eae6cb2417db 100644 --- a/sample-plugins/sample-namespace/plugin-gotd/package.json +++ b/sample-plugins/sample-namespace/plugin-gotd/package.json @@ -1,7 +1,7 @@ { "private": true, "name": "plugin-gotd", - "version": "1.53.0", + "version": "1.54.0", "license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0", "repository": { "type": "git", @@ -15,7 +15,7 @@ "*" ], "devDependencies": { - "@theia/api-provider-sample": "1.53.0" + "@theia/api-provider-sample": "1.54.0" }, "scripts": { "prepare": "yarn -s package",